From a5c3cf6a99fbe1b471e64b7aecb0bcb3cf3454aa Mon Sep 17 00:00:00 2001 From: Tobias Doerffel Date: Tue, 7 Jan 2014 23:42:17 +0100 Subject: [PATCH 001/647] Revised journalling (undo/redo) to record full states instead of changes Recording single changes of objects or their specific properties is completely superfluous as we have full implemented state tracking in all objects already. Therefore use SerializingObject::saveState() and SerializingObject::restoreState() in order to implement the undo/redo functionality. This is just an initial commit and needs some further work (especially regarding stability). However even things like undo/redo of addition/removal of Tracks and TrackContentObjects do work already. --- include/AutomatableModel.h | 22 ++-- include/JournallingObject.h | 67 ++++-------- include/note.h | 15 +-- include/surround_area.h | 14 +-- include/track.h | 18 +-- include/track_container_view.h | 5 +- src/core/AutomatableModel.cpp | 67 +++--------- src/core/JournallingObject.cpp | 66 ++++++----- src/core/ProjectJournal.cpp | 8 +- src/core/note.cpp | 50 +-------- src/core/track.cpp | 181 ++----------------------------- src/core/track_container.cpp | 12 +- src/gui/track_container_view.cpp | 71 +----------- src/gui/widgets/knob.cpp | 11 +- src/gui/widgets/lcd_spinbox.cpp | 15 ++- 15 files changed, 134 insertions(+), 488 deletions(-) diff --git a/include/AutomatableModel.h b/include/AutomatableModel.h index 453949b73..9488e8511 100644 --- a/include/AutomatableModel.h +++ b/include/AutomatableModel.h @@ -1,7 +1,7 @@ /* * AutomatableModel.h - declaration of class AutomatableModel * - * Copyright (c) 2007-2009 Tobias Doerffel + * Copyright (c) 2007-2014 Tobias Doerffel * * This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net * @@ -180,23 +180,19 @@ public: static void unlinkModels( AutomatableModel * _m1, AutomatableModel * _m2 ); - virtual void saveSettings( QDomDocument & _doc, - QDomElement & _this, - const QString & _name = QString( "value" ) ); + virtual void saveSettings( QDomDocument &doc, QDomElement &_this ); + virtual void loadSettings( const QDomElement &_this ); - virtual void loadSettings( const QDomElement & _this, - const QString & _name = QString( "value" ) ); + virtual void saveSettings( QDomDocument &doc, + QDomElement &_this, + const QString &name ); + virtual void loadSettings( const QDomElement &_this, const QString &name ); virtual QString nodeName() const { return "automatablemodel"; } - void prepareJournalEntryFromOldVal(); - - void addJournalEntryFromOldToCurVal(); - - QString displayValue( const float _val ) const { switch( m_dataType ) @@ -217,9 +213,6 @@ public slots: protected: - virtual void redoStep( JournalEntry & _je ); - virtual void undoStep( JournalEntry & _je ); - float fittedValue( float _value ) const; @@ -239,7 +232,6 @@ private: // most objects will need this temporarily (until sampleExact is // standard) float m_oldValue; - bool m_journalEntryReady; int m_setValueDepth; AutoModelVector m_linkedModels; diff --git a/include/JournallingObject.h b/include/JournallingObject.h index df9902546..84731c07c 100644 --- a/include/JournallingObject.h +++ b/include/JournallingObject.h @@ -1,7 +1,7 @@ /* * JournallingObject.h - declaration of class JournallingObject * - * Copyright (c) 2006-2009 Tobias Doerffel + * Copyright (c) 2006-2014 Tobias Doerffel * * This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net * @@ -27,6 +27,7 @@ #include "lmms_basics.h" #include "export.h" +#include "mmp.h" #include "SerializingObject.h" #include @@ -34,57 +35,37 @@ #include -typedef uint32_t t_action_id; - - -class JournalEntry +class JournalCheckPoint { public: - JournalEntry( const t_action_id _action_id, const QVariant & _data ) : - m_actionID( _action_id ), - m_data( _data ) + JournalCheckPoint( const multimediaProject &data = + multimediaProject( multimediaProject::JournalData ) ) : + m_data( data ) { } - JournalEntry() : - m_actionID( 0 ), - m_data( 0 ) + ~JournalCheckPoint() { } - ~JournalEntry() - { - } - - t_action_id actionID() const - { - return m_actionID; - } - - t_action_id & actionID() - { - return m_actionID; - } - - const QVariant & data() const + const multimediaProject &data() const { return m_data; } - QVariant & data() + multimediaProject &data() { return m_data; } private: - t_action_id m_actionID; - QVariant m_data; + multimediaProject m_data; } ; -typedef QVector JournalEntryVector; +typedef QVector JournalCheckPointVector; class EXPORT JournallingObject : public SerializingObject @@ -103,15 +84,15 @@ public: void clear() { - m_journalEntries.clear(); - m_currentJournalEntry = m_journalEntries.end(); + m_journalCheckPoints.clear(); + m_currentJournalCheckPoint = m_journalCheckPoints.end(); } void clearRedoSteps() { - m_journalEntries.erase( m_currentJournalEntry, - m_journalEntries.end() ); - m_currentJournalEntry = m_journalEntries.end(); + m_journalCheckPoints.erase( m_currentJournalCheckPoint, + m_journalCheckPoints.end() ); + m_currentJournalCheckPoint = m_journalCheckPoints.end(); } @@ -126,6 +107,8 @@ public: m_journalling = m_journallingStateStack.pop(); } + void addJournalCheckPoint(); + virtual QDomElement saveState( QDomDocument & _doc, QDomElement & _parent ); @@ -153,16 +136,6 @@ public: protected: void changeID( jo_id_t _id ); - void addJournalEntry( const JournalEntry & _je ); - - // to be implemented by sub-objects - virtual void undoStep( JournalEntry & ) - { - } - virtual void redoStep( JournalEntry & ) - { - } - private: void saveJournal( QDomDocument & _doc, QDomElement & _parent ); @@ -171,8 +144,8 @@ private: jo_id_t m_id; - JournalEntryVector m_journalEntries; - JournalEntryVector::Iterator m_currentJournalEntry; + JournalCheckPointVector m_journalCheckPoints; + JournalCheckPointVector::Iterator m_currentJournalCheckPoint; bool m_journalling; diff --git a/include/note.h b/include/note.h index 36bf1640d..11d2e4a17 100644 --- a/include/note.h +++ b/include/note.h @@ -2,7 +2,7 @@ * note.h - declaration of class note which contains all informations about a * note + definitions of several constants and enums * - * Copyright (c) 2004-2010 Tobias Doerffel + * Copyright (c) 2004-2014 Tobias Doerffel * * This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net * @@ -208,21 +208,8 @@ protected: QDomElement & _parent ); virtual void loadSettings( const QDomElement & _this ); -/* virtual void undoStep( JournalEntry & _je ); - virtual void redoStep( JournalEntry & _je );*/ - private: -/* enum Actions - { - ChangeKey, - ChangeVolume, - ChangePanning, - ChangeLength, - ChangePosition - } ;*/ - - // for piano roll editing bool m_selected; int m_oldKey; diff --git a/include/surround_area.h b/include/surround_area.h index 16b5822e1..30969a93a 100644 --- a/include/surround_area.h +++ b/include/surround_area.h @@ -3,7 +3,7 @@ * position of a channel + calculation of volume for each * speaker * - * Copyright (c) 2004-2008 Tobias Doerffel + * Copyright (c) 2004-2014 Tobias Doerffel * * This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net * @@ -57,18 +57,6 @@ public: void loadSettings( const QDomElement & _this, const QString & _name = "surpos" ); - inline void prepareJournalEntryFromOldVal() - { - m_posX.prepareJournalEntryFromOldVal(); - m_posY.prepareJournalEntryFromOldVal(); - } - - inline void addJournalEntryFromOldToCurVal() - { - m_posX.addJournalEntryFromOldToCurVal(); - m_posY.addJournalEntryFromOldToCurVal(); - } - // AutomationPattern * automationPatternX(); // AutomationPattern * automationPatternY(); diff --git a/include/track.h b/include/track.h index 1011c245d..2d7349be4 100644 --- a/include/track.h +++ b/include/track.h @@ -2,7 +2,7 @@ * track.h - declaration of classes concerning tracks -> necessary for all * track-like objects (beat/bassline, sample-track...) * - * Copyright (c) 2004-2009 Tobias Doerffel + * Copyright (c) 2004-2014 Tobias Doerffel * * This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net * @@ -128,11 +128,6 @@ public slots: void toggleMute(); -protected: - virtual void undoStep( JournalEntry & _je ); - virtual void redoStep( JournalEntry & _je ); - - signals: void lengthChanged(); void positionChanged(); @@ -275,17 +270,8 @@ protected: return "trackcontentwidget"; } - virtual void undoStep( JournalEntry & _je ); - virtual void redoStep( JournalEntry & _je ); - private: - enum Actions - { - AddTrackContentObject, - RemoveTrackContentObject - } ; - track * getTrack(); midiTime getPosition( int _mouse_x ); @@ -539,8 +525,6 @@ public slots: protected: virtual void modelChanged(); - virtual void undoStep( JournalEntry & _je ); - virtual void redoStep( JournalEntry & _je ); virtual QString nodeName() const { diff --git a/include/track_container_view.h b/include/track_container_view.h index cace6bf8e..6597a39ac 100644 --- a/include/track_container_view.h +++ b/include/track_container_view.h @@ -1,7 +1,7 @@ /* * track_container_view.h - view-component for trackContainer * - * Copyright (c) 2004-2009 Tobias Doerffel + * Copyright (c) 2004-2014 Tobias Doerffel * * This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net * @@ -139,9 +139,6 @@ protected: virtual void mouseReleaseEvent( QMouseEvent * _me ); virtual void resizeEvent( QResizeEvent * ); - virtual void undoStep( JournalEntry & _je ); - virtual void redoStep( JournalEntry & _je ); - midiTime m_currentPosition; diff --git a/src/core/AutomatableModel.cpp b/src/core/AutomatableModel.cpp index 034be3bb5..29ee3cb12 100644 --- a/src/core/AutomatableModel.cpp +++ b/src/core/AutomatableModel.cpp @@ -1,7 +1,7 @@ /* * AutomatableModel.cpp - some implementations of AutomatableModel-class * - * Copyright (c) 2008-2012 Tobias Doerffel + * Copyright (c) 2008-2014 Tobias Doerffel * * This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net * @@ -50,7 +50,6 @@ AutomatableModel::AutomatableModel( DataType _type, m_maxValue( _max ), m_step( _step ), m_range( _max - _min ), - m_journalEntryReady( false ), m_setValueDepth( 0 ), m_hasLinkedModels( false ), m_controllerConnection( NULL ) @@ -88,6 +87,22 @@ bool AutomatableModel::isAutomated() const +void AutomatableModel::saveSettings( QDomDocument &doc, QDomElement &_this ) +{ + saveSettings( doc, _this, "value" ); +} + + + + +void AutomatableModel::loadSettings( const QDomElement &_this ) +{ + loadSettings( _this, "value" ); +} + + + + void AutomatableModel::saveSettings( QDomDocument & _doc, QDomElement & _this, const QString & _name ) { @@ -184,7 +199,7 @@ void AutomatableModel::setValue( const float _value ) if( old_val != m_value ) { // add changes to history so user can undo it - addJournalEntry( JournalEntry( 0, m_value - old_val ) ); + addJournalCheckPoint(); // notify linked models for( AutoModelVector::Iterator it = @@ -319,52 +334,6 @@ float AutomatableModel::fittedValue( float _value ) const -void AutomatableModel::redoStep( JournalEntry & _je ) -{ - bool journalling = testAndSetJournalling( false ); - setValue( value() + (float) _je.data().toDouble() ); - setJournalling( journalling ); -} - - - - -void AutomatableModel::undoStep( JournalEntry & _je ) -{ - JournalEntry je( _je.actionID(), -_je.data().toDouble() ); - redoStep( je ); -} - - - - -void AutomatableModel::prepareJournalEntryFromOldVal() -{ - m_oldValue = value(); - saveJournallingState( false ); - m_journalEntryReady = true; -} - - - - -void AutomatableModel::addJournalEntryFromOldToCurVal() -{ - if( m_journalEntryReady ) - { - restoreJournallingState(); - if( value() != m_oldValue ) - { - addJournalEntry( JournalEntry( 0, value() - - m_oldValue ) ); - } - m_journalEntryReady = false; - } -} - - - - void AutomatableModel::linkModel( AutomatableModel * _model ) { if( !m_linkedModels.contains( _model ) ) diff --git a/src/core/JournallingObject.cpp b/src/core/JournallingObject.cpp index b2a4bc575..7d3229597 100644 --- a/src/core/JournallingObject.cpp +++ b/src/core/JournallingObject.cpp @@ -1,7 +1,7 @@ /* * JournallingObject.cpp - implementation of journalling-object related stuff * - * Copyright (c) 2006-2009 Tobias Doerffel + * Copyright (c) 2006-2014 Tobias Doerffel * * This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net * @@ -37,8 +37,8 @@ JournallingObject::JournallingObject() : SerializingObject(), m_id( engine::projectJournal()->allocID( this ) ), - m_journalEntries(), - m_currentJournalEntry( m_journalEntries.end() ), + m_journalCheckPoints(), + m_currentJournalCheckPoint( m_journalCheckPoints.end() ), m_journalling( true ), m_journallingStateStack() { @@ -60,14 +60,15 @@ JournallingObject::~JournallingObject() void JournallingObject::undo() { - if( m_journalEntries.empty() == true ) + if( m_journalCheckPoints.empty() == true ) { return; } - if( m_currentJournalEntry - 1 >= m_journalEntries.begin() ) + if( m_currentJournalCheckPoint - 1 >= m_journalCheckPoints.begin() ) { - undoStep( *--m_currentJournalEntry ); + --m_currentJournalCheckPoint; + restoreState( m_currentJournalCheckPoint->data().content().firstChildElement() ); } } @@ -76,14 +77,15 @@ void JournallingObject::undo() void JournallingObject::redo() { - if( m_journalEntries.empty() == true ) + if( m_journalCheckPoints.empty() == true ) { return; } - if( m_currentJournalEntry < m_journalEntries.end() ) + if( m_currentJournalCheckPoint < m_journalCheckPoints.end() ) { - redoStep( *m_currentJournalEntry++ ); + restoreState( m_currentJournalCheckPoint->data().content().firstChildElement() ); + ++m_currentJournalCheckPoint; } } @@ -124,14 +126,19 @@ void JournallingObject::restoreState( const QDomElement & _this ) -void JournallingObject::addJournalEntry( const JournalEntry & _je ) +void JournallingObject::addJournalCheckPoint() { if( engine::projectJournal()->isJournalling() && isJournalling() ) { - m_journalEntries.erase( m_currentJournalEntry, - m_journalEntries.end() ); - m_journalEntries.push_back( _je ); - m_currentJournalEntry = m_journalEntries.end(); + m_journalCheckPoints.erase( m_currentJournalCheckPoint, + m_journalCheckPoints.end() ); + + multimediaProject mmp( multimediaProject::JournalData ); + saveState( mmp, mmp.content() ); + + m_journalCheckPoints.push_back( JournalCheckPoint( mmp ) ); + + m_currentJournalCheckPoint = m_journalCheckPoints.end(); engine::projectJournal()->journalEntryAdded( id() ); } } @@ -172,25 +179,25 @@ void JournallingObject::saveJournal( QDomDocument & _doc, QDomElement & _parent ) { /* // avoid creating empty journal-nodes - if( m_journalEntries.size() == 0 ) + if( m_journalCheckPoints.size() == 0 ) { return; }*/ QDomElement journal_de = _doc.createElement( "journal" ); journal_de.setAttribute( "id", id() ); - journal_de.setAttribute( "entries", m_journalEntries.size() ); - journal_de.setAttribute( "curentry", (int)( m_currentJournalEntry - - m_journalEntries.begin() ) ); + journal_de.setAttribute( "entries", m_journalCheckPoints.size() ); + journal_de.setAttribute( "curentry", (int)( m_currentJournalCheckPoint - + m_journalCheckPoints.begin() ) ); journal_de.setAttribute( "metadata", true ); - for( JournalEntryVector::const_iterator it = m_journalEntries.begin(); - it != m_journalEntries.end(); ++it ) + for( JournalCheckPointVector::const_iterator it = m_journalCheckPoints.begin(); + it != m_journalCheckPoints.end(); ++it ) { QDomElement je_de = _doc.createElement( "entry" ); je_de.setAttribute( "pos", (int)( it - - m_journalEntries.begin() ) ); - je_de.setAttribute( "actionid", it->actionID() ); - je_de.setAttribute( "data", base64::encode( it->data() ) ); + m_journalCheckPoints.begin() ) ); + //je_de.setAttribute( "data", base64::encode( it->data().toString() ) ); + je_de.setAttribute( "data", it->data().toString() ); journal_de.appendChild( je_de ); } @@ -213,7 +220,7 @@ void JournallingObject::loadJournal( const QDomElement & _this ) changeID( new_id ); - m_journalEntries.resize( _this.attribute( "entries" ).toInt() ); + m_journalCheckPoints.resize( _this.attribute( "entries" ).toInt() ); QDomNode node = _this.firstChild(); while( !node.isNull() ) @@ -221,15 +228,14 @@ void JournallingObject::loadJournal( const QDomElement & _this ) if( node.isElement() ) { const QDomElement & je = node.toElement(); - m_journalEntries[je.attribute( "pos" ).toInt()] = - JournalEntry( - je.attribute( "actionid" ).toInt(), - base64::decode( je.attribute( "data" ) ) ); + m_journalCheckPoints[je.attribute( "pos" ).toInt()] = + JournalCheckPoint( + multimediaProject( je.attribute( "data" ).toUtf8() ) ); } node = node.nextSibling(); - } + } - m_currentJournalEntry = m_journalEntries.begin() + + m_currentJournalCheckPoint = m_journalCheckPoints.begin() + _this.attribute( "curentry" ).toInt(); } diff --git a/src/core/ProjectJournal.cpp b/src/core/ProjectJournal.cpp index dffd60eee..04e452fde 100644 --- a/src/core/ProjectJournal.cpp +++ b/src/core/ProjectJournal.cpp @@ -1,7 +1,7 @@ /* * ProjectJournal.cpp - implementation of ProjectJournal * - * Copyright (c) 2006-2009 Tobias Doerffel + * Copyright (c) 2006-2014 Tobias Doerffel * * This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net * @@ -60,7 +60,10 @@ void ProjectJournal::undo() if( m_currentJournalEntry - 1 >= m_journalEntries.begin() && ( jo = m_joIDs[*--m_currentJournalEntry] ) != NULL ) { + bool prev = isJournalling(); + setJournalling( false ); jo->undo(); + setJournalling( prev ); engine::getSong()->setModified(); } } @@ -81,7 +84,10 @@ void ProjectJournal::redo() if( m_currentJournalEntry < m_journalEntries.end() && ( jo = m_joIDs[*m_currentJournalEntry++] ) != NULL ) { + bool prev = isJournalling(); + setJournalling( false ); jo->redo(); + setJournalling( prev ); engine::getSong()->setModified(); } } diff --git a/src/core/note.cpp b/src/core/note.cpp index 2088e1188..e40d5f59f 100644 --- a/src/core/note.cpp +++ b/src/core/note.cpp @@ -1,7 +1,7 @@ /* * note.cpp - implementation of class note * - * Copyright (c) 2004-2009 Tobias Doerffel + * Copyright (c) 2004-2014 Tobias Doerffel * * This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net * @@ -50,8 +50,6 @@ note::note( const midiTime & _length, const midiTime & _pos, m_pos( _pos ), m_detuning( NULL ) { - //saveJournallingState( false ); -// setJournalling( false ); if( _detuning ) { m_detuning = sharedObject::ref( _detuning ); @@ -60,7 +58,6 @@ note::note( const midiTime & _length, const midiTime & _pos, { createDetuning(); } - //restoreJournallingState(); } @@ -106,7 +103,6 @@ note::~note() void note::setLength( const midiTime & _length ) { -// addJournalEntry( journalEntry( ChangeLength, m_length - _length ) ); m_length = _length; } @@ -115,7 +111,6 @@ void note::setLength( const midiTime & _length ) void note::setPos( const midiTime & _pos ) { -// addJournalEntry( journalEntry( ChangePosition, m_pos - _pos ) ); m_pos = _pos; } @@ -125,7 +120,6 @@ void note::setPos( const midiTime & _pos ) void note::setKey( const int _key ) { const int k = tLimit( _key, 0, NumKeys ); -// addJournalEntry( journalEntry( ChangeKey, m_key - k ) ); m_key = k; } @@ -135,7 +129,6 @@ void note::setKey( const int _key ) void note::setVolume( const volume_t _volume ) { const volume_t v = tLimit( _volume, MinVolume, MaxVolume ); -// addJournalEntry( journalEntry( ChangeVolume, (int) m_volume - v ) ); m_volume = v; } @@ -145,7 +138,6 @@ void note::setVolume( const volume_t _volume ) void note::setPanning( const panning_t _panning ) { const panning_t p = tLimit( _panning, PanningLeft, PanningRight ); -// addJournalEntry( journalEntry( ChangePanning, (int) m_panning - p ) ); m_panning = p; } @@ -219,46 +211,6 @@ void note::loadSettings( const QDomElement & _this ) -/*void note::undoStep( journalEntry & _je ) -{ - saveJournallingState( false ); - switch( static_cast( _je.actionID() ) ) - { - case ChangeKey: - setKey( key() - _je.data().toInt() ); - break; - - case ChangeVolume: - setVolume( getVolume() - _je.data().toInt() ); - break; - - case ChangePanning: - setPanning( getPanning() - _je.data().toInt() ); - break; - - case ChangeLength: - setLength( length() - _je.data().toInt() ); - break; - - case ChangePosition: - setPos( pos() - _je.data().toInt() ); - break; - } - restoreJournallingState(); -} - - - - -void note::redoStep( journalEntry & _je ) -{ - journalEntry je( _je.actionID(), -_je.data().toInt() ); - undoStep( je ); -}*/ - - - - void note::editDetuningPattern() { m_detuning->automationPattern()->openInAutomationEditor(); diff --git a/src/core/track.cpp b/src/core/track.cpp index 82694aaf5..f24ec6d0f 100644 --- a/src/core/track.cpp +++ b/src/core/track.cpp @@ -2,7 +2,7 @@ * track.cpp - implementation of classes concerning tracks -> necessary for * all track-like objects (beat/bassline, sample-track...) * - * Copyright (c) 2004-2012 Tobias Doerffel + * Copyright (c) 2004-2014 Tobias Doerffel * * This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net * @@ -149,7 +149,6 @@ void trackContentObject::movePosition( const midiTime & _pos ) { if( m_startPosition != _pos ) { - addJournalEntry( JournalEntry( Move, m_startPosition - _pos ) ); m_startPosition = _pos; engine::getSong()->updateLength(); } @@ -170,7 +169,6 @@ void trackContentObject::changeLength( const midiTime & _length ) { if( m_length != _length ) { - addJournalEntry( JournalEntry( Resize, m_length - _length ) ); m_length = _length; engine::getSong()->updateLength(); } @@ -180,47 +178,6 @@ void trackContentObject::changeLength( const midiTime & _length ) -/*! \brief Undo one journal entry of this trackContentObject - * - * Restore the previous state of this track content object. This will - * restore the position or the length of the track content object - * depending on what was changed. - * - * \param _je The journal entry to undo - */ -void trackContentObject::undoStep( JournalEntry & _je ) -{ - saveJournallingState( false ); - switch( _je.actionID() ) - { - case Move: - movePosition( startPosition() + _je.data().toInt() ); - break; - case Resize: - changeLength( length() + _je.data().toInt() ); - break; - } - restoreJournallingState(); -} - - - - -/*! \brief Redo one journal entry of this trackContentObject - * - * Undoes one 'undo' of this track content object. - * - * \param _je The journal entry to redo - */ -void trackContentObject::redoStep( JournalEntry & _je ) -{ - JournalEntry je( _je.actionID(), -_je.data().toInt() ); - undoStep( je ); -} - - - - /*! \brief Copy this trackContentObject to the clipboard. * * Copies this track content object to the clipboard. @@ -367,6 +324,8 @@ bool trackContentObjectView::fixedTCOs() */ bool trackContentObjectView::close() { + m_trackView->getTrack()->addJournalCheckPoint(); + m_trackView->getTrackContentWidget()->removeTCOView( this ); return QWidget::close(); } @@ -577,6 +536,8 @@ void trackContentObjectView::mousePressEvent( QMouseEvent * _me ) /* engine::mainWindow()->isShiftPressed() == false &&*/ fixedTCOs() == false ) { + m_tco->addJournalCheckPoint(); + // move or resize m_tco->setJournalling( false ); @@ -773,9 +734,6 @@ void trackContentObjectView::mouseReleaseEvent( QMouseEvent * _me ) if( m_action == Move || m_action == Resize ) { m_tco->setJournalling( true ); - m_tco->addJournalEntry( JournalEntry( m_action, m_oldTime - - ( ( m_action == Move ) ? - m_tco->startPosition() : m_tco->length() ) ) ); } m_action = NoAction; delete m_hint; @@ -951,9 +909,6 @@ void trackContentWidget::updateBackground() void trackContentWidget::addTCOView( trackContentObjectView * _tcov ) { trackContentObject * tco = _tcov->getTrackContentObject(); -/* QMap map; - map["id"] = tco->id(); - addJournalEntry( JournalEntry( AddTrackContentObject, map ) );*/ m_tcoViews.push_back( _tcov ); @@ -978,14 +933,6 @@ void trackContentWidget::removeTCOView( trackContentObjectView * _tcov ) _tcov ); if( it != m_tcoViews.end() ) { -/* QMap map; - multimediaProject mmp( multimediaProject::JournalData ); - _tcov->getTrackContentObject()->saveState( mmp, mmp.content() ); - map["id"] = _tcov->getTrackContentObject()->id(); - map["state"] = mmp.toString(); - addJournalEntry( JournalEntry( RemoveTrackContentObject, - map ) );*/ - m_tcoViews.erase( it ); engine::getSong()->setModified(); } @@ -1127,6 +1074,7 @@ void trackContentWidget::dropEvent( QDropEvent * _de ) { const midiTime pos = getPosition( _de->pos().x() ).toNearestTact(); + getTrack()->addJournalCheckPoint(); trackContentObject * tco = getTrack()->createTCO( pos ); // value contains our XML-data so simply create a @@ -1167,6 +1115,7 @@ void trackContentWidget::mousePressEvent( QMouseEvent * _me ) { const midiTime pos = getPosition( _me->x() ).getTact() * midiTime::ticksPerTact(); + getTrack()->addJournalCheckPoint(); trackContentObject * tco = getTrack()->createTCO( pos ); tco->saveJournallingState( false ); @@ -1215,71 +1164,6 @@ void trackContentWidget::resizeEvent( QResizeEvent * resizeEvent ) -/*! \brief Undo an action on the trackContentWidget - * - * \param _je the details of the edit journal - */ -void trackContentWidget::undoStep( JournalEntry & _je ) -{ - saveJournallingState( false ); - switch( _je.actionID() ) - { - case AddTrackContentObject: - { - QMap map = _je.data().toMap(); - trackContentObject * tco = - dynamic_cast( - engine::projectJournal()->journallingObject( map["id"].toInt() ) ); - multimediaProject mmp( multimediaProject::JournalData ); - tco->saveState( mmp, mmp.content() ); - map["state"] = mmp.toString(); - _je.data() = map; - tco->deleteLater(); - break; - } - - case RemoveTrackContentObject: - { - trackContentObject * tco = getTrack()->createTCO( midiTime( 0 ) ); - multimediaProject mmp( - _je.data().toMap()["state"]. - toString().toUtf8() ); - tco->restoreState( mmp.content().firstChild().toElement() ); - break; - } - } - restoreJournallingState(); -} - - - - -/*! \brief Redo an action of the trackContentWidget - * - * \param _je the entry in the edit journal to redo. - */ -void trackContentWidget::redoStep( JournalEntry & _je ) -{ - switch( _je.actionID() ) - { - case AddTrackContentObject: - case RemoveTrackContentObject: - _je.actionID() = ( _je.actionID() == - AddTrackContentObject ) ? - RemoveTrackContentObject : - AddTrackContentObject; - undoStep( _je ); - _je.actionID() = ( _je.actionID() == - AddTrackContentObject ) ? - RemoveTrackContentObject : - AddTrackContentObject; - break; - } -} - - - - /*! \brief Return the track shown by the trackContentWidget * */ @@ -2231,55 +2115,6 @@ void trackView::modelChanged() -/*! \brief Undo a change to this track View. - * - * \param _je the Journal Entry to undo. - */ -void trackView::undoStep( JournalEntry & _je ) -{ - saveJournallingState( false ); - switch( _je.actionID() ) - { - case MoveTrack: - if( _je.data().toInt() > 0 ) - { - m_trackContainerView->moveTrackViewUp( this ); - } - else - { - m_trackContainerView->moveTrackViewDown( this ); - } - break; - case ResizeTrack: - setFixedHeight( qMax( height() + - _je.data().toInt(), - MINIMAL_TRACK_HEIGHT ) ); - m_trackContainerView->realignTracks(); - break; - /*case RestoreTrack: - setFixedHeight( DEFAULT_TRACK_HEIGHT ); - m_trackContainerView->realignTracks(); - break; */ - } - restoreJournallingState(); -} - - - - -/*! \brief Redo a change to this track View. - * - * \param _je the Journal Event to redo. - */ -void trackView::redoStep( JournalEntry & _je ) -{ - JournalEntry je( _je.actionID(), -_je.data().toInt() ); - undoStep( je ); -} - - - - /*! \brief Start a drag event on this track View. * * \param _dee the DragEnterEvent to start. @@ -2414,6 +2249,7 @@ void trackView::mouseMoveEvent( QMouseEvent * _me ) // a track-widget not equal to ourself? if( track_at_y != NULL && track_at_y != this ) { + addJournalCheckPoint(); // then move us up/down there! if( _me->y() < 0 ) { @@ -2423,7 +2259,6 @@ void trackView::mouseMoveEvent( QMouseEvent * _me ) { m_trackContainerView->moveTrackViewDown( this ); } - addJournalEntry( JournalEntry( MoveTrack, _me->y() ) ); } } else if( m_action == ResizeTrack ) diff --git a/src/core/track_container.cpp b/src/core/track_container.cpp index d9266f448..e366c42e2 100644 --- a/src/core/track_container.cpp +++ b/src/core/track_container.cpp @@ -2,7 +2,7 @@ * track_container.cpp - implementation of base-class for all track-containers * like Song-Editor, BB-Editor... * - * Copyright (c) 2004-2009 Tobias Doerffel + * Copyright (c) 2004-2014 Tobias Doerffel * * This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net * @@ -73,10 +73,16 @@ void trackContainer::saveSettings( QDomDocument & _doc, QDomElement & _this ) void trackContainer::loadSettings( const QDomElement & _this ) { + bool journalRestore = _this.parentNode().nodeName() == "journaldata"; + if( journalRestore ) + { + clearAllTracks(); + } + static QProgressDialog * pd = NULL; bool was_null = ( pd == NULL ); int start_val = 0; - if( engine::hasGUI() ) + if( !journalRestore && engine::hasGUI() ) { if( pd == NULL ) { @@ -154,6 +160,8 @@ void trackContainer::addTrack( track * _track ) { if( _track->type() != track::HiddenAutomationTrack ) { + addJournalCheckPoint(); + m_tracksMutex.lockForWrite(); m_tracks.push_back( _track ); m_tracksMutex.unlock(); diff --git a/src/gui/track_container_view.cpp b/src/gui/track_container_view.cpp index d9da9e471..77f1305a4 100644 --- a/src/gui/track_container_view.cpp +++ b/src/gui/track_container_view.cpp @@ -121,10 +121,6 @@ void trackContainerView::loadSettings( const QDomElement & _this ) trackView * trackContainerView::addTrackView( trackView * _tv ) { -/* QMap map; - map["id"] = _tv->getTrack()->id(); - addJournalEntry( JournalEntry( AddTrack, map ) );*/ - m_trackViews.push_back( _tv ); m_scrollLayout->addWidget( _tv ); connect( this, SIGNAL( positionChanged( const midiTime & ) ), @@ -142,13 +138,6 @@ void trackContainerView::removeTrackView( trackView * _tv ) int index = m_trackViews.indexOf( _tv ); if( index != -1 ) { -/* QMap map; - multimediaProject mmp( multimediaProject::JournalData ); - _tv->getTrack()->saveState( mmp, mmp.content() ); - map["id"] = _tv->getTrack()->id(); - map["state"] = mmp.toString(); - addJournalEntry( JournalEntry( RemoveTrack, map ) );*/ - m_trackViews.removeAt( index ); disconnect( _tv ); @@ -238,6 +227,8 @@ void trackContainerView::createTrackView( track * _t ) void trackContainerView::deleteTrackView( trackView * _tv ) { + m_tc->addJournalCheckPoint(); + track * t = _tv->getTrack(); removeTrackView( _tv ); delete _tv; @@ -307,64 +298,6 @@ void trackContainerView::clearAllTracks() -void trackContainerView::undoStep( JournalEntry & _je ) -{ -#if 0 - saveJournallingState( false ); - switch( _je.actionID() ) - { - case AddTrack: - { - QMap map = _je.data().toMap(); - track * t = - dynamic_cast( - engine::projectJournal()->getJournallingObject( - map["id"].toInt() ) ); - assert( t != NULL ); - multimediaProject mmp( multimediaProject::JournalData ); - t->saveState( mmp, mmp.content() ); - map["state"] = mmp.toString(); - _je.data() = map; - t->deleteLater(); - break; - } - - case RemoveTrack: - { - multimediaProject mmp( - _je.data().toMap()["state"].toString().utf8() ); - track::create( mmp.content().firstChild().toElement(), - m_tc ); - break; - } - } - restoreJournallingState(); -#endif -} - - - - -void trackContainerView::redoStep( JournalEntry & _je ) -{ -#if 0 - switch( _je.actionID() ) - { - case AddTrack: - case RemoveTrack: - _je.actionID() = ( _je.actionID() == AddTrack ) ? - RemoveTrack : AddTrack; - undoStep( _je ); - _je.actionID() = ( _je.actionID() == AddTrack ) ? - RemoveTrack : AddTrack; - break; - } -#endif -} - - - - void trackContainerView::dragEnterEvent( QDragEnterEvent * _dee ) { stringPairDrag::processDragEnterEvent( _dee, diff --git a/src/gui/widgets/knob.cpp b/src/gui/widgets/knob.cpp index efb4b6e0b..9f6840349 100644 --- a/src/gui/widgets/knob.cpp +++ b/src/gui/widgets/knob.cpp @@ -1,7 +1,7 @@ /* * knob.cpp - powerful knob-widget * - * Copyright (c) 2004-2011 Tobias Doerffel + * Copyright (c) 2004-2014 Tobias Doerffel * * This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net * @@ -438,7 +438,12 @@ void knob::mousePressEvent( QMouseEvent * _me ) ! ( _me->modifiers() & Qt::ControlModifier ) && ! ( _me->modifiers() & Qt::ShiftModifier ) ) { - model()->prepareJournalEntryFromOldVal(); + AutomatableModel *thisModel = model(); + if( thisModel ) + { + thisModel->addJournalCheckPoint(); + thisModel->saveJournallingState( false ); + } const QPoint & p = _me->pos(); m_origMousePos = p; @@ -485,7 +490,7 @@ void knob::mouseMoveEvent( QMouseEvent * _me ) void knob::mouseReleaseEvent( QMouseEvent * /* _me*/ ) { - model()->addJournalEntryFromOldToCurVal(); + model()->restoreJournallingState(); m_buttonPressed = false; diff --git a/src/gui/widgets/lcd_spinbox.cpp b/src/gui/widgets/lcd_spinbox.cpp index dcc1ebd09..b3b27ce06 100644 --- a/src/gui/widgets/lcd_spinbox.cpp +++ b/src/gui/widgets/lcd_spinbox.cpp @@ -100,7 +100,13 @@ void lcdSpinBox::mousePressEvent( QMouseEvent* event ) { m_origMousePos = event->globalPos(); QApplication::setOverrideCursor( Qt::BlankCursor ); - model()->prepareJournalEntryFromOldVal(); + + AutomatableModel *thisModel = model(); + if( thisModel ) + { + thisModel->addJournalCheckPoint(); + thisModel->saveJournallingState( false ); + } } else { @@ -131,7 +137,12 @@ void lcdSpinBox::mouseMoveEvent( QMouseEvent* event ) void lcdSpinBox::mouseReleaseEvent( QMouseEvent* event ) { - model()->addJournalEntryFromOldToCurVal(); + AutomatableModel *thisModel = model(); + if( thisModel ) + { + thisModel->restoreJournallingState(); + } + QCursor::setPos( m_origMousePos ); QApplication::restoreOverrideCursor(); From d0f6eaef3b503cc18d477aeaee4023436158337b Mon Sep 17 00:00:00 2001 From: Tobias Doerffel Date: Tue, 7 Jan 2014 23:43:36 +0100 Subject: [PATCH 002/647] PianoRoll: initial undo/redo support Most editing operations in PianoRoll are now tracked by the revised journalling and thus are included in global undo/redo. --- src/gui/piano_roll.cpp | 34 ++++++++++++++++++++++++++++------ 1 file changed, 28 insertions(+), 6 deletions(-) diff --git a/src/gui/piano_roll.cpp b/src/gui/piano_roll.cpp index 41cdc060e..567ae0803 100644 --- a/src/gui/piano_roll.cpp +++ b/src/gui/piano_roll.cpp @@ -2,7 +2,7 @@ * piano_roll.cpp - implementation of piano-roll which is used for actual * writing of melodies * - * Copyright (c) 2004-2010 Tobias Doerffel + * Copyright (c) 2004-2014 Tobias Doerffel * Copyright (c) 2008 Andrew Kelley * * This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net @@ -1369,6 +1369,15 @@ void pianoRoll::keyReleaseEvent( QKeyEvent * _ke ) m_editMode = m_ctrlMode; update(); break; + + // update after undo/redo + case Qt::Key_Z: + case Qt::Key_R: + if( validPattern() && _ke->modifiers() == Qt::ControlModifier ) + { + update(); + } + break; } } @@ -1535,6 +1544,7 @@ void pianoRoll::mousePressEvent( QMouseEvent * _me ) // area if( edit_note == true ) { + m_pattern->addJournalCheckPoint(); // scribble note edit changes mouseMoveEvent( _me ); return; @@ -1552,6 +1562,7 @@ void pianoRoll::mousePressEvent( QMouseEvent * _me ) if( it == notes.begin()-1 ) { is_new_note = true; + m_pattern->addJournalCheckPoint(); m_pattern->setType( pattern::MelodyPattern ); // then set new note @@ -1597,8 +1608,7 @@ void pianoRoll::mousePressEvent( QMouseEvent * _me ) // ops (move, resize) after this // code-block it = notes.begin(); - while( it != notes.end() && - *it != created_new_note ) + while( it != notes.end() && *it != created_new_note ) { ++it; } @@ -1677,6 +1687,7 @@ void pianoRoll::mousePressEvent( QMouseEvent * _me ) RESIZE_AREA_WIDTH && m_currentNote->length() > 0 ) { + m_pattern->addJournalCheckPoint(); // then resize the note m_action = ActionResizeNote; @@ -1686,6 +1697,11 @@ void pianoRoll::mousePressEvent( QMouseEvent * _me ) } else { + if( !created_new_note ) + { + m_pattern->addJournalCheckPoint(); + } + // otherwise move it m_action = ActionMoveNote; @@ -1741,6 +1757,7 @@ void pianoRoll::mousePressEvent( QMouseEvent * _me ) m_mouseDownRight = true; if( it != notes.begin()-1 ) { + m_pattern->addJournalCheckPoint(); if( ( *it )->length() > 0 ) { m_pattern->removeNote( *it ); @@ -2595,7 +2612,6 @@ void pianoRoll::dragNotes( int x, int y, bool alt, bool shift ) if( ( *it )->selected() ) { - if( m_action == ActionMoveNote ) { // moving note @@ -3599,7 +3615,12 @@ void pianoRoll::pasteNotes() // remove selection and select the newly pasted notes clearSelectedNotes(); - + + if( !list.isEmpty() ) + { + m_pattern->addJournalCheckPoint(); + } + for( int i = 0; !list.item( i ).isNull(); ++i ) { // create the note @@ -3635,7 +3656,8 @@ void pianoRoll::deleteSelectedNotes() } bool update_after_delete = false; - + + m_pattern->addJournalCheckPoint(); // get note-vector of current pattern const NoteVector & notes = m_pattern->notes(); From 1f203a10f9fa30910ebf9cf286a8c064bf45c16e Mon Sep 17 00:00:00 2001 From: Tobias Doerffel Date: Tue, 7 Jan 2014 23:49:07 +0100 Subject: [PATCH 003/647] Widgets/Knob: only restore journalling state on release of left mouse button Do not try to restore the journalling state of the underlying model when releasing e.g the right mouse button as this causes a crash otherwise. --- src/gui/widgets/knob.cpp | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/gui/widgets/knob.cpp b/src/gui/widgets/knob.cpp index 9f6840349..333925106 100644 --- a/src/gui/widgets/knob.cpp +++ b/src/gui/widgets/knob.cpp @@ -488,9 +488,16 @@ void knob::mouseMoveEvent( QMouseEvent * _me ) -void knob::mouseReleaseEvent( QMouseEvent * /* _me*/ ) +void knob::mouseReleaseEvent( QMouseEvent* event ) { - model()->restoreJournallingState(); + if( event && event->button() == Qt::LeftButton ) + { + AutomatableModel *thisModel = model(); + if( thisModel ) + { + thisModel->restoreJournallingState(); + } + } m_buttonPressed = false; From 4641a8001b5ebd98087870c0fb25c094e3189d76 Mon Sep 17 00:00:00 2001 From: Tobias Doerffel Date: Tue, 7 Jan 2014 23:50:27 +0100 Subject: [PATCH 004/647] JournallingObject, ProjectJournal: global checkpoint management There's no need for having each JournallingObject maintain it's own checkpoints and build a complex (and buggy) logic in ProjectJournal in order to manage all the JournallingObject with their checkpoints. Instead do it the simple way: in ProjectJournal maintain a stack for undo checkpoints and a stack for redo checkpoints. On each undo or redo operation simply push and pop to/from the according stacks and save and load states of the concerned JournallingObject. This basically strips most functionality from JournallingObject. All what's left is the management of its ID which unluckily is still required in order to properly implement undo/redo of additions and removals of JournallingObject. --- include/JournallingObject.h | 69 ++--------------- include/ProjectJournal.h | 32 +++++--- src/core/JournallingObject.cpp | 133 ++++----------------------------- src/core/ProjectJournal.cpp | 99 +++++++++++------------- 4 files changed, 85 insertions(+), 248 deletions(-) diff --git a/include/JournallingObject.h b/include/JournallingObject.h index 84731c07c..1be811d20 100644 --- a/include/JournallingObject.h +++ b/include/JournallingObject.h @@ -27,7 +27,6 @@ #include "lmms_basics.h" #include "export.h" -#include "mmp.h" #include "SerializingObject.h" #include @@ -35,39 +34,6 @@ #include -class JournalCheckPoint -{ -public: - JournalCheckPoint( const multimediaProject &data = - multimediaProject( multimediaProject::JournalData ) ) : - m_data( data ) - { - } - - ~JournalCheckPoint() - { - } - - const multimediaProject &data() const - { - return m_data; - } - - multimediaProject &data() - { - return m_data; - } - - -private: - multimediaProject m_data; - -} ; - - -typedef QVector JournalCheckPointVector; - - class EXPORT JournallingObject : public SerializingObject { public: @@ -79,27 +45,10 @@ public: return m_id; } - void undo(); - void redo(); - - void clear() - { - m_journalCheckPoints.clear(); - m_currentJournalCheckPoint = m_journalCheckPoints.end(); - } - - void clearRedoSteps() - { - m_journalCheckPoints.erase( m_currentJournalCheckPoint, - m_journalCheckPoints.end() ); - m_currentJournalCheckPoint = m_journalCheckPoints.end(); - - } - - void saveJournallingState( const bool _new_state ) + void saveJournallingState( const bool newState ) { m_journallingStateStack.push( m_journalling ); - m_journalling = _new_state; + m_journalling = newState; } void restoreJournallingState() @@ -110,11 +59,10 @@ public: void addJournalCheckPoint(); virtual QDomElement saveState( QDomDocument & _doc, - QDomElement & _parent ); + QDomElement & _parent ); virtual void restoreState( const QDomElement & _this ); - inline bool isJournalling() const { return m_journalling; @@ -125,10 +73,10 @@ public: m_journalling = _sr; } - inline bool testAndSetJournalling( const bool _sr ) + inline bool testAndSetJournalling( const bool newState ) { const bool oldJournalling = m_journalling; - m_journalling = _sr; + m_journalling = newState; return oldJournalling; } @@ -138,15 +86,8 @@ protected: private: - void saveJournal( QDomDocument & _doc, QDomElement & _parent ); - void loadJournal( const QDomElement & _this ); - - jo_id_t m_id; - JournalCheckPointVector m_journalCheckPoints; - JournalCheckPointVector::Iterator m_currentJournalCheckPoint; - bool m_journalling; QStack m_journallingStateStack; diff --git a/include/ProjectJournal.h b/include/ProjectJournal.h index 041f7507e..7c819daa0 100644 --- a/include/ProjectJournal.h +++ b/include/ProjectJournal.h @@ -1,7 +1,7 @@ /* * ProjectJournal.h - declaration of class ProjectJournal * - * Copyright (c) 2006-2008 Tobias Doerffel + * Copyright (c) 2006-2010 Tobias Doerffel * * This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net * @@ -26,10 +26,10 @@ #define _PROJECT_JOURNAL_H #include -#include -#include +#include #include "lmms_basics.h" +#include "mmp.h" class JournallingObject; @@ -43,8 +43,7 @@ public: void undo(); void redo(); - // tell history that a new journal entry was added to object with ID _id - void journalEntryAdded( const jo_id_t _id ); + void addJournalCheckPoint( JournallingObject *jo ); bool isJournalling() const { @@ -72,10 +71,6 @@ public: reallocID( _id, NULL ); } - // completely remove everything linked with ID _id - all global - // journalling information about the ID get's lost - void forgetAboutID( const jo_id_t _id ); - void clearJournal(); JournallingObject * journallingObject( const jo_id_t _id ) @@ -90,12 +85,25 @@ public: private: typedef QHash JoIdMap; - typedef QVector JournalEntryVector; + + struct CheckPoint + { + CheckPoint( jo_id_t initID = 0, + const multimediaProject &initData = + multimediaProject( multimediaProject::JournalData ) ) : + joID( initID ), + data( initData ) + { + } + jo_id_t joID; + multimediaProject data; + } ; + typedef QStack CheckPointStack; JoIdMap m_joIDs; - JournalEntryVector m_journalEntries; - JournalEntryVector::Iterator m_currentJournalEntry; + CheckPointStack m_undoCheckPoints; + CheckPointStack m_redoCheckPoints; bool m_journalling; diff --git a/src/core/JournallingObject.cpp b/src/core/JournallingObject.cpp index 7d3229597..ce565551f 100644 --- a/src/core/JournallingObject.cpp +++ b/src/core/JournallingObject.cpp @@ -37,8 +37,6 @@ JournallingObject::JournallingObject() : SerializingObject(), m_id( engine::projectJournal()->allocID( this ) ), - m_journalCheckPoints(), - m_currentJournalCheckPoint( m_journalCheckPoints.end() ), m_journalling( true ), m_journallingStateStack() { @@ -58,34 +56,11 @@ JournallingObject::~JournallingObject() -void JournallingObject::undo() +void JournallingObject::addJournalCheckPoint() { - if( m_journalCheckPoints.empty() == true ) + if( isJournalling() ) { - return; - } - - if( m_currentJournalCheckPoint - 1 >= m_journalCheckPoints.begin() ) - { - --m_currentJournalCheckPoint; - restoreState( m_currentJournalCheckPoint->data().content().firstChildElement() ); - } -} - - - - -void JournallingObject::redo() -{ - if( m_journalCheckPoints.empty() == true ) - { - return; - } - - if( m_currentJournalCheckPoint < m_journalCheckPoints.end() ) - { - restoreState( m_currentJournalCheckPoint->data().content().firstChildElement() ); - ++m_currentJournalCheckPoint; + engine::projectJournal()->addJournalCheckPoint( this ); } } @@ -96,7 +71,12 @@ QDomElement JournallingObject::saveState( QDomDocument & _doc, QDomElement & _parent ) { QDomElement _this = SerializingObject::saveState( _doc, _parent ); - saveJournal( _doc, _this ); + + QDomElement journalNode = _doc.createElement( "journallingObject" ); + journalNode.setAttribute( "id", id() ); + journalNode.setAttribute( "metadata", true ); + _this.appendChild( journalNode ); + return _this; } @@ -115,7 +95,11 @@ void JournallingObject::restoreState( const QDomElement & _this ) { if( node.isElement() && node.nodeName() == "journal" ) { - loadJournal( node.toElement() ); + const jo_id_t new_id = node.toElement().attribute( "id" ).toInt(); + if( new_id ) + { + changeID( new_id ); + } } node = node.nextSibling(); } @@ -126,26 +110,6 @@ void JournallingObject::restoreState( const QDomElement & _this ) -void JournallingObject::addJournalCheckPoint() -{ - if( engine::projectJournal()->isJournalling() && isJournalling() ) - { - m_journalCheckPoints.erase( m_currentJournalCheckPoint, - m_journalCheckPoints.end() ); - - multimediaProject mmp( multimediaProject::JournalData ); - saveState( mmp, mmp.content() ); - - m_journalCheckPoints.push_back( JournalCheckPoint( mmp ) ); - - m_currentJournalCheckPoint = m_journalCheckPoints.end(); - engine::projectJournal()->journalEntryAdded( id() ); - } -} - - - - void JournallingObject::changeID( jo_id_t _id ) { if( id() != _id ) @@ -166,77 +130,10 @@ void JournallingObject::changeID( jo_id_t _id ) (int) _id, used_by.toUtf8().constData() ); return; } - engine::projectJournal()->forgetAboutID( id() ); + engine::projectJournal()->reallocID( _id, this ); m_id = _id; } } - - -void JournallingObject::saveJournal( QDomDocument & _doc, - QDomElement & _parent ) -{ -/* // avoid creating empty journal-nodes - if( m_journalCheckPoints.size() == 0 ) - { - return; - }*/ - QDomElement journal_de = _doc.createElement( "journal" ); - journal_de.setAttribute( "id", id() ); - journal_de.setAttribute( "entries", m_journalCheckPoints.size() ); - journal_de.setAttribute( "curentry", (int)( m_currentJournalCheckPoint - - m_journalCheckPoints.begin() ) ); - journal_de.setAttribute( "metadata", true ); - - for( JournalCheckPointVector::const_iterator it = m_journalCheckPoints.begin(); - it != m_journalCheckPoints.end(); ++it ) - { - QDomElement je_de = _doc.createElement( "entry" ); - je_de.setAttribute( "pos", (int)( it - - m_journalCheckPoints.begin() ) ); - //je_de.setAttribute( "data", base64::encode( it->data().toString() ) ); - je_de.setAttribute( "data", it->data().toString() ); - journal_de.appendChild( je_de ); - } - - _parent.appendChild( journal_de ); -} - - - - -void JournallingObject::loadJournal( const QDomElement & _this ) -{ - clear(); - - const jo_id_t new_id = _this.attribute( "id" ).toInt(); - - if( new_id == 0 ) - { - return; - } - - changeID( new_id ); - - m_journalCheckPoints.resize( _this.attribute( "entries" ).toInt() ); - - QDomNode node = _this.firstChild(); - while( !node.isNull() ) - { - if( node.isElement() ) - { - const QDomElement & je = node.toElement(); - m_journalCheckPoints[je.attribute( "pos" ).toInt()] = - JournalCheckPoint( - multimediaProject( je.attribute( "data" ).toUtf8() ) ); - } - node = node.nextSibling(); - } - - m_currentJournalCheckPoint = m_journalCheckPoints.begin() + - _this.attribute( "curentry" ).toInt(); -} - - diff --git a/src/core/ProjectJournal.cpp b/src/core/ProjectJournal.cpp index 04e452fde..bcd30d807 100644 --- a/src/core/ProjectJournal.cpp +++ b/src/core/ProjectJournal.cpp @@ -32,8 +32,8 @@ ProjectJournal::ProjectJournal() : m_joIDs(), - m_journalEntries(), - m_currentJournalEntry( m_journalEntries.end() ), + m_undoCheckPoints(), + m_redoCheckPoints(), m_journalling( false ) { } @@ -50,57 +50,66 @@ ProjectJournal::~ProjectJournal() void ProjectJournal::undo() { - if( m_journalEntries.empty() == true ) + while( !m_undoCheckPoints.isEmpty() ) { - return; - } + CheckPoint c = m_undoCheckPoints.pop(); + JournallingObject *jo = m_joIDs[c.joID]; - JournallingObject * jo; + if( jo ) + { + multimediaProject curState( multimediaProject::JournalData ); + jo->saveState( curState, curState.content() ); + m_redoCheckPoints.push( CheckPoint( c.joID, curState ) ); - if( m_currentJournalEntry - 1 >= m_journalEntries.begin() && - ( jo = m_joIDs[*--m_currentJournalEntry] ) != NULL ) - { - bool prev = isJournalling(); - setJournalling( false ); - jo->undo(); - setJournalling( prev ); - engine::getSong()->setModified(); + bool prev = isJournalling(); + setJournalling( false ); + jo->restoreState( c.data.content().firstChildElement() ); + setJournalling( prev ); + engine::getSong()->setModified(); + break; + } } } - void ProjectJournal::redo() { - if( m_journalEntries.empty() == true ) + while( !m_redoCheckPoints.isEmpty() ) { - return; - } + CheckPoint c = m_redoCheckPoints.pop(); + JournallingObject *jo = m_joIDs[c.joID]; - JournallingObject * jo; + if( jo ) + { + multimediaProject curState( multimediaProject::JournalData ); + jo->saveState( curState, curState.content() ); + m_undoCheckPoints.push( CheckPoint( c.joID, curState ) ); - //printf("%d\n", m_joIDs[*(m_currentJournalEntry+1)] ); - if( m_currentJournalEntry < m_journalEntries.end() && - ( jo = m_joIDs[*m_currentJournalEntry++] ) != NULL ) - { - bool prev = isJournalling(); - setJournalling( false ); - jo->redo(); - setJournalling( prev ); - engine::getSong()->setModified(); + bool prev = isJournalling(); + setJournalling( false ); + jo->restoreState( c.data.content().firstChildElement() ); + setJournalling( prev ); + engine::getSong()->setModified(); + break; + } } } -void ProjectJournal::journalEntryAdded( const jo_id_t _id ) +void ProjectJournal::addJournalCheckPoint( JournallingObject *jo ) { - m_journalEntries.erase( m_currentJournalEntry, m_journalEntries.end() ); - m_journalEntries.push_back( _id ); - m_currentJournalEntry = m_journalEntries.end(); - engine::getSong()->setModified(); + if( isJournalling() ) + { + m_redoCheckPoints.clear(); + + multimediaProject mmp( multimediaProject::JournalData ); + jo->saveState( mmp, mmp.content() ); + + m_undoCheckPoints.push( CheckPoint( jo->id(), mmp ) ); + } } @@ -136,29 +145,11 @@ void ProjectJournal::reallocID( const jo_id_t _id, JournallingObject * _obj ) -void ProjectJournal::forgetAboutID( const jo_id_t _id ) -{ - //printf("forget about %d\n", _id ); - JournalEntryVector::Iterator it; - while( ( it = qFind( m_journalEntries.begin(), m_journalEntries.end(), - _id ) ) != m_journalEntries.end() ) - { - if( m_currentJournalEntry >= it ) - { - --m_currentJournalEntry; - } - m_journalEntries.erase( it ); - } - m_joIDs.remove( _id ); -} - - - - void ProjectJournal::clearJournal() { - m_journalEntries.clear(); - m_currentJournalEntry = m_journalEntries.end(); + m_undoCheckPoints.clear(); + m_redoCheckPoints.clear(); + for( JoIdMap::Iterator it = m_joIDs.begin(); it != m_joIDs.end(); ) { if( it.value() == NULL ) From 4f9ec51d7aa88c25249811af8cb7bc378576935a Mon Sep 17 00:00:00 2001 From: Tobias Doerffel Date: Tue, 7 Jan 2014 23:51:31 +0100 Subject: [PATCH 005/647] JournallingObject: header cleanups No need to include various QtCore header files anymore. Fix resulting missing headers in some other files. --- include/AutomationPattern.h | 1 + include/JournallingObject.h | 9 +++------ include/MidiPort.h | 4 ++-- plugins/vst_base/VstPlugin.h | 1 + 4 files changed, 7 insertions(+), 8 deletions(-) diff --git a/include/AutomationPattern.h b/include/AutomationPattern.h index 1d144d9bd..3c403cd17 100644 --- a/include/AutomationPattern.h +++ b/include/AutomationPattern.h @@ -27,6 +27,7 @@ #ifndef _AUTOMATION_PATTERN_H #define _AUTOMATION_PATTERN_H +#include #include #include "track.h" diff --git a/include/JournallingObject.h b/include/JournallingObject.h index 1be811d20..3f6e47a82 100644 --- a/include/JournallingObject.h +++ b/include/JournallingObject.h @@ -25,14 +25,11 @@ #ifndef _JOURNALLING_OBJECT_H #define _JOURNALLING_OBJECT_H -#include "lmms_basics.h" -#include "export.h" -#include "SerializingObject.h" - -#include -#include #include +#include "lmms_basics.h" +#include "SerializingObject.h" + class EXPORT JournallingObject : public SerializingObject { diff --git a/include/MidiPort.h b/include/MidiPort.h index a5b1aee0e..f1a1a3e83 100644 --- a/include/MidiPort.h +++ b/include/MidiPort.h @@ -2,7 +2,7 @@ * MidiPort.h - abstraction of MIDI ports which are part of LMMS's MIDI- * sequencing system * - * Copyright (c) 2005-2009 Tobias Doerffel + * Copyright (c) 2005-2010 Tobias Doerffel * * This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net * @@ -28,7 +28,7 @@ #include #include -#include +#include #include "midi.h" #include "AutomatableModel.h" diff --git a/plugins/vst_base/VstPlugin.h b/plugins/vst_base/VstPlugin.h index 992e59ff0..705c61511 100644 --- a/plugins/vst_base/VstPlugin.h +++ b/plugins/vst_base/VstPlugin.h @@ -25,6 +25,7 @@ #ifndef _VST_PLUGIN_H #define _VST_PLUGIN_H +#include #include #include #include From a955fb755a9b99d4a43fcbd35200d54328117d3a Mon Sep 17 00:00:00 2001 From: Tobias Doerffel Date: Wed, 8 Jan 2014 23:19:07 +0100 Subject: [PATCH 006/647] FxMixer, Mixer, FxMixerView: backported FX send support from master branch There once have been huge efforts to implement FX send support in the master branch. In order to make it available on a stable base here's a backport which is non-trivial as there have been major rewrites of the mixer's worker thread architecture. There still seem to be bugs which we have to fix before merging into stable branch. Thanks to Andrew Kelley for the original work. --- data/themes/default/mixer_send_off.png | Bin 0 -> 467 bytes data/themes/default/mixer_send_on.png | Bin 0 -> 471 bytes data/themes/default/send_bg_arrow.png | Bin 0 -> 267 bytes include/AudioPort.h | 11 +- include/FxLine.h | 66 +++ include/FxMixer.h | 104 +++-- include/FxMixerView.h | 70 ++- include/MixerWorkerThread.h | 118 +++++ include/SendButtonIndicator.h | 32 ++ include/ThreadableJob.h | 84 ++++ include/play_handle.h | 17 +- plugins/flp_import/FlpImport.cpp | 24 +- src/core/FxMixer.cpp | 587 ++++++++++++++++++++---- src/core/Mixer.cpp | 243 +--------- src/core/MixerWorkerThread.cpp | 165 +++++++ src/core/audio/AudioPort.cpp | 13 +- src/gui/FxMixerView.cpp | 500 ++++++++++++-------- src/gui/widgets/FxLine.cpp | 147 ++++++ src/gui/widgets/SendButtonIndicator.cpp | 53 +++ src/tracks/InstrumentTrack.cpp | 5 +- 20 files changed, 1660 insertions(+), 579 deletions(-) create mode 100644 data/themes/default/mixer_send_off.png create mode 100644 data/themes/default/mixer_send_on.png create mode 100644 data/themes/default/send_bg_arrow.png create mode 100644 include/FxLine.h create mode 100644 include/MixerWorkerThread.h create mode 100644 include/SendButtonIndicator.h create mode 100644 include/ThreadableJob.h create mode 100644 src/core/MixerWorkerThread.cpp create mode 100644 src/gui/widgets/FxLine.cpp create mode 100644 src/gui/widgets/SendButtonIndicator.cpp diff --git a/data/themes/default/mixer_send_off.png b/data/themes/default/mixer_send_off.png new file mode 100644 index 0000000000000000000000000000000000000000..6f426c36f9599a1fd8dbef8de6a5577d8bd17a86 GIT binary patch literal 467 zcmeAS@N?(olHy`uVBq!ia0vp^;y^6G!3HG%>OYYHQjEnx?oJHr&dIz4a@dl*-CY>| zgW!U_%O?XxI14-?iy0WWg+Z8+Vb&aw9`+JXUsv{pv8=Oo-U3d7N_4%_Vs2;6ltAbUXgxcsrj+STZmA#r#x`+VakQr%=69w}#N>KWdkoG$usOe!NJm`PLE-Y4eAX_o^#) zJU<}%Tzq=`8c(k5D{T8hgc2^izxdWfvfrNZ#8d7m-md+HR^958ToxOiTB@|OhB4vU z)S#m#y5Ak`5&v(|sw-B&;AQZ1^>bP0 Hl+XkKQoFyV literal 0 HcmV?d00001 diff --git a/data/themes/default/mixer_send_on.png b/data/themes/default/mixer_send_on.png new file mode 100644 index 0000000000000000000000000000000000000000..6861c7acdf717cd4e6b164956346fa7413447423 GIT binary patch literal 471 zcmeAS@N?(olHy`uVBq!ia0vp^;y^6G!3HG%>OYYHQjEnx?oJHr&dIz4a@dl*-CY>| zgW!U_%O?XxI14-?iy0WWg+Z8+Vb&aw9`+JXUsv{wc6x=<11Hv2mfEF_vdAc};Se#DYvmx@kJ##OEFf;GL6%QjA zxtW=n4{tlXUvgUh@3SBN39IC7_j#K3;pD%rMFMKmL{6L%cyj32gUNrVCY}z-V*`R6 zQF?rAY__IpZD$J1*b*7lIvy5Z|Cf}Z{U9M=a(YriN{Wl2fb5#vzuOOzd3YmbCL~-8NJ^Tq>yP;1M`!m--mCf1etospCLf+?{(r}`jvqdH zLg4l3V+B92#k|p^cO=b!v%Y|bc^{t+Pxkje$1*LIt7aG* z8yme?ZERRjyvg8=-9PsH4HB6~#vclejcR^1&HSElaM9{xJq9w*jO6^-+9c$|M5Zr} zK62v3i3iE&PZ=a%)fZ{5-L&7Rz)9J}yo+~HnaOW{{lkpCf(e%sr~M281~G%DtDnm{ Hr-UW|EQGns literal 0 HcmV?d00001 diff --git a/data/themes/default/send_bg_arrow.png b/data/themes/default/send_bg_arrow.png new file mode 100644 index 0000000000000000000000000000000000000000..fde514da62ab29e40dd44632fa9757edc65ea2bf GIT binary patch literal 267 zcmeAS@N?(olHy`uVBq!ia0vp^GC*v>!3HGX8O+!Mq!^2X+?^QKos)S9lbCYGe8D3oWGWGJ|M`UZqI@`(c#rFptIhD02GdvhT#gQ9@T#a1hhrhnN^ z6J9q9r|YM%30?VLcJ%XR!L+5@BC}?1jO;tj$b<#dExmd%wr>8#%YrW!aH%zNtx7W5 m;Us&8>3@Lu?N?uVKQPJ7l)NGl%6T1VBZH@_pUXO@geCy^?oqG+ literal 0 HcmV?d00001 diff --git a/include/AudioPort.h b/include/AudioPort.h index 47129aede..735c313b8 100644 --- a/include/AudioPort.h +++ b/include/AudioPort.h @@ -1,7 +1,7 @@ /* * AudioPort.h - base-class for objects providing sound at a port * - * Copyright (c) 2005-2009 Tobias Doerffel + * Copyright (c) 2005-2014 Tobias Doerffel * * This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net * @@ -33,7 +33,7 @@ class EffectChain; -class AudioPort +class AudioPort : public ThreadableJob { public: AudioPort( const QString & _name, bool _has_effect_chain = true ); @@ -109,6 +109,13 @@ public: bool processEffects(); + // ThreadableJob stuff + virtual void doProcessing( sampleFrame * ); + virtual bool requiresProcessing() const + { + return true; + } + enum bufferUsages { diff --git a/include/FxLine.h b/include/FxLine.h new file mode 100644 index 000000000..55f2daa7f --- /dev/null +++ b/include/FxLine.h @@ -0,0 +1,66 @@ +/* + * FxLine.h - FX line widget + * + * Copyright (c) 2009 Andrew Kelley + * Copyright (c) 2014 Tobias Doerffel + * + * This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net + * + * 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 _FX_LINE_H +#define _FX_LINE_H + +#include +#include + +#include "knob.h" +#include "lcd_spinbox.h" +#include "SendButtonIndicator.h" + +class FxMixerView; +class SendButtonIndicator; + +class FxLine : public QWidget +{ + Q_OBJECT +public: + FxLine( QWidget * _parent, FxMixerView * _mv, int _channelIndex); + ~FxLine(); + + virtual void paintEvent( QPaintEvent * ); + virtual void mousePressEvent( QMouseEvent * ); + virtual void mouseDoubleClickEvent( QMouseEvent * ); + + inline int channelIndex() { return m_channelIndex; } + void setChannelIndex(int index); + + knob * m_sendKnob; + SendButtonIndicator * m_sendBtn; + +private: + FxMixerView * m_mv; + lcdSpinBox * m_lcd; + + + int m_channelIndex; + +} ; + + +#endif // FXLINE_H diff --git a/include/FxMixer.h b/include/FxMixer.h index 10b6b2cc6..8ff396cc6 100644 --- a/include/FxMixer.h +++ b/include/FxMixer.h @@ -1,7 +1,7 @@ /* * FxMixer.h - effect-mixer for LMMS * - * Copyright (c) 2008-2009 Tobias Doerffel + * Copyright (c) 2008-2014 Tobias Doerffel * * This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net * @@ -29,46 +29,58 @@ #include "Mixer.h" #include "EffectChain.h" #include "JournallingObject.h" +#include "ThreadableJob.h" -const int NumFxChannels = 64; -struct FxChannel +class FxChannel : public ThreadableJob { - FxChannel( Model * _parent ); - ~FxChannel(); + public: + FxChannel( int idx, Model * _parent ); + virtual ~FxChannel(); - EffectChain m_fxChain; - bool m_used; - bool m_stillRunning; - float m_peakLeft; - float m_peakRight; - sampleFrame * m_buffer; - BoolModel m_muteModel; - FloatModel m_volumeModel; - QString m_name; - QMutex m_lock; + EffectChain m_fxChain; -} ; + // set to true if any effect in the channel is enabled and running + bool m_stillRunning; + + float m_peakLeft; + float m_peakRight; + sampleFrame * m_buffer; + BoolModel m_muteModel; + FloatModel m_volumeModel; + QString m_name; + QMutex m_lock; + int m_channelIndex; // what channel index are we + bool m_queued; // are we queued up for rendering yet? + + // pointers to other channels that this one sends to + QVector m_sends; + QVector m_sendAmount; + + // pointers to other channels that send to this one + QVector m_receives; + + virtual bool requiresProcessing() const { return true; } + + private: + virtual void doProcessing( sampleFrame * _working_buffer ); +}; -class FxMixer : public JournallingObject, public Model +class EXPORT FxMixer : public JournallingObject, public Model { public: FxMixer(); virtual ~FxMixer(); void mixToChannel( const sampleFrame * _buf, fx_ch_t _ch ); - void processChannel( fx_ch_t _ch, sampleFrame * _buf = NULL ); void prepareMasterMix(); void masterMix( sampleFrame * _buf ); - - void clear(); - virtual void saveSettings( QDomDocument & _doc, QDomElement & _parent ); virtual void loadSettings( const QDomElement & _this ); @@ -79,17 +91,55 @@ public: FxChannel * effectChannel( int _ch ) { - if( _ch >= 0 && _ch <= NumFxChannels ) - { - return m_fxChannels[_ch]; - } - return NULL; + return m_fxChannels[_ch]; } + // make the output of channel fromChannel go to the input of channel toChannel + // it is safe to call even if the send already exists + void createChannelSend(fx_ch_t fromChannel, fx_ch_t toChannel, + float amount = 1.0f); + + // delete the connection made by createChannelSend + void deleteChannelSend(fx_ch_t fromChannel, fx_ch_t toChannel); + + // determine if adding a send from sendFrom to + // sendTo would result in an infinite mixer loop. + bool isInfiniteLoop(fx_ch_t fromChannel, fx_ch_t toChannel); + + // return the FloatModel of fromChannel sending its output to the input of + // toChannel. NULL if there is no send. + FloatModel * channelSendModel(fx_ch_t fromChannel, fx_ch_t toChannel); + + // add a new channel to the Fx Mixer. + // returns the index of the channel that was just added + int createChannel(); + + // delete a channel from the FX mixer. + void deleteChannel(int index); + + // delete all the mixer channels except master and remove all effects + void clear(); + + // re-arrange channels + void moveChannelLeft(int index); + void moveChannelRight(int index); + + // reset a channel's name, fx, sends, etc + void clearChannel(fx_ch_t channelIndex); + + inline fx_ch_t numChannels() const + { + return m_fxChannels.size(); + } private: - FxChannel * m_fxChannels[NumFxChannels+1]; // +1 = master + // the fx channels in the mixer. index 0 is always master. + QVector m_fxChannels; + // make sure we have at least num channels + void allocateChannelsTo(int num); + + void addChannelLeaf( int _ch, sampleFrame * _buf ); friend class MixerWorkerThread; friend class FxMixerView; diff --git a/include/FxMixerView.h b/include/FxMixerView.h index dab34caaf..6449a0306 100644 --- a/include/FxMixerView.h +++ b/include/FxMixerView.h @@ -26,59 +26,91 @@ #define _FX_MIXER_VIEW_H #include +#include +#include +#include "FxLine.h" #include "FxMixer.h" #include "ModelView.h" +#include "engine.h" +#include "fader.h" +#include "pixmap_button.h" +#include "tooltip.h" +#include "embed.h" +#include "EffectRackView.h" -class QStackedLayout; class QButtonGroup; -class fader; class FxLine; -class EffectRackView; -class pixmapButton; - -class FxMixerView : public QWidget, public ModelView, +class EXPORT FxMixerView : public QWidget, public ModelView, public SerializingObjectHook { Q_OBJECT public: + struct FxChannelView + { + FxChannelView(QWidget * _parent, FxMixerView * _mv, int _chIndex ); + + FxLine * m_fxLine; + pixmapButton * m_muteBtn; + fader * m_fader; + }; + + FxMixerView(); virtual ~FxMixerView(); + virtual void keyPressEvent(QKeyEvent * e); + virtual void saveSettings( QDomDocument & _doc, QDomElement & _this ); virtual void loadSettings( const QDomElement & _this ); - FxLine * currentFxLine() + inline FxLine * currentFxLine() { return m_currentFxLine; } + + inline FxChannelView * channelView(int index) + { + return m_fxChannelViews[index]; + } + void setCurrentFxLine( FxLine * _line ); void setCurrentFxLine( int _line ); void clear(); + // display the send button and knob correctly + void updateFxLine(int index); + + // notify the view that an fx channel was deleted + void deleteChannel(int index); + + // move the channel to the left or right + void moveChannelLeft(int index); + void moveChannelRight(int index); + + // make sure the display syncs up with the fx mixer. + // useful for loading projects + void refreshDisplay(); + private slots: void updateFaders(); - + void addNewChannel(); private: - struct FxChannelView - { - FxLine * m_fxLine; - EffectRackView * m_rackView; - pixmapButton * m_muteBtn; - fader * m_fader; - } ; - FxChannelView m_fxChannelViews[NumFxChannels+1]; + QVector m_fxChannelViews; - QStackedLayout * m_fxRacksLayout; - QStackedLayout * m_fxLineBanks; - QButtonGroup * m_bankButtons; FxLine * m_currentFxLine; + QScrollArea * channelArea; + QHBoxLayout * chLayout; + QWidget * m_channelAreaWidget; + EffectRackView * m_rackView; + + void updateMaxChannelSelector(); } ; #endif diff --git a/include/MixerWorkerThread.h b/include/MixerWorkerThread.h new file mode 100644 index 000000000..199c38884 --- /dev/null +++ b/include/MixerWorkerThread.h @@ -0,0 +1,118 @@ +/* + * MixerWorkerThread.h - declaration of class MixerWorkerThread + * + * Copyright (c) 2009-2014 Tobias Doerffel + * + * This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net + * + * 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 _MIXER_WORKER_THREAD_H +#define _MIXER_WORKER_THREAD_H + +#include +#include + +#include "ThreadableJob.h" +#include "Mixer.h" + + +class MixerWorkerThread : public QThread +{ +public: + // internal representation of the job queue - all functions are thread-safe + class JobQueue + { + public: + enum OperationMode + { + Static, // no jobs added while processing queue + Dynamic // jobs can be added while processing queue + } ; + + JobQueue() : + m_items(), + m_queueSize( 0 ), + m_itemsDone( 0 ), + m_opMode( Static ) + { + } + + void reset( OperationMode _opMode ); + + void addJob( ThreadableJob * _job ); + + void run( sampleFrame * _buffer ); + void wait(); + + private: +#define JOB_QUEUE_SIZE 1024 + QAtomicPointer m_items[JOB_QUEUE_SIZE]; + QAtomicInt m_queueSize; + QAtomicInt m_itemsDone; + OperationMode m_opMode; + + } ; + + + MixerWorkerThread( Mixer* mixer ); + virtual ~MixerWorkerThread(); + + virtual void quit(); + + static void resetJobQueue( JobQueue::OperationMode _opMode = + JobQueue::Static ) + { + globalJobQueue.reset( _opMode ); + } + + static void addJob( ThreadableJob * _job ) + { + globalJobQueue.addJob( _job ); + } + + // a convenient helper function allowing to pass a container with pointers + // to ThreadableJob objects + template + static void fillJobQueue( const T & _vec, + JobQueue::OperationMode _opMode = JobQueue::Static ) + { + resetJobQueue( _opMode ); + for( typename T::ConstIterator it = _vec.begin(); it != _vec.end(); ++it ) + { + addJob( *it ); + } + } + + static void startAndWaitForJobs(); + + +private: + virtual void run(); + + static JobQueue globalJobQueue; + static QWaitCondition * queueReadyWaitCond; + static QList workerThreads; + + sampleFrame * m_workingBuf; + volatile bool m_quit; + +} ; + + +#endif diff --git a/include/SendButtonIndicator.h b/include/SendButtonIndicator.h new file mode 100644 index 000000000..2b0819791 --- /dev/null +++ b/include/SendButtonIndicator.h @@ -0,0 +1,32 @@ +#ifndef SENDBUTTONINDICATOR_H +#define SENDBUTTONINDICATOR_H + +#include +#include +#include + +#include "FxLine.h" +#include "FxMixerView.h" + +class FxLine; +class FxMixerView; + +class SendButtonIndicator : public QLabel { + public: + SendButtonIndicator( QWidget * _parent, FxLine * _owner, + FxMixerView * _mv); + + virtual void mousePressEvent( QMouseEvent * e ); + void updateLightStatus(); + + private: + + FxLine * m_parent; + FxMixerView * m_mv; + QPixmap qpmOn; + QPixmap qpmOff; + + FloatModel * getSendModel(); +}; + +#endif // SENDBUTTONINDICATOR_H diff --git a/include/ThreadableJob.h b/include/ThreadableJob.h new file mode 100644 index 000000000..1eb1e1612 --- /dev/null +++ b/include/ThreadableJob.h @@ -0,0 +1,84 @@ +/* + * ThreadableJob.h - declaration of class ThreadableJob + * + * Copyright (c) 2009-2014 Tobias Doerffel + * + * This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net + * + * 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 _THREADABLE_JOB_H +#define _THREADABLE_JOB_H + +#include + +#include "lmms_basics.h" + + +class ThreadableJob +{ +public: + + enum ProcessingState + { + Unstarted, + Queued, + InProgress, + Done + }; + + ThreadableJob() : + m_state( ThreadableJob::Unstarted ) + { + } + + inline ProcessingState state() const + { + return static_cast( (int) m_state ); + } + + inline void reset() + { + m_state = Unstarted; + } + + inline void queue() + { + m_state = Queued; + } + + void process( sampleFrame* workingBuffer = NULL ) + { + if( m_state.testAndSetOrdered( Queued, InProgress ) ) + { + doProcessing( workingBuffer ); + m_state = Done; + } + } + + virtual bool requiresProcessing() const = 0; + + +protected: + virtual void doProcessing( sampleFrame* workingBuffer) = 0; + + QAtomicInt m_state; + +} ; + +#endif diff --git a/include/play_handle.h b/include/play_handle.h index 27aa27573..ed8fc188a 100644 --- a/include/play_handle.h +++ b/include/play_handle.h @@ -1,7 +1,7 @@ /* * play_handle.h - base-class playHandle - core of rendering engine * - * Copyright (c) 2004-2009 Tobias Doerffel + * Copyright (c) 2004-2014 Tobias Doerffel * * This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net * @@ -28,12 +28,13 @@ #include #include +#include "ThreadableJob.h" #include "lmms_basics.h" class track; -class playHandle +class playHandle : public ThreadableJob { public: enum types @@ -70,6 +71,18 @@ public: return m_type; } + // required for ThreadableJob + virtual void doProcessing( sampleFrame * _working_buffer ) + { + play( _working_buffer ); + } + + virtual bool requiresProcessing() const + { + return !done(); + } + + virtual void play( sampleFrame * _working_buffer ) = 0; virtual bool done( void ) const = 0; diff --git a/plugins/flp_import/FlpImport.cpp b/plugins/flp_import/FlpImport.cpp index dd539df00..a61daef64 100644 --- a/plugins/flp_import/FlpImport.cpp +++ b/plugins/flp_import/FlpImport.cpp @@ -27,6 +27,7 @@ #include #include #include +#include #include "FlpImport.h" #include "note_play_handle.h" @@ -40,6 +41,7 @@ #include "Effect.h" #include "engine.h" #include "FxMixer.h" +#include "FxMixerView.h" #include "group_box.h" #include "Instrument.h" #include "InstrumentTrack.h" @@ -96,7 +98,7 @@ extern QString outstring; } - +const int NumFLFxChannels = 64; static void dump_mem( const void * buffer, uint n_bytes ) { @@ -534,7 +536,7 @@ struct FL_Project int currentPattern; int activeEditPattern; - FL_EffectChannel effectChannels[NumFxChannels+1]; + FL_EffectChannel effectChannels[NumFLFxChannels+1]; int currentEffectChannel; QString projectNotes; @@ -884,7 +886,7 @@ bool FlpImport::tryImport( trackContainer * _tc ) break; case FLP_EffectChannelMuted: -if( p.currentEffectChannel <= NumFxChannels ) +if( p.currentEffectChannel <= NumFLFxChannels ) { p.effectChannels[p.currentEffectChannel].isMuted = ( data & 0x08 ) > 0 ? false : true; @@ -1121,7 +1123,7 @@ if( p.currentEffectChannel <= NumFxChannels ) case FLP_Text_EffectChanName: ++p.currentEffectChannel; - if( p.currentEffectChannel <= NumFxChannels ) + if( p.currentEffectChannel <= NumFLFxChannels ) { p.effectChannels[p.currentEffectChannel].name = text; } @@ -1344,7 +1346,7 @@ if( p.currentEffectChannel <= NumFxChannels ) const int param = pi[i*3+1] & 0xffff; const int ch = ( pi[i*3+1] >> 22 ) & 0x7f; - if( ch < 0 || ch > NumFxChannels ) + if( ch < 0 || ch > NumFLFxChannels ) { continue; } @@ -1405,9 +1407,15 @@ else // now create a project from FL_Project data structure - engine::getSong()->clearProject(); + // configure the mixer + for( int i=0; icreateChannel(); + } + engine::fxMixerView()->refreshDisplay(); + // set global parameters engine::getSong()->setMasterVolume( p.mainVolume ); engine::getSong()->setMasterPitch( p.mainPitch ); @@ -1644,7 +1652,7 @@ p->putValue( jt->pos, value, false ); } } - for( int fx_ch = 0; fx_ch <= NumFxChannels ; ++fx_ch ) + for( int fx_ch = 0; fx_ch <= NumFLFxChannels ; ++fx_ch ) { FxChannel * ch = engine::fxMixer()->effectChannel( fx_ch ); if( !ch ) @@ -1704,7 +1712,7 @@ p->putValue( jt->pos, value, false ); break; } if( effName.isEmpty() || it->fxChannel < 0 || - it->fxChannel > NumFxChannels ) + it->fxChannel > NumFLFxChannels ) { continue; } diff --git a/src/core/FxMixer.cpp b/src/core/FxMixer.cpp index 864364cf5..d41276d17 100644 --- a/src/core/FxMixer.cpp +++ b/src/core/FxMixer.cpp @@ -1,10 +1,8 @@ -#ifndef SINGLE_SOURCE_COMPILE - /* * FxMixer.cpp - effect mixer for LMMS * * Copyright (c) 2008-2011 Tobias Doerffel - * + * * This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net * * This program is free software; you can redistribute it and/or @@ -24,17 +22,20 @@ * */ - #include #include "FxMixer.h" +#include "MixerWorkerThread.h" +#include "MixHelpers.h" #include "Effect.h" #include "song.h" +#include "InstrumentTrack.h" +#include "bb_track_container.h" -FxChannel::FxChannel( Model * _parent ) : + +FxChannel::FxChannel( int idx, Model * _parent ) : m_fxChain( NULL ), - m_used( false ), m_stillRunning( false ), m_peakLeft( 0.0f ), m_peakRight( 0.0f ), @@ -42,7 +43,9 @@ FxChannel::FxChannel( Model * _parent ) : m_muteModel( false, _parent ), m_volumeModel( 1.0, 0.0, 2.0, 0.01, _parent ), m_name(), - m_lock() + m_lock(), + m_channelIndex( idx ), + m_queued( false ) { engine::mixer()->clearAudioBuffer( m_buffer, engine::mixer()->framesPerPeriod() ); @@ -59,81 +62,373 @@ FxChannel::~FxChannel() +void FxChannel::doProcessing( sampleFrame * _buf ) +{ + FxMixer * fxm = engine::fxMixer(); + const fpp_t fpp = engine::mixer()->framesPerPeriod(); + + // ignore the passed _buf + // always use m_buffer + // this is just an auxilliary buffer if doProcessing() + // needs one for processing while running + // particularly important for playHandles, so Instruments + // can operate on this buffer the whole time + // this improves cache hit rate + _buf = m_buffer; + + // SMF: OK, due to the fact, that the data from the audio-tracks has been + // written into our buffer already, all which needs to be done at this + // stage is to process inter-channel sends. I really don't like the idea + // of using threads for this -- it just doesn't make any sense and wastes + // cpu-cylces... so I just go through every child of this channel and + // call the acc. doProcessing() directly. + + if( m_muteModel.value() == false ) + { + // OK, we are not muted, so we go recursively through all the channels + // which send to us (our children)... + foreach( fx_ch_t senderIndex, m_receives ) + { + FxChannel * sender = fxm->effectChannel( senderIndex ); + + // wait for the sender job - either it's just been queued yet, + // then ThreadableJob::process() will process it now within this + // thread - otherwise it has been is is being processed by another + // thread and we just have to wait for it to finish + while( sender->state() != ThreadableJob::Done ) + { + sender->process(); + } + + // get the send level... + const float amt = + fxm->channelSendModel( senderIndex, m_channelIndex )->value(); + + // mix it's output with this one's output + sampleFrame * ch_buf = sender->m_buffer; + const float v = sender->m_volumeModel.value() * amt; + for( f_cnt_t f = 0; f < fpp; ++f ) + { + _buf[f][0] += ch_buf[f][0] * v; + _buf[f][1] += ch_buf[f][1] * v; + } + } + } + + const float v = m_volumeModel.value(); + + if( !engine::getSong()->isFreezingPattern() ) + { + m_fxChain.startRunning(); + m_stillRunning = m_fxChain.processAudioBuffer( _buf, fpp ); + m_peakLeft = engine::mixer()->peakValueLeft( _buf, fpp ) * v; + m_peakRight = engine::mixer()->peakValueRight( _buf, fpp ) * v; + } +} + FxMixer::FxMixer() : JournallingObject(), - Model( NULL ) + Model( NULL ), + m_fxChannels() { - for( int i = 0; i < NumFxChannels+1; ++i ) - { - m_fxChannels[i] = new FxChannel( this ); - } - // reset name etc. - clear(); + // create master channel + createChannel(); } - FxMixer::~FxMixer() { - for( int i = 0; i < NumFxChannels+1; ++i ) + for( int i = 0; i < m_fxChannels.size(); ++i ) { + for( int j = 0; j < m_fxChannels[i]->m_sendAmount.size(); ++j) + { + delete m_fxChannels[i]->m_sendAmount[j]; + } delete m_fxChannels[i]; } } - -void FxMixer::mixToChannel( const sampleFrame * _buf, fx_ch_t _ch ) +int FxMixer::createChannel() { - if( m_fxChannels[_ch]->m_muteModel.value() == false ) + const int index = m_fxChannels.size(); + // create new channel + m_fxChannels.push_back( new FxChannel( index, this ) ); + + // reset channel state + clearChannel( index ); + + return index; +} + + +void FxMixer::deleteChannel(int index) +{ + m_fxChannels[index]->m_lock.lock(); + + // go through every instrument and adjust for the channel index change + QVector songTrackList = engine::getSong()->tracks(); + QVector bbTrackList = engine::getBBTrackContainer()->tracks(); + + QVector trackLists[] = {songTrackList, bbTrackList}; + for(int tl=0; tl<2; ++tl) { - m_fxChannels[_ch]->m_lock.lock(); - sampleFrame * buf = m_fxChannels[_ch]->m_buffer; - for( f_cnt_t f = 0; f < engine::mixer()->framesPerPeriod(); - ++f ) + QVector trackList = trackLists[tl]; + for(int i=0; itype() == track::InstrumentTrack ) + { + InstrumentTrack * inst = (InstrumentTrack *) trackList[i]; + int val = inst->effectChannelModel()->value(0); + if( val == index ) + { + // we are deleting this track's fx send + // send to master + inst->effectChannelModel()->setValue(0); + } + else if( val > index ) + { + // subtract 1 to make up for the missing channel + inst->effectChannelModel()->setValue(val-1); + } + + } } - m_fxChannels[_ch]->m_used = true; - m_fxChannels[_ch]->m_lock.unlock(); } + + // delete all of this channel's sends and receives + for(int i=0; im_sends.size(); ++i) + { + deleteChannelSend(index, m_fxChannels[index]->m_sends[i]); + } + for(int i=0; im_receives.size(); ++i) + { + deleteChannelSend(m_fxChannels[index]->m_receives[i], index); + } + + for(int i=0; im_sends.size(); ++j) + { + if( m_fxChannels[i]->m_sends[j] > index ) + { + // subtract 1 to make up for the missing channel + --m_fxChannels[i]->m_sends[j]; + } + } + for(int j=0; jm_receives.size(); ++j) + { + if( m_fxChannels[i]->m_receives[j] > index ) + { + // subtract 1 to make up for the missing channel + --m_fxChannels[i]->m_receives[j]; + } + } + + } + + // actually delete the channel + delete m_fxChannels[index]; + m_fxChannels.remove(index); } - -void FxMixer::processChannel( fx_ch_t _ch, sampleFrame * _buf ) +void FxMixer::moveChannelLeft(int index) { - if( m_fxChannels[_ch]->m_muteModel.value() == false && - ( m_fxChannels[_ch]->m_used || - m_fxChannels[_ch]->m_stillRunning || - _ch == 0 ) ) + // can't move master or first channel + if( index <= 1 || index >= m_fxChannels.size() ) { - if( _buf == NULL ) - { - _buf = m_fxChannels[_ch]->m_buffer; - } - const fpp_t f = engine::mixer()->framesPerPeriod(); - if( !engine::getSong()->isFreezingPattern() ) - { - m_fxChannels[_ch]->m_fxChain.startRunning(); - m_fxChannels[_ch]->m_stillRunning = m_fxChannels[_ch]->m_fxChain.processAudioBuffer( _buf, f ); - m_fxChannels[_ch]->m_peakLeft = engine::mixer()->peakValueLeft( _buf, f ) * - m_fxChannels[_ch]->m_volumeModel.value(); - m_fxChannels[_ch]->m_peakRight = engine::mixer()->peakValueRight( _buf, f ) * - m_fxChannels[_ch]->m_volumeModel.value(); - } - m_fxChannels[_ch]->m_used = true; + return; } - else + + // channels to swap + int a = index - 1, b = index; + + // go through every instrument and adjust for the channel index change + QVector songTrackList = engine::getSong()->tracks(); + QVector bbTrackList = engine::getBBTrackContainer()->tracks(); + + QVector trackLists[] = {songTrackList, bbTrackList}; + for(int tl=0; tl<2; ++tl) { - m_fxChannels[_ch]->m_peakLeft = - m_fxChannels[_ch]->m_peakRight = 0.0f; + QVector trackList = trackLists[tl]; + for(int i=0; itype() == track::InstrumentTrack ) + { + InstrumentTrack * inst = (InstrumentTrack *) trackList[i]; + int val = inst->effectChannelModel()->value(0); + if( val == a ) + { + inst->effectChannelModel()->setValue(b); + } + else if( val == b ) + { + inst->effectChannelModel()->setValue(a); + } + + } + } + } + + for(int i=0; im_sends.size(); ++j) + { + if( m_fxChannels[i]->m_sends[j] == a ) + { + m_fxChannels[i]->m_sends[j] = b; + } + else if( m_fxChannels[i]->m_sends[j] == b ) + { + m_fxChannels[i]->m_sends[j] = a; + } + } + for(int j=0; jm_receives.size(); ++j) + { + if( m_fxChannels[i]->m_receives[j] == a ) + { + m_fxChannels[i]->m_receives[j] = b; + } + else if( m_fxChannels[i]->m_receives[j] == b ) + { + m_fxChannels[i]->m_receives[j] = a; + } + } + } + + // actually do the swap + FxChannel * tmpChannel = m_fxChannels[a]; + m_fxChannels[a] = m_fxChannels[b]; + m_fxChannels[b] = tmpChannel; +} + + + +void FxMixer::moveChannelRight(int index) +{ + moveChannelLeft(index+1); +} + + + +void FxMixer::createChannelSend(fx_ch_t fromChannel, fx_ch_t toChannel, + float amount) +{ + // find the existing connection + FxChannel * from = m_fxChannels[fromChannel]; + for(int i=0; im_sends.size(); ++i){ + if( from->m_sends[i] == toChannel ) + { + // simply adjust the amount + from->m_sendAmount[i]->setValue(amount); + return; + } + } + + // connection does not exist. create a new one + + // add to from's sends + from->m_sends.push_back(toChannel); + from->m_sendAmount.push_back(new FloatModel(amount, 0, 1, 0.001, NULL, + tr("Amount to send"))); + + // add to to's receives + m_fxChannels[toChannel]->m_receives.push_back(fromChannel); + +} + + + +// delete the connection made by createChannelSend +void FxMixer::deleteChannelSend(fx_ch_t fromChannel, fx_ch_t toChannel) +{ + // delete the send + FxChannel * from = m_fxChannels[fromChannel]; + FxChannel * to = m_fxChannels[toChannel]; + + // find and delete the send entry + for(int i=0; im_sends.size(); ++i) { + if( from->m_sends[i] == toChannel ) + { + // delete this index + delete from->m_sendAmount[i]; + from->m_sendAmount.remove(i); + from->m_sends.remove(i); + break; + } + } + + // find and delete the receive entry + for(int i=0; im_receives.size(); ++i) + { + if( to->m_receives[i] == fromChannel ) + { + // delete this index + to->m_receives.remove(i); + break; + } + } +} + + +bool FxMixer::isInfiniteLoop(fx_ch_t sendFrom, fx_ch_t sendTo) { + // can't send master to anything + if( sendFrom == 0 ) return true; + + // can't send channel to itself + if( sendFrom == sendTo ) return true; + + // follow sendTo's outputs recursively looking for something that sends + // to sendFrom + for(int i=0; im_sends.size(); ++i) + { + if( isInfiniteLoop( sendFrom, m_fxChannels[sendTo]->m_sends[i] ) ) + { + return true; + } + } + + return false; +} + + +// how much does fromChannel send its output to the input of toChannel? +FloatModel * FxMixer::channelSendModel(fx_ch_t fromChannel, fx_ch_t toChannel) +{ + FxChannel * from = m_fxChannels[fromChannel]; + for(int i=0; im_sends.size(); ++i){ + if( from->m_sends[i] == toChannel ) + return from->m_sendAmount[i]; + } + return NULL; +} + + + +void FxMixer::mixToChannel( const sampleFrame * _buf, fx_ch_t _ch ) +{ + // SMF: it seems like here the track-channels are mixed in... but from where + // is this called and when and why...?!? + // + // OK, found it (git grep is your friend...): This is the next part, + // where there is a mix between push and pull model inside the core, as + // the audio-tracks *push* their data into the fx-channels hopefully just + // before the Mixer-Channels are processed... Sorry to say this: but this + // took me senseless hours to find out and is silly, too... + + if( m_fxChannels[_ch]->m_muteModel.value() == false ) + { + m_fxChannels[_ch]->m_lock.lock(); + MixHelpers::add( m_fxChannels[_ch]->m_buffer, _buf, engine::mixer()->framesPerPeriod() ); + m_fxChannels[_ch]->m_lock.unlock(); } } @@ -148,47 +443,58 @@ void FxMixer::prepareMasterMix() +void FxMixer::addChannelLeaf( int _ch, sampleFrame * _buf ) +{ + FxChannel * thisCh = m_fxChannels[_ch]; + + // if we're muted or this channel is seen already, discount it + if( thisCh->m_muteModel.value() || thisCh->m_queued ) + { + return; + } + + foreach( const int senderIndex, thisCh->m_receives ) + { + addChannelLeaf( senderIndex, _buf ); + } + + // add this channel to job list + thisCh->m_queued = true; + MixerWorkerThread::addJob( thisCh ); +} + + void FxMixer::masterMix( sampleFrame * _buf ) { const int fpp = engine::mixer()->framesPerPeriod(); - memcpy( _buf, m_fxChannels[0]->m_buffer, sizeof( sampleFrame ) * fpp ); - for( int i = 1; i < NumFxChannels+1; ++i ) + // recursively loop through channel dependency chain + // and add all channels to job list that have no dependencies + // when the channel completes it will check its parent to see if it needs + // to be processed. + MixerWorkerThread::resetJobQueue( MixerWorkerThread::JobQueue::Dynamic ); + addChannelLeaf( 0, _buf ); + while( m_fxChannels[0]->state() != ThreadableJob::Done ) { - if( m_fxChannels[i]->m_used ) - { - sampleFrame * ch_buf = m_fxChannels[i]->m_buffer; - const float v = m_fxChannels[i]->m_volumeModel.value(); - for( f_cnt_t f = 0; f < fpp; ++f ) - { - _buf[f][0] += ch_buf[f][0] * v; - _buf[f][1] += ch_buf[f][1] * v; - } - engine::mixer()->clearAudioBuffer( ch_buf, - engine::mixer()->framesPerPeriod() ); - m_fxChannels[i]->m_used = false; - } - } - - processChannel( 0, _buf ); - - if( m_fxChannels[0]->m_muteModel.value() ) - { - engine::mixer()->clearAudioBuffer( _buf, - engine::mixer()->framesPerPeriod() ); - return; + MixerWorkerThread::startAndWaitForJobs(); } + //m_fxChannels[0]->doProcessing( NULL ); const float v = m_fxChannels[0]->m_volumeModel.value(); - for( f_cnt_t f = 0; f < engine::mixer()->framesPerPeriod(); ++f ) - { - _buf[f][0] *= v; - _buf[f][1] *= v; - } + MixHelpers::addMultiplied( _buf, m_fxChannels[0]->m_buffer, v, fpp ); m_fxChannels[0]->m_peakLeft *= engine::mixer()->masterGain(); m_fxChannels[0]->m_peakRight *= engine::mixer()->masterGain(); + + // clear all channel buffers and + // reset channel process state + for( int i = 0; i < numChannels(); ++i) + { + engine::mixer()->clearAudioBuffer( m_fxChannels[i]->m_buffer, engine::mixer()->framesPerPeriod() ); + m_fxChannels[i]->reset(); + m_fxChannels[i]->m_queued = false; + } } @@ -196,60 +502,139 @@ void FxMixer::masterMix( sampleFrame * _buf ) void FxMixer::clear() { - for( int i = 0; i <= NumFxChannels; ++i ) + while( m_fxChannels.size() > 1 ) { - m_fxChannels[i]->m_fxChain.clear(); - m_fxChannels[i]->m_volumeModel.setValue( 1.0f ); - m_fxChannels[i]->m_muteModel.setValue( false ); - m_fxChannels[i]->m_name = ( i == 0 ) ? - tr( "Master" ) : tr( "FX %1" ).arg( i ); - m_fxChannels[i]->m_volumeModel.setDisplayName( - m_fxChannels[i]->m_name ); - + deleteChannel(1); } + + clearChannel(0); } +void FxMixer::clearChannel(fx_ch_t index) +{ + FxChannel * ch = m_fxChannels[index]; + ch->m_fxChain.clear(); + ch->m_volumeModel.setValue( 1.0f ); + ch->m_muteModel.setValue( false ); + ch->m_name = ( index == 0 ) ? tr( "Master" ) : tr( "FX %1" ).arg( index ); + ch->m_volumeModel.setDisplayName(ch->m_name ); + + // send only to master + if( index > 0) + { + // delete existing sends + for( int i=0; im_sends.size(); ++i) + { + deleteChannelSend(index, ch->m_sends[i]); + } + + // add send to master + createChannelSend(index, 0); + } + + // delete receives + for( int i=0; im_receives.size(); ++i) + { + deleteChannelSend(ch->m_receives[i], index); + } + +} void FxMixer::saveSettings( QDomDocument & _doc, QDomElement & _this ) { - for( int i = 0; i <= NumFxChannels; ++i ) + for( int i = 0; i < m_fxChannels.size(); ++i ) { + FxChannel * ch = m_fxChannels[i]; + QDomElement fxch = _doc.createElement( QString( "fxchannel" ) ); _this.appendChild( fxch ); - m_fxChannels[i]->m_fxChain.saveState( _doc, fxch ); - m_fxChannels[i]->m_volumeModel.saveSettings( _doc, fxch, - "volume" ); - m_fxChannels[i]->m_muteModel.saveSettings( _doc, fxch, - "muted" ); + + ch->m_fxChain.saveState( _doc, fxch ); + ch->m_volumeModel.saveSettings( _doc, fxch, "volume" ); + ch->m_muteModel.saveSettings( _doc, fxch, "muted" ); fxch.setAttribute( "num", i ); - fxch.setAttribute( "name", m_fxChannels[i]->m_name ); + fxch.setAttribute( "name", ch->m_name ); + + // add the channel sends + for( int si = 0; si < ch->m_sends.size(); ++si ) + { + QDomElement sendsDom = _doc.createElement( QString( "send" ) ); + fxch.appendChild( sendsDom ); + + sendsDom.setAttribute( "channel", ch->m_sends[si] ); + ch->m_sendAmount[si]->saveSettings( _doc, sendsDom, "amount"); + } } } +// make sure we have at least num channels +void FxMixer::allocateChannelsTo(int num) +{ + while( num > m_fxChannels.size() - 1 ) + { + createChannel(); + // delete the default send to master + deleteChannelSend(m_fxChannels.size()-1, 0); + } +} void FxMixer::loadSettings( const QDomElement & _this ) { clear(); QDomNode node = _this.firstChild(); - for( int i = 0; i <= NumFxChannels; ++i ) + bool thereIsASend = false; + + while( ! node.isNull() ) { QDomElement fxch = node.toElement(); + + // index of the channel we are about to load int num = fxch.attribute( "num" ).toInt(); - m_fxChannels[num]->m_fxChain.restoreState( - fxch.firstChildElement( - m_fxChannels[num]->m_fxChain.nodeName() ) ); + + // allocate enough channels + allocateChannelsTo( num ); + m_fxChannels[num]->m_volumeModel.loadSettings( fxch, "volume" ); m_fxChannels[num]->m_muteModel.loadSettings( fxch, "muted" ); m_fxChannels[num]->m_name = fxch.attribute( "name" ); + + m_fxChannels[num]->m_fxChain.restoreState( fxch.firstChildElement( + m_fxChannels[num]->m_fxChain.nodeName() ) ); + + // mixer sends + QDomNodeList chData = fxch.childNodes(); + for( unsigned int i=0; i __fx_channel_jobs( NumFxChannels ); - static void aligned_free( void * _buf ) @@ -91,210 +90,6 @@ static void * aligned_malloc( int _bytes ) -class MixerWorkerThread : public QThread -{ -public: - enum JobTypes - { - InvalidJob, - PlayHandle, - AudioPortEffects, - EffectChannel, - NumJobTypes - } ; - - struct JobQueueItem - { - JobQueueItem() : - type( InvalidJob ), - job( NULL ), - param( 0 ), - done( false ) - { - } - JobQueueItem( JobTypes _type, void * _job, int _param = 0 ) : - type( _type ), - job( _job ), - param( _param ), - done( false ) - { - } - - JobTypes type; - void * job; - int param; - - AtomicInt done; - } ; - - - struct JobQueue - { -#define JOB_QUEUE_SIZE 1024 - JobQueue() : - queueSize( 0 ) - { - } - - JobQueueItem items[JOB_QUEUE_SIZE]; - int queueSize; - AtomicInt itemsDone; - } ; - - static JobQueue s_jobQueue; - - MixerWorkerThread( int _worker_num, Mixer* mixer ) : - QThread( mixer ), - m_workingBuf( (sampleFrame *) aligned_malloc( - mixer->framesPerPeriod() * - sizeof( sampleFrame ) ) ), - m_workerNum( _worker_num ), - m_quit( false ), - m_mixer( mixer ), - m_queueReadyWaitCond( &m_mixer->m_queueReadyWaitCond ) - { - } - - virtual ~MixerWorkerThread() - { - aligned_free( m_workingBuf ); - } - - virtual void quit() - { - m_quit = true; - } - - void processJobQueue(); - - -private: - virtual void run() - { -#if 0 -#ifdef LMMS_BUILD_LINUX -#ifdef LMMS_HAVE_SCHED_H - cpu_set_t mask; - CPU_ZERO( &mask ); - CPU_SET( m_workerNum, &mask ); - sched_setaffinity( 0, sizeof( mask ), &mask ); -#endif -#endif -#endif - QMutex m; - while( m_quit == false ) - { - m.lock(); - m_queueReadyWaitCond->wait( &m ); - processJobQueue(); - m.unlock(); - } - } - - sampleFrame * m_workingBuf; - int m_workerNum; - volatile bool m_quit; - Mixer* m_mixer; - QWaitCondition * m_queueReadyWaitCond; - -} ; - - -MixerWorkerThread::JobQueue MixerWorkerThread::s_jobQueue; - - - -void MixerWorkerThread::processJobQueue() -{ - for( int i = 0; i < s_jobQueue.queueSize; ++i ) - { - JobQueueItem * it = &s_jobQueue.items[i]; - if( it->done.fetchAndStoreOrdered( 1 ) == 0 ) - { - switch( it->type ) - { - case PlayHandle: - ( (playHandle *) it->job )-> - play( m_workingBuf ); - break; - case AudioPortEffects: - { - AudioPort * a = (AudioPort *) it->job; - const bool me = a->processEffects(); - if( me || a->m_bufferUsage != AudioPort::NoUsage ) - { - engine::fxMixer()->mixToChannel( a->firstBuffer(), - a->nextFxChannel() ); - a->nextPeriod(); - } - } - break; - case EffectChannel: - engine::fxMixer()->processChannel( (fx_ch_t) it->param ); - break; - default: - break; - } - s_jobQueue.itemsDone.fetchAndAddOrdered( 1 ); - } - } -} - -#define FILL_JOB_QUEUE_BEGIN(_vec_type,_vec,_condition) \ - MixerWorkerThread::s_jobQueue.queueSize = 0; \ - MixerWorkerThread::s_jobQueue.itemsDone = 0; \ - for( _vec_type::Iterator it = _vec.begin(); \ - it != _vec.end(); ++it ) \ - { \ - if( _condition ) \ - { - -#define FILL_JOB_QUEUE_END() \ - ++MixerWorkerThread::s_jobQueue.queueSize; \ - } \ - } - -#define FILL_JOB_QUEUE(_vec_type,_vec,_job_type,_condition) \ - FILL_JOB_QUEUE_BEGIN(_vec_type,_vec,_condition) \ - MixerWorkerThread::s_jobQueue.items \ - [MixerWorkerThread::s_jobQueue.queueSize] = \ - MixerWorkerThread::JobQueueItem( _job_type, \ - (void *) *it ); \ - FILL_JOB_QUEUE_END() - -#define FILL_JOB_QUEUE_PARAM(_vec_type,_vec,_job_type,_condition) \ - FILL_JOB_QUEUE_BEGIN(_vec_type,_vec,_condition) \ - MixerWorkerThread::s_jobQueue.items \ - [MixerWorkerThread::s_jobQueue.queueSize] = \ - MixerWorkerThread::JobQueueItem( _job_type, \ - NULL, *it ); \ - FILL_JOB_QUEUE_END() - -#define START_JOBS() \ - m_queueReadyWaitCond.wakeAll(); - -// define a pause instruction for spinlock-loop - merely useful on -// HyperThreading systems with just one physical core (e.g. Intel Atom) -#ifdef LMMS_HOST_X86 -#define SPINLOCK_PAUSE() asm( "pause" ) -#else -#ifdef LMMS_HOST_X86_64 -#define SPINLOCK_PAUSE() asm( "pause" ) -#else -#define SPINLOCK_PAUSE() -#endif -#endif - -#define WAIT_FOR_JOBS() \ - m_workers[m_numWorkers]->processJobQueue(); \ - while( MixerWorkerThread::s_jobQueue.itemsDone < \ - MixerWorkerThread::s_jobQueue.queueSize ) \ - { \ - SPINLOCK_PAUSE(); \ - } \ - - - Mixer::Mixer() : m_framesPerPeriod( DEFAULT_BUFFER_SIZE ), @@ -321,11 +116,6 @@ Mixer::Mixer() : clearAudioBuffer( m_inputBuffer[i], m_inputBufferSize[i] ); } - for( int i = 1; i < NumFxChannels+1; ++i ) - { - __fx_channel_jobs[i-1] = (fx_ch_t) i; - } - // just rendering? if( !engine::hasGUI() ) { @@ -372,7 +162,7 @@ Mixer::Mixer() : for( int i = 0; i < m_numWorkers+1; ++i ) { - MixerWorkerThread * wt = new MixerWorkerThread( i, this ); + MixerWorkerThread * wt = new MixerWorkerThread( this ); if( i < m_numWorkers ) { wt->start( QThread::TimeCriticalPriority ); @@ -390,14 +180,13 @@ Mixer::Mixer() : Mixer::~Mixer() { - // distribute an empty job-queue so that worker-threads - // get out of their processing-loop - MixerWorkerThread::s_jobQueue.queueSize = 0; for( int w = 0; w < m_numWorkers; ++w ) { m_workers[w]->quit(); } - START_JOBS(); + + MixerWorkerThread::startAndWaitForJobs(); + for( int w = 0; w < m_numWorkers; ++w ) { m_workers[w]->wait( 500 ); @@ -618,11 +407,8 @@ const surroundSampleFrame * Mixer::renderNextBuffer() // STAGE 1: run and render all play handles - FILL_JOB_QUEUE(PlayHandleList,m_playHandles, - MixerWorkerThread::PlayHandle, - !( *it )->done()); - START_JOBS(); - WAIT_FOR_JOBS(); + MixerWorkerThread::fillJobQueue( m_playHandles ); + MixerWorkerThread::startAndWaitForJobs(); // removed all play handles which are done for( PlayHandleList::Iterator it = m_playHandles.begin(); @@ -647,20 +433,11 @@ const surroundSampleFrame * Mixer::renderNextBuffer() // STAGE 2: process effects of all instrument- and sampletracks - FILL_JOB_QUEUE(QVector,m_audioPorts, - MixerWorkerThread::AudioPortEffects,1); - START_JOBS(); - WAIT_FOR_JOBS(); + MixerWorkerThread::fillJobQueue >( m_audioPorts ); + MixerWorkerThread::startAndWaitForJobs(); - // STAGE 3: process effects in FX mixer - FILL_JOB_QUEUE_PARAM(QVector,__fx_channel_jobs, - MixerWorkerThread::EffectChannel,1); - START_JOBS(); - WAIT_FOR_JOBS(); - - - // STAGE 4: do master mix in FX mixer + // STAGE 3: do master mix in FX mixer engine::fxMixer()->masterMix( m_writeBuf ); unlock(); diff --git a/src/core/MixerWorkerThread.cpp b/src/core/MixerWorkerThread.cpp new file mode 100644 index 000000000..143fffa84 --- /dev/null +++ b/src/core/MixerWorkerThread.cpp @@ -0,0 +1,165 @@ +/* + * MixerWorkerThread.cpp - implementation of MixerWorkerThread + * + * Copyright (c) 2009-2014 Tobias Doerffel + * + * This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net + * + * 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 "MixerWorkerThread.h" +#include "engine.h" + + +MixerWorkerThread::JobQueue MixerWorkerThread::globalJobQueue; +QWaitCondition * MixerWorkerThread::queueReadyWaitCond = NULL; +QList MixerWorkerThread::workerThreads; + + + +// implementation of internal JobQueue +void MixerWorkerThread::JobQueue::reset( OperationMode _opMode ) +{ + m_queueSize = 0; + m_itemsDone = 0; + m_opMode = _opMode; +} + + + + +void MixerWorkerThread::JobQueue::addJob( ThreadableJob * _job ) +{ + if( _job->requiresProcessing() ) + { + // update job state + _job->queue(); + // actually queue the job via atomic operations + m_items[m_queueSize.fetchAndAddOrdered(1)] = _job; + } +} + + + +void MixerWorkerThread::JobQueue::run( sampleFrame * _buffer ) +{ + bool processedJob = true; + while( processedJob && (int) m_itemsDone < (int) m_queueSize ) + { + processedJob = false; + for( int i = 0; i < m_queueSize; ++i ) + { + ThreadableJob * job = m_items[i].fetchAndStoreOrdered( NULL ); + if( job ) + { + job->process( _buffer ); + processedJob = true; + m_itemsDone.fetchAndAddOrdered( 1 ); + } + } + // always exit loop if we're not in dynamic mode + processedJob = processedJob && ( m_opMode == Dynamic ); + } +} + + + + +void MixerWorkerThread::JobQueue::wait() +{ + while( (int) m_itemsDone < (int) m_queueSize ) + { +#if defined(LMMS_HOST_X86) || defined(LMMS_HOST_X86_64) + asm( "pause" ); +#endif + } +} + + + + + +// implementation of worker threads + +MixerWorkerThread::MixerWorkerThread( Mixer* mixer ) : + QThread( mixer ), + m_workingBuf( new sampleFrame[mixer->framesPerPeriod()] ), + m_quit( false ) +{ + // initialize global static data + if( queueReadyWaitCond == NULL ) + { + queueReadyWaitCond = new QWaitCondition; + } + + // keep track of all instantiated worker threads - this is used for + // processing the last worker thread "inline", see comments in + // MixerWorkerThread::startAndWaitForJobs() for details + workerThreads << this; + + resetJobQueue(); +} + + + + +MixerWorkerThread::~MixerWorkerThread() +{ + delete[] m_workingBuf; + + workerThreads.removeAll( this ); +} + + + + +void MixerWorkerThread::quit() +{ + m_quit = true; + resetJobQueue(); +} + + + + +void MixerWorkerThread::startAndWaitForJobs() +{ + queueReadyWaitCond->wakeAll(); + // The last worker-thread is never started. Instead it's processed "inline" + // i.e. within the global Mixer thread. This way we can reduce latencies + // that otherwise would be caused by synchronizing with another thread. + globalJobQueue.run( workerThreads.last()->m_workingBuf ); + globalJobQueue.wait(); +} + + + + +void MixerWorkerThread::run() +{ + QMutex m; + while( m_quit == false ) + { + m.lock(); + queueReadyWaitCond->wait( &m ); + globalJobQueue.run( m_workingBuf ); + m.unlock(); + } +} + + diff --git a/src/core/audio/AudioPort.cpp b/src/core/audio/AudioPort.cpp index 5071cc369..64cf6cfd2 100644 --- a/src/core/audio/AudioPort.cpp +++ b/src/core/audio/AudioPort.cpp @@ -1,7 +1,7 @@ /* * AudioPort.cpp - base-class for objects providing sound at a port * - * Copyright (c) 2004-2009 Tobias Doerffel + * Copyright (c) 2004-2014 Tobias Doerffel * * This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net * @@ -25,6 +25,7 @@ #include "AudioPort.h" #include "AudioDevice.h" #include "EffectChain.h" +#include "FxMixer.h" #include "engine.h" @@ -121,3 +122,13 @@ bool AudioPort::processEffects() } +void AudioPort::doProcessing( sampleFrame * ) +{ + const bool me = processEffects(); + if( me || m_bufferUsage != NoUsage ) + { + engine::fxMixer()->mixToChannel( firstBuffer(), nextFxChannel() ); + nextPeriod(); + } +} + diff --git a/src/gui/FxMixerView.cpp b/src/gui/FxMixerView.cpp index 834a4dbcc..453e25a26 100644 --- a/src/gui/FxMixerView.cpp +++ b/src/gui/FxMixerView.cpp @@ -22,6 +22,9 @@ * */ +#include +#include + #include #include #include @@ -31,80 +34,19 @@ #include #include #include +#include +#include +#include #include "FxMixerView.h" -#include "fader.h" -#include "EffectRackView.h" +#include "knob.h" #include "engine.h" #include "embed.h" #include "MainWindow.h" -#include "LcdWidget.h" #include "gui_templates.h" -#include "tooltip.h" -#include "pixmap_button.h" - - - -class FxLine : public QWidget -{ -public: - FxLine( QWidget * _parent, FxMixerView * _mv, QString & _name ) : - QWidget( _parent ), - m_mv( _mv ), - m_name( _name ) - { - setFixedSize( 32, 232 ); - setAttribute( Qt::WA_OpaquePaintEvent, true ); - setCursor( QCursor( embed::getIconPixmap( "hand" ), 0, 0 ) ); - } - - virtual void paintEvent( QPaintEvent * ) - { - QPainter p( this ); - p.fillRect( rect(), QColor( 72, 76, 88 ) ); - p.setPen( QColor( 40, 42, 48 ) ); - p.drawRect( 0, 0, width()-2, height()-2 ); - p.setPen( QColor( 108, 114, 132 ) ); - p.drawRect( 1, 1, width()-2, height()-2 ); - p.setPen( QColor( 20, 24, 32 ) ); - p.drawRect( 0, 0, width()-1, height()-1 ); - - p.rotate( -90 ); - p.setPen( m_mv->currentFxLine() == this ? - QColor( 0, 255, 0 ) : Qt::white ); - p.setFont( pointSizeF( font(), 7.5f ) ); - p.drawText( -90, 20, m_name ); - } - - virtual void mousePressEvent( QMouseEvent * ) - { - m_mv->setCurrentFxLine( this ); - } - - virtual void mouseDoubleClickEvent( QMouseEvent * ) - { - bool ok; - QString new_name = QInputDialog::getText( this, - FxMixerView::tr( "Rename FX channel" ), - FxMixerView::tr( "Enter the new name for this " - "FX channel" ), - QLineEdit::Normal, m_name, &ok ); - if( ok && !new_name.isEmpty() ) - { - m_name = new_name; - update(); - } - } - - -private: - FxMixerView * m_mv; - QString & m_name; - -} ; - - - +#include "InstrumentTrack.h" +#include "song.h" +#include "bb_track_container.h" FxMixerView::FxMixerView() : QWidget(), @@ -114,117 +56,81 @@ FxMixerView::FxMixerView() : FxMixer * m = engine::fxMixer(); m->setHook( this ); - QPalette pal = palette(); - pal.setColor( QPalette::Background, QColor( 72, 76, 88 ) ); - setPalette( pal ); + //QPalette pal = palette(); + //pal.setColor( QPalette::Background, QColor( 72, 76, 88 ) ); + //setPalette( pal ); setAutoFillBackground( true ); - setSizePolicy( QSizePolicy::Preferred, QSizePolicy::Minimum ); setWindowTitle( tr( "FX-Mixer" ) ); setWindowIcon( embed::getIconPixmap( "fx_mixer" ) ); - m_fxLineBanks = new QStackedLayout; - m_fxLineBanks->setSpacing( 0 ); - m_fxLineBanks->setMargin( 1 ); - - m_fxRacksLayout = new QStackedLayout; - m_fxRacksLayout->setSpacing( 0 ); - m_fxRacksLayout->setMargin( 0 ); - // main-layout QHBoxLayout * ml = new QHBoxLayout; - ml->setMargin( 0 ); - ml->setSpacing( 0 ); - ml->addSpacing( 6 ); + // Channel area + m_channelAreaWidget = new QWidget; + chLayout = new QHBoxLayout(m_channelAreaWidget); + chLayout->setSizeConstraint(QLayout::SetMinimumSize); + chLayout->setSpacing( 0 ); + chLayout->setMargin( 0 ); + m_channelAreaWidget->setLayout(chLayout); - QHBoxLayout * banks[NumFxChannels/16]; - for( int i = 0; i < NumFxChannels/16; ++i ) + // add master channel + m_fxChannelViews.resize(m->numChannels()); + m_fxChannelViews[0] = new FxChannelView(this, this, 0); + + FxChannelView * masterView = m_fxChannelViews[0]; + ml->addWidget( masterView->m_fxLine, 0, Qt::AlignTop ); + + QSize fxLineSize = masterView->m_fxLine->size(); + + // add mixer channels + for( int i = 1; i < m_fxChannelViews.size(); ++i ) { - QWidget * w = new QWidget( this ); - banks[i] = new QHBoxLayout( w ); - banks[i]->setMargin( 5 ); - banks[i]->setSpacing( 1 ); - m_fxLineBanks->addWidget( w ); + m_fxChannelViews[i] = new FxChannelView(m_channelAreaWidget, this, i); + chLayout->addWidget(m_fxChannelViews[i]->m_fxLine); } - for( int i = 0; i < NumFxChannels+1; ++i ) + // add the scrolling section to the main layout + // class solely for scroll area to pass key presses down + class ChannelArea : public QScrollArea { - FxChannelView * cv = &m_fxChannelViews[i]; - if( i == 0 ) - { - cv->m_fxLine = new FxLine( NULL, this, - m->m_fxChannels[i]->m_name ); - ml->addWidget( cv->m_fxLine ); - ml->addSpacing( 10 ); - } - else - { - const int bank = (i-1) / 16; - cv->m_fxLine = new FxLine( NULL, this, - m->m_fxChannels[i]->m_name ); - banks[bank]->addWidget( cv->m_fxLine ); - } - LcdWidget* l = new LcdWidget( 2, cv->m_fxLine ); - l->setValue( i ); - l->move( 3, 4 ); - l->setMarginWidth( 1 ); - - - cv->m_fader = new fader( &m->m_fxChannels[i]->m_volumeModel, - tr( "FX Fader %1" ).arg( i ), - cv->m_fxLine ); - cv->m_fader->move( 15-cv->m_fader->width()/2, - cv->m_fxLine->height()- - cv->m_fader->height()-5 ); - - cv->m_muteBtn = new pixmapButton( cv->m_fxLine, tr( "Mute" ) ); - cv->m_muteBtn->setModel( &m->m_fxChannels[i]->m_muteModel ); - cv->m_muteBtn->setActiveGraphic( - embed::getIconPixmap( "led_off" ) ); - cv->m_muteBtn->setInactiveGraphic( - embed::getIconPixmap( "led_green" ) ); - cv->m_muteBtn->setCheckable( true ); - cv->m_muteBtn->move( 9, cv->m_fader->y()-16); - toolTip::add( cv->m_muteBtn, tr( "Mute this FX channel" ) ); - - cv->m_rackView = new EffectRackView( - &m->m_fxChannels[i]->m_fxChain, this ); - m_fxRacksLayout->addWidget( cv->m_rackView ); - if( i == 0 ) - { - QVBoxLayout * l = new QVBoxLayout; - l->addSpacing( 10 ); - QButtonGroup * g = new QButtonGroup( this ); - m_bankButtons = g; - g->setExclusive( true ); - for( int j = 0; j < 4; ++j ) + public: + ChannelArea(QWidget * parent, FxMixerView * mv) : + QScrollArea(parent), m_mv(mv) {} + ~ChannelArea() {} + virtual void keyPressEvent(QKeyEvent * e) { - QToolButton * btn = new QToolButton; - btn->setText( QString( 'A'+j ) ); - btn->setCheckable( true ); - btn->setSizePolicy( QSizePolicy::Preferred, - QSizePolicy::Expanding ); - l->addWidget( btn ); - g->addButton( btn, j ); - btn->setChecked( j == 0); + m_mv->keyPressEvent(e); } - l->addSpacing( 10 ); - ml->addLayout( l ); - connect( g, SIGNAL( buttonClicked( int ) ), - m_fxLineBanks, SLOT( setCurrentIndex( int ) ) ); - } - } + private: + FxMixerView * m_mv; + }; + channelArea = new ChannelArea(this, this); + channelArea->setWidget(m_channelAreaWidget); + channelArea->setVerticalScrollBarPolicy( Qt::ScrollBarAlwaysOff ); + channelArea->setFrameStyle( QFrame::NoFrame ); + channelArea->setMinimumWidth( fxLineSize.width() * 6 ); + channelArea->setFixedHeight( fxLineSize.height() + + style()->pixelMetric( QStyle::PM_ScrollBarExtent ) ); + ml->addWidget(channelArea); - ml->addLayout( m_fxLineBanks ); - ml->addLayout( m_fxRacksLayout ); + // show the add new effect channel button + QPushButton * newChannelBtn = new QPushButton("new", this ); + newChannelBtn->setFont(QFont("sans-serif", 10, 1, false)); + newChannelBtn->setFixedSize(fxLineSize); + connect( newChannelBtn, SIGNAL(clicked()), this, SLOT(addNewChannel())); + ml->addWidget( newChannelBtn, 0, Qt::AlignTop ); + + + // Create EffectRack and set initial index to master channel + m_rackView = new EffectRackView( &m->m_fxChannels[0]->m_fxChain, this ); + ml->addWidget( m_rackView, 0, Qt::AlignTop ); + setCurrentFxLine( m_fxChannelViews[0]->m_fxLine ); setLayout( ml ); updateGeometry(); - m_fxLineBanks->setCurrentIndex( 0 ); - setCurrentFxLine( m_fxChannelViews[0].m_fxLine ); - // timer for updating faders connect( engine::mainWindow(), SIGNAL( periodicUpdate() ), this, SLOT( updateFaders() ) ); @@ -234,10 +140,10 @@ FxMixerView::FxMixerView() : QMdiSubWindow * subWin = engine::mainWindow()->workspace()->addSubWindow( this ); Qt::WindowFlags flags = subWin->windowFlags(); - flags |= Qt::MSWindowsFixedSizeDialogHint; flags &= ~Qt::WindowMaximizeButtonHint; subWin->setWindowFlags( flags ); - //subWin->layout()->setSizeConstraint(QLayout::SetFixedSize); + layout()->setSizeConstraint( QLayout::SetMinAndMaxSize ); + subWin->layout()->setSizeConstraint( QLayout::SetMinAndMaxSize ); parentWidget()->setAttribute( Qt::WA_DeleteOnClose, false ); parentWidget()->move( 5, 310 ); @@ -246,15 +152,75 @@ FxMixerView::FxMixerView() : setModel( m ); } - - - FxMixerView::~FxMixerView() { } +void FxMixerView::addNewChannel() +{ + // add new fx mixer channel and redraw the form. + FxMixer * mix = engine::fxMixer(); + + int newChannelIndex = mix->createChannel(); + m_fxChannelViews.push_back(new FxChannelView(m_channelAreaWidget, this, + newChannelIndex)); + chLayout->addWidget(m_fxChannelViews[newChannelIndex]->m_fxLine); + + updateFxLine(newChannelIndex); + + updateMaxChannelSelector(); +} + + +void FxMixerView::refreshDisplay() +{ + // delete all views and re-add them + for( int i = 1; iremoveWidget(m_fxChannelViews[i]->m_fxLine); + delete m_fxChannelViews[i]->m_fader; + delete m_fxChannelViews[i]->m_muteBtn; + delete m_fxChannelViews[i]->m_fxLine; + delete m_fxChannelViews[i]; + } + m_channelAreaWidget->adjustSize(); + + // re-add the views + m_fxChannelViews.resize(engine::fxMixer()->numChannels()); + for( int i = 1; i < m_fxChannelViews.size(); ++i ) + { + m_fxChannelViews[i] = new FxChannelView(m_channelAreaWidget, this, i); + chLayout->addWidget(m_fxChannelViews[i]->m_fxLine); + } + + updateMaxChannelSelector(); +} + + +// update the and max. channel number for every instrument +void FxMixerView::updateMaxChannelSelector() +{ + QVector songTrackList = engine::getSong()->tracks(); + QVector bbTrackList = engine::getBBTrackContainer()->tracks(); + + QVector trackLists[] = {songTrackList, bbTrackList}; + for(int tl=0; tl<2; ++tl) + { + QVector trackList = trackLists[tl]; + for(int i=0; itype() == track::InstrumentTrack ) + { + InstrumentTrack * inst = (InstrumentTrack *) trackList[i]; + inst->effectChannelModel()->setRange(0, + m_fxChannelViews.size()-1,1); + } + } + } +} + void FxMixerView::saveSettings( QDomDocument & _doc, QDomElement & _this ) { @@ -270,18 +236,189 @@ void FxMixerView::loadSettings( const QDomElement & _this ) } +FxMixerView::FxChannelView::FxChannelView(QWidget * _parent, FxMixerView * _mv, + int _chIndex ) +{ + m_fxLine = new FxLine(_parent, _mv, _chIndex); + + FxMixer * m = engine::fxMixer(); + m_fader = new fader( &m->effectChannel(_chIndex)->m_volumeModel, + tr( "FX Fader %1" ).arg( _chIndex ), m_fxLine ); + m_fader->move( 15-m_fader->width()/2, + m_fxLine->height()- + m_fader->height()-5 ); + + m_muteBtn = new pixmapButton( m_fxLine, tr( "Mute" ) ); + m_muteBtn->setModel( &m->effectChannel(_chIndex)->m_muteModel ); + m_muteBtn->setActiveGraphic( + embed::getIconPixmap( "led_off" ) ); + m_muteBtn->setInactiveGraphic( + embed::getIconPixmap( "led_green" ) ); + m_muteBtn->setCheckable( true ); + m_muteBtn->move( 9, m_fader->y()-16); + toolTip::add( m_muteBtn, tr( "Mute this FX channel" ) ); +} void FxMixerView::setCurrentFxLine( FxLine * _line ) { + // select m_currentFxLine = _line; - for( int i = 0; i < NumFxChannels+1; ++i ) + m_rackView->setModel( &engine::fxMixer()->m_fxChannels[_line->channelIndex()]->m_fxChain ); + + // set up send knob + for(int i = 0; i < m_fxChannelViews.size(); ++i) { - if( m_fxChannelViews[i].m_fxLine == _line ) + updateFxLine(i); + } +} + + +void FxMixerView::updateFxLine(int index) +{ + FxMixer * mix = engine::fxMixer(); + + // does current channel send to this channel? + int selIndex = m_currentFxLine->channelIndex(); + FxLine * thisLine = m_fxChannelViews[index]->m_fxLine; + FloatModel * sendModel = mix->channelSendModel(selIndex, index); + if( sendModel == NULL ) + { + // does not send, hide send knob + thisLine->m_sendKnob->setVisible(false); + } + else + { + // it does send, show knob and connect + thisLine->m_sendKnob->setVisible(true); + thisLine->m_sendKnob->setModel(sendModel); + } + + // disable the send button if it would cause an infinite loop + thisLine->m_sendBtn->setVisible(! mix->isInfiniteLoop(selIndex, index)); + thisLine->m_sendBtn->updateLightStatus(); + thisLine->update(); +} + + +void FxMixerView::deleteChannel(int index) +{ + // can't delete master + if( index == 0 ) return; + + // remember selected line + int selLine = m_currentFxLine->channelIndex(); + + // delete the real channel + engine::fxMixer()->deleteChannel(index); + + // delete the view + chLayout->removeWidget(m_fxChannelViews[index]->m_fxLine); + delete m_fxChannelViews[index]->m_fader; + delete m_fxChannelViews[index]->m_muteBtn; + delete m_fxChannelViews[index]->m_fxLine; + delete m_fxChannelViews[index]; + m_channelAreaWidget->adjustSize(); + + // make sure every channel knows what index it is + for(int i=0; i index ) { - m_fxRacksLayout->setCurrentIndex( i ); + m_fxChannelViews[i]->m_fxLine->setChannelIndex(i-1); } - m_fxChannelViews[i].m_fxLine->update(); + } + m_fxChannelViews.remove(index); + + // select the next channel + if( selLine >= m_fxChannelViews.size() ) + { + selLine = m_fxChannelViews.size()-1; + } + setCurrentFxLine(selLine); + + updateMaxChannelSelector(); +} + + + +void FxMixerView::moveChannelLeft(int index) +{ + // can't move master or first channel left or last channel right + if( index <= 1 || index >= m_fxChannelViews.size() ) return; + + int selIndex = m_currentFxLine->channelIndex(); + + FxMixer * mix = engine::fxMixer(); + mix->moveChannelLeft(index); + + // refresh the two mixer views + for( int i = index-1; i <= index; ++i ) + { + // delete the mixer view + int replaceIndex = chLayout->indexOf(m_fxChannelViews[i]->m_fxLine); + + chLayout->removeWidget(m_fxChannelViews[i]->m_fxLine); + delete m_fxChannelViews[i]->m_fader; + delete m_fxChannelViews[i]->m_muteBtn; + delete m_fxChannelViews[i]->m_fxLine; + delete m_fxChannelViews[i]; + + // add it again + m_fxChannelViews[i] = new FxChannelView(m_channelAreaWidget, this, i); + chLayout->insertWidget(replaceIndex, m_fxChannelViews[i]->m_fxLine); + } + + // keep selected channel + if( selIndex == index ) + { + selIndex = index-1; + } + else if( selIndex == index - 1 ) + { + selIndex = index; + } + setCurrentFxLine(selIndex); +} + + + +void FxMixerView::moveChannelRight(int index) +{ + moveChannelLeft(index+1); +} + + + +void FxMixerView::keyPressEvent(QKeyEvent * e) +{ + switch(e->key()) + { + case Qt::Key_Delete: + deleteChannel(m_currentFxLine->channelIndex()); + break; + case Qt::Key_Left: + if( e->modifiers() & Qt::AltModifier ) + { + moveChannelLeft( m_currentFxLine->channelIndex() ); + } + else + { + // select channel to the left + setCurrentFxLine( m_currentFxLine->channelIndex()-1 ); + } + break; + case Qt::Key_Right: + if( e->modifiers() & Qt::AltModifier ) + { + moveChannelRight( m_currentFxLine->channelIndex() ); + } + else + { + // select channel to the right + setCurrentFxLine( m_currentFxLine->channelIndex()+1 ); + } + break; } } @@ -289,23 +426,18 @@ void FxMixerView::setCurrentFxLine( FxLine * _line ) void FxMixerView::setCurrentFxLine( int _line ) { - if ( _line >= 0 && _line < NumFxChannels+1 ) + if( _line >= 0 && _line < m_fxChannelViews.size() ) { - setCurrentFxLine( m_fxChannelViews[_line].m_fxLine ); - - m_bankButtons->button( (_line-1) / 16 )->click(); + setCurrentFxLine( m_fxChannelViews[_line]->m_fxLine ); } } - void FxMixerView::clear() { - for( int i = 0; i <= NumFxChannels; ++i ) - { - m_fxChannelViews[i].m_rackView->clearViews(); - } + m_rackView->clearViews(); + refreshDisplay(); } @@ -314,28 +446,28 @@ void FxMixerView::clear() void FxMixerView::updateFaders() { FxMixer * m = engine::fxMixer(); - for( int i = 0; i < NumFxChannels+1; ++i ) + for( int i = 0; i < m_fxChannelViews.size(); ++i ) { - const float opl = m_fxChannelViews[i].m_fader->getPeak_L(); - const float opr = m_fxChannelViews[i].m_fader->getPeak_R(); + const float opl = m_fxChannelViews[i]->m_fader->getPeak_L(); + const float opr = m_fxChannelViews[i]->m_fader->getPeak_R(); const float fall_off = 1.2; if( m->m_fxChannels[i]->m_peakLeft > opl ) { - m_fxChannelViews[i].m_fader->setPeak_L( + m_fxChannelViews[i]->m_fader->setPeak_L( m->m_fxChannels[i]->m_peakLeft ); } else { - m_fxChannelViews[i].m_fader->setPeak_L( opl/fall_off ); + m_fxChannelViews[i]->m_fader->setPeak_L( opl/fall_off ); } if( m->m_fxChannels[i]->m_peakRight > opr ) { - m_fxChannelViews[i].m_fader->setPeak_R( + m_fxChannelViews[i]->m_fader->setPeak_R( m->m_fxChannels[i]->m_peakRight ); } else { - m_fxChannelViews[i].m_fader->setPeak_R( opr/fall_off ); + m_fxChannelViews[i]->m_fader->setPeak_R( opr/fall_off ); } } } diff --git a/src/gui/widgets/FxLine.cpp b/src/gui/widgets/FxLine.cpp new file mode 100644 index 000000000..b90f647b5 --- /dev/null +++ b/src/gui/widgets/FxLine.cpp @@ -0,0 +1,147 @@ +/* + * FxLine.cpp - FX line widget + * + * Copyright (c) 2009 Andrew Kelley + * Copyright (c) 2014 Tobias Doerffel + * + * This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net + * + * 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 "FxLine.h" + +#include +#include +#include +#include + +#include "FxMixer.h" +#include "FxMixerView.h" +#include "embed.h" +#include "engine.h" +#include "SendButtonIndicator.h" +#include "gui_templates.h" + +FxLine::FxLine( QWidget * _parent, FxMixerView * _mv, int _channelIndex) : + QWidget( _parent ), + m_mv( _mv ), + m_channelIndex( _channelIndex ) +{ + setFixedSize( 32, 287 ); + setAttribute( Qt::WA_OpaquePaintEvent, true ); + setCursor( QCursor( embed::getIconPixmap( "hand" ), 0, 0 ) ); + + // mixer sends knob + m_sendKnob = new knob(0, this, tr("Channel send amount")); + m_sendKnob->move(0, 22); + m_sendKnob->setVisible(false); + + // send button indicator + m_sendBtn = new SendButtonIndicator(this, this, m_mv); + m_sendBtn->setPixmap(embed::getIconPixmap("mixer_send_off", 23, 16)); + m_sendBtn->move(4,4); + + // channel number + m_lcd = new lcdSpinBox( 2, this ); + m_lcd->model()->setRange( m_channelIndex, m_channelIndex ); + m_lcd->model()->setValue( m_channelIndex ); + m_lcd->move( 2, 58 ); + m_lcd->setMarginWidth( 1 ); +} + +FxLine::~FxLine() +{ + delete m_sendKnob; + delete m_sendBtn; + delete m_lcd; +} + + +void FxLine::setChannelIndex(int index) { + m_channelIndex = index; + + m_lcd->model()->setRange( m_channelIndex, m_channelIndex ); + m_lcd->model()->setValue( m_channelIndex ); + m_lcd->update(); +} + + +static void drawFxLine( QPainter* p, const QWidget *fxLine, const QString& name, bool isActive, bool sendToThis ) +{ + int width = fxLine->rect().width(); + int height = fxLine->rect().height(); + + p->fillRect( fxLine->rect(), QColor( 72, 76, 88 ) ); + p->setPen( QColor( 40, 42, 48 ) ); + p->drawRect( 0, 0, width-2, height-2 ); + p->setPen( QColor( 108, 114, 132 ) ); + p->drawRect( 1, 1, width-2, height-2 ); + p->setPen( QColor( 20, 24, 32 ) ); + p->drawRect( 0, 0, width-1, height-1 ); + + // draw the mixer send background + if( sendToThis ) + { + p->drawPixmap(2, 0, 28, 56, + embed::getIconPixmap("send_bg_arrow", 28, 56)); + } + + // draw the channel name + p->rotate( -90 ); + p->setPen( isActive ? QColor( 0, 255, 0 ) : Qt::white ); + p->setFont( pointSizeF( fxLine->font(), 7.5f ) ); + p->drawText( -145, 20, name ); + +} + +void FxLine::paintEvent( QPaintEvent * ) +{ + FxMixer * mix = engine::fxMixer(); + bool sendToThis = mix->channelSendModel( + m_mv->currentFxLine()->m_channelIndex, m_channelIndex) != NULL; + QPainter painter; + painter.begin( this ); + drawFxLine( &painter, this, + mix->effectChannel(m_channelIndex)->m_name, + m_mv->currentFxLine() == this, sendToThis ); + painter.end(); +} + +void FxLine::mousePressEvent( QMouseEvent * ) +{ + m_mv->setCurrentFxLine( this ); +} + +void FxLine::mouseDoubleClickEvent( QMouseEvent * ) +{ + bool ok; + FxMixer * mix = engine::fxMixer(); + QString new_name = QInputDialog::getText( this, + FxMixerView::tr( "Rename FX channel" ), + FxMixerView::tr( "Enter the new name for this " + "FX channel" ), + QLineEdit::Normal, mix->effectChannel(m_channelIndex)->m_name, &ok ); + if( ok && !new_name.isEmpty() ) + { + mix->effectChannel(m_channelIndex)->m_name = new_name; + update(); + } +} + +#include "moc_FxLine.cxx" + diff --git a/src/gui/widgets/SendButtonIndicator.cpp b/src/gui/widgets/SendButtonIndicator.cpp new file mode 100644 index 000000000..a932f136a --- /dev/null +++ b/src/gui/widgets/SendButtonIndicator.cpp @@ -0,0 +1,53 @@ +#include "SendButtonIndicator.h" + +#include "engine.h" +#include "FxMixer.h" +#include "Model.h" + +SendButtonIndicator:: SendButtonIndicator( QWidget * _parent, FxLine * _owner, + FxMixerView * _mv) : + QLabel( _parent ), + m_parent( _owner ), + m_mv( _mv ) +{ + qpmOff = embed::getIconPixmap("mixer_send_off", 23, 16); + qpmOn = embed::getIconPixmap("mixer_send_on", 23, 16); + + // don't do any initializing yet, because the FxMixerView and FxLine + // that were passed to this constructor are not done with their constructors + // yet. + +} + +void SendButtonIndicator::mousePressEvent( QMouseEvent * e ) +{ + FxMixer * mix = engine::fxMixer(); + int from = m_mv->currentFxLine()->channelIndex(); + int to = m_parent->channelIndex(); + FloatModel * sendModel = mix->channelSendModel(from, to); + if( sendModel == NULL ) + { + // not sending. create a mixer send. + mix->createChannelSend( from, to ); + } + else + { + // sending. delete the mixer send. + mix->deleteChannelSend( from, to ); + } + + m_mv->updateFxLine(m_parent->channelIndex()); + updateLightStatus(); +} + +FloatModel * SendButtonIndicator::getSendModel() +{ + FxMixer * mix = engine::fxMixer(); + return mix->channelSendModel( + m_mv->currentFxLine()->channelIndex(), m_parent->channelIndex()); +} + +void SendButtonIndicator::updateLightStatus() +{ + setPixmap( getSendModel() == NULL ? qpmOff : qpmOn ); +} diff --git a/src/tracks/InstrumentTrack.cpp b/src/tracks/InstrumentTrack.cpp index 3387f585c..7c90d5f0d 100644 --- a/src/tracks/InstrumentTrack.cpp +++ b/src/tracks/InstrumentTrack.cpp @@ -2,7 +2,7 @@ * InstrumentTrack.cpp - implementation of instrument-track-class * (window + data-structures) * - * Copyright (c) 2004-2013 Tobias Doerffel + * Copyright (c) 2004-2014 Tobias Doerffel * * This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net * @@ -106,13 +106,14 @@ InstrumentTrack::InstrumentTrack( trackContainer * _tc ) : m_panningModel( DefaultPanning, PanningLeft, PanningRight, 0.1f, this, tr( "Panning" ) ), m_pitchModel( 0, -100, 100, 1, this, tr( "Pitch" ) ), - m_effectChannelModel( 0, 0, NumFxChannels, this, tr( "FX channel" ) ), + m_effectChannelModel( 0, 0, 0, this, tr( "FX channel" ) ), m_instrument( NULL ), m_soundShaping( this ), m_arpeggiator( this ), m_chordCreator( this ), m_piano( this ) { + m_effectChannelModel.setRange( 0, engine::fxMixer()->numChannels()-1, 1); m_baseNoteModel.setInitValue( DefaultKey ); connect( &m_baseNoteModel, SIGNAL( dataChanged() ), this, SLOT( updateBaseNote() ) ); From 5b480dd89824c6cf56fbb0f3b60ff8c7c746d559 Mon Sep 17 00:00:00 2001 From: Tobias Doerffel Date: Tue, 14 Jan 2014 18:04:51 +0100 Subject: [PATCH 007/647] FxMixer: rewrote loop for adjusting FX channel models in deleteChannel() --- src/core/FxMixer.cpp | 37 ++++++++++++++++--------------------- 1 file changed, 16 insertions(+), 21 deletions(-) diff --git a/src/core/FxMixer.cpp b/src/core/FxMixer.cpp index d41276d17..982620c98 100644 --- a/src/core/FxMixer.cpp +++ b/src/core/FxMixer.cpp @@ -171,31 +171,26 @@ void FxMixer::deleteChannel(int index) m_fxChannels[index]->m_lock.lock(); // go through every instrument and adjust for the channel index change - QVector songTrackList = engine::getSong()->tracks(); - QVector bbTrackList = engine::getBBTrackContainer()->tracks(); + TrackContainer::TrackList tracks; + tracks += engine::getSong()->tracks(); + tracks += engine::getBBTrackContainer()->tracks(); - QVector trackLists[] = {songTrackList, bbTrackList}; - for(int tl=0; tl<2; ++tl) + foreach( track* t, tracks ) { - QVector trackList = trackLists[tl]; - for(int i=0; itype() == track::InstrumentTrack ) { - if( trackList[i]->type() == track::InstrumentTrack ) + InstrumentTrack* inst = dynamic_cast( t ); + int val = inst->effectChannelModel()->value(0); + if( val == index ) { - InstrumentTrack * inst = (InstrumentTrack *) trackList[i]; - int val = inst->effectChannelModel()->value(0); - if( val == index ) - { - // we are deleting this track's fx send - // send to master - inst->effectChannelModel()->setValue(0); - } - else if( val > index ) - { - // subtract 1 to make up for the missing channel - inst->effectChannelModel()->setValue(val-1); - } - + // we are deleting this track's fx send + // send to master + inst->effectChannelModel()->setValue(0); + } + else if( val > index ) + { + // subtract 1 to make up for the missing channel + inst->effectChannelModel()->setValue(val-1); } } } From 27b51c250865c42633f98d98742cf9d7f903931b Mon Sep 17 00:00:00 2001 From: Tobias Doerffel Date: Tue, 14 Jan 2014 18:17:51 +0100 Subject: [PATCH 008/647] Song: added missing refresh of FxMixerView when loading project Missed this call when backporting. --- src/core/song.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/core/song.cpp b/src/core/song.cpp index a2c5457aa..2af716a48 100644 --- a/src/core/song.cpp +++ b/src/core/song.cpp @@ -1154,6 +1154,11 @@ void song::loadProject( const QString & _file_name ) else if( node.nodeName() == engine::fxMixer()->nodeName() ) { engine::fxMixer()->restoreState( node.toElement() ); + if( engine::hasGUI() ) + { + // refresh FxMixerView + engine::fxMixerView()->refreshDisplay(); + } } else if( engine::hasGUI() ) { From dbb4a8e6ab63ceb08731e0928ca0175e6c9d5b57 Mon Sep 17 00:00:00 2001 From: Tobias Doerffel Date: Tue, 14 Jan 2014 18:18:59 +0100 Subject: [PATCH 009/647] FxMixerView: fixed clear() Before calling refreshDisplay() we have to actually clear the backend model. --- src/gui/FxMixerView.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/gui/FxMixerView.cpp b/src/gui/FxMixerView.cpp index 453e25a26..d8382ed9d 100644 --- a/src/gui/FxMixerView.cpp +++ b/src/gui/FxMixerView.cpp @@ -437,6 +437,9 @@ void FxMixerView::setCurrentFxLine( int _line ) void FxMixerView::clear() { m_rackView->clearViews(); + + engine::fxMixer()->clear(); + refreshDisplay(); } From 037b977137980f777652e7830569085272f418db Mon Sep 17 00:00:00 2001 From: Vesa Date: Wed, 15 Jan 2014 21:51:35 +0200 Subject: [PATCH 010/647] Ported the FX mixer UI changes from stable-0.4 --- src/gui/widgets/FxLine.cpp | 30 ++++++++++++++++++++++++------ 1 file changed, 24 insertions(+), 6 deletions(-) diff --git a/src/gui/widgets/FxLine.cpp b/src/gui/widgets/FxLine.cpp index b90f647b5..681810aa8 100644 --- a/src/gui/widgets/FxLine.cpp +++ b/src/gui/widgets/FxLine.cpp @@ -86,12 +86,25 @@ static void drawFxLine( QPainter* p, const QWidget *fxLine, const QString& name, int width = fxLine->rect().width(); int height = fxLine->rect().height(); - p->fillRect( fxLine->rect(), QColor( 72, 76, 88 ) ); - p->setPen( QColor( 40, 42, 48 ) ); + QColor bg_color = QApplication::palette().color( QPalette::Active, + QPalette::Background ); + QColor sh_color = QApplication::palette().color( QPalette::Active, + QPalette::Shadow ); + QColor te_color = QApplication::palette().color( QPalette::Active, + QPalette::Text ); + QColor bt_color = QApplication::palette().color( QPalette::Active, + QPalette::BrightText ); + + + p->fillRect( fxLine->rect(), isActive ? bg_color.lighter(130) : bg_color ); + + p->setPen( bg_color.darker(130) ); p->drawRect( 0, 0, width-2, height-2 ); - p->setPen( QColor( 108, 114, 132 ) ); + + p->setPen( bg_color.lighter(150) ); p->drawRect( 1, 1, width-2, height-2 ); - p->setPen( QColor( 20, 24, 32 ) ); + + p->setPen( isActive ? sh_color : bg_color.darker(130) ); p->drawRect( 0, 0, width-1, height-1 ); // draw the mixer send background @@ -103,8 +116,13 @@ static void drawFxLine( QPainter* p, const QWidget *fxLine, const QString& name, // draw the channel name p->rotate( -90 ); - p->setPen( isActive ? QColor( 0, 255, 0 ) : Qt::white ); - p->setFont( pointSizeF( fxLine->font(), 7.5f ) ); + + p->setFont( pointSizeF( fxLine->font(), 7.5f ) ); + p->setPen( sh_color ); + p->drawText( -146, 21, name ); + + p->setPen( isActive ? bt_color : te_color ); + p->drawText( -145, 20, name ); } From dddf5eb61c7b5cbb168e485be53860deed7a950a Mon Sep 17 00:00:00 2001 From: Tobias Doerffel Date: Fri, 17 Jan 2014 19:53:05 +0100 Subject: [PATCH 011/647] FxMixer: ignore mute state in addChannelLeaf() to fix lockup Even if we do not process the FX chain later, we at least have to enqueue all related FX channels to the job queue in order to prevent a lockup. --- src/core/FxMixer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/FxMixer.cpp b/src/core/FxMixer.cpp index 982620c98..5739cc2a6 100644 --- a/src/core/FxMixer.cpp +++ b/src/core/FxMixer.cpp @@ -443,7 +443,7 @@ void FxMixer::addChannelLeaf( int _ch, sampleFrame * _buf ) FxChannel * thisCh = m_fxChannels[_ch]; // if we're muted or this channel is seen already, discount it - if( thisCh->m_muteModel.value() || thisCh->m_queued ) + if( thisCh->m_queued ) { return; } From 12939c24df48047e8b75b2cd1730a3593a37803d Mon Sep 17 00:00:00 2001 From: Tobias Doerffel Date: Fri, 17 Jan 2014 20:01:24 +0100 Subject: [PATCH 012/647] InstrumentTrack: set range of FX channel model to infinite when loading settings When loading a project, instrument tracks usually are instantiated/loaded before the FX mixer settings are loaded which results in an empty FX mixer and thus 0 FX channels. The actual FX channel value for the instrument track would be lost that way. Therefore set a big value which is being corrected later by the FxMixerView for all instruments. --- src/tracks/InstrumentTrack.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/tracks/InstrumentTrack.cpp b/src/tracks/InstrumentTrack.cpp index 414192551..a848b0dc1 100644 --- a/src/tracks/InstrumentTrack.cpp +++ b/src/tracks/InstrumentTrack.cpp @@ -803,6 +803,7 @@ void InstrumentTrack::loadTrackSpecificSettings( const QDomElement & _this ) } m_pitchModel.loadSettings( _this, "pitch" ); + m_effectChannelModel.setRange( 0, INT_MAX ); m_effectChannelModel.loadSettings( _this, "fxch" ); if( _this.hasAttribute( "baseoct" ) ) From f969bd4650e746747e8f22af138a1427226d60d6 Mon Sep 17 00:00:00 2001 From: Tobias Doerffel Date: Tue, 18 Feb 2014 19:35:25 +0100 Subject: [PATCH 013/647] Added separate ZynAddSubFX repository as submodule --- .gitmodules | 3 +++ plugins/zynaddsubfx/zynaddsubfx | 1 + 2 files changed, 4 insertions(+) create mode 100644 .gitmodules create mode 160000 plugins/zynaddsubfx/zynaddsubfx diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 000000000..c45eeb480 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "plugins/zynaddsubfx/zynaddsubfx"] + path = plugins/zynaddsubfx/zynaddsubfx + url = git://github.com/LMMS/zynaddsubfx.git diff --git a/plugins/zynaddsubfx/zynaddsubfx b/plugins/zynaddsubfx/zynaddsubfx new file mode 160000 index 000000000..0d76dc8aa --- /dev/null +++ b/plugins/zynaddsubfx/zynaddsubfx @@ -0,0 +1 @@ +Subproject commit 0d76dc8aa6e4bfc2b4ca6e670b905e7d2d7293f2 From 9209ef59e3262a209e075a7924ea3e3c2a41ec69 Mon Sep 17 00:00:00 2001 From: Tobias Doerffel Date: Tue, 18 Feb 2014 19:56:12 +0100 Subject: [PATCH 014/647] Initial integration of updated ZynAddSubFX --- include/Midi.h | 2 +- plugins/zynaddsubfx/CMakeLists.txt | 116 +- plugins/zynaddsubfx/LocalZynAddSubFx.cpp | 66 +- plugins/zynaddsubfx/LocalZynAddSubFx.h | 2 + plugins/zynaddsubfx/RemoteZynAddSubFx.cpp | 21 +- plugins/zynaddsubfx/ZynAddSubFx.h | 2 +- plugins/zynaddsubfx/src/DSP/AnalogFilter.cpp | 450 -- plugins/zynaddsubfx/src/DSP/AnalogFilter.h | 82 - plugins/zynaddsubfx/src/DSP/CMakeLists.txt | 14 - plugins/zynaddsubfx/src/DSP/FFTwrapper.cpp | 136 - plugins/zynaddsubfx/src/DSP/FFTwrapper.h | 70 - plugins/zynaddsubfx/src/DSP/Filter.cpp | 87 - plugins/zynaddsubfx/src/DSP/Filter.h | 52 - plugins/zynaddsubfx/src/DSP/Filter_.h | 43 - plugins/zynaddsubfx/src/DSP/FormantFilter.cpp | 231 - plugins/zynaddsubfx/src/DSP/FormantFilter.h | 69 - plugins/zynaddsubfx/src/DSP/SVFilter.cpp | 186 - plugins/zynaddsubfx/src/DSP/SVFilter.h | 71 - plugins/zynaddsubfx/src/DSP/Unison.cpp | 184 - plugins/zynaddsubfx/src/DSP/Unison.h | 69 - plugins/zynaddsubfx/src/Effects/Alienwah.cpp | 281 -- plugins/zynaddsubfx/src/Effects/Alienwah.h | 85 - .../zynaddsubfx/src/Effects/CMakeLists.txt | 19 - plugins/zynaddsubfx/src/Effects/Chorus.cpp | 320 -- plugins/zynaddsubfx/src/Effects/Chorus.h | 114 - .../zynaddsubfx/src/Effects/Distorsion.cpp | 481 -- plugins/zynaddsubfx/src/Effects/Distorsion.h | 75 - .../zynaddsubfx/src/Effects/DynamicFilter.cpp | 352 -- .../zynaddsubfx/src/Effects/DynamicFilter.h | 72 - plugins/zynaddsubfx/src/Effects/EQ.cpp | 212 - plugins/zynaddsubfx/src/Effects/EQ.h | 58 - plugins/zynaddsubfx/src/Effects/Echo.cpp | 270 -- plugins/zynaddsubfx/src/Effects/Echo.h | 140 - plugins/zynaddsubfx/src/Effects/Effect.cpp | 36 - plugins/zynaddsubfx/src/Effects/Effect.h | 105 - plugins/zynaddsubfx/src/Effects/EffectLFO.cpp | 127 - plugins/zynaddsubfx/src/Effects/EffectLFO.h | 53 - plugins/zynaddsubfx/src/Effects/EffectMgr.cpp | 357 -- plugins/zynaddsubfx/src/Effects/EffectMgr.h | 102 - plugins/zynaddsubfx/src/Effects/Phaser.cpp | 473 -- plugins/zynaddsubfx/src/Effects/Phaser.h | 103 - plugins/zynaddsubfx/src/Effects/Reverb.cpp | 551 --- plugins/zynaddsubfx/src/Effects/Reverb.h | 135 - plugins/zynaddsubfx/src/Input/ALSAMidiIn.cpp | 118 - plugins/zynaddsubfx/src/Input/ALSAMidiIn.h | 51 - plugins/zynaddsubfx/src/Input/CMakeLists.txt | 19 - plugins/zynaddsubfx/src/Input/MidiIn.cpp | 96 - plugins/zynaddsubfx/src/Input/MidiIn.h | 52 - plugins/zynaddsubfx/src/Input/NULLMidiIn.cpp | 41 - plugins/zynaddsubfx/src/Input/NULLMidiIn.h | 50 - plugins/zynaddsubfx/src/Input/OSSMidiIn.cpp | 123 - plugins/zynaddsubfx/src/Input/OSSMidiIn.h | 50 - plugins/zynaddsubfx/src/Input/WINMidiIn.cpp | 94 - plugins/zynaddsubfx/src/Input/WINMidiIn.h | 34 - plugins/zynaddsubfx/src/Misc/Bank.cpp | 644 --- plugins/zynaddsubfx/src/Misc/Bank.h | 108 - plugins/zynaddsubfx/src/Misc/CMakeLists.txt | 24 - plugins/zynaddsubfx/src/Misc/Config.cpp | 409 -- plugins/zynaddsubfx/src/Misc/Config.h | 73 - plugins/zynaddsubfx/src/Misc/Control.h | 100 - plugins/zynaddsubfx/src/Misc/Dump.cpp | 124 - plugins/zynaddsubfx/src/Misc/Dump.h | 64 - plugins/zynaddsubfx/src/Misc/LASHClient.cpp | 104 - plugins/zynaddsubfx/src/Misc/LASHClient.h | 66 - plugins/zynaddsubfx/src/Misc/Master.cpp | 828 ---- plugins/zynaddsubfx/src/Misc/Master.h | 177 - plugins/zynaddsubfx/src/Misc/Microtonal.cpp | 687 --- plugins/zynaddsubfx/src/Misc/Microtonal.h | 135 - plugins/zynaddsubfx/src/Misc/Part.cpp | 1370 ------ plugins/zynaddsubfx/src/Misc/Part.h | 206 - plugins/zynaddsubfx/src/Misc/QtXmlWrapper.cpp | 550 --- plugins/zynaddsubfx/src/Misc/QtXmlWrapper.h | 125 - plugins/zynaddsubfx/src/Misc/Stereo.cpp | 39 - plugins/zynaddsubfx/src/Misc/Stereo.h | 42 - plugins/zynaddsubfx/src/Misc/Util.cpp | 130 - plugins/zynaddsubfx/src/Misc/Util.h | 84 - plugins/zynaddsubfx/src/Misc/XMLwrapper.cpp | 617 --- plugins/zynaddsubfx/src/Misc/XMLwrapper.h | 275 -- plugins/zynaddsubfx/src/Output/CMakeLists.txt | 33 - .../src/Output/DSSIaudiooutput.cpp | 685 --- .../zynaddsubfx/src/Output/DSSIaudiooutput.h | 111 - .../src/Output/JACK_RTaudiooutput.cpp | 229 - .../src/Output/JACKaudiooutput.cpp | 185 - .../zynaddsubfx/src/Output/JACKaudiooutput.h | 48 - .../zynaddsubfx/src/Output/OSSaudiooutput.cpp | 128 - .../zynaddsubfx/src/Output/OSSaudiooutput.h | 50 - .../zynaddsubfx/src/Output/PAaudiooutput.cpp | 80 - .../zynaddsubfx/src/Output/PAaudiooutput.h | 34 - plugins/zynaddsubfx/src/Output/Recorder.cpp | 113 - plugins/zynaddsubfx/src/Output/Recorder.h | 57 - .../zynaddsubfx/src/Output/VSTaudiooutput.cpp | 68 - .../zynaddsubfx/src/Output/VSTaudiooutput.h | 60 - .../zynaddsubfx/src/Output/WAVaudiooutput.cpp | 101 - .../zynaddsubfx/src/Output/WAVaudiooutput.h | 43 - .../src/Params/ADnoteParameters.cpp | 840 ---- .../zynaddsubfx/src/Params/ADnoteParameters.h | 307 -- plugins/zynaddsubfx/src/Params/CMakeLists.txt | 19 - plugins/zynaddsubfx/src/Params/Controller.cpp | 415 -- plugins/zynaddsubfx/src/Params/Controller.h | 221 - .../zynaddsubfx/src/Params/EnvelopeParams.cpp | 298 -- .../zynaddsubfx/src/Params/EnvelopeParams.h | 90 - .../zynaddsubfx/src/Params/FilterParams.cpp | 392 -- plugins/zynaddsubfx/src/Params/FilterParams.h | 103 - plugins/zynaddsubfx/src/Params/LFOParams.cpp | 105 - plugins/zynaddsubfx/src/Params/LFOParams.h | 72 - .../src/Params/PADnoteParameters.cpp | 909 ---- .../src/Params/PADnoteParameters.h | 183 - plugins/zynaddsubfx/src/Params/Presets.cpp | 122 - plugins/zynaddsubfx/src/Params/Presets.h | 57 - .../zynaddsubfx/src/Params/PresetsArray.cpp | 138 - plugins/zynaddsubfx/src/Params/PresetsArray.h | 60 - .../zynaddsubfx/src/Params/PresetsStore.cpp | 195 - plugins/zynaddsubfx/src/Params/PresetsStore.h | 67 - .../src/Params/SUBnoteParameters.cpp | 251 - .../src/Params/SUBnoteParameters.h | 104 - .../zynaddsubfx/src/Samples/CMakeLists.txt | 11 - plugins/zynaddsubfx/src/Samples/Sample.cpp | 193 - plugins/zynaddsubfx/src/Samples/Sample.h | 74 - plugins/zynaddsubfx/src/Seq/CMakeLists.txt | 11 - plugins/zynaddsubfx/src/Seq/MIDIEvents.cpp | 93 - plugins/zynaddsubfx/src/Seq/MIDIEvents.h | 69 - plugins/zynaddsubfx/src/Seq/MIDIFile.cpp | 424 -- plugins/zynaddsubfx/src/Seq/MIDIFile.h | 89 - plugins/zynaddsubfx/src/Seq/Sequencer.cpp | 189 - plugins/zynaddsubfx/src/Seq/Sequencer.h | 90 - plugins/zynaddsubfx/src/Synth/ADnote.cpp | 1987 -------- plugins/zynaddsubfx/src/Synth/ADnote.h | 349 -- plugins/zynaddsubfx/src/Synth/CMakeLists.txt | 16 - plugins/zynaddsubfx/src/Synth/Envelope.cpp | 199 - plugins/zynaddsubfx/src/Synth/Envelope.h | 65 - plugins/zynaddsubfx/src/Synth/LFO.cpp | 184 - plugins/zynaddsubfx/src/Synth/LFO.h | 59 - plugins/zynaddsubfx/src/Synth/OscilGen.cpp | 1475 ------ plugins/zynaddsubfx/src/Synth/OscilGen.h | 183 - plugins/zynaddsubfx/src/Synth/PADnote.cpp | 614 --- plugins/zynaddsubfx/src/Synth/PADnote.h | 143 - plugins/zynaddsubfx/src/Synth/Resonance.cpp | 282 -- plugins/zynaddsubfx/src/Synth/Resonance.h | 70 - plugins/zynaddsubfx/src/Synth/SUBnote.cpp | 790 ---- plugins/zynaddsubfx/src/Synth/SUBnote.h | 135 - plugins/zynaddsubfx/src/UI/ADnoteUI.cc | 2202 --------- plugins/zynaddsubfx/src/UI/ADnoteUI.fl | 1161 ----- plugins/zynaddsubfx/src/UI/ADnoteUI.h | 387 -- plugins/zynaddsubfx/src/UI/BankUI.cc | 421 -- plugins/zynaddsubfx/src/UI/BankUI.fl | 355 -- plugins/zynaddsubfx/src/UI/BankUI.h | 101 - plugins/zynaddsubfx/src/UI/CMakeLists.txt | 32 - plugins/zynaddsubfx/src/UI/ConfigUI.cc | 562 --- plugins/zynaddsubfx/src/UI/ConfigUI.fl | 451 -- plugins/zynaddsubfx/src/UI/ConfigUI.h | 120 - plugins/zynaddsubfx/src/UI/EffUI.cc | 4113 ----------------- plugins/zynaddsubfx/src/UI/EffUI.fl | 2361 ---------- plugins/zynaddsubfx/src/UI/EffUI.h | 820 ---- plugins/zynaddsubfx/src/UI/EnvelopeUI.cc | 1525 ------ plugins/zynaddsubfx/src/UI/EnvelopeUI.fl | 851 ---- plugins/zynaddsubfx/src/UI/EnvelopeUI.h | 280 -- plugins/zynaddsubfx/src/UI/FilterUI.cc | 987 ---- plugins/zynaddsubfx/src/UI/FilterUI.fl | 624 --- plugins/zynaddsubfx/src/UI/FilterUI.h | 198 - plugins/zynaddsubfx/src/UI/LFOUI.cc | 289 -- plugins/zynaddsubfx/src/UI/LFOUI.fl | 176 - plugins/zynaddsubfx/src/UI/LFOUI.h | 83 - plugins/zynaddsubfx/src/UI/MasterUI.cc | 2504 ---------- plugins/zynaddsubfx/src/UI/MasterUI.fl | 1815 -------- plugins/zynaddsubfx/src/UI/MasterUI.h | 448 -- plugins/zynaddsubfx/src/UI/MicrotonalUI.cc | 463 -- plugins/zynaddsubfx/src/UI/MicrotonalUI.fl | 270 -- plugins/zynaddsubfx/src/UI/MicrotonalUI.h | 112 - plugins/zynaddsubfx/src/UI/OscilGenUI.cc | 1410 ------ plugins/zynaddsubfx/src/UI/OscilGenUI.fl | 1133 ----- plugins/zynaddsubfx/src/UI/OscilGenUI.h | 281 -- plugins/zynaddsubfx/src/UI/PADnoteUI.cc | 1504 ------ plugins/zynaddsubfx/src/UI/PADnoteUI.fl | 1101 ----- plugins/zynaddsubfx/src/UI/PADnoteUI.h | 305 -- plugins/zynaddsubfx/src/UI/PartUI.cc | 1880 -------- plugins/zynaddsubfx/src/UI/PartUI.fl | 1125 ----- plugins/zynaddsubfx/src/UI/PartUI.h | 338 -- plugins/zynaddsubfx/src/UI/PresetsUI.cc | 274 -- plugins/zynaddsubfx/src/UI/PresetsUI.fl | 208 - plugins/zynaddsubfx/src/UI/PresetsUI.h | 84 - plugins/zynaddsubfx/src/UI/ResonanceUI.cc | 553 --- plugins/zynaddsubfx/src/UI/ResonanceUI.fl | 392 -- plugins/zynaddsubfx/src/UI/ResonanceUI.h | 120 - plugins/zynaddsubfx/src/UI/SUBnoteUI.cc | 735 --- plugins/zynaddsubfx/src/UI/SUBnoteUI.fl | 449 -- plugins/zynaddsubfx/src/UI/SUBnoteUI.h | 179 - plugins/zynaddsubfx/src/UI/SeqUI.cc | 98 - plugins/zynaddsubfx/src/UI/SeqUI.fl | 73 - plugins/zynaddsubfx/src/UI/SeqUI.h | 39 - plugins/zynaddsubfx/src/UI/VirKeyboard.cc | 499 -- plugins/zynaddsubfx/src/UI/VirKeyboard.fl | 424 -- plugins/zynaddsubfx/src/UI/VirKeyboard.h | 90 - plugins/zynaddsubfx/src/UI/WidgetPDial.cc | 215 - plugins/zynaddsubfx/src/UI/WidgetPDial.fl | 253 - plugins/zynaddsubfx/src/UI/WidgetPDial.h | 46 - plugins/zynaddsubfx/src/UI/filechooser.h | 27 - plugins/zynaddsubfx/src/globals.h | 235 - src/core/midi/MidiPort.cpp | 2 +- 198 files changed, 128 insertions(+), 66605 deletions(-) delete mode 100644 plugins/zynaddsubfx/src/DSP/AnalogFilter.cpp delete mode 100644 plugins/zynaddsubfx/src/DSP/AnalogFilter.h delete mode 100644 plugins/zynaddsubfx/src/DSP/CMakeLists.txt delete mode 100644 plugins/zynaddsubfx/src/DSP/FFTwrapper.cpp delete mode 100644 plugins/zynaddsubfx/src/DSP/FFTwrapper.h delete mode 100644 plugins/zynaddsubfx/src/DSP/Filter.cpp delete mode 100644 plugins/zynaddsubfx/src/DSP/Filter.h delete mode 100644 plugins/zynaddsubfx/src/DSP/Filter_.h delete mode 100644 plugins/zynaddsubfx/src/DSP/FormantFilter.cpp delete mode 100644 plugins/zynaddsubfx/src/DSP/FormantFilter.h delete mode 100644 plugins/zynaddsubfx/src/DSP/SVFilter.cpp delete mode 100644 plugins/zynaddsubfx/src/DSP/SVFilter.h delete mode 100644 plugins/zynaddsubfx/src/DSP/Unison.cpp delete mode 100644 plugins/zynaddsubfx/src/DSP/Unison.h delete mode 100644 plugins/zynaddsubfx/src/Effects/Alienwah.cpp delete mode 100644 plugins/zynaddsubfx/src/Effects/Alienwah.h delete mode 100644 plugins/zynaddsubfx/src/Effects/CMakeLists.txt delete mode 100644 plugins/zynaddsubfx/src/Effects/Chorus.cpp delete mode 100644 plugins/zynaddsubfx/src/Effects/Chorus.h delete mode 100644 plugins/zynaddsubfx/src/Effects/Distorsion.cpp delete mode 100644 plugins/zynaddsubfx/src/Effects/Distorsion.h delete mode 100644 plugins/zynaddsubfx/src/Effects/DynamicFilter.cpp delete mode 100644 plugins/zynaddsubfx/src/Effects/DynamicFilter.h delete mode 100644 plugins/zynaddsubfx/src/Effects/EQ.cpp delete mode 100644 plugins/zynaddsubfx/src/Effects/EQ.h delete mode 100644 plugins/zynaddsubfx/src/Effects/Echo.cpp delete mode 100644 plugins/zynaddsubfx/src/Effects/Echo.h delete mode 100644 plugins/zynaddsubfx/src/Effects/Effect.cpp delete mode 100644 plugins/zynaddsubfx/src/Effects/Effect.h delete mode 100644 plugins/zynaddsubfx/src/Effects/EffectLFO.cpp delete mode 100644 plugins/zynaddsubfx/src/Effects/EffectLFO.h delete mode 100644 plugins/zynaddsubfx/src/Effects/EffectMgr.cpp delete mode 100644 plugins/zynaddsubfx/src/Effects/EffectMgr.h delete mode 100644 plugins/zynaddsubfx/src/Effects/Phaser.cpp delete mode 100644 plugins/zynaddsubfx/src/Effects/Phaser.h delete mode 100644 plugins/zynaddsubfx/src/Effects/Reverb.cpp delete mode 100644 plugins/zynaddsubfx/src/Effects/Reverb.h delete mode 100644 plugins/zynaddsubfx/src/Input/ALSAMidiIn.cpp delete mode 100644 plugins/zynaddsubfx/src/Input/ALSAMidiIn.h delete mode 100644 plugins/zynaddsubfx/src/Input/CMakeLists.txt delete mode 100644 plugins/zynaddsubfx/src/Input/MidiIn.cpp delete mode 100644 plugins/zynaddsubfx/src/Input/MidiIn.h delete mode 100644 plugins/zynaddsubfx/src/Input/NULLMidiIn.cpp delete mode 100644 plugins/zynaddsubfx/src/Input/NULLMidiIn.h delete mode 100644 plugins/zynaddsubfx/src/Input/OSSMidiIn.cpp delete mode 100644 plugins/zynaddsubfx/src/Input/OSSMidiIn.h delete mode 100644 plugins/zynaddsubfx/src/Input/WINMidiIn.cpp delete mode 100644 plugins/zynaddsubfx/src/Input/WINMidiIn.h delete mode 100644 plugins/zynaddsubfx/src/Misc/Bank.cpp delete mode 100644 plugins/zynaddsubfx/src/Misc/Bank.h delete mode 100644 plugins/zynaddsubfx/src/Misc/CMakeLists.txt delete mode 100644 plugins/zynaddsubfx/src/Misc/Config.cpp delete mode 100644 plugins/zynaddsubfx/src/Misc/Config.h delete mode 100644 plugins/zynaddsubfx/src/Misc/Control.h delete mode 100644 plugins/zynaddsubfx/src/Misc/Dump.cpp delete mode 100644 plugins/zynaddsubfx/src/Misc/Dump.h delete mode 100644 plugins/zynaddsubfx/src/Misc/LASHClient.cpp delete mode 100644 plugins/zynaddsubfx/src/Misc/LASHClient.h delete mode 100644 plugins/zynaddsubfx/src/Misc/Master.cpp delete mode 100644 plugins/zynaddsubfx/src/Misc/Master.h delete mode 100644 plugins/zynaddsubfx/src/Misc/Microtonal.cpp delete mode 100644 plugins/zynaddsubfx/src/Misc/Microtonal.h delete mode 100644 plugins/zynaddsubfx/src/Misc/Part.cpp delete mode 100644 plugins/zynaddsubfx/src/Misc/Part.h delete mode 100644 plugins/zynaddsubfx/src/Misc/QtXmlWrapper.cpp delete mode 100644 plugins/zynaddsubfx/src/Misc/QtXmlWrapper.h delete mode 100644 plugins/zynaddsubfx/src/Misc/Stereo.cpp delete mode 100644 plugins/zynaddsubfx/src/Misc/Stereo.h delete mode 100644 plugins/zynaddsubfx/src/Misc/Util.cpp delete mode 100644 plugins/zynaddsubfx/src/Misc/Util.h delete mode 100644 plugins/zynaddsubfx/src/Misc/XMLwrapper.cpp delete mode 100644 plugins/zynaddsubfx/src/Misc/XMLwrapper.h delete mode 100644 plugins/zynaddsubfx/src/Output/CMakeLists.txt delete mode 100644 plugins/zynaddsubfx/src/Output/DSSIaudiooutput.cpp delete mode 100644 plugins/zynaddsubfx/src/Output/DSSIaudiooutput.h delete mode 100644 plugins/zynaddsubfx/src/Output/JACK_RTaudiooutput.cpp delete mode 100644 plugins/zynaddsubfx/src/Output/JACKaudiooutput.cpp delete mode 100644 plugins/zynaddsubfx/src/Output/JACKaudiooutput.h delete mode 100644 plugins/zynaddsubfx/src/Output/OSSaudiooutput.cpp delete mode 100644 plugins/zynaddsubfx/src/Output/OSSaudiooutput.h delete mode 100644 plugins/zynaddsubfx/src/Output/PAaudiooutput.cpp delete mode 100644 plugins/zynaddsubfx/src/Output/PAaudiooutput.h delete mode 100644 plugins/zynaddsubfx/src/Output/Recorder.cpp delete mode 100644 plugins/zynaddsubfx/src/Output/Recorder.h delete mode 100644 plugins/zynaddsubfx/src/Output/VSTaudiooutput.cpp delete mode 100644 plugins/zynaddsubfx/src/Output/VSTaudiooutput.h delete mode 100644 plugins/zynaddsubfx/src/Output/WAVaudiooutput.cpp delete mode 100644 plugins/zynaddsubfx/src/Output/WAVaudiooutput.h delete mode 100644 plugins/zynaddsubfx/src/Params/ADnoteParameters.cpp delete mode 100644 plugins/zynaddsubfx/src/Params/ADnoteParameters.h delete mode 100644 plugins/zynaddsubfx/src/Params/CMakeLists.txt delete mode 100644 plugins/zynaddsubfx/src/Params/Controller.cpp delete mode 100644 plugins/zynaddsubfx/src/Params/Controller.h delete mode 100644 plugins/zynaddsubfx/src/Params/EnvelopeParams.cpp delete mode 100644 plugins/zynaddsubfx/src/Params/EnvelopeParams.h delete mode 100644 plugins/zynaddsubfx/src/Params/FilterParams.cpp delete mode 100644 plugins/zynaddsubfx/src/Params/FilterParams.h delete mode 100644 plugins/zynaddsubfx/src/Params/LFOParams.cpp delete mode 100644 plugins/zynaddsubfx/src/Params/LFOParams.h delete mode 100644 plugins/zynaddsubfx/src/Params/PADnoteParameters.cpp delete mode 100644 plugins/zynaddsubfx/src/Params/PADnoteParameters.h delete mode 100644 plugins/zynaddsubfx/src/Params/Presets.cpp delete mode 100644 plugins/zynaddsubfx/src/Params/Presets.h delete mode 100644 plugins/zynaddsubfx/src/Params/PresetsArray.cpp delete mode 100644 plugins/zynaddsubfx/src/Params/PresetsArray.h delete mode 100644 plugins/zynaddsubfx/src/Params/PresetsStore.cpp delete mode 100644 plugins/zynaddsubfx/src/Params/PresetsStore.h delete mode 100644 plugins/zynaddsubfx/src/Params/SUBnoteParameters.cpp delete mode 100644 plugins/zynaddsubfx/src/Params/SUBnoteParameters.h delete mode 100644 plugins/zynaddsubfx/src/Samples/CMakeLists.txt delete mode 100644 plugins/zynaddsubfx/src/Samples/Sample.cpp delete mode 100644 plugins/zynaddsubfx/src/Samples/Sample.h delete mode 100644 plugins/zynaddsubfx/src/Seq/CMakeLists.txt delete mode 100644 plugins/zynaddsubfx/src/Seq/MIDIEvents.cpp delete mode 100644 plugins/zynaddsubfx/src/Seq/MIDIEvents.h delete mode 100644 plugins/zynaddsubfx/src/Seq/MIDIFile.cpp delete mode 100644 plugins/zynaddsubfx/src/Seq/MIDIFile.h delete mode 100644 plugins/zynaddsubfx/src/Seq/Sequencer.cpp delete mode 100644 plugins/zynaddsubfx/src/Seq/Sequencer.h delete mode 100644 plugins/zynaddsubfx/src/Synth/ADnote.cpp delete mode 100644 plugins/zynaddsubfx/src/Synth/ADnote.h delete mode 100644 plugins/zynaddsubfx/src/Synth/CMakeLists.txt delete mode 100644 plugins/zynaddsubfx/src/Synth/Envelope.cpp delete mode 100644 plugins/zynaddsubfx/src/Synth/Envelope.h delete mode 100644 plugins/zynaddsubfx/src/Synth/LFO.cpp delete mode 100644 plugins/zynaddsubfx/src/Synth/LFO.h delete mode 100644 plugins/zynaddsubfx/src/Synth/OscilGen.cpp delete mode 100644 plugins/zynaddsubfx/src/Synth/OscilGen.h delete mode 100644 plugins/zynaddsubfx/src/Synth/PADnote.cpp delete mode 100644 plugins/zynaddsubfx/src/Synth/PADnote.h delete mode 100644 plugins/zynaddsubfx/src/Synth/Resonance.cpp delete mode 100644 plugins/zynaddsubfx/src/Synth/Resonance.h delete mode 100644 plugins/zynaddsubfx/src/Synth/SUBnote.cpp delete mode 100644 plugins/zynaddsubfx/src/Synth/SUBnote.h delete mode 100644 plugins/zynaddsubfx/src/UI/ADnoteUI.cc delete mode 100644 plugins/zynaddsubfx/src/UI/ADnoteUI.fl delete mode 100644 plugins/zynaddsubfx/src/UI/ADnoteUI.h delete mode 100644 plugins/zynaddsubfx/src/UI/BankUI.cc delete mode 100644 plugins/zynaddsubfx/src/UI/BankUI.fl delete mode 100644 plugins/zynaddsubfx/src/UI/BankUI.h delete mode 100644 plugins/zynaddsubfx/src/UI/CMakeLists.txt delete mode 100644 plugins/zynaddsubfx/src/UI/ConfigUI.cc delete mode 100644 plugins/zynaddsubfx/src/UI/ConfigUI.fl delete mode 100644 plugins/zynaddsubfx/src/UI/ConfigUI.h delete mode 100644 plugins/zynaddsubfx/src/UI/EffUI.cc delete mode 100644 plugins/zynaddsubfx/src/UI/EffUI.fl delete mode 100644 plugins/zynaddsubfx/src/UI/EffUI.h delete mode 100644 plugins/zynaddsubfx/src/UI/EnvelopeUI.cc delete mode 100644 plugins/zynaddsubfx/src/UI/EnvelopeUI.fl delete mode 100644 plugins/zynaddsubfx/src/UI/EnvelopeUI.h delete mode 100644 plugins/zynaddsubfx/src/UI/FilterUI.cc delete mode 100644 plugins/zynaddsubfx/src/UI/FilterUI.fl delete mode 100644 plugins/zynaddsubfx/src/UI/FilterUI.h delete mode 100644 plugins/zynaddsubfx/src/UI/LFOUI.cc delete mode 100644 plugins/zynaddsubfx/src/UI/LFOUI.fl delete mode 100644 plugins/zynaddsubfx/src/UI/LFOUI.h delete mode 100644 plugins/zynaddsubfx/src/UI/MasterUI.cc delete mode 100644 plugins/zynaddsubfx/src/UI/MasterUI.fl delete mode 100644 plugins/zynaddsubfx/src/UI/MasterUI.h delete mode 100644 plugins/zynaddsubfx/src/UI/MicrotonalUI.cc delete mode 100644 plugins/zynaddsubfx/src/UI/MicrotonalUI.fl delete mode 100644 plugins/zynaddsubfx/src/UI/MicrotonalUI.h delete mode 100644 plugins/zynaddsubfx/src/UI/OscilGenUI.cc delete mode 100644 plugins/zynaddsubfx/src/UI/OscilGenUI.fl delete mode 100644 plugins/zynaddsubfx/src/UI/OscilGenUI.h delete mode 100644 plugins/zynaddsubfx/src/UI/PADnoteUI.cc delete mode 100644 plugins/zynaddsubfx/src/UI/PADnoteUI.fl delete mode 100644 plugins/zynaddsubfx/src/UI/PADnoteUI.h delete mode 100644 plugins/zynaddsubfx/src/UI/PartUI.cc delete mode 100644 plugins/zynaddsubfx/src/UI/PartUI.fl delete mode 100644 plugins/zynaddsubfx/src/UI/PartUI.h delete mode 100644 plugins/zynaddsubfx/src/UI/PresetsUI.cc delete mode 100644 plugins/zynaddsubfx/src/UI/PresetsUI.fl delete mode 100644 plugins/zynaddsubfx/src/UI/PresetsUI.h delete mode 100644 plugins/zynaddsubfx/src/UI/ResonanceUI.cc delete mode 100644 plugins/zynaddsubfx/src/UI/ResonanceUI.fl delete mode 100644 plugins/zynaddsubfx/src/UI/ResonanceUI.h delete mode 100644 plugins/zynaddsubfx/src/UI/SUBnoteUI.cc delete mode 100644 plugins/zynaddsubfx/src/UI/SUBnoteUI.fl delete mode 100644 plugins/zynaddsubfx/src/UI/SUBnoteUI.h delete mode 100644 plugins/zynaddsubfx/src/UI/SeqUI.cc delete mode 100644 plugins/zynaddsubfx/src/UI/SeqUI.fl delete mode 100644 plugins/zynaddsubfx/src/UI/SeqUI.h delete mode 100644 plugins/zynaddsubfx/src/UI/VirKeyboard.cc delete mode 100644 plugins/zynaddsubfx/src/UI/VirKeyboard.fl delete mode 100644 plugins/zynaddsubfx/src/UI/VirKeyboard.h delete mode 100644 plugins/zynaddsubfx/src/UI/WidgetPDial.cc delete mode 100644 plugins/zynaddsubfx/src/UI/WidgetPDial.fl delete mode 100644 plugins/zynaddsubfx/src/UI/WidgetPDial.h delete mode 100644 plugins/zynaddsubfx/src/UI/filechooser.h delete mode 100644 plugins/zynaddsubfx/src/globals.h diff --git a/include/Midi.h b/include/Midi.h index 1b6b69383..2ff24d77c 100644 --- a/include/Midi.h +++ b/include/Midi.h @@ -128,7 +128,7 @@ const int MidiControllerCount = 128; const int MidiProgramCount = 128; const int MidiMaxVelocity = 127; const int MidiMaxControllerValue = 127; -const int MidiMaxNote = 127; +const int MidiMaxKey = 127; const int MidiMaxPanning = 127; const int MidiMinPanning = -128; diff --git a/plugins/zynaddsubfx/CMakeLists.txt b/plugins/zynaddsubfx/CMakeLists.txt index 773632b3f..ea2ed51af 100644 --- a/plugins/zynaddsubfx/CMakeLists.txt +++ b/plugins/zynaddsubfx/CMakeLists.txt @@ -1,26 +1,5 @@ INCLUDE(BuildPlugin) -SET(ZYN_SRC_GUI - "${CMAKE_CURRENT_SOURCE_DIR}/src/UI/MasterUI.cc" - "${CMAKE_CURRENT_SOURCE_DIR}/src/UI/VirKeyboard.cc" - "${CMAKE_CURRENT_SOURCE_DIR}/src/UI/ConfigUI.cc" - "${CMAKE_CURRENT_SOURCE_DIR}/src/UI/OscilGenUI.cc" - "${CMAKE_CURRENT_SOURCE_DIR}/src/UI/WidgetPDial.cc" - "${CMAKE_CURRENT_SOURCE_DIR}/src/UI/ResonanceUI.cc" - "${CMAKE_CURRENT_SOURCE_DIR}/src/UI/MicrotonalUI.cc" - "${CMAKE_CURRENT_SOURCE_DIR}/src/UI/ADnoteUI.cc" - "${CMAKE_CURRENT_SOURCE_DIR}/src/UI/PresetsUI.cc" - "${CMAKE_CURRENT_SOURCE_DIR}/src/UI/EffUI.cc" - "${CMAKE_CURRENT_SOURCE_DIR}/src/UI/FilterUI.cc" - "${CMAKE_CURRENT_SOURCE_DIR}/src/UI/PartUI.cc" - "${CMAKE_CURRENT_SOURCE_DIR}/src/UI/EnvelopeUI.cc" - "${CMAKE_CURRENT_SOURCE_DIR}/src/UI/LFOUI.cc" - "${CMAKE_CURRENT_SOURCE_DIR}/src/UI/SeqUI.cc" - "${CMAKE_CURRENT_SOURCE_DIR}/src/UI/PADnoteUI.cc" - "${CMAKE_CURRENT_SOURCE_DIR}/src/UI/SUBnoteUI.cc" - "${CMAKE_CURRENT_SOURCE_DIR}/src/UI/BankUI.cc" -) - # definitions for ZynAddSubFX IF(LMMS_BUILD_LINUX OR LMMS_BUILD_APPLE) @@ -48,42 +27,80 @@ ENDIF(LMMS_BUILD_WIN32) SET(FLTK_SKIP_OPENGL TRUE) SET(FLTK_SKIP_FORMS TRUE) SET(FLTK_SKIP_IMAGES TRUE) -SET(FLTK_SKIP_FLUID TRUE) +SET(FLTK_SKIP_MATH TRUE) +IF(MINGW_PREFIX) + SET(FLTK_SKIP_FLUID TRUE) +ENDIF() FIND_PACKAGE(FLTK REQUIRED) +IF(MINGW_PREFIX) + SET(FLTK_FLUID_EXECUTABLE "${MINGW_PREFIX}/bin/fluid") +ENDIF() + INCLUDE_DIRECTORIES("${FLTK_INCLUDE_DIR}" "${CMAKE_CURRENT_SOURCE_DIR}" ${FFTW3F_INCLUDE_DIRS} "${CMAKE_CURRENT_BINARY_DIR}" "${CMAKE_BINARY_DIR}") -set(ZASF_CORE_LIBS - zynaddsubfx_input - zynaddsubfx_output - zynaddsubfx_misc - zynaddsubfx_synth - zynaddsubfx_seq - zynaddsubfx_effect - zynaddsubfx_params - zynaddsubfx_dsp - zynaddsubfx_samples + +include_directories( ${CMAKE_CURRENT_SOURCE_DIR}/zynaddsubfx/src/UI) + +add_subdirectory(zynaddsubfx/src/Nio) +add_subdirectory(zynaddsubfx/src/UI) + +SET(zynaddsubfx_core_SRCS + zynaddsubfx/src/DSP/AnalogFilter.cpp + zynaddsubfx/src/DSP/FFTwrapper.cpp + zynaddsubfx/src/DSP/Filter.cpp + zynaddsubfx/src/DSP/FormantFilter.cpp + zynaddsubfx/src/DSP/SVFilter.cpp + zynaddsubfx/src/DSP/Unison.cpp + zynaddsubfx/src/Effects/Alienwah.cpp + zynaddsubfx/src/Effects/Chorus.cpp + zynaddsubfx/src/Effects/Distorsion.cpp + zynaddsubfx/src/Effects/DynamicFilter.cpp + zynaddsubfx/src/Effects/Echo.cpp + zynaddsubfx/src/Effects/Effect.cpp + zynaddsubfx/src/Effects/EffectLFO.cpp + zynaddsubfx/src/Effects/EffectMgr.cpp + zynaddsubfx/src/Effects/EQ.cpp + zynaddsubfx/src/Effects/Phaser.cpp + zynaddsubfx/src/Effects/Reverb.cpp + zynaddsubfx/src/Misc/Bank.cpp + zynaddsubfx/src/Misc/Config.cpp + zynaddsubfx/src/Misc/Dump.cpp + zynaddsubfx/src/Misc/Master.cpp + zynaddsubfx/src/Misc/Microtonal.cpp + zynaddsubfx/src/Misc/Part.cpp + zynaddsubfx/src/Misc/Util.cpp + zynaddsubfx/src/Misc/QtXmlWrapper.cpp + zynaddsubfx/src/Misc/Recorder.cpp + zynaddsubfx/src/Misc/WavFile.cpp + zynaddsubfx/src/Misc/WaveShapeSmps.cpp + zynaddsubfx/src/Params/ADnoteParameters.cpp + zynaddsubfx/src/Params/Controller.cpp + zynaddsubfx/src/Params/EnvelopeParams.cpp + zynaddsubfx/src/Params/FilterParams.cpp + zynaddsubfx/src/Params/LFOParams.cpp + zynaddsubfx/src/Params/PADnoteParameters.cpp + zynaddsubfx/src/Params/Presets.cpp + zynaddsubfx/src/Params/PresetsArray.cpp + zynaddsubfx/src/Params/PresetsStore.cpp + zynaddsubfx/src/Params/SUBnoteParameters.cpp + zynaddsubfx/src/Synth/SynthNote.cpp + zynaddsubfx/src/Synth/ADnote.cpp + zynaddsubfx/src/Synth/Envelope.cpp + zynaddsubfx/src/Synth/LFO.cpp + zynaddsubfx/src/Synth/OscilGen.cpp + zynaddsubfx/src/Synth/PADnote.cpp + zynaddsubfx/src/Synth/Resonance.cpp + zynaddsubfx/src/Synth/SUBnote.cpp ) -macro(unit_test NAME CXX_FILE FILES) -endmacro(unit_test) -add_subdirectory(src/Misc) -add_subdirectory(src/Input) -add_subdirectory(src/Synth) -add_subdirectory(src/Output) -add_subdirectory(src/Seq) -add_subdirectory(src/Effects) -add_subdirectory(src/Params) -add_subdirectory(src/DSP) -add_subdirectory(src/Samples) - -ADD_LIBRARY(ZynAddSubFxCore SHARED LocalZynAddSubFx.cpp) -TARGET_LINK_LIBRARIES(ZynAddSubFxCore ${ZASF_CORE_LIBS} ${FFTW3F_LIBRARIES} ${QT_LIBRARIES} -lz -lpthread) +ADD_LIBRARY(ZynAddSubFxCore SHARED LocalZynAddSubFx.cpp ${zynaddsubfx_core_SRCS}) +TARGET_LINK_LIBRARIES(ZynAddSubFxCore zynaddsubfx_nio ${FFTW3F_LIBRARIES} ${QT_LIBRARIES} -lz -lpthread) IF(LMMS_BUILD_WIN32) TARGET_LINK_LIBRARIES(ZynAddSubFxCore -lws2_32) INSTALL(TARGETS ZynAddSubFxCore RUNTIME DESTINATION "${PLUGIN_DIR}") @@ -106,12 +123,11 @@ ENDIF(WIN32) SET(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/${PLUGIN_DIR}") SET(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE) -ADD_EXECUTABLE(RemoteZynAddSubFx RemoteZynAddSubFx.cpp ${ZYN_SRC_GUI} "${WINRC}") +ADD_EXECUTABLE(RemoteZynAddSubFx RemoteZynAddSubFx.cpp "${WINRC}") INSTALL(TARGETS RemoteZynAddSubFx RUNTIME DESTINATION "${PLUGIN_DIR}") -TARGET_LINK_LIBRARIES(RemoteZynAddSubFx ${FLTK_LIBRARIES} -lpthread "-L\"${CMAKE_CURRENT_BINARY_DIR}\"" -lZynAddSubFxCore ) -ADD_DEPENDENCIES(RemoteZynAddSubFx ZynAddSubFxCore) +TARGET_LINK_LIBRARIES(RemoteZynAddSubFx zynaddsubfx_gui ZynAddSubFxCore ${FLTK_LIBRARIES} -lpthread ) -# link system libraries when on win32 +# link Qt libraries when on win32 IF(LMMS_BUILD_WIN32) TARGET_LINK_LIBRARIES(RemoteZynAddSubFx ${QT_LIBRARIES}) ENDIF(LMMS_BUILD_WIN32) diff --git a/plugins/zynaddsubfx/LocalZynAddSubFx.cpp b/plugins/zynaddsubfx/LocalZynAddSubFx.cpp index 6705bb33d..5f053ff48 100644 --- a/plugins/zynaddsubfx/LocalZynAddSubFx.cpp +++ b/plugins/zynaddsubfx/LocalZynAddSubFx.cpp @@ -24,19 +24,25 @@ #include +#include "zynaddsubfx/src/Misc/Util.h" #include #include "LocalZynAddSubFx.h" -#include "src/Input/NULLMidiIn.h" -#include "src/Misc/Master.h" -#include "src/Misc/Dump.h" +#include "zynaddsubfx/src/Nio/NulEngine.h" +#include "zynaddsubfx/src/Misc/Master.h" +#include "zynaddsubfx/src/Misc/Part.h" +#include "zynaddsubfx/src/Misc/Dump.h" +SYNTH_T* synth = NULL; + int LocalZynAddSubFx::s_instanceCount = 0; -LocalZynAddSubFx::LocalZynAddSubFx() +LocalZynAddSubFx::LocalZynAddSubFx() : + m_master( NULL ), + m_ioEngine( new NulEngine ) { for( int i = 0; i < NumKeys; ++i ) { @@ -53,15 +59,19 @@ LocalZynAddSubFx::LocalZynAddSubFx() initConfig(); - OSCIL_SIZE = config.cfg.OscilSize; + synth = new SYNTH_T; + synth->oscilsize = config.cfg.OscilSize; + synth->alias(); srand( time( NULL ) ); - denormalkillbuf = new REALTYPE[SOUND_BUFFER_SIZE]; - for( int i = 0; i < SOUND_BUFFER_SIZE; ++i ) + + denormalkillbuf = new float[synth->buffersize]; + for( int i = 0; i < synth->buffersize; ++i ) { denormalkillbuf[i] = (RND-0.5)*1e-16; } } + ++s_instanceCount; m_master = new Master(); @@ -94,17 +104,19 @@ void LocalZynAddSubFx::initConfig() -void LocalZynAddSubFx::setSampleRate( int _sampleRate ) +void LocalZynAddSubFx::setSampleRate( int sampleRate ) { - SAMPLE_RATE = _sampleRate; + synth->samplerate = sampleRate; + synth->alias(); } -void LocalZynAddSubFx::setBufferSize( int _bufferSize ) +void LocalZynAddSubFx::setBufferSize( int bufferSize ) { - SOUND_BUFFER_SIZE = _bufferSize; + synth->buffersize = bufferSize; + synth->alias(); } @@ -160,14 +172,12 @@ void LocalZynAddSubFx::setPresetDir( const std::string & _dir ) m_presetsDir = _dir; for( int i = 0; i < MAX_BANK_ROOT_DIRS; ++i ) { - if( config.cfg.bankRootDirList[i] == NULL ) + if( config.cfg.bankRootDirList[i].empty() ) { - config.cfg.bankRootDirList[i] = new char[MAX_STRING_SIZE]; - strcpy( config.cfg.bankRootDirList[i], m_presetsDir.c_str() ); + config.cfg.bankRootDirList[i] = m_presetsDir; break; } - else if( strcmp( config.cfg.bankRootDirList[i], - m_presetsDir.c_str() ) == 0 ) + else if( config.cfg.bankRootDirList[i] == m_presetsDir ) { break; } @@ -192,41 +202,38 @@ void LocalZynAddSubFx::setLmmsWorkingDir( const std::string & _dir ) void LocalZynAddSubFx::processMidiEvent( const MidiEvent& event ) { - // all functions are called while m_master->mutex is held - static NULLMidiIn midiIn; - switch( event.type() ) { case MidiNoteOn: if( event.velocity() > 0 ) { - if( event.key() <= 0 || event.key() >= 128 ) + if( event.key() < 0 || event.key() > MidiMaxKey ) { break; } if( m_runningNotes[event.key()] > 0 ) { - m_master->NoteOff( event.channel(), event.key() ); + m_master->noteOff( event.channel(), event.key() ); } ++m_runningNotes[event.key()]; - m_master->NoteOn( event.channel(), event.key(), event.velocity() ); + m_master->noteOn( event.channel(), event.key(), event.velocity() ); break; } case MidiNoteOff: - if( event.key() <= 0 || event.key() >= 128 ) + if( event.key() < 0 || event.key() > MidiMaxKey ) { break; } if( --m_runningNotes[event.key()] <= 0 ) { - m_master->NoteOff( event.channel(), event.key() ); + m_master->noteOff( event.channel(), event.key() ); } break; case MidiPitchBend: - m_master->SetController( event.channel(), C_pitchwheel, event.pitchBend()-8192 ); + m_master->setController( event.channel(), C_pitchwheel, event.pitchBend()-8192 ); break; case MidiControlChange: - m_master->SetController( event.channel(), midiIn.getcontroller( event.controllerNumber() ), event.controllerValue() ); + m_master->setController( event.channel(), event.controllerNumber(), event.controllerValue() ); break; default: break; @@ -238,12 +245,13 @@ void LocalZynAddSubFx::processMidiEvent( const MidiEvent& event ) void LocalZynAddSubFx::processAudio( sampleFrame * _out ) { - REALTYPE outputl[SOUND_BUFFER_SIZE]; - REALTYPE outputr[SOUND_BUFFER_SIZE]; + float outputl[synth->buffersize]; + float outputr[synth->buffersize]; m_master->AudioOut( outputl, outputr ); - for( int f = 0; f < SOUND_BUFFER_SIZE; ++f ) + // TODO: move to MixHelpers + for( int f = 0; f < synth->buffersize; ++f ) { _out[f][0] = outputl[f]; _out[f][1] = outputr[f]; diff --git a/plugins/zynaddsubfx/LocalZynAddSubFx.h b/plugins/zynaddsubfx/LocalZynAddSubFx.h index 3aeab8ba5..f35cb12a0 100644 --- a/plugins/zynaddsubfx/LocalZynAddSubFx.h +++ b/plugins/zynaddsubfx/LocalZynAddSubFx.h @@ -29,6 +29,7 @@ #include "note.h" class Master; +class NulEngine; class LocalZynAddSubFx { @@ -66,6 +67,7 @@ protected: int m_runningNotes[NumKeys]; Master * m_master; + NulEngine* m_ioEngine; } ; diff --git a/plugins/zynaddsubfx/RemoteZynAddSubFx.cpp b/plugins/zynaddsubfx/RemoteZynAddSubFx.cpp index 5e25de9fa..a57e69489 100644 --- a/plugins/zynaddsubfx/RemoteZynAddSubFx.cpp +++ b/plugins/zynaddsubfx/RemoteZynAddSubFx.cpp @@ -35,7 +35,7 @@ #include "RemoteZynAddSubFx.h" #include "LocalZynAddSubFx.h" -#include "src/UI/MasterUI.h" +#include "zynaddsubfx/src/UI/MasterUI.h" #include @@ -282,3 +282,22 @@ int main( int _argc, char * * _argv ) } +#ifdef NTK_GUI +static Fl_Tiled_Image *module_backdrop; +#endif + +void set_module_parameters ( Fl_Widget *o ) +{ +#ifdef NTK_GUI + o->box( FL_DOWN_FRAME ); + o->align( o->align() | FL_ALIGN_IMAGE_BACKDROP ); + o->color( FL_BLACK ); + o->image( module_backdrop ); + o->labeltype( FL_SHADOW_LABEL ); +#else + o->box( FL_PLASTIC_UP_BOX ); + o->color( FL_CYAN ); + o->labeltype( FL_EMBOSSED_LABEL ); +#endif +} + diff --git a/plugins/zynaddsubfx/ZynAddSubFx.h b/plugins/zynaddsubfx/ZynAddSubFx.h index ed65d24f5..e29f02f2b 100644 --- a/plugins/zynaddsubfx/ZynAddSubFx.h +++ b/plugins/zynaddsubfx/ZynAddSubFx.h @@ -32,7 +32,7 @@ #include "Instrument.h" #include "InstrumentView.h" #include "RemotePlugin.h" -#include "src/globals.h" +#include "zynaddsubfx/src/globals.h" class QPushButton; diff --git a/plugins/zynaddsubfx/src/DSP/AnalogFilter.cpp b/plugins/zynaddsubfx/src/DSP/AnalogFilter.cpp deleted file mode 100644 index bb1ad75c8..000000000 --- a/plugins/zynaddsubfx/src/DSP/AnalogFilter.cpp +++ /dev/null @@ -1,450 +0,0 @@ -/* - ZynAddSubFX - a software synthesizer - - AnalogFilter.cpp - Several analog filters (lowpass, highpass...) - Copyright (C) 2002-2005 Nasca Octavian Paul - Author: Nasca Octavian Paul - - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License - as published by the Free Software Foundation. - - 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 (version 2 or later) for more details. - - You should have received a copy of the GNU General Public License (version 2) - along with this program; if not, write to the Free Software Foundation, - Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -*/ - -#include -#include -#include "AnalogFilter.h" - -AnalogFilter::AnalogFilter(unsigned char Ftype, - REALTYPE Ffreq, - REALTYPE Fq, - unsigned char Fstages) -{ - stages = Fstages; - for(int i = 0; i < 3; i++) { - oldc[i] = 0.0; - oldd[i] = 0.0; - c[i] = 0.0; - d[i] = 0.0; - } - type = Ftype; - freq = Ffreq; - q = Fq; - gain = 1.0; - if(stages >= MAX_FILTER_STAGES) - stages = MAX_FILTER_STAGES; - cleanup(); - firsttime = 0; - abovenq = 0; - oldabovenq = 0; - setfreq_and_q(Ffreq, Fq); - firsttime = 1; - d[0] = 0; //this is not used - outgain = 1.0; -} - -AnalogFilter::~AnalogFilter() -{} - -void AnalogFilter::cleanup() -{ - for(int i = 0; i < MAX_FILTER_STAGES + 1; i++) { - x[i].c1 = 0.0; - x[i].c2 = 0.0; - y[i].c1 = 0.0; - y[i].c2 = 0.0; - oldx[i] = x[i]; - oldy[i] = y[i]; - } - needsinterpolation = 0; -} - -void AnalogFilter::computefiltercoefs() -{ - REALTYPE tmp; - REALTYPE omega, sn, cs, alpha, beta; - int zerocoefs = 0; //this is used if the freq is too high - - //do not allow frequencies bigger than samplerate/2 - REALTYPE freq = this->freq; - if(freq > (SAMPLE_RATE / 2 - 500.0)) { - freq = SAMPLE_RATE / 2 - 500.0; - zerocoefs = 1; - } - if(freq < 0.1) - freq = 0.1; - //do not allow bogus Q - if(q < 0.0) - q = 0.0; - REALTYPE tmpq, tmpgain; - if(stages == 0) { - tmpq = q; - tmpgain = gain; - } - else { - tmpq = (q > 1.0 ? pow(q, 1.0 / (stages + 1)) : q); - tmpgain = pow(gain, 1.0 / (stages + 1)); - } - - //most of theese are implementations of - //the "Cookbook formulae for audio EQ" by Robert Bristow-Johnson - //The original location of the Cookbook is: - //http://www.harmony-central.com/Computer/Programming/Audio-EQ-Cookbook.txt - switch(type) { - case 0: //LPF 1 pole - if(zerocoefs == 0) - tmp = exp(-2.0 * PI * freq / SAMPLE_RATE); - else - tmp = 0.0; - c[0] = 1.0 - tmp; - c[1] = 0.0; - c[2] = 0.0; - d[1] = tmp; - d[2] = 0.0; - order = 1; - break; - case 1: //HPF 1 pole - if(zerocoefs == 0) - tmp = exp(-2.0 * PI * freq / SAMPLE_RATE); - else - tmp = 0.0; - c[0] = (1.0 + tmp) / 2.0; - c[1] = -(1.0 + tmp) / 2.0; - c[2] = 0.0; - d[1] = tmp; - d[2] = 0.0; - order = 1; - break; - case 2: //LPF 2 poles - if(zerocoefs == 0) { - omega = 2 * PI * freq / SAMPLE_RATE; - sn = sin(omega); - cs = cos(omega); - alpha = sn / (2 * tmpq); - tmp = 1 + alpha; - c[0] = (1.0 - cs) / 2.0 / tmp; - c[1] = (1.0 - cs) / tmp; - c[2] = (1.0 - cs) / 2.0 / tmp; - d[1] = -2 * cs / tmp * (-1); - d[2] = (1 - alpha) / tmp * (-1); - } - else { - c[0] = 1.0; - c[1] = 0.0; - c[2] = 0.0; - d[1] = 0.0; - d[2] = 0.0; - } - order = 2; - break; - case 3: //HPF 2 poles - if(zerocoefs == 0) { - omega = 2 * PI * freq / SAMPLE_RATE; - sn = sin(omega); - cs = cos(omega); - alpha = sn / (2 * tmpq); - tmp = 1 + alpha; - c[0] = (1.0 + cs) / 2.0 / tmp; - c[1] = -(1.0 + cs) / tmp; - c[2] = (1.0 + cs) / 2.0 / tmp; - d[1] = -2 * cs / tmp * (-1); - d[2] = (1 - alpha) / tmp * (-1); - } - else { - c[0] = 0.0; - c[1] = 0.0; - c[2] = 0.0; - d[1] = 0.0; - d[2] = 0.0; - } - order = 2; - break; - case 4: //BPF 2 poles - if(zerocoefs == 0) { - omega = 2 * PI * freq / SAMPLE_RATE; - sn = sin(omega); - cs = cos(omega); - alpha = sn / (2 * tmpq); - tmp = 1 + alpha; - c[0] = alpha / tmp *sqrt(tmpq + 1); - c[1] = 0; - c[2] = -alpha / tmp *sqrt(tmpq + 1); - d[1] = -2 * cs / tmp * (-1); - d[2] = (1 - alpha) / tmp * (-1); - } - else { - c[0] = 0.0; - c[1] = 0.0; - c[2] = 0.0; - d[1] = 0.0; - d[2] = 0.0; - } - order = 2; - break; - case 5: //NOTCH 2 poles - if(zerocoefs == 0) { - omega = 2 * PI * freq / SAMPLE_RATE; - sn = sin(omega); - cs = cos(omega); - alpha = sn / (2 * sqrt(tmpq)); - tmp = 1 + alpha; - c[0] = 1 / tmp; - c[1] = -2 * cs / tmp; - c[2] = 1 / tmp; - d[1] = -2 * cs / tmp * (-1); - d[2] = (1 - alpha) / tmp * (-1); - } - else { - c[0] = 1.0; - c[1] = 0.0; - c[2] = 0.0; - d[1] = 0.0; - d[2] = 0.0; - } - order = 2; - break; - case 6: //PEAK (2 poles) - if(zerocoefs == 0) { - omega = 2 * PI * freq / SAMPLE_RATE; - sn = sin(omega); - cs = cos(omega); - tmpq *= 3.0; - alpha = sn / (2 * tmpq); - tmp = 1 + alpha / tmpgain; - c[0] = (1.0 + alpha * tmpgain) / tmp; - c[1] = (-2.0 * cs) / tmp; - c[2] = (1.0 - alpha * tmpgain) / tmp; - d[1] = -2 * cs / tmp * (-1); - d[2] = (1 - alpha / tmpgain) / tmp * (-1); - } - else { - c[0] = 1.0; - c[1] = 0.0; - c[2] = 0.0; - d[1] = 0.0; - d[2] = 0.0; - } - order = 2; - break; - case 7: //Low Shelf - 2 poles - if(zerocoefs == 0) { - omega = 2 * PI * freq / SAMPLE_RATE; - sn = sin(omega); - cs = cos(omega); - tmpq = sqrt(tmpq); - alpha = sn / (2 * tmpq); - beta = sqrt(tmpgain) / tmpq; - tmp = (tmpgain + 1.0) + (tmpgain - 1.0) * cs + beta * sn; - - c[0] = tmpgain - * ((tmpgain - + 1.0) - (tmpgain - 1.0) * cs + beta * sn) / tmp; - c[1] = 2.0 * tmpgain - * ((tmpgain - 1.0) - (tmpgain + 1.0) * cs) / tmp; - c[2] = tmpgain - * ((tmpgain - + 1.0) - (tmpgain - 1.0) * cs - beta * sn) / tmp; - d[1] = -2.0 * ((tmpgain - 1.0) + (tmpgain + 1.0) * cs) / tmp * (-1); - d[2] = - ((tmpgain - + 1.0) + (tmpgain - 1.0) * cs - beta * sn) / tmp * (-1); - } - else { - c[0] = tmpgain; - c[1] = 0.0; - c[2] = 0.0; - d[1] = 0.0; - d[2] = 0.0; - } - order = 2; - break; - case 8: //High Shelf - 2 poles - if(zerocoefs == 0) { - omega = 2 * PI * freq / SAMPLE_RATE; - sn = sin(omega); - cs = cos(omega); - tmpq = sqrt(tmpq); - alpha = sn / (2 * tmpq); - beta = sqrt(tmpgain) / tmpq; - tmp = (tmpgain + 1.0) - (tmpgain - 1.0) * cs + beta * sn; - - c[0] = tmpgain - * ((tmpgain - + 1.0) + (tmpgain - 1.0) * cs + beta * sn) / tmp; - c[1] = -2.0 * tmpgain - * ((tmpgain - 1.0) + (tmpgain + 1.0) * cs) / tmp; - c[2] = tmpgain - * ((tmpgain - + 1.0) + (tmpgain - 1.0) * cs - beta * sn) / tmp; - d[1] = 2.0 * ((tmpgain - 1.0) - (tmpgain + 1.0) * cs) / tmp * (-1); - d[2] = - ((tmpgain - + 1.0) - (tmpgain - 1.0) * cs - beta * sn) / tmp * (-1); - } - else { - c[0] = 1.0; - c[1] = 0.0; - c[2] = 0.0; - d[1] = 0.0; - d[2] = 0.0; - } - order = 2; - break; - default: //wrong type - type = 0; - computefiltercoefs(); - break; - } -} - - -void AnalogFilter::setfreq(REALTYPE frequency) -{ - if(frequency < 0.1) - frequency = 0.1; - REALTYPE rap = freq / frequency; - if(rap < 1.0) - rap = 1.0 / rap; - - oldabovenq = abovenq; - abovenq = frequency > (SAMPLE_RATE / 2 - 500.0); - - int nyquistthresh = (abovenq ^ oldabovenq); - - - if((rap > 3.0) || (nyquistthresh != 0)) { //if the frequency is changed fast, it needs interpolation (now, filter and coeficients backup) - for(int i = 0; i < 3; i++) { - oldc[i] = c[i]; - oldd[i] = d[i]; - } - for(int i = 0; i < MAX_FILTER_STAGES + 1; i++) { - oldx[i] = x[i]; - oldy[i] = y[i]; - } - if(firsttime == 0) - needsinterpolation = 1; - } - freq = frequency; - computefiltercoefs(); - firsttime = 0; -} - -void AnalogFilter::setfreq_and_q(REALTYPE frequency, REALTYPE q_) -{ - q = q_; - setfreq(frequency); -} - -void AnalogFilter::setq(REALTYPE q_) -{ - q = q_; - computefiltercoefs(); -} - -void AnalogFilter::settype(int type_) -{ - type = type_; - computefiltercoefs(); -} - -void AnalogFilter::setgain(REALTYPE dBgain) -{ - gain = dB2rap(dBgain); - computefiltercoefs(); -} - -void AnalogFilter::setstages(int stages_) -{ - if(stages_ >= MAX_FILTER_STAGES) - stages_ = MAX_FILTER_STAGES - 1; - stages = stages_; - cleanup(); - computefiltercoefs(); -} - -void AnalogFilter::singlefilterout(REALTYPE *smp, - fstage &x, - fstage &y, - REALTYPE *c, - REALTYPE *d) -{ - int i; - REALTYPE y0; - if(order == 1) { //First order filter - for(i = 0; i < SOUND_BUFFER_SIZE; i++) { - y0 = smp[i] * c[0] + x.c1 * c[1] + y.c1 * d[1]; - y.c1 = y0; - x.c1 = smp[i]; - //output - smp[i] = y0; - } - } - if(order == 2) { //Second order filter - for(i = 0; i < SOUND_BUFFER_SIZE; i++) { - y0 = smp[i] * c[0] + x.c1 * c[1] + x.c2 * c[2] + y.c1 * d[1] - + y.c2 * d[2]; - y.c2 = y.c1; - y.c1 = y0; - x.c2 = x.c1; - x.c1 = smp[i]; - //output - smp[i] = y0; - } - } -} -void AnalogFilter::filterout(REALTYPE *smp) -{ - REALTYPE *ismp = NULL; //used if it needs interpolation - int i; - if(needsinterpolation != 0) { - ismp = new REALTYPE[SOUND_BUFFER_SIZE]; - for(i = 0; i < SOUND_BUFFER_SIZE; i++) - ismp[i] = smp[i]; - for(i = 0; i < stages + 1; i++) - singlefilterout(ismp, oldx[i], oldy[i], oldc, oldd); - } - - for(i = 0; i < stages + 1; i++) - singlefilterout(smp, x[i], y[i], c, d); - - if(needsinterpolation != 0) { - for(i = 0; i < SOUND_BUFFER_SIZE; i++) { - REALTYPE x = i / (REALTYPE) SOUND_BUFFER_SIZE; - smp[i] = ismp[i] * (1.0 - x) + smp[i] * x; - } - delete [] ismp; - needsinterpolation = 0; - } - - for(i = 0; i < SOUND_BUFFER_SIZE; i++) - smp[i] *= outgain; -} - -REALTYPE AnalogFilter::H(REALTYPE freq) -{ - REALTYPE fr = freq / SAMPLE_RATE * PI * 2.0; - REALTYPE x = c[0], y = 0.0; - for(int n = 1; n < 3; n++) { - x += cos(n * fr) * c[n]; - y -= sin(n * fr) * c[n]; - } - REALTYPE h = x * x + y * y; - x = 1.0; - y = 0.0; - for(int n = 1; n < 3; n++) { - x -= cos(n * fr) * d[n]; - y += sin(n * fr) * d[n]; - } - h = h / (x * x + y * y); - return pow(h, (stages + 1.0) / 2.0); -} - diff --git a/plugins/zynaddsubfx/src/DSP/AnalogFilter.h b/plugins/zynaddsubfx/src/DSP/AnalogFilter.h deleted file mode 100644 index aeca9f1a3..000000000 --- a/plugins/zynaddsubfx/src/DSP/AnalogFilter.h +++ /dev/null @@ -1,82 +0,0 @@ -/* - ZynAddSubFX - a software synthesizer - - Analog Filter.h - Several analog filters (lowpass, highpass...) - Copyright (C) 2002-2005 Nasca Octavian Paul - Author: Nasca Octavian Paul - - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License - as published by the Free Software Foundation. - - 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 (version 2 or later) for more details. - - You should have received a copy of the GNU General Public License (version 2) - along with this program; if not, write to the Free Software Foundation, - Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -*/ - -#ifndef ANALOG_FILTER_H -#define ANALOG_FILTER_H - -#include "../globals.h" -#include "Filter_.h" - -/**Implementation of Several analog filters (lowpass, highpass...)*/ -class AnalogFilter:public Filter_ -{ - public: - AnalogFilter(unsigned char Ftype, - REALTYPE Ffreq, - REALTYPE Fq, - unsigned char Fstages); - ~AnalogFilter(); - void filterout(REALTYPE *smp); - void setfreq(REALTYPE frequency); - void setfreq_and_q(REALTYPE frequency, REALTYPE q_); - void setq(REALTYPE q_); - - void settype(int type_); - void setgain(REALTYPE dBgain); - void setstages(int stages_); - void cleanup(); - - REALTYPE H(REALTYPE freq); //Obtains the response for a given frequency - - private: - struct fstage { - REALTYPE c1, c2; - } x[MAX_FILTER_STAGES + 1], y[MAX_FILTER_STAGES + 1], - oldx[MAX_FILTER_STAGES + 1], oldy[MAX_FILTER_STAGES + 1]; - - void singlefilterout(REALTYPE *smp, - fstage &x, - fstage &y, - REALTYPE *c, - REALTYPE *d); - void computefiltercoefs(); - int type; //The type of the filter (LPF1,HPF1,LPF2,HPF2...) - int stages; //how many times the filter is applied (0->1,1->2,etc.) - REALTYPE freq; //Frequency given in Hz - REALTYPE q; //Q factor (resonance or Q factor) - REALTYPE gain; //the gain of the filter (if are shelf/peak) filters - - int order; //the order of the filter (number of poles) - - REALTYPE c[3], d[3]; //coefficients - - REALTYPE oldc[3], oldd[3]; //old coefficients(used only if some filter paremeters changes very fast, and it needs interpolation) - - REALTYPE xd[3], yd[3]; //used if the filter is applied more times - int needsinterpolation, firsttime; /**\todo see if bool works for these*/ - int abovenq; //this is 1 if the frequency is above the nyquist - int oldabovenq; //if the last time was above nyquist (used to see if it needs interpolation) -}; - - -#endif - diff --git a/plugins/zynaddsubfx/src/DSP/CMakeLists.txt b/plugins/zynaddsubfx/src/DSP/CMakeLists.txt deleted file mode 100644 index 263a1babb..000000000 --- a/plugins/zynaddsubfx/src/DSP/CMakeLists.txt +++ /dev/null @@ -1,14 +0,0 @@ -set(zynaddsubfx_dsp_SRCS - AnalogFilter.cpp - FFTwrapper.cpp - Filter.cpp - FormantFilter.cpp - SVFilter.cpp - Unison.cpp -) - -add_library(zynaddsubfx_dsp STATIC - ${zynaddsubfx_dsp_SRCS} - ) - -target_link_libraries(zynaddsubfx_dsp) diff --git a/plugins/zynaddsubfx/src/DSP/FFTwrapper.cpp b/plugins/zynaddsubfx/src/DSP/FFTwrapper.cpp deleted file mode 100644 index d93c0c40c..000000000 --- a/plugins/zynaddsubfx/src/DSP/FFTwrapper.cpp +++ /dev/null @@ -1,136 +0,0 @@ -/* - ZynAddSubFX - a software synthesizer - - FFTwrapper.c - A wrapper for Fast Fourier Transforms - Copyright (C) 2002-2005 Nasca Octavian Paul - Author: Nasca Octavian Paul - - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License - as published by the Free Software Foundation. - - 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 (version 2 or later) for more details. - - You should have received a copy of the GNU General Public License (version 2) - along with this program; if not, write to the Free Software Foundation, - Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -*/ - -#include -#include "FFTwrapper.h" - -FFTwrapper::FFTwrapper(int fftsize_) -{ - fftsize = fftsize_; - tmpfftdata1 = new fftw_real[fftsize]; - tmpfftdata2 = new fftw_real[fftsize]; -#ifdef FFTW_VERSION_2 - planfftw = rfftw_create_plan(fftsize, - FFTW_REAL_TO_COMPLEX, - FFTW_ESTIMATE | FFTW_IN_PLACE); - planfftw_inv = rfftw_create_plan(fftsize, - FFTW_COMPLEX_TO_REAL, - FFTW_ESTIMATE | FFTW_IN_PLACE); -#else - planfftw = fftwf_plan_r2r_1d(fftsize, - tmpfftdata1, - tmpfftdata1, - FFTW_R2HC, - FFTW_ESTIMATE); - planfftw_inv = fftwf_plan_r2r_1d(fftsize, - tmpfftdata2, - tmpfftdata2, - FFTW_HC2R, - FFTW_ESTIMATE); -#endif -} - -FFTwrapper::~FFTwrapper() -{ -#ifdef FFTW_VERSION_2 - rfftw_destroy_plan(planfftw); - rfftw_destroy_plan(planfftw_inv); -#else - fftwf_destroy_plan(planfftw); - fftwf_destroy_plan(planfftw_inv); -#endif - - delete [] tmpfftdata1; - delete [] tmpfftdata2; -} - -/* - * do the Fast Fourier Transform - */ -void FFTwrapper::smps2freqs(REALTYPE *smps, FFTFREQS freqs) -{ -#ifdef FFTW_VERSION_2 - for(int i = 0; i < fftsize; i++) - tmpfftdata1[i] = smps[i]; - rfftw_one(planfftw, tmpfftdata1, tmpfftdata2); - for(int i = 0; i < fftsize / 2; i++) { - freqs.c[i] = tmpfftdata2[i]; - if(i != 0) - freqs.s[i] = tmpfftdata2[fftsize - i]; - } -#else - for(int i = 0; i < fftsize; i++) - tmpfftdata1[i] = smps[i]; - fftwf_execute(planfftw); - for(int i = 0; i < fftsize / 2; i++) { - freqs.c[i] = tmpfftdata1[i]; - if(i != 0) - freqs.s[i] = tmpfftdata1[fftsize - i]; - } -#endif - tmpfftdata2[fftsize / 2] = 0.0; -} - -/* - * do the Inverse Fast Fourier Transform - */ -void FFTwrapper::freqs2smps(FFTFREQS freqs, REALTYPE *smps) -{ - tmpfftdata2[fftsize / 2] = 0.0; -#ifdef FFTW_VERSION_2 - for(int i = 0; i < fftsize / 2; i++) { - tmpfftdata1[i] = freqs.c[i]; - if(i != 0) - tmpfftdata1[fftsize - i] = freqs.s[i]; - } - rfftw_one(planfftw_inv, tmpfftdata1, tmpfftdata2); - for(int i = 0; i < fftsize; i++) - smps[i] = tmpfftdata2[i]; -#else - for(int i = 0; i < fftsize / 2; i++) { - tmpfftdata2[i] = freqs.c[i]; - if(i != 0) - tmpfftdata2[fftsize - i] = freqs.s[i]; - } - fftwf_execute(planfftw_inv); - for(int i = 0; i < fftsize; i++) - smps[i] = tmpfftdata2[i]; -#endif -} - -void newFFTFREQS(FFTFREQS *f, int size) -{ - f->c = new REALTYPE[size]; - f->s = new REALTYPE[size]; - for(int i = 0; i < size; i++) { - f->c[i] = 0.0; - f->s[i] = 0.0; - } -} - -void deleteFFTFREQS(FFTFREQS *f) -{ - delete[] f->c; - delete[] f->s; - f->c = f->s = NULL; -} - diff --git a/plugins/zynaddsubfx/src/DSP/FFTwrapper.h b/plugins/zynaddsubfx/src/DSP/FFTwrapper.h deleted file mode 100644 index 17d40805a..000000000 --- a/plugins/zynaddsubfx/src/DSP/FFTwrapper.h +++ /dev/null @@ -1,70 +0,0 @@ -/* - ZynAddSubFX - a software synthesizer - - FFTwrapper.h - A wrapper for Fast Fourier Transforms - Copyright (C) 2002-2005 Nasca Octavian Paul - Author: Nasca Octavian Paul - - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License - as published by the Free Software Foundation. - - 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 (version 2 or later) for more details. - - You should have received a copy of the GNU General Public License (version 2) - along with this program; if not, write to the Free Software Foundation, - Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -*/ - -#ifndef FFT_WRAPPER_H -#define FFT_WRAPPER_H - -#include "../globals.h" - -#ifdef FFTW_VERSION_2 - -#include - -/* If you got error messages about rfftw.h, replace the next include line with "#include " -or with "#include (if one doesn't work try the other). It may be necessary to replace -the with or . If the neither one doesn't work, -please install latest version of fftw(recomanded from the sources) from www.fftw.org. -If you'll install fftw3 you need to change the Makefile.inc -Hope all goes right." */ -#include - -#else - -#include -#define fftw_real float -#define rfftw_plan fftwf_plan -#endif - -/**A wrapper for the FFTW library (Fast Fourier Transforms)*/ -class FFTwrapper -{ - public: - /**Constructor - * @param fftsize The size of samples to be fed to fftw*/ - FFTwrapper(int fftsize_); - /**Destructor*/ - ~FFTwrapper(); - /**Convert Samples to Frequencies using Fourier Transform - * @param smps Pointer to Samples to be converted; has length fftsize_ - * @param freqs Structure FFTFREQS which stores the frequencies*/ - void smps2freqs(REALTYPE *smps, FFTFREQS freqs); - void freqs2smps(FFTFREQS freqs, REALTYPE *smps); - private: - int fftsize; - fftw_real *tmpfftdata1, *tmpfftdata2; - rfftw_plan planfftw, planfftw_inv; -}; - -void newFFTFREQS(FFTFREQS *f, int size); -void deleteFFTFREQS(FFTFREQS *f); -#endif - diff --git a/plugins/zynaddsubfx/src/DSP/Filter.cpp b/plugins/zynaddsubfx/src/DSP/Filter.cpp deleted file mode 100644 index c6a3ce976..000000000 --- a/plugins/zynaddsubfx/src/DSP/Filter.cpp +++ /dev/null @@ -1,87 +0,0 @@ -/* - ZynAddSubFX - a software synthesizer - - Filter.cpp - Filters, uses analog,formant,etc. filters - Copyright (C) 2002-2005 Nasca Octavian Paul - Author: Nasca Octavian Paul - - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License - as published by the Free Software Foundation. - - 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 (version 2 or later) for more details. - - You should have received a copy of the GNU General Public License (version 2) - along with this program; if not, write to the Free Software Foundation, - Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -*/ - -#include -#include - -#include "Filter.h" - -Filter::Filter(FilterParams *pars) -{ - unsigned char Ftype = pars->Ptype; - unsigned char Fstages = pars->Pstages; - - category = pars->Pcategory; - - switch(category) { - case 1: - filter = new FormantFilter(pars); - break; - case 2: - filter = new SVFilter(Ftype, 1000.0, pars->getq(), Fstages); - filter->outgain = dB2rap(pars->getgain()); - if(filter->outgain > 1.0) - filter->outgain = sqrt(filter->outgain); - break; - default: - filter = new AnalogFilter(Ftype, 1000.0, pars->getq(), Fstages); - if((Ftype >= 6) && (Ftype <= 8)) - filter->setgain(pars->getgain()); - else - filter->outgain = dB2rap(pars->getgain()); - break; - } -} - -Filter::~Filter() -{ - delete (filter); -} - -void Filter::filterout(REALTYPE *smp) -{ - filter->filterout(smp); -} - -void Filter::setfreq(REALTYPE frequency) -{ - filter->setfreq(frequency); -} - -void Filter::setfreq_and_q(REALTYPE frequency, REALTYPE q_) -{ - filter->setfreq_and_q(frequency, q_); -} - -void Filter::setq(REALTYPE q_) -{ - filter->setq(q_); -} - -REALTYPE Filter::getrealfreq(REALTYPE freqpitch) -{ - if((category == 0) || (category == 2)) - return pow(2.0, freqpitch + 9.96578428); //log2(1000)=9.95748 - else - return freqpitch; -} - diff --git a/plugins/zynaddsubfx/src/DSP/Filter.h b/plugins/zynaddsubfx/src/DSP/Filter.h deleted file mode 100644 index b8f568b21..000000000 --- a/plugins/zynaddsubfx/src/DSP/Filter.h +++ /dev/null @@ -1,52 +0,0 @@ -/* - ZynAddSubFX - a software synthesizer - - Filter.h - Filters, uses analog,formant,etc. filters - Copyright (C) 2002-2005 Nasca Octavian Paul - Author: Nasca Octavian Paul - - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License - as published by the Free Software Foundation. - - 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 (version 2 or later) for more details. - - You should have received a copy of the GNU General Public License (version 2) - along with this program; if not, write to the Free Software Foundation, - Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -*/ - -#ifndef FILTER_H -#define FILTER_H - -#include "../globals.h" - -#include "Filter_.h" -#include "AnalogFilter.h" -#include "FormantFilter.h" -#include "SVFilter.h" -#include "../Params/FilterParams.h" - -class Filter -{ - public: - Filter(FilterParams *pars); - ~Filter(); - void filterout(REALTYPE *smp); - void setfreq(REALTYPE frequency); - void setfreq_and_q(REALTYPE frequency, REALTYPE q_); - void setq(REALTYPE q_); - - REALTYPE getrealfreq(REALTYPE freqpitch); - private: - Filter_ *filter; - unsigned char category; -}; - - -#endif - diff --git a/plugins/zynaddsubfx/src/DSP/Filter_.h b/plugins/zynaddsubfx/src/DSP/Filter_.h deleted file mode 100644 index 88716f0b2..000000000 --- a/plugins/zynaddsubfx/src/DSP/Filter_.h +++ /dev/null @@ -1,43 +0,0 @@ -/* - ZynAddSubFX - a software synthesizer - - Filter_.h - This class is inherited by filter classes - Copyright (C) 2002-2005 Nasca Octavian Paul - Author: Nasca Octavian Paul - - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License - as published by the Free Software Foundation. - - 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 (version 2 or later) for more details. - - You should have received a copy of the GNU General Public License (version 2) - along with this program; if not, write to the Free Software Foundation, - Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -*/ - -#ifndef FILTER__H -#define FILTER__H - -#include "../globals.h" - -class Filter_ -{ - public: - virtual ~Filter_() {} - virtual void filterout(REALTYPE *smp) = 0; - virtual void setfreq(REALTYPE frequency) = 0; - virtual void setfreq_and_q(REALTYPE frequency, REALTYPE q_) = 0; - virtual void setq(REALTYPE q_) = 0; - virtual void setgain(REALTYPE dBgain) = 0; - REALTYPE outgain; - private: -}; - - -#endif - diff --git a/plugins/zynaddsubfx/src/DSP/FormantFilter.cpp b/plugins/zynaddsubfx/src/DSP/FormantFilter.cpp deleted file mode 100644 index 6d6771901..000000000 --- a/plugins/zynaddsubfx/src/DSP/FormantFilter.cpp +++ /dev/null @@ -1,231 +0,0 @@ -/* - ZynAddSubFX - a software synthesizer - - FormantFilter.cpp - formant filters - Copyright (C) 2002-2005 Nasca Octavian Paul - Author: Nasca Octavian Paul - - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License - as published by the Free Software Foundation. - - 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 (version 2 or later) for more details. - - You should have received a copy of the GNU General Public License (version 2) - along with this program; if not, write to the Free Software Foundation, - Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -*/ - -#include -#include -#include "FormantFilter.h" - -FormantFilter::FormantFilter(FilterParams *pars) -{ - numformants = pars->Pnumformants; - for(int i = 0; i < numformants; i++) - formant[i] = new AnalogFilter(4 /*BPF*/, 1000.0, 10.0, pars->Pstages); - cleanup(); - inbuffer = new REALTYPE [SOUND_BUFFER_SIZE]; - tmpbuf = new REALTYPE [SOUND_BUFFER_SIZE]; - - for(int j = 0; j < FF_MAX_VOWELS; j++) - for(int i = 0; i < numformants; i++) { - formantpar[j][i].freq = pars->getformantfreq( - pars->Pvowels[j].formants[i].freq); - formantpar[j][i].amp = pars->getformantamp( - pars->Pvowels[j].formants[i].amp); - formantpar[j][i].q = pars->getformantq( - pars->Pvowels[j].formants[i].q); - } - ; - for(int i = 0; i < FF_MAX_FORMANTS; i++) - oldformantamp[i] = 1.0; - for(int i = 0; i < numformants; i++) { - currentformants[i].freq = 1000.0; - currentformants[i].amp = 1.0; - currentformants[i].q = 2.0; - } - - formantslowness = pow(1.0 - (pars->Pformantslowness / 128.0), 3.0); - - sequencesize = pars->Psequencesize; - if(sequencesize == 0) - sequencesize = 1; - for(int k = 0; k < sequencesize; k++) - sequence[k].nvowel = pars->Psequence[k].nvowel; - - vowelclearness = pow(10.0, (pars->Pvowelclearness - 32.0) / 48.0); - - sequencestretch = pow(0.1, (pars->Psequencestretch - 32.0) / 48.0); - if(pars->Psequencereversed) - sequencestretch *= -1.0; - - outgain = dB2rap(pars->getgain()); - - oldinput = -1.0; - Qfactor = 1.0; - oldQfactor = Qfactor; - firsttime = 1; -} - -FormantFilter::~FormantFilter() -{ - for(int i = 0; i < numformants; i++) - delete (formant[i]); - delete[] inbuffer; - delete[] tmpbuf; -} - - - - -void FormantFilter::cleanup() -{ - for(int i = 0; i < numformants; i++) - formant[i]->cleanup(); -} - -void FormantFilter::setpos(REALTYPE input) -{ - int p1, p2; - - if(firsttime != 0) - slowinput = input; - else - slowinput = slowinput - * (1.0 - formantslowness) + input * formantslowness; - - if((fabs(oldinput - input) < 0.001) && (fabs(slowinput - input) < 0.001) - && (fabs(Qfactor - oldQfactor) < 0.001)) { -// oldinput=input; daca setez asta, o sa faca probleme la schimbari foarte lente - firsttime = 0; - return; - } - else - oldinput = input; - - - REALTYPE pos = fmod(input * sequencestretch, 1.0); - if(pos < 0.0) - pos += 1.0; - - F2I(pos * sequencesize, p2); - p1 = p2 - 1; - if(p1 < 0) - p1 += sequencesize; - - pos = fmod(pos * sequencesize, 1.0); - if(pos < 0.0) - pos = 0.0; - else - if(pos > 1.0) - pos = 1.0; - pos = - (atan((pos * 2.0 - - 1.0) * vowelclearness) / atan(vowelclearness) + 1.0) * 0.5; - - p1 = sequence[p1].nvowel; - p2 = sequence[p2].nvowel; - - if(firsttime != 0) { - for(int i = 0; i < numformants; i++) { - currentformants[i].freq = formantpar[p1][i].freq - * (1.0 - - pos) + formantpar[p2][i].freq * pos; - currentformants[i].amp = formantpar[p1][i].amp - * (1.0 - - pos) + formantpar[p2][i].amp * pos; - currentformants[i].q = formantpar[p1][i].q - * (1.0 - pos) + formantpar[p2][i].q * pos; - formant[i]->setfreq_and_q(currentformants[i].freq, - currentformants[i].q * Qfactor); - oldformantamp[i] = currentformants[i].amp; - } - firsttime = 0; - } - else { - for(int i = 0; i < numformants; i++) { - currentformants[i].freq = currentformants[i].freq - * (1.0 - formantslowness) - + (formantpar[p1][i].freq - * (1.0 - - pos) + formantpar[p2][i].freq - * pos) * formantslowness; - - currentformants[i].amp = currentformants[i].amp - * (1.0 - formantslowness) - + (formantpar[p1][i].amp - * (1.0 - - pos) + formantpar[p2][i].amp - * pos) * formantslowness; - - currentformants[i].q = currentformants[i].q - * (1.0 - formantslowness) - + (formantpar[p1][i].q - * (1.0 - - pos) + formantpar[p2][i].q - * pos) * formantslowness; - - formant[i]->setfreq_and_q(currentformants[i].freq, - currentformants[i].q * Qfactor); - } - } - - oldQfactor = Qfactor; -} - -void FormantFilter::setfreq(REALTYPE frequency) -{ - setpos(frequency); -} - -void FormantFilter::setq(REALTYPE q_) -{ - Qfactor = q_; - for(int i = 0; i < numformants; i++) - formant[i]->setq(Qfactor * currentformants[i].q); -} - -void FormantFilter::setgain(REALTYPE dBgain) -{} - - -void FormantFilter::setfreq_and_q(REALTYPE frequency, REALTYPE q_) -{ - Qfactor = q_; - setpos(frequency); -} - - -void FormantFilter::filterout(REALTYPE *smp) -{ - int i, j; - for(i = 0; i < SOUND_BUFFER_SIZE; i++) { - inbuffer[i] = smp[i]; - smp[i] = 0.0; - } - - for(j = 0; j < numformants; j++) { - for(i = 0; i < SOUND_BUFFER_SIZE; i++) - tmpbuf[i] = inbuffer[i] * outgain; - formant[j]->filterout(tmpbuf); - - if(ABOVE_AMPLITUDE_THRESHOLD(oldformantamp[j], currentformants[j].amp)) - for(i = 0; i < SOUND_BUFFER_SIZE; i++) - smp[i] += tmpbuf[i] - * INTERPOLATE_AMPLITUDE(oldformantamp[j], - currentformants[j].amp, - i, - SOUND_BUFFER_SIZE); - else - for(i = 0; i < SOUND_BUFFER_SIZE; i++) - smp[i] += tmpbuf[i] * currentformants[j].amp; - oldformantamp[j] = currentformants[j].amp; - } -} - diff --git a/plugins/zynaddsubfx/src/DSP/FormantFilter.h b/plugins/zynaddsubfx/src/DSP/FormantFilter.h deleted file mode 100644 index 4efe24fa5..000000000 --- a/plugins/zynaddsubfx/src/DSP/FormantFilter.h +++ /dev/null @@ -1,69 +0,0 @@ -/* - ZynAddSubFX - a software synthesizer - - FormantFilter.h - formant filter - Copyright (C) 2002-2005 Nasca Octavian Paul - Author: Nasca Octavian Paul - - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License - as published by the Free Software Foundation. - - 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 (version 2 or later) for more details. - - You should have received a copy of the GNU General Public License (version 2) - along with this program; if not, write to the Free Software Foundation, - Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -*/ - -#ifndef FORMANT_FILTER_H -#define FORMANT_FILTER_H - -#include "../globals.h" -#include "Filter_.h" -#include "AnalogFilter.h" -#include "../Params/FilterParams.h" - - -class FormantFilter:public Filter_ -{ - public: - FormantFilter(FilterParams *pars); - ~FormantFilter(); - void filterout(REALTYPE *smp); - void setfreq(REALTYPE frequency); - void setfreq_and_q(REALTYPE frequency, REALTYPE q_); - void setq(REALTYPE q_); - void setgain(REALTYPE dBgain); - - void cleanup(); - private: - AnalogFilter *formant[FF_MAX_FORMANTS]; - REALTYPE *inbuffer, *tmpbuf; - - struct { - REALTYPE freq, amp, q; //frequency,amplitude,Q - } formantpar[FF_MAX_VOWELS][FF_MAX_FORMANTS], - currentformants[FF_MAX_FORMANTS]; - - struct { - unsigned char nvowel; - } sequence [FF_MAX_SEQUENCE]; - - REALTYPE oldformantamp[FF_MAX_FORMANTS]; - - int sequencesize, numformants, firsttime; - REALTYPE oldinput, slowinput; - REALTYPE Qfactor, formantslowness, oldQfactor; - REALTYPE vowelclearness, sequencestretch; - - void setpos(REALTYPE input); -}; - - -#endif - diff --git a/plugins/zynaddsubfx/src/DSP/SVFilter.cpp b/plugins/zynaddsubfx/src/DSP/SVFilter.cpp deleted file mode 100644 index 636835a8c..000000000 --- a/plugins/zynaddsubfx/src/DSP/SVFilter.cpp +++ /dev/null @@ -1,186 +0,0 @@ -/* - ZynAddSubFX - a software synthesizer - - SVFilter.cpp - Several state-variable filters - Copyright (C) 2002-2005 Nasca Octavian Paul - Author: Nasca Octavian Paul - - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License - as published by the Free Software Foundation. - - 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 (version 2 or later) for more details. - - You should have received a copy of the GNU General Public License (version 2) - along with this program; if not, write to the Free Software Foundation, - Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -*/ - -#include -#include -#include "SVFilter.h" - -SVFilter::SVFilter(unsigned char Ftype, - REALTYPE Ffreq, - REALTYPE Fq, - unsigned char Fstages) -{ - stages = Fstages; - type = Ftype; - freq = Ffreq; - q = Fq; - gain = 1.0; - outgain = 1.0; - needsinterpolation = 0; - firsttime = 1; - if(stages >= MAX_FILTER_STAGES) - stages = MAX_FILTER_STAGES; - cleanup(); - setfreq_and_q(Ffreq, Fq); -} - -SVFilter::~SVFilter() -{} - -void SVFilter::cleanup() -{ - for(int i = 0; i < MAX_FILTER_STAGES + 1; i++) { - st[i].low = 0.0; - st[i].high = 0.0; - st[i].band = 0.0; - st[i].notch = 0.0; - } - oldabovenq = 0; - abovenq = 0; -} - -void SVFilter::computefiltercoefs() -{ - par.f = freq / SAMPLE_RATE * 4.0; - if(par.f > 0.99999) - par.f = 0.99999; - par.q = 1.0 - atan(sqrt(q)) * 2.0 / PI; - par.q = pow(par.q, 1.0 / (stages + 1)); - par.q_sqrt = sqrt(par.q); -} - - -void SVFilter::setfreq(REALTYPE frequency) -{ - if(frequency < 0.1) - frequency = 0.1; - REALTYPE rap = freq / frequency; - if(rap < 1.0) - rap = 1.0 / rap; - - oldabovenq = abovenq; - abovenq = frequency > (SAMPLE_RATE / 2 - 500.0); - - int nyquistthresh = (abovenq ^ oldabovenq); - - - if((rap > 3.0) || (nyquistthresh != 0)) { //if the frequency is changed fast, it needs interpolation (now, filter and coeficients backup) - if(firsttime == 0) - needsinterpolation = 1; - ipar = par; - } - freq = frequency; - computefiltercoefs(); - firsttime = 0; -} - -void SVFilter::setfreq_and_q(REALTYPE frequency, REALTYPE q_) -{ - q = q_; - setfreq(frequency); -} - -void SVFilter::setq(REALTYPE q_) -{ - q = q_; - computefiltercoefs(); -} - -void SVFilter::settype(int type_) -{ - type = type_; - computefiltercoefs(); -} - -void SVFilter::setgain(REALTYPE dBgain) -{ - gain = dB2rap(dBgain); - computefiltercoefs(); -} - -void SVFilter::setstages(int stages_) -{ - if(stages_ >= MAX_FILTER_STAGES) - stages_ = MAX_FILTER_STAGES - 1; - stages = stages_; - cleanup(); - computefiltercoefs(); -} - -void SVFilter::singlefilterout(REALTYPE *smp, fstage &x, parameters &par) -{ - int i; - REALTYPE *out = NULL; - switch(type) { - case 0: - out = &x.low; - break; - case 1: - out = &x.high; - break; - case 2: - out = &x.band; - break; - case 3: - out = &x.notch; - break; - } - - for(i = 0; i < SOUND_BUFFER_SIZE; i++) { - x.low = x.low + par.f * x.band; - x.high = par.q_sqrt * smp[i] - x.low - par.q * x.band; - x.band = par.f * x.high + x.band; - x.notch = x.high + x.low; - - smp[i] = *out; - } -} - -void SVFilter::filterout(REALTYPE *smp) -{ - int i; - REALTYPE *ismp = NULL; - - if(needsinterpolation != 0) { - ismp = new REALTYPE[SOUND_BUFFER_SIZE]; - for(i = 0; i < SOUND_BUFFER_SIZE; i++) - ismp[i] = smp[i]; - for(i = 0; i < stages + 1; i++) - singlefilterout(ismp, st[i], ipar); - } - - for(i = 0; i < stages + 1; i++) - singlefilterout(smp, st[i], par); - - if(needsinterpolation != 0) { - for(i = 0; i < SOUND_BUFFER_SIZE; i++) { - REALTYPE x = i / (REALTYPE) SOUND_BUFFER_SIZE; - smp[i] = ismp[i] * (1.0 - x) + smp[i] * x; - } - delete [] ismp; - needsinterpolation = 0; - } - - for(i = 0; i < SOUND_BUFFER_SIZE; i++) - smp[i] *= outgain; -} - diff --git a/plugins/zynaddsubfx/src/DSP/SVFilter.h b/plugins/zynaddsubfx/src/DSP/SVFilter.h deleted file mode 100644 index e90419e7d..000000000 --- a/plugins/zynaddsubfx/src/DSP/SVFilter.h +++ /dev/null @@ -1,71 +0,0 @@ -/* - ZynAddSubFX - a software synthesizer - - SV Filter.h - Several state-variable filters - Copyright (C) 2002-2005 Nasca Octavian Paul - Author: Nasca Octavian Paul - - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License - as published by the Free Software Foundation. - - 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 (version 2 or later) for more details. - - You should have received a copy of the GNU General Public License (version 2) - along with this program; if not, write to the Free Software Foundation, - Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -*/ - -#ifndef SV_FILTER_H -#define SV_FILTER_H - -#include "../globals.h" -#include "Filter_.h" -class SVFilter:public Filter_ -{ - public: - SVFilter(unsigned char Ftype, - REALTYPE Ffreq, - REALTYPE Fq, - unsigned char Fstages); - ~SVFilter(); - void filterout(REALTYPE *smp); - void setfreq(REALTYPE frequency); - void setfreq_and_q(REALTYPE frequency, REALTYPE q_); - void setq(REALTYPE q_); - - void settype(int type_); - void setgain(REALTYPE dBgain); - void setstages(int stages_); - void cleanup(); - - private: - struct fstage { - REALTYPE low, high, band, notch; - } st[MAX_FILTER_STAGES + 1]; - - struct parameters { - REALTYPE f, q, q_sqrt; - } par, ipar; - - - void singlefilterout(REALTYPE *smp, fstage &x, parameters &par); - void computefiltercoefs(); - int type; //The type of the filter (LPF1,HPF1,LPF2,HPF2...) - int stages; //how many times the filter is applied (0->1,1->2,etc.) - REALTYPE freq; //Frequency given in Hz - REALTYPE q; //Q factor (resonance or Q factor) - REALTYPE gain; //the gain of the filter (if are shelf/peak) filters - - int abovenq; //this is 1 if the frequency is above the nyquist - int oldabovenq; - int needsinterpolation, firsttime; -}; - - -#endif - diff --git a/plugins/zynaddsubfx/src/DSP/Unison.cpp b/plugins/zynaddsubfx/src/DSP/Unison.cpp deleted file mode 100644 index 798b2ecec..000000000 --- a/plugins/zynaddsubfx/src/DSP/Unison.cpp +++ /dev/null @@ -1,184 +0,0 @@ -/* - ZynAddSubFX - a software synthesizer - - Unison.cpp - Unison effect (multivoice chorus) - Copyright (C) 2002-2009 Nasca Octavian Paul - Author: Nasca Octavian Paul - - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License - as published by the Free Software Foundation. - - 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 (version 2 or later) for more details. - - You should have received a copy of the GNU General Public License (version 2) - along with this program; if not, write to the Free Software Foundation, - Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#include -#include -#include "Unison.h" - -Unison::Unison(int update_period_samples_, REALTYPE max_delay_sec_) { - update_period_samples = update_period_samples_; - max_delay = (int)(max_delay_sec_ * (REALTYPE)SAMPLE_RATE + 1); - if(max_delay < 10) - max_delay = 10; - delay_buffer = new REALTYPE[max_delay]; - delay_k = 0; - base_freq = 1.0; - unison_bandwidth_cents = 10.0; - - ZERO_REALTYPE(delay_buffer, max_delay); - - uv = NULL; - update_period_sample_k = 0; - first_time = 0; - - set_size(1); -} - -Unison::~Unison() { - delete [] delay_buffer; - if(uv) - delete [] uv; -} - -void Unison::set_size(int new_size) { - if(new_size < 1) - new_size = 1; - unison_size = new_size; - if(uv) - delete [] uv; - uv = new UnisonVoice[unison_size]; - first_time = true; - update_parameters(); -} - -void Unison::set_base_frequency(REALTYPE freq) { - base_freq = freq; - update_parameters(); -} - -void Unison::set_bandwidth(REALTYPE bandwidth) { - if(bandwidth < 0) - bandwidth = 0.0; - if(bandwidth > 1200.0) - bandwidth = 1200.0; - - //printf("bandwidth %g\n", bandwidth); - unison_bandwidth_cents = bandwidth; - update_parameters(); -} - -void Unison::update_parameters() { - if(!uv) - return; - REALTYPE increments_per_second = SAMPLE_RATE - / (REALTYPE) update_period_samples; -// printf("#%g, %g\n",increments_per_second,base_freq); - for(int i = 0; i < unison_size; i++) { - REALTYPE base = pow(UNISON_FREQ_SPAN, RND * 2.0 - 1.0); - uv[i].relative_amplitude = base; - REALTYPE period = base / base_freq; - REALTYPE m = 4.0 / (period * increments_per_second); - if(RND < 0.5) - m = -m; - uv[i].step = m; -// printf("%g %g\n",uv[i].relative_amplitude,period); - } - - REALTYPE max_speed = pow(2.0, unison_bandwidth_cents / 1200.0); - unison_amplitude_samples = 0.125 - * (max_speed - 1.0) * SAMPLE_RATE / base_freq; - //printf("unison_amplitude_samples %g\n", unison_amplitude_samples); - - if(unison_amplitude_samples >= max_delay - 1) - unison_amplitude_samples = max_delay - 2; - - update_unison_data(); -} - -void Unison::process(int bufsize, REALTYPE *inbuf, REALTYPE *outbuf) { - if(!uv) - return; - if(!outbuf) - outbuf = inbuf; - - REALTYPE volume = 1.0 / sqrt(unison_size); - REALTYPE xpos_step = 1.0 / (REALTYPE) update_period_samples; - REALTYPE xpos = (REALTYPE) update_period_sample_k * xpos_step; - for(int i = 0; i < bufsize; i++) { - if((update_period_sample_k++) >= update_period_samples) { - update_unison_data(); - update_period_sample_k = 0; - xpos = 0.0; - } - xpos += xpos_step; - REALTYPE in = inbuf[i], out = 0.0; - - REALTYPE sign = 1.0; - for(int k = 0; k < unison_size; k++) { - REALTYPE vpos = uv[k].realpos1 - * (1.0 - xpos) + uv[k].realpos2 * xpos; //optimize - REALTYPE pos = delay_k + max_delay - vpos - 1.0; //optimize - int posi; - REALTYPE posf; - F2I(pos, posi); //optimize! - if(posi >= max_delay) - posi -= max_delay; - posf = pos - floor(pos); - out += - ((1.0 - - posf) * delay_buffer[posi] + posf - * delay_buffer[posi + 1]) * sign; - sign = -sign; - } - outbuf[i] = out * volume; -// printf("%d %g\n",i,outbuf[i]); - delay_buffer[delay_k] = in; - if((++delay_k) >= max_delay) - delay_k = 0; - } -} - -void Unison::update_unison_data() { - if(!uv) - return; - - for(int k = 0; k < unison_size; k++) { - REALTYPE pos = uv[k].position; - REALTYPE step = uv[k].step; - pos += step; - if(pos <= -1.0) { - pos = -1.0; - step = -step; - } - if(pos >= 1.0) { - pos = 1.0; - step = -step; - } - REALTYPE vibratto_val = (pos - 0.333333333 * pos * pos * pos) * 1.5; //make the vibratto lfo smoother - REALTYPE newval = 1.0 + 0.5 - * (vibratto_val - + 1.0) * unison_amplitude_samples - * uv[k].relative_amplitude; - - if(first_time) - uv[k].realpos1 = uv[k].realpos2 = newval; - else{ - uv[k].realpos1 = uv[k].realpos2; - uv[k].realpos2 = newval; - } - - uv[k].position = pos; - uv[k].step = step; - } - if(first_time) - first_time = false; -} - diff --git a/plugins/zynaddsubfx/src/DSP/Unison.h b/plugins/zynaddsubfx/src/DSP/Unison.h deleted file mode 100644 index d4254a114..000000000 --- a/plugins/zynaddsubfx/src/DSP/Unison.h +++ /dev/null @@ -1,69 +0,0 @@ -/* - ZynAddSubFX - a software synthesizer - - Unison.h - Unison effect (multivoice chorus) - Copyright (C) 2002-2009 Nasca Octavian Paul - Author: Nasca Octavian Paul - - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License - as published by the Free Software Foundation. - - 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 (version 2 or later) for more details. - - You should have received a copy of the GNU General Public License (version 2) - along with this program; if not, write to the Free Software Foundation, - Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#ifndef UNISON_H -#define UNISON_H -#include -#include "../globals.h" - -#define UNISON_FREQ_SPAN 2.0 -//how much the unison frequencies varies (always >= 1.0) - -class Unison -{ - public: - Unison(int update_period_samples_, REALTYPE max_delay_sec_); - ~Unison(); - - void set_size(int new_size); - void set_base_frequency(REALTYPE freq); - void set_bandwidth(REALTYPE bandwidth_cents); - - void process(int bufsize, REALTYPE *inbuf, REALTYPE *outbuf = NULL); - - private: - void update_parameters(); - void update_unison_data(); - - int unison_size; - REALTYPE base_freq; - struct UnisonVoice { - REALTYPE step, position; //base LFO - REALTYPE realpos1, realpos2; //the position regarding samples - REALTYPE relative_amplitude; - REALTYPE lin_fpos, lin_ffreq; - UnisonVoice() { - position = RND * 1.8 - 0.9; - realpos1 = 0.0; - realpos2 = 0.0; - step = 0.0; - relative_amplitude = 1.0; - } - } *uv; - int update_period_samples, update_period_sample_k; - int max_delay, delay_k; - bool first_time; - REALTYPE *delay_buffer; - REALTYPE unison_amplitude_samples; - REALTYPE unison_bandwidth_cents; -}; -#endif - diff --git a/plugins/zynaddsubfx/src/Effects/Alienwah.cpp b/plugins/zynaddsubfx/src/Effects/Alienwah.cpp deleted file mode 100644 index 9d13ea8c1..000000000 --- a/plugins/zynaddsubfx/src/Effects/Alienwah.cpp +++ /dev/null @@ -1,281 +0,0 @@ -/* - ZynAddSubFX - a software synthesizer - - Alienwah.cpp - "AlienWah" effect - Copyright (C) 2002-2005 Nasca Octavian Paul - Author: Nasca Octavian Paul - - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License - as published by the Free Software Foundation. - - 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 (version 2 or later) for more details. - - You should have received a copy of the GNU General Public License (version 2) - along with this program; if not, write to the Free Software Foundation, - Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -*/ - -#include -#include "Alienwah.h" - -Alienwah::Alienwah(const int &insertion_, - REALTYPE *const efxoutl_, - REALTYPE *const efxoutr_) - :Effect(insertion_, efxoutl_, efxoutr_, NULL, 0), oldl(NULL), oldr(NULL) -{ - setpreset(Ppreset); - cleanup(); - oldclfol = complex(fb, 0.0); - oldclfor = complex(fb, 0.0); -} - -Alienwah::~Alienwah() -{ - if(oldl != NULL) - delete [] oldl; - if(oldr != NULL) - delete [] oldr; -} - - -/* - * Apply the effect - */ -void Alienwah::out(const Stereo &smp) -{ - REALTYPE lfol, lfor; //Left/Right LFOs - complex clfol, clfor, out, tmp; - /**\todo Rework, as optimization can be used when the new complex type is - * utilized. - * Before all calculations needed to be done with individual REALTYPE, - * but now they can be done together*/ - lfo.effectlfoout(&lfol, &lfor); - lfol *= depth * PI * 2.0; - lfor *= depth * PI * 2.0; - clfol = complex(cos(lfol + phase) * fb, sin(lfol + phase) * fb); //rework - clfor = complex(cos(lfor + phase) * fb, sin(lfor + phase) * fb); //rework - - for(int i = 0; i < SOUND_BUFFER_SIZE; i++) { - REALTYPE x = ((REALTYPE) i) / SOUND_BUFFER_SIZE; - REALTYPE x1 = 1.0 - x; - //left - tmp = clfol * x + oldclfol * x1; - - out = tmp * oldl[oldk]; - out.real() += (1 - fabs(fb)) * smp.l[i] * (1.0 - panning); - - oldl[oldk] = out; - REALTYPE l = out.real() * 10.0 * (fb + 0.1); - - //right - tmp = clfor * x + oldclfor * x1; - - out = tmp * oldr[oldk]; - out.real() += (1 - fabs(fb)) * smp.r[i] * (1.0 - panning); - - oldr[oldk] = out; - REALTYPE r = out.real() * 10.0 * (fb + 0.1); - - - if(++oldk >= Pdelay) - oldk = 0; - //LRcross - efxoutl[i] = l * (1.0 - lrcross) + r * lrcross; - efxoutr[i] = r * (1.0 - lrcross) + l * lrcross; - } - - oldclfol = clfol; - oldclfor = clfor; -} - -/* - * Cleanup the effect - */ -void Alienwah::cleanup() -{ - for(int i = 0; i < Pdelay; i++) { - oldl[i] = complex(0.0, 0.0); - oldr[i] = complex(0.0, 0.0); - } - oldk = 0; -} - - -/* - * Parameter control - */ - -void Alienwah::setdepth(unsigned char Pdepth) -{ - this->Pdepth = Pdepth; - depth = (Pdepth / 127.0); -} - -void Alienwah::setfb(unsigned char Pfb) -{ - this->Pfb = Pfb; - fb = fabs((Pfb - 64.0) / 64.1); - fb = sqrt(fb); - if(fb < 0.4) - fb = 0.4; - if(Pfb < 64) - fb = -fb; -} - -void Alienwah::setvolume(unsigned char Pvolume) -{ - this->Pvolume = Pvolume; - outvolume = Pvolume / 127.0; - if(insertion == 0) - volume = 1.0; - else - volume = outvolume; -} - -void Alienwah::setpanning(unsigned char Ppanning) -{ - this->Ppanning = Ppanning; - panning = Ppanning / 127.0; -} - -void Alienwah::setlrcross(unsigned char Plrcross) -{ - this->Plrcross = Plrcross; - lrcross = Plrcross / 127.0; -} - -void Alienwah::setphase(unsigned char Pphase) -{ - this->Pphase = Pphase; - phase = (Pphase - 64.0) / 64.0 * PI; -} - -void Alienwah::setdelay(unsigned char Pdelay) -{ - if(oldl != NULL) - delete [] oldl; - if(oldr != NULL) - delete [] oldr; - if(Pdelay >= MAX_ALIENWAH_DELAY) - this->Pdelay = MAX_ALIENWAH_DELAY; - else - this->Pdelay = Pdelay; - oldl = new complex[Pdelay]; - oldr = new complex[Pdelay]; - cleanup(); -} - -void Alienwah::setpreset(unsigned char npreset) -{ - const int PRESET_SIZE = 11; - const int NUM_PRESETS = 4; - unsigned char presets[NUM_PRESETS][PRESET_SIZE] = { - //AlienWah1 - {127, 64, 70, 0, 0, 62, 60, 105, 25, 0, 64}, - //AlienWah2 - {127, 64, 73, 106, 0, 101, 60, 105, 17, 0, 64}, - //AlienWah3 - {127, 64, 63, 0, 1, 100, 112, 105, 31, 0, 42}, - //AlienWah4 - {93, 64, 25, 0, 1, 66, 101, 11, 47, 0, 86} - }; - - if(npreset >= NUM_PRESETS) - npreset = NUM_PRESETS - 1; - for(int n = 0; n < PRESET_SIZE; n++) - changepar(n, presets[npreset][n]); - if(insertion == 0) - changepar(0, presets[npreset][0] / 2); //lower the volume if this is system effect - Ppreset = npreset; -} - - -void Alienwah::changepar(int npar, unsigned char value) -{ - switch(npar) { - case 0: - setvolume(value); - break; - case 1: - setpanning(value); - break; - case 2: - lfo.Pfreq = value; - lfo.updateparams(); - break; - case 3: - lfo.Prandomness = value; - lfo.updateparams(); - break; - case 4: - lfo.PLFOtype = value; - lfo.updateparams(); - break; - case 5: - lfo.Pstereo = value; - lfo.updateparams(); - break; - case 6: - setdepth(value); - break; - case 7: - setfb(value); - break; - case 8: - setdelay(value); - break; - case 9: - setlrcross(value); - break; - case 10: - setphase(value); - break; - } -} - -unsigned char Alienwah::getpar(int npar) const -{ - switch(npar) { - case 0: - return Pvolume; - break; - case 1: - return Ppanning; - break; - case 2: - return lfo.Pfreq; - break; - case 3: - return lfo.Prandomness; - break; - case 4: - return lfo.PLFOtype; - break; - case 5: - return lfo.Pstereo; - break; - case 6: - return Pdepth; - break; - case 7: - return Pfb; - break; - case 8: - return Pdelay; - break; - case 9: - return Plrcross; - break; - case 10: - return Pphase; - break; - default: - return 0; - } -} - diff --git a/plugins/zynaddsubfx/src/Effects/Alienwah.h b/plugins/zynaddsubfx/src/Effects/Alienwah.h deleted file mode 100644 index 9ad695403..000000000 --- a/plugins/zynaddsubfx/src/Effects/Alienwah.h +++ /dev/null @@ -1,85 +0,0 @@ -/* - ZynAddSubFX - a software synthesizer - - Alienwah.h - "AlienWah" effect - Copyright (C) 2002-2005 Nasca Octavian Paul - Author: Nasca Octavian Paul - - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License - as published by the Free Software Foundation. - - 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 (version 2 or later) for more details. - - You should have received a copy of the GNU General Public License (version 2) - along with this program; if not, write to the Free Software Foundation, - Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -*/ - -#ifndef ALIENWAH_H -#define ALIENWAH_H -#include -#include "../globals.h" -#include "Effect.h" -#include "EffectLFO.h" - -using namespace std; - -#define MAX_ALIENWAH_DELAY 100 - -/**"AlienWah" Effect*/ -class Alienwah:public Effect -{ - public: - /** - * Constructor - * @param insetion_ 1 for insertion Effect, 0 for others - * @param efxoutl_ Pointer to Alienwah's left channel output buffer - * @param efxoutr_ Pointer to Alienwah's left channel output buffer - * @return Initialized Alienwah - */ - Alienwah(const int &insetion_, - REALTYPE *const efxoutl_, - REALTYPE *const efxoutr_); - ~Alienwah(); - void out(const Stereo &smp); - - void setpreset(unsigned char npreset); - void changepar(int npar, unsigned char value); - unsigned char getpar(int npar) const; - void cleanup(); - - private: - //Alienwah Parameters - EffectLFO lfo; //lfo-ul Alienwah - unsigned char Pvolume; - unsigned char Ppanning; - unsigned char Pdepth; //the depth of the Alienwah - unsigned char Pfb; //feedback - unsigned char Plrcross; //feedback - unsigned char Pdelay; - unsigned char Pphase; - - - //Control Parameters - void setvolume(unsigned char Pvolume); - void setpanning(unsigned char Ppanning); - void setdepth(unsigned char Pdepth); - void setfb(unsigned char Pfb); - void setlrcross(unsigned char Plrcross); - void setdelay(unsigned char Pdelay); - void setphase(unsigned char Pphase); - - //Internal Values - REALTYPE panning, fb, depth, lrcross, phase; - complex *oldl, *oldr; - complex oldclfol, oldclfor; - int oldk; -}; - -#endif - diff --git a/plugins/zynaddsubfx/src/Effects/CMakeLists.txt b/plugins/zynaddsubfx/src/Effects/CMakeLists.txt deleted file mode 100644 index 0c15dfa87..000000000 --- a/plugins/zynaddsubfx/src/Effects/CMakeLists.txt +++ /dev/null @@ -1,19 +0,0 @@ -set(zynaddsubfx_effect_SRCS - Alienwah.cpp - Chorus.cpp - Distorsion.cpp - DynamicFilter.cpp - Echo.cpp - Effect.cpp - EffectLFO.cpp - EffectMgr.cpp - EQ.cpp - Phaser.cpp - Reverb.cpp -) - -add_library(zynaddsubfx_effect STATIC - ${zynaddsubfx_effect_SRCS} - ) - -target_link_libraries(zynaddsubfx_effect) diff --git a/plugins/zynaddsubfx/src/Effects/Chorus.cpp b/plugins/zynaddsubfx/src/Effects/Chorus.cpp deleted file mode 100644 index b39c0032b..000000000 --- a/plugins/zynaddsubfx/src/Effects/Chorus.cpp +++ /dev/null @@ -1,320 +0,0 @@ -/* - ZynAddSubFX - a software synthesizer - - Chorus.cpp - Chorus and Flange effects - Copyright (C) 2002-2005 Nasca Octavian Paul - Author: Nasca Octavian Paul - - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License - as published by the Free Software Foundation. - - 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 (version 2 or later) for more details. - - You should have received a copy of the GNU General Public License (version 2) - along with this program; if not, write to the Free Software Foundation, - Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -*/ - -#include -#include "Chorus.h" -#include - -using namespace std; - -Chorus::Chorus(const int &insertion_, - REALTYPE *const efxoutl_, - REALTYPE *const efxoutr_) - :Effect(insertion_, efxoutl_, efxoutr_, NULL, 0), - maxdelay((int)(MAX_CHORUS_DELAY / 1000.0 * SAMPLE_RATE)), - delaySample(maxdelay) -{ - dlk = 0; - drk = 0; - - setpreset(Ppreset); - - lfo.effectlfoout(&lfol, &lfor); - dl2 = getdelay(lfol); - dr2 = getdelay(lfor); - cleanup(); -} - -Chorus::~Chorus() {} - -/* - * get the delay value in samples; xlfo is the current lfo value - */ -REALTYPE Chorus::getdelay(REALTYPE xlfo) -{ - REALTYPE result; - if(Pflangemode == 0) - result = (delay + xlfo * depth) * SAMPLE_RATE; - else - result = 0; - - //check if it is too big delay(caused bu errornous setdelay() and setdepth() - /**\todo fix setdelay() and setdepth(), so this error cannot occur*/ - if((result + 0.5) >= maxdelay) { - cerr - << - "WARNING: Chorus.cpp::getdelay(..) too big delay (see setdelay and setdepth funcs.)\n"; - result = maxdelay - 1.0; - } - return result; -} - -void Chorus::out(const Stereo &input) -{ - const REALTYPE one = 1.0; - dl1 = dl2; - dr1 = dr2; - lfo.effectlfoout(&lfol, &lfor); - - dl2 = getdelay(lfol); - dr2 = getdelay(lfor); - - for(int i = 0; i < SOUND_BUFFER_SIZE; i++) { - REALTYPE inl = input.l[i]; - REALTYPE inr = input.r[i]; - //LRcross - Stereo tmpc(inl, inr); - //REALTYPE r=inr; - inl = tmpc.l * (1.0 - lrcross) + tmpc.r * lrcross; - inr = tmpc.r * (1.0 - lrcross) + tmpc.l * lrcross; - - //Left channel - - //compute the delay in samples using linear interpolation between the lfo delays - mdel = (dl1 * (SOUND_BUFFER_SIZE - i) + dl2 * i) / SOUND_BUFFER_SIZE; - if(++dlk >= maxdelay) - dlk = 0; - REALTYPE tmp = dlk - mdel + maxdelay * 2.0; //where should I get the sample from - - F2I(tmp, dlhi); - dlhi %= maxdelay; - - dlhi2 = (dlhi - 1 + maxdelay) % maxdelay; - dllo = 1.0 - fmod(tmp, one); - efxoutl[i] = delaySample.l[dlhi2] * dllo + delaySample.l[dlhi] - * (1.0 - dllo); - delaySample.l[dlk] = inl + efxoutl[i] * fb; - - //Right channel - - //compute the delay in samples using linear interpolation between the lfo delays - mdel = (dr1 * (SOUND_BUFFER_SIZE - i) + dr2 * i) / SOUND_BUFFER_SIZE; - if(++drk >= maxdelay) - drk = 0; - tmp = drk * 1.0 - mdel + maxdelay * 2.0; //where should I get the sample from - - F2I(tmp, dlhi); - dlhi %= maxdelay; - - dlhi2 = (dlhi - 1 + maxdelay) % maxdelay; - dllo = 1.0 - fmod(tmp, one); - efxoutr[i] = delaySample.r[dlhi2] * dllo + delaySample.r[dlhi] - * (1.0 - dllo); - delaySample.r[dlk] = inr + efxoutr[i] * fb; - } - - if(Poutsub != 0) - for(int i = 0; i < SOUND_BUFFER_SIZE; i++) { - efxoutl[i] *= -1.0; - efxoutr[i] *= -1.0; - } - ; - - - for(int i = 0; i < SOUND_BUFFER_SIZE; i++) { - efxoutl[i] *= panning; - efxoutr[i] *= (1.0 - panning); - } -} - -/* - * Cleanup the effect - */ -void Chorus::cleanup() -{ - delaySample.l.clear(); - delaySample.r.clear(); -} - -/* - * Parameter control - */ -void Chorus::setdepth(unsigned char Pdepth) -{ - this->Pdepth = Pdepth; - depth = (pow(8.0, (Pdepth / 127.0) * 2.0) - 1.0) / 1000.0; //seconds -} - -void Chorus::setdelay(unsigned char Pdelay) -{ - this->Pdelay = Pdelay; - delay = (pow(10.0, (Pdelay / 127.0) * 2.0) - 1.0) / 1000.0; //seconds -} - -void Chorus::setfb(unsigned char Pfb) -{ - this->Pfb = Pfb; - fb = (Pfb - 64.0) / 64.1; -} -void Chorus::setvolume(unsigned char Pvolume) -{ - this->Pvolume = Pvolume; - outvolume = Pvolume / 127.0; - if(insertion == 0) - volume = 1.0; - else - volume = outvolume; -} - -void Chorus::setpanning(unsigned char Ppanning) -{ - this->Ppanning = Ppanning; - panning = Ppanning / 127.0; -} - -void Chorus::setlrcross(unsigned char Plrcross) -{ - this->Plrcross = Plrcross; - lrcross = Plrcross / 127.0; -} - -void Chorus::setpreset(unsigned char npreset) -{ - const int PRESET_SIZE = 12; - const int NUM_PRESETS = 10; - unsigned char presets[NUM_PRESETS][PRESET_SIZE] = { - //Chorus1 - {64, 64, 50, 0, 0, 90, 40, 85, 64, 119, 0, 0 }, - //Chorus2 - {64, 64, 45, 0, 0, 98, 56, 90, 64, 19, 0, 0 }, - //Chorus3 - {64, 64, 29, 0, 1, 42, 97, 95, 90, 127, 0, 0 }, - //Celeste1 - {64, 64, 26, 0, 0, 42, 115, 18, 90, 127, 0, 0 }, - //Celeste2 - {64, 64, 29, 117, 0, 50, 115, 9, 31, 127, 0, 1 }, - //Flange1 - {64, 64, 57, 0, 0, 60, 23, 3, 62, 0, 0, 0 }, - //Flange2 - {64, 64, 33, 34, 1, 40, 35, 3, 109, 0, 0, 0 }, - //Flange3 - {64, 64, 53, 34, 1, 94, 35, 3, 54, 0, 0, 1 }, - //Flange4 - {64, 64, 40, 0, 1, 62, 12, 19, 97, 0, 0, 0 }, - //Flange5 - {64, 64, 55, 105, 0, 24, 39, 19, 17, 0, 0, 1 } - }; - - if(npreset >= NUM_PRESETS) - npreset = NUM_PRESETS - 1; - for(int n = 0; n < PRESET_SIZE; n++) - changepar(n, presets[npreset][n]); - Ppreset = npreset; -} - - -void Chorus::changepar(int npar, unsigned char value) -{ - switch(npar) { - case 0: - setvolume(value); - break; - case 1: - setpanning(value); - break; - case 2: - lfo.Pfreq = value; - lfo.updateparams(); - break; - case 3: - lfo.Prandomness = value; - lfo.updateparams(); - break; - case 4: - lfo.PLFOtype = value; - lfo.updateparams(); - break; - case 5: - lfo.Pstereo = value; - lfo.updateparams(); - break; - case 6: - setdepth(value); - break; - case 7: - setdelay(value); - break; - case 8: - setfb(value); - break; - case 9: - setlrcross(value); - break; - case 10: - if(value > 1) - Pflangemode = 1; - else - Pflangemode = value; - break; - case 11: - if(value > 1) - Poutsub = 1; - else - Poutsub = value; - break; - } -} - -unsigned char Chorus::getpar(int npar) const -{ - switch(npar) { - case 0: - return Pvolume; - break; - case 1: - return Ppanning; - break; - case 2: - return lfo.Pfreq; - break; - case 3: - return lfo.Prandomness; - break; - case 4: - return lfo.PLFOtype; - break; - case 5: - return lfo.Pstereo; - break; - case 6: - return Pdepth; - break; - case 7: - return Pdelay; - break; - case 8: - return Pfb; - break; - case 9: - return Plrcross; - break; - case 10: - return Pflangemode; - break; - case 11: - return Poutsub; - break; - default: - return 0; - } -} - diff --git a/plugins/zynaddsubfx/src/Effects/Chorus.h b/plugins/zynaddsubfx/src/Effects/Chorus.h deleted file mode 100644 index 2aeb1a191..000000000 --- a/plugins/zynaddsubfx/src/Effects/Chorus.h +++ /dev/null @@ -1,114 +0,0 @@ -/* - ZynAddSubFX - a software synthesizer - - Chorus.h - Chorus and Flange effects - Copyright (C) 2002-2005 Nasca Octavian Paul - Author: Nasca Octavian Paul - - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License - as published by the Free Software Foundation. - - 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 (version 2 or later) for more details. - - You should have received a copy of the GNU General Public License (version 2) - along with this program; if not, write to the Free Software Foundation, - Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -*/ - -#ifndef CHORUS_H -#define CHORUS_H -#include "../globals.h" -#include "Effect.h" -#include "EffectLFO.h" -#include "../Samples/Sample.h" -#include "../Misc/Stereo.h" - -#define MAX_CHORUS_DELAY 250.0 //ms - -/**Chorus and Flange effects*/ -class Chorus:public Effect -{ - public: - Chorus(const int &insetion_, REALTYPE *efxoutl_, REALTYPE *efxoutr_); - /**Destructor*/ - ~Chorus(); - void out(const Stereo &input); - void setpreset(unsigned char npreset); - /** - * Sets the value of the chosen variable - * - * The possible parameters are: - * -# Volume - * -# Panning - * -# LFO Frequency - * -# LFO Randomness - * -# LFO Type - * -# LFO stereo - * -# Depth - * -# Delay - * -# Feedback - * -# Flange Mode - * -# Subtractive - * @param npar number of chosen parameter - * @param value the new value - */ - void changepar(int npar, unsigned char value); - /** - * Gets the value of the chosen variable - * - * The possible parameters are: - * -# Volume - * -# Panning - * -# LFO Frequency - * -# LFO Randomness - * -# LFO Type - * -# LFO stereo - * -# Depth - * -# Delay - * -# Feedback - * -# Flange Mode - * -# Subtractive - * @param npar number of chosen parameter - * @return the value of the parameter - */ - unsigned char getpar(int npar) const; - void cleanup(); - - private: - //Chorus Parameters - EffectLFO lfo; //lfo-ul chorus - unsigned char Pvolume; - unsigned char Ppanning; - unsigned char Pdepth; //the depth of the Chorus(ms) - unsigned char Pdelay; //the delay (ms) - unsigned char Pfb; //feedback - unsigned char Plrcross; //feedback - unsigned char Pflangemode; //how the LFO is scaled, to result chorus or flange - unsigned char Poutsub; //if I wish to substract the output instead of the adding it - - - //Parameter Controls - void setvolume(unsigned char Pvolume); - void setpanning(unsigned char Ppanning); - void setdepth(unsigned char Pdepth); - void setdelay(unsigned char Pdelay); - void setfb(unsigned char Pfb); - void setlrcross(unsigned char Plrcross); - - //Internal Values - REALTYPE depth, delay, fb, lrcross, panning; - REALTYPE dl1, dl2, dr1, dr2, lfol, lfor; - int maxdelay; - Stereo delaySample; - int dlk, drk, dlhi, dlhi2; - REALTYPE getdelay(REALTYPE xlfo); - REALTYPE dllo, mdel; -}; - -#endif - diff --git a/plugins/zynaddsubfx/src/Effects/Distorsion.cpp b/plugins/zynaddsubfx/src/Effects/Distorsion.cpp deleted file mode 100644 index a0b6a2e62..000000000 --- a/plugins/zynaddsubfx/src/Effects/Distorsion.cpp +++ /dev/null @@ -1,481 +0,0 @@ -/* - ZynAddSubFX - a software synthesizer - - Distorsion.cpp - Distorsion effect - Copyright (C) 2002-2005 Nasca Octavian Paul - Author: Nasca Octavian Paul - - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License - as published by the Free Software Foundation. - - 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 (version 2 or later) for more details. - - You should have received a copy of the GNU General Public License (version 2) - along with this program; if not, write to the Free Software Foundation, - Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -*/ - -#include -#include "Distorsion.h" - - -/* - * Waveshape (this is called by OscilGen::waveshape and Distorsion::process) - */ - -void waveshapesmps(int n, - REALTYPE *smps, - unsigned char type, - unsigned char drive) -{ - int i; - REALTYPE ws = drive / 127.0; - REALTYPE tmpv; - - switch(type) { - case 1: - ws = pow(10, ws * ws * 3.0) - 1.0 + 0.001; //Arctangent - for(i = 0; i < n; i++) - smps[i] = atan(smps[i] * ws) / atan(ws); - break; - case 2: - ws = ws * ws * 32.0 + 0.0001; //Asymmetric - if(ws < 1.0) - tmpv = sin(ws) + 0.1; - else - tmpv = 1.1; - for(i = 0; i < n; i++) - smps[i] = sin(smps[i] * (0.1 + ws - ws * smps[i])) / tmpv; - ; - break; - case 3: - ws = ws * ws * ws * 20.0 + 0.0001; //Pow - for(i = 0; i < n; i++) { - smps[i] *= ws; - if(fabs(smps[i]) < 1.0) { - smps[i] = (smps[i] - pow(smps[i], 3.0)) * 3.0; - if(ws < 1.0) - smps[i] /= ws; - } - else - smps[i] = 0.0; - } - break; - case 4: - ws = ws * ws * ws * 32.0 + 0.0001; //Sine - if(ws < 1.57) - tmpv = sin(ws); - else - tmpv = 1.0; - for(i = 0; i < n; i++) - smps[i] = sin(smps[i] * ws) / tmpv; - break; - case 5: - ws = ws * ws + 0.000001; //Quantisize - for(i = 0; i < n; i++) - smps[i] = floor(smps[i] / ws + 0.5) * ws; - break; - case 6: - ws = ws * ws * ws * 32 + 0.0001; //Zigzag - if(ws < 1.0) - tmpv = sin(ws); - else - tmpv = 1.0; - for(i = 0; i < n; i++) - smps[i] = asin(sin(smps[i] * ws)) / tmpv; - break; - case 7: - ws = pow(2.0, -ws * ws * 8.0); //Limiter - for(i = 0; i < n; i++) { - REALTYPE tmp = smps[i]; - if(fabs(tmp) > ws) { - if(tmp >= 0.0) - smps[i] = 1.0; - else - smps[i] = -1.0; - } - else - smps[i] /= ws; - } - break; - case 8: - ws = pow(2.0, -ws * ws * 8.0); //Upper Limiter - for(i = 0; i < n; i++) { - REALTYPE tmp = smps[i]; - if(tmp > ws) - smps[i] = ws; - smps[i] *= 2.0; - } - break; - case 9: - ws = pow(2.0, -ws * ws * 8.0); //Lower Limiter - for(i = 0; i < n; i++) { - REALTYPE tmp = smps[i]; - if(tmp < -ws) - smps[i] = -ws; - smps[i] *= 2.0; - } - break; - case 10: - ws = (pow(2.0, ws * 6.0) - 1.0) / pow(2.0, 6.0); //Inverse Limiter - for(i = 0; i < n; i++) { - REALTYPE tmp = smps[i]; - if(fabs(tmp) > ws) { - if(tmp >= 0.0) - smps[i] = tmp - ws; - else - smps[i] = tmp + ws; - } - else - smps[i] = 0; - } - break; - case 11: - ws = pow(5, ws * ws * 1.0) - 1.0; //Clip - for(i = 0; i < n; i++) - smps[i] = smps[i] - * (ws + 0.5) * 0.9999 - floor( - 0.5 + smps[i] * (ws + 0.5) * 0.9999); - break; - case 12: - ws = ws * ws * ws * 30 + 0.001; //Asym2 - if(ws < 0.3) - tmpv = ws; - else - tmpv = 1.0; - for(i = 0; i < n; i++) { - REALTYPE tmp = smps[i] * ws; - if((tmp > -2.0) && (tmp < 1.0)) - smps[i] = tmp * (1.0 - tmp) * (tmp + 2.0) / tmpv; - else - smps[i] = 0.0; - } - break; - case 13: - ws = ws * ws * ws * 32.0 + 0.0001; //Pow2 - if(ws < 1.0) - tmpv = ws * (1 + ws) / 2.0; - else - tmpv = 1.0; - for(i = 0; i < n; i++) { - REALTYPE tmp = smps[i] * ws; - if((tmp > -1.0) && (tmp < 1.618034)) - smps[i] = tmp * (1.0 - tmp) / tmpv; - else - if(tmp > 0.0) - smps[i] = -1.0; - else - smps[i] = -2.0; - } - break; - case 14: - ws = pow(ws, 5.0) * 80.0 + 0.0001; //sigmoid - if(ws > 10.0) - tmpv = 0.5; - else - tmpv = 0.5 - 1.0 / (exp(ws) + 1.0); - for(i = 0; i < n; i++) { - REALTYPE tmp = smps[i] * ws; - if(tmp < -10.0) - tmp = -10.0; - else - if(tmp > 10.0) - tmp = 10.0; - tmp = 0.5 - 1.0 / (exp(tmp) + 1.0); - smps[i] = tmp / tmpv; - } - break; - /**\todo update to Distorsion::changepar (Ptype max) if there is added more waveshapings functions*/ - } -} - - -Distorsion::Distorsion(const int &insertion_, - REALTYPE *efxoutl_, - REALTYPE *efxoutr_) - :Effect(insertion_, efxoutl_, efxoutr_, NULL, 0) -{ - lpfl = new AnalogFilter(2, 22000, 1, 0); - lpfr = new AnalogFilter(2, 22000, 1, 0); - hpfl = new AnalogFilter(3, 20, 1, 0); - hpfr = new AnalogFilter(3, 20, 1, 0); - - - //default values - Pvolume = 50; - Plrcross = 40; - Pdrive = 90; - Plevel = 64; - Ptype = 0; - Pnegate = 0; - Plpf = 127; - Phpf = 0; - Pstereo = 0; - Pprefiltering = 0; - - setpreset(Ppreset); - cleanup(); -} - -Distorsion::~Distorsion() -{ - delete lpfl; - delete lpfr; - delete hpfl; - delete hpfr; -} - -/* - * Cleanup the effect - */ -void Distorsion::cleanup() -{ - lpfl->cleanup(); - hpfl->cleanup(); - lpfr->cleanup(); - hpfr->cleanup(); -} - - -/* - * Apply the filters - */ - -void Distorsion::applyfilters(REALTYPE *efxoutl, REALTYPE *efxoutr) -{ - lpfl->filterout(efxoutl); - hpfl->filterout(efxoutl); - if(Pstereo != 0) { //stereo - lpfr->filterout(efxoutr); - hpfr->filterout(efxoutr); - } -} - - -/* - * Effect output - */ -void Distorsion::out(const Stereo &smp) -{ - int i; - REALTYPE l, r, lout, rout; - - REALTYPE inputvol = pow(5.0, (Pdrive - 32.0) / 127.0); - if(Pnegate != 0) - inputvol *= -1.0; - - if(Pstereo != 0) { //Stereo - for(i = 0; i < SOUND_BUFFER_SIZE; i++) { - efxoutl[i] = smp.l[i] * inputvol * panning; - efxoutr[i] = smp.r[i] * inputvol * (1.0 - panning); - } - } - else { - for(i = 0; i < SOUND_BUFFER_SIZE; i++) - efxoutl[i] = - (smp.l[i] * panning + smp.r[i] * (1.0 - panning)) * inputvol; - ; - } - - if(Pprefiltering != 0) - applyfilters(efxoutl, efxoutr); - - //no optimised, yet (no look table) - waveshapesmps(SOUND_BUFFER_SIZE, efxoutl, Ptype + 1, Pdrive); - if(Pstereo != 0) - waveshapesmps(SOUND_BUFFER_SIZE, efxoutr, Ptype + 1, Pdrive); - - if(Pprefiltering == 0) - applyfilters(efxoutl, efxoutr); - - if(Pstereo == 0) - for(i = 0; i < SOUND_BUFFER_SIZE; i++) - efxoutr[i] = efxoutl[i]; - - REALTYPE level = dB2rap(60.0 * Plevel / 127.0 - 40.0); - for(i = 0; i < SOUND_BUFFER_SIZE; i++) { - lout = efxoutl[i]; - rout = efxoutr[i]; - l = lout * (1.0 - lrcross) + rout * lrcross; - r = rout * (1.0 - lrcross) + lout * lrcross; - lout = l; - rout = r; - - efxoutl[i] = lout * 2.0 * level; - efxoutr[i] = rout * 2.0 * level; - } -} - - -/* - * Parameter control - */ -void Distorsion::setvolume(unsigned char Pvolume) -{ - this->Pvolume = Pvolume; - - if(insertion == 0) { - outvolume = pow(0.01, (1.0 - Pvolume / 127.0)) * 4.0; - volume = 1.0; - } - else - volume = outvolume = Pvolume / 127.0; - ; - if(Pvolume == 0) - cleanup(); -} - -void Distorsion::setpanning(unsigned char Ppanning) -{ - this->Ppanning = Ppanning; - panning = (Ppanning + 0.5) / 127.0; -} - - -void Distorsion::setlrcross(unsigned char Plrcross) -{ - this->Plrcross = Plrcross; - lrcross = Plrcross / 127.0 * 1.0; -} - -void Distorsion::setlpf(unsigned char Plpf) -{ - this->Plpf = Plpf; - REALTYPE fr = exp(pow(Plpf / 127.0, 0.5) * log(25000.0)) + 40; - lpfl->setfreq(fr); - lpfr->setfreq(fr); -} - -void Distorsion::sethpf(unsigned char Phpf) -{ - this->Phpf = Phpf; - REALTYPE fr = exp(pow(Phpf / 127.0, 0.5) * log(25000.0)) + 20.0; - hpfl->setfreq(fr); - hpfr->setfreq(fr); -} - - -void Distorsion::setpreset(unsigned char npreset) -{ - const int PRESET_SIZE = 11; - const int NUM_PRESETS = 6; - unsigned char presets[NUM_PRESETS][PRESET_SIZE] = { - //Overdrive 1 - {127, 64, 35, 56, 70, 0, 0, 96, 0, 0, 0 }, - //Overdrive 2 - {127, 64, 35, 29, 75, 1, 0, 127, 0, 0, 0 }, - //A. Exciter 1 - {64, 64, 35, 75, 80, 5, 0, 127, 105, 1, 0 }, - //A. Exciter 2 - {64, 64, 35, 85, 62, 1, 0, 127, 118, 1, 0 }, - //Guitar Amp - {127, 64, 35, 63, 75, 2, 0, 55, 0, 0, 0 }, - //Quantisize - {127, 64, 35, 88, 75, 4, 0, 127, 0, 1, 0 } - }; - - - if(npreset >= NUM_PRESETS) - npreset = NUM_PRESETS - 1; - for(int n = 0; n < PRESET_SIZE; n++) - changepar(n, presets[npreset][n]); - if(insertion == 0) - changepar(0, (int) (presets[npreset][0] / 1.5)); //lower the volume if this is system effect - Ppreset = npreset; - cleanup(); -} - - -void Distorsion::changepar(int npar, unsigned char value) -{ - switch(npar) { - case 0: - setvolume(value); - break; - case 1: - setpanning(value); - break; - case 2: - setlrcross(value); - break; - case 3: - Pdrive = value; - break; - case 4: - Plevel = value; - break; - case 5: - if(value > 13) - Ptype = 13; //this must be increased if more distorsion types are added - else - Ptype = value; - break; - case 6: - if(value > 1) - Pnegate = 1; - else - Pnegate = value; - break; - case 7: - setlpf(value); - break; - case 8: - sethpf(value); - break; - case 9: - if(value > 1) - Pstereo = 1; - else - Pstereo = value; - break; - case 10: - Pprefiltering = value; - break; - } -} - -unsigned char Distorsion::getpar(int npar) const -{ - switch(npar) { - case 0: - return Pvolume; - break; - case 1: - return Ppanning; - break; - case 2: - return Plrcross; - break; - case 3: - return Pdrive; - break; - case 4: - return Plevel; - break; - case 5: - return Ptype; - break; - case 6: - return Pnegate; - break; - case 7: - return Plpf; - break; - case 8: - return Phpf; - break; - case 9: - return Pstereo; - break; - case 10: - return Pprefiltering; - break; - } - return 0; //in case of bogus parameter number -} - diff --git a/plugins/zynaddsubfx/src/Effects/Distorsion.h b/plugins/zynaddsubfx/src/Effects/Distorsion.h deleted file mode 100644 index 472af3ffd..000000000 --- a/plugins/zynaddsubfx/src/Effects/Distorsion.h +++ /dev/null @@ -1,75 +0,0 @@ -/* - ZynAddSubFX - a software synthesizer - - Distorsion.h - Distorsion Effect - Copyright (C) 2002-2005 Nasca Octavian Paul - Author: Nasca Octavian Paul - - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License - as published by the Free Software Foundation. - - 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 (version 2 or later) for more details. - - You should have received a copy of the GNU General Public License (version 2) - along with this program; if not, write to the Free Software Foundation, - Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -*/ - -#ifndef DISTORSION_H -#define DISTORSION_H - -#include "../globals.h" -#include "../DSP/AnalogFilter.h" -#include "Effect.h" - -//Waveshaping(called by Distorsion effect and waveshape from OscilGen) -void waveshapesmps(int n, - REALTYPE *smps, - unsigned char type, - unsigned char drive); -/**Distortion Effect*/ -class Distorsion:public Effect -{ - public: - Distorsion(const int &insertion, REALTYPE *efxoutl_, REALTYPE *efxoutr_); - ~Distorsion(); - void out(const Stereo &smp); - void setpreset(unsigned char npreset); - void changepar(int npar, unsigned char value); - unsigned char getpar(int npar) const; - void cleanup(); - void applyfilters(REALTYPE *efxoutl, REALTYPE *efxoutr); - - private: - //Parametrii - unsigned char Pvolume; //Volume or E/R - unsigned char Ppanning; //Panning - unsigned char Plrcross; // L/R Mixing - unsigned char Pdrive; //the input amplification - unsigned char Plevel; //the output amplification - unsigned char Ptype; //Distorsion type - unsigned char Pnegate; //if the input is negated - unsigned char Plpf; //lowpass filter - unsigned char Phpf; //highpass filter - unsigned char Pstereo; //0=mono,1=stereo - unsigned char Pprefiltering; //if you want to do the filtering before the distorsion - - void setvolume(unsigned char Pvolume); - void setpanning(unsigned char Ppanning); - void setlrcross(unsigned char Plrcross); - void setlpf(unsigned char Plpf); - void sethpf(unsigned char Phpf); - - //Real Parameters - REALTYPE panning, lrcross; - AnalogFilter *lpfl, *lpfr, *hpfl, *hpfr; -}; - - -#endif - diff --git a/plugins/zynaddsubfx/src/Effects/DynamicFilter.cpp b/plugins/zynaddsubfx/src/Effects/DynamicFilter.cpp deleted file mode 100644 index b60f40142..000000000 --- a/plugins/zynaddsubfx/src/Effects/DynamicFilter.cpp +++ /dev/null @@ -1,352 +0,0 @@ -/* - ZynAddSubFX - a software synthesizer - - DynamicFilter.cpp - "WahWah" effect and others - Copyright (C) 2002-2005 Nasca Octavian Paul - Author: Nasca Octavian Paul - - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License - as published by the Free Software Foundation. - - 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 (version 2 or later) for more details. - - You should have received a copy of the GNU General Public License (version 2) - along with this program; if not, write to the Free Software Foundation, - Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -*/ - -#include -#include "DynamicFilter.h" - -DynamicFilter::DynamicFilter(int insertion_, - REALTYPE *efxoutl_, - REALTYPE *efxoutr_) - :Effect(insertion_, efxoutl_, efxoutr_, new FilterParams(0, 64, 64), 0), - Pvolume(110), Ppanning(64), Pdepth(0), Pampsns(90), - Pampsnsinv(0), Pampsmooth(60), - filterl(NULL), filterr(NULL) -{ - setpreset(Ppreset); - cleanup(); -} - -DynamicFilter::~DynamicFilter() -{ - delete filterpars; - delete filterl; - delete filterr; -} - - -/* - * Apply the effect - */ -void DynamicFilter::out(const Stereo &smp) -{ - int i; - if(filterpars->changed) { - filterpars->changed = false; - cleanup(); - } - - REALTYPE lfol, lfor; - lfo.effectlfoout(&lfol, &lfor); - lfol *= depth * 5.0; - lfor *= depth * 5.0; - REALTYPE freq = filterpars->getfreq(); - REALTYPE q = filterpars->getq(); - - for(i = 0; i < SOUND_BUFFER_SIZE; i++) { - efxoutl[i] = smp.l[i]; - efxoutr[i] = smp.r[i]; - - REALTYPE x = (fabs(smp.l[i]) + fabs(smp.l[i])) * 0.5; - ms1 = ms1 * (1.0 - ampsmooth) + x * ampsmooth + 1e-10; - } - - - REALTYPE ampsmooth2 = pow(ampsmooth, 0.2) * 0.3; - ms2 = ms2 * (1.0 - ampsmooth2) + ms1 * ampsmooth2; - ms3 = ms3 * (1.0 - ampsmooth2) + ms2 * ampsmooth2; - ms4 = ms4 * (1.0 - ampsmooth2) + ms3 * ampsmooth2; - REALTYPE rms = (sqrt(ms4)) * ampsns; - - REALTYPE frl = filterl->getrealfreq(freq + lfol + rms); - REALTYPE frr = filterr->getrealfreq(freq + lfor + rms); - - filterl->setfreq_and_q(frl, q); - filterr->setfreq_and_q(frr, q); - - - filterl->filterout(efxoutl); - filterr->filterout(efxoutr); - - //panning - for(i = 0; i < SOUND_BUFFER_SIZE; i++) { - efxoutl[i] *= panning; - efxoutr[i] *= (1.0 - panning); - } -} - -/* - * Cleanup the effect - */ -void DynamicFilter::cleanup() -{ - reinitfilter(); - ms1 = 0.0; - ms2 = 0.0; - ms3 = 0.0; - ms4 = 0.0; -} - - -/* - * Parameter control - */ - -void DynamicFilter::setdepth(unsigned char Pdepth) -{ - this->Pdepth = Pdepth; - depth = pow((Pdepth / 127.0), 2.0); -} - - -void DynamicFilter::setvolume(unsigned char Pvolume) -{ - this->Pvolume = Pvolume; - outvolume = Pvolume / 127.0; - if(insertion == 0) - volume = 1.0; - else - volume = outvolume; -} - -void DynamicFilter::setpanning(unsigned char Ppanning) -{ - this->Ppanning = Ppanning; - panning = Ppanning / 127.0; -} - - -void DynamicFilter::setampsns(unsigned char Pampsns) -{ - ampsns = pow(Pampsns / 127.0, 2.5) * 10.0; - if(Pampsnsinv != 0) - ampsns = -ampsns; - ampsmooth = exp(-Pampsmooth / 127.0 * 10.0) * 0.99; - this->Pampsns = Pampsns; -} - -void DynamicFilter::reinitfilter() -{ - if(filterl != NULL) - delete (filterl); - if(filterr != NULL) - delete (filterr); - filterl = new Filter(filterpars); - filterr = new Filter(filterpars); -} - -void DynamicFilter::setpreset(unsigned char npreset) -{ - const int PRESET_SIZE = 10; - const int NUM_PRESETS = 5; - unsigned char presets[NUM_PRESETS][PRESET_SIZE] = { - //WahWah - {110, 64, 80, 0, 0, 64, 0, 90, 0, 60}, - //AutoWah - {110, 64, 70, 0, 0, 80, 70, 0, 0, 60}, - //Sweep - {100, 64, 30, 0, 0, 50, 80, 0, 0, 60}, - //VocalMorph1 - {110, 64, 80, 0, 0, 64, 0, 64, 0, 60}, - //VocalMorph1 - {127, 64, 50, 0, 0, 96, 64, 0, 0, 60} - }; - - if(npreset >= NUM_PRESETS) - npreset = NUM_PRESETS - 1; - for(int n = 0; n < PRESET_SIZE; n++) - changepar(n, presets[npreset][n]); - - filterpars->defaults(); - switch(npreset) { - case 0: - filterpars->Pcategory = 0; - filterpars->Ptype = 2; - filterpars->Pfreq = 45; - filterpars->Pq = 64; - filterpars->Pstages = 1; - filterpars->Pgain = 64; - break; - case 1: - filterpars->Pcategory = 2; - filterpars->Ptype = 0; - filterpars->Pfreq = 72; - filterpars->Pq = 64; - filterpars->Pstages = 0; - filterpars->Pgain = 64; - break; - case 2: - filterpars->Pcategory = 0; - filterpars->Ptype = 4; - filterpars->Pfreq = 64; - filterpars->Pq = 64; - filterpars->Pstages = 2; - filterpars->Pgain = 64; - break; - case 3: - filterpars->Pcategory = 1; - filterpars->Ptype = 0; - filterpars->Pfreq = 50; - filterpars->Pq = 70; - filterpars->Pstages = 1; - filterpars->Pgain = 64; - - filterpars->Psequencesize = 2; - // "I" - filterpars->Pvowels[0].formants[0].freq = 34; - filterpars->Pvowels[0].formants[0].amp = 127; - filterpars->Pvowels[0].formants[0].q = 64; - filterpars->Pvowels[0].formants[1].freq = 99; - filterpars->Pvowels[0].formants[1].amp = 122; - filterpars->Pvowels[0].formants[1].q = 64; - filterpars->Pvowels[0].formants[2].freq = 108; - filterpars->Pvowels[0].formants[2].amp = 112; - filterpars->Pvowels[0].formants[2].q = 64; - // "A" - filterpars->Pvowels[1].formants[0].freq = 61; - filterpars->Pvowels[1].formants[0].amp = 127; - filterpars->Pvowels[1].formants[0].q = 64; - filterpars->Pvowels[1].formants[1].freq = 71; - filterpars->Pvowels[1].formants[1].amp = 121; - filterpars->Pvowels[1].formants[1].q = 64; - filterpars->Pvowels[1].formants[2].freq = 99; - filterpars->Pvowels[1].formants[2].amp = 117; - filterpars->Pvowels[1].formants[2].q = 64; - break; - case 4: - filterpars->Pcategory = 1; - filterpars->Ptype = 0; - filterpars->Pfreq = 64; - filterpars->Pq = 70; - filterpars->Pstages = 1; - filterpars->Pgain = 64; - - filterpars->Psequencesize = 2; - filterpars->Pnumformants = 2; - filterpars->Pvowelclearness = 0; - - filterpars->Pvowels[0].formants[0].freq = 70; - filterpars->Pvowels[0].formants[0].amp = 127; - filterpars->Pvowels[0].formants[0].q = 64; - filterpars->Pvowels[0].formants[1].freq = 80; - filterpars->Pvowels[0].formants[1].amp = 122; - filterpars->Pvowels[0].formants[1].q = 64; - - filterpars->Pvowels[1].formants[0].freq = 20; - filterpars->Pvowels[1].formants[0].amp = 127; - filterpars->Pvowels[1].formants[0].q = 64; - filterpars->Pvowels[1].formants[1].freq = 100; - filterpars->Pvowels[1].formants[1].amp = 121; - filterpars->Pvowels[1].formants[1].q = 64; - break; - } - -// for (int i=0;i<5;i++){ -// printf("freq=%d amp=%d q=%d\n",filterpars->Pvowels[0].formants[i].freq,filterpars->Pvowels[0].formants[i].amp,filterpars->Pvowels[0].formants[i].q); -// }; - if(insertion == 0) - changepar(0, presets[npreset][0] / 2); //lower the volume if this is system effect - Ppreset = npreset; - - reinitfilter(); -} - - -void DynamicFilter::changepar(int npar, unsigned char value) -{ - switch(npar) { - case 0: - setvolume(value); - break; - case 1: - setpanning(value); - break; - case 2: - lfo.Pfreq = value; - lfo.updateparams(); - break; - case 3: - lfo.Prandomness = value; - lfo.updateparams(); - break; - case 4: - lfo.PLFOtype = value; - lfo.updateparams(); - break; - case 5: - lfo.Pstereo = value; - lfo.updateparams(); - break; - case 6: - setdepth(value); - break; - case 7: - setampsns(value); - break; - case 8: - Pampsnsinv = value; - setampsns(Pampsns); - break; - case 9: - Pampsmooth = value; - setampsns(Pampsns); - break; - } -} - -unsigned char DynamicFilter::getpar(int npar) const -{ - switch(npar) { - case 0: - return Pvolume; - break; - case 1: - return Ppanning; - break; - case 2: - return lfo.Pfreq; - break; - case 3: - return lfo.Prandomness; - break; - case 4: - return lfo.PLFOtype; - break; - case 5: - return lfo.Pstereo; - break; - case 6: - return Pdepth; - break; - case 7: - return Pampsns; - break; - case 8: - return Pampsnsinv; - break; - case 9: - return Pampsmooth; - break; - default: - return 0; - } -} - diff --git a/plugins/zynaddsubfx/src/Effects/DynamicFilter.h b/plugins/zynaddsubfx/src/Effects/DynamicFilter.h deleted file mode 100644 index 6ce10f5ee..000000000 --- a/plugins/zynaddsubfx/src/Effects/DynamicFilter.h +++ /dev/null @@ -1,72 +0,0 @@ -/* - ZynAddSubFX - a software synthesizer - - DynamicFilter.h - "WahWah" effect and others - Copyright (C) 2002-2005 Nasca Octavian Paul - Author: Nasca Octavian Paul - - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License - as published by the Free Software Foundation. - - 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 (version 2 or later) for more details. - - You should have received a copy of the GNU General Public License (version 2) - along with this program; if not, write to the Free Software Foundation, - Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -*/ - -#ifndef DYNAMICFILTER_H -#define DYNAMICFILTER_H -#include "../globals.h" -#include "Effect.h" -#include "EffectLFO.h" - -#include "../DSP/Filter.h" -/**DynamicFilter Effect*/ -class DynamicFilter:public Effect -{ - public: - DynamicFilter(int insetion_, REALTYPE *efxoutl_, REALTYPE *efxoutr_); - ~DynamicFilter(); - void out(const Stereo &smp); - - void setpreset(unsigned char npreset); - void changepar(int npar, unsigned char value); - unsigned char getpar(int npar) const; - void cleanup(); - -// void setdryonly(); - - private: - //Parametrii DynamicFilter - EffectLFO lfo; //lfo-ul DynamicFilter - unsigned char Pvolume; - unsigned char Ppanning; - unsigned char Pdepth; /** -#include "EQ.h" - -EQ::EQ(const int &insertion_, REALTYPE *efxoutl_, REALTYPE *efxoutr_) - :Effect(insertion_, efxoutl_, efxoutr_, NULL, 0) -{ - for(int i = 0; i < MAX_EQ_BANDS; i++) { - filter[i].Ptype = 0; - filter[i].Pfreq = 64; - filter[i].Pgain = 64; - filter[i].Pq = 64; - filter[i].Pstages = 0; - filter[i].l = new AnalogFilter(6, 1000.0, 1.0, 0); - filter[i].r = new AnalogFilter(6, 1000.0, 1.0, 0); - } - //default values - Pvolume = 50; - - setpreset(Ppreset); - cleanup(); -} - -EQ::~EQ() -{} - -void EQ::cleanup() -{ - for(int i = 0; i < MAX_EQ_BANDS; i++) { - filter[i].l->cleanup(); - filter[i].r->cleanup(); - } -} - -void EQ::out(const Stereo &smp) -{ - int i; - for(i = 0; i < SOUND_BUFFER_SIZE; i++) { - efxoutl[i] = smp.l[i] * volume; - efxoutr[i] = smp.r[i] * volume; - } - - for(i = 0; i < MAX_EQ_BANDS; i++) { - if(filter[i].Ptype == 0) - continue; - filter[i].l->filterout(efxoutl); - filter[i].r->filterout(efxoutr); - } -} - - -/* - * Parameter control - */ -void EQ::setvolume(unsigned char Pvolume) -{ - this->Pvolume = Pvolume; - - outvolume = pow(0.005, (1.0 - Pvolume / 127.0)) * 10.0; - if(insertion == 0) - volume = 1.0; - else - volume = outvolume; - ; -} - - -void EQ::setpreset(unsigned char npreset) -{ - const int PRESET_SIZE = 1; - const int NUM_PRESETS = 2; - unsigned char presets[NUM_PRESETS][PRESET_SIZE] = { - //EQ 1 - {67}, - //EQ 2 - {67} - }; - - if(npreset >= NUM_PRESETS) - npreset = NUM_PRESETS - 1; - for(int n = 0; n < PRESET_SIZE; n++) - changepar(n, presets[npreset][n]); - Ppreset = npreset; -} - - -void EQ::changepar(int npar, unsigned char value) -{ - switch(npar) { - case 0: - setvolume(value); - break; - } - if(npar < 10) - return; - - int nb = (npar - 10) / 5; //number of the band (filter) - if(nb >= MAX_EQ_BANDS) - return; - int bp = npar % 5; //band paramenter - - REALTYPE tmp; - switch(bp) { - case 0: - filter[nb].Ptype = value; - if(value > 9) - filter[nb].Ptype = 0; //has to be changed if more filters will be added - if(filter[nb].Ptype != 0) { - filter[nb].l->settype(value - 1); - filter[nb].r->settype(value - 1); - } - break; - case 1: - filter[nb].Pfreq = value; - tmp = 600.0 * pow(30.0, (value - 64.0) / 64.0); - filter[nb].l->setfreq(tmp); - filter[nb].r->setfreq(tmp); - break; - case 2: - filter[nb].Pgain = value; - tmp = 30.0 * (value - 64.0) / 64.0; - filter[nb].l->setgain(tmp); - filter[nb].r->setgain(tmp); - break; - case 3: - filter[nb].Pq = value; - tmp = pow(30.0, (value - 64.0) / 64.0); - filter[nb].l->setq(tmp); - filter[nb].r->setq(tmp); - break; - case 4: - filter[nb].Pstages = value; - if(value >= MAX_FILTER_STAGES) - filter[nb].Pstages = MAX_FILTER_STAGES - 1; - filter[nb].l->setstages(value); - filter[nb].r->setstages(value); - break; - } -} - -unsigned char EQ::getpar(int npar) const -{ - switch(npar) { - case 0: - return Pvolume; - break; - } - - if(npar < 10) - return 0; - - int nb = (npar - 10) / 5; //number of the band (filter) - if(nb >= MAX_EQ_BANDS) - return 0; - int bp = npar % 5; //band paramenter - switch(bp) { - case 0: - return filter[nb].Ptype; - break; - case 1: - return filter[nb].Pfreq; - break; - case 2: - return filter[nb].Pgain; - break; - case 3: - return filter[nb].Pq; - break; - case 4: - return filter[nb].Pstages; - break; - } - - return 0; //in case of bogus parameter number -} - - - - -REALTYPE EQ::getfreqresponse(REALTYPE freq) -{ - REALTYPE resp = 1.0; - - for(int i = 0; i < MAX_EQ_BANDS; i++) { - if(filter[i].Ptype == 0) - continue; - resp *= filter[i].l->H(freq); - } - return rap2dB(resp * outvolume); -} - diff --git a/plugins/zynaddsubfx/src/Effects/EQ.h b/plugins/zynaddsubfx/src/Effects/EQ.h deleted file mode 100644 index 7ac328404..000000000 --- a/plugins/zynaddsubfx/src/Effects/EQ.h +++ /dev/null @@ -1,58 +0,0 @@ -/* - ZynAddSubFX - a software synthesizer - - EQ.h - EQ Effect - Copyright (C) 2002-2005 Nasca Octavian Paul - Author: Nasca Octavian Paul - - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License - as published by the Free Software Foundation. - - 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 (version 2 or later) for more details. - - You should have received a copy of the GNU General Public License (version 2) - along with this program; if not, write to the Free Software Foundation, - Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -*/ - -#ifndef EQ_H -#define EQ_H - -#include "../globals.h" -#include "../DSP/AnalogFilter.h" -#include "Effect.h" - -/**EQ Effect*/ -class EQ:public Effect -{ - public: - EQ(const int &insertion_, REALTYPE *efxoutl_, REALTYPE *efxoutr_); - ~EQ(); - void out(const Stereo &smp); - void setpreset(unsigned char npreset); - void changepar(int npar, unsigned char value); - unsigned char getpar(int npar) const; - void cleanup(); - REALTYPE getfreqresponse(REALTYPE freq); - private: - //Parameters - unsigned char Pvolume; /** -#include "Echo.h" - -#define MAX_DELAY 2 - -Echo::Echo(const int &insertion_, - REALTYPE *const efxoutl_, - REALTYPE *const efxoutr_) - :Effect(insertion_, efxoutl_, efxoutr_, NULL, 0), - samplerate(SAMPLE_RATE), - Pvolume(50), Ppanning(64), Pdelay(60), - Plrdelay(100), Plrcross(100), Pfb(40), Phidamp(60), - delayTime(1), lrdelay(0), avgDelay(0), - delay(new REALTYPE[(int)(MAX_DELAY * samplerate)], - new REALTYPE[(int)(MAX_DELAY * samplerate)]), - old(0.0), pos(0), delta(1), ndelta(1) -{ - initdelays(); - setpreset(Ppreset); -} - -Echo::~Echo() -{ - delete[] delay.l; - delete[] delay.r; -} - -/* - * Cleanup the effect - */ -void Echo::cleanup() -{ - memset(delay.l,0,MAX_DELAY*samplerate*sizeof(REALTYPE)); - memset(delay.r,0,MAX_DELAY*samplerate*sizeof(REALTYPE)); - old = Stereo(0.0); -} - -inline int max(int a, int b) -{ - return a > b ? a : b; -} - -/* - * Initialize the delays - */ -void Echo::initdelays() -{ - cleanup(); - //number of seconds to delay left chan - float dl = avgDelay - lrdelay; - - //number of seconds to delay right chan - float dr = avgDelay + lrdelay; - - ndelta.l = max(1,(int) (dl * samplerate)); - ndelta.r = max(1,(int) (dr * samplerate)); -} - -void Echo::out(const Stereo &input) -{ - REALTYPE ldl, rdl; - - for(int i = 0; i < SOUND_BUFFER_SIZE; ++i) { - ldl = delay.l[pos.l]; - rdl = delay.r[pos.r]; - ldl = ldl * (1.0 - lrcross) + rdl * lrcross; - rdl = rdl * (1.0 - lrcross) + ldl * lrcross; - - efxoutl[i] = ldl * 2.0; - efxoutr[i] = rdl * 2.0; - - ldl = input.l[i] * panning - ldl * fb; - rdl = input.r[i] * (1.0 - panning) - rdl * fb; - - //LowPass Filter - old.l = delay.l[(pos.l+delta.l)%(MAX_DELAY * samplerate)] = ldl * hidamp + old.l * (1.0 - hidamp); - old.r = delay.r[(pos.r+delta.r)%(MAX_DELAY * samplerate)] = rdl * hidamp + old.r * (1.0 - hidamp); - - //increment - ++pos.l;// += delta.l; - ++pos.r;// += delta.r; - - //ensure that pos is still in bounds - pos.l %= MAX_DELAY * samplerate; - pos.r %= MAX_DELAY * samplerate; - - //adjust delay if needed - delta.l = (15*delta.l + ndelta.l)/16; - delta.r = (15*delta.r + ndelta.r)/16; - } -} - - -/* - * Parameter control - */ -void Echo::setvolume(unsigned char Pvolume) -{ - this->Pvolume = Pvolume; - - if(insertion == 0) { - outvolume = pow(0.01, (1.0 - Pvolume / 127.0)) * 4.0; - volume = 1.0; - } - else - volume = outvolume = Pvolume / 127.0; - ; - if(Pvolume == 0) - cleanup(); -} - -void Echo::setpanning(unsigned char Ppanning) -{ - this->Ppanning = Ppanning; - panning = (Ppanning + 0.5) / 127.0; -} - -void Echo::setdelay(unsigned char Pdelay) -{ - this->Pdelay=Pdelay; - avgDelay=(Pdelay/127.0*1.5);//0 .. 1.5 sec - initdelays(); -} - -void Echo::setlrdelay(unsigned char Plrdelay) -{ - REALTYPE tmp; - this->Plrdelay = Plrdelay; - tmp = - (pow(2, fabs(Plrdelay - 64.0) / 64.0 * 9) - 1.0) / 1000.0; - if(Plrdelay < 64.0) - tmp = -tmp; - lrdelay = tmp; - initdelays(); -} - -void Echo::setlrcross(unsigned char Plrcross) -{ - this->Plrcross = Plrcross; - lrcross = Plrcross / 127.0 * 1.0; -} - -void Echo::setfb(unsigned char Pfb) -{ - this->Pfb = Pfb; - fb = Pfb / 128.0; -} - -void Echo::sethidamp(unsigned char Phidamp) -{ - this->Phidamp = Phidamp; - hidamp = 1.0 - Phidamp / 127.0; -} - -void Echo::setpreset(unsigned char npreset) -{ - /**\todo see if the preset array can be replaced with a struct or a class*/ - const int PRESET_SIZE = 7; - const int NUM_PRESETS = 9; - unsigned char presets[NUM_PRESETS][PRESET_SIZE] = { - //Echo 1 - {67, 64, 35, 64, 30, 59, 0 }, - //Echo 2 - {67, 64, 21, 64, 30, 59, 0 }, - //Echo 3 - {67, 75, 60, 64, 30, 59, 10 }, - //Simple Echo - {67, 60, 44, 64, 30, 0, 0 }, - //Canyon - {67, 60, 102, 50, 30, 82, 48 }, - //Panning Echo 1 - {67, 64, 44, 17, 0, 82, 24 }, - //Panning Echo 2 - {81, 60, 46, 118, 100, 68, 18 }, - //Panning Echo 3 - {81, 60, 26, 100, 127, 67, 36 }, - //Feedback Echo - {62, 64, 28, 64, 100, 90, 55 } - }; - - - if(npreset >= NUM_PRESETS) - npreset = NUM_PRESETS - 1; - for(int n = 0; n < PRESET_SIZE; n++) - changepar(n, presets[npreset][n]); - if(insertion) - setvolume(presets[npreset][0] / 2); //lower the volume if this is insertion effect - Ppreset = npreset; -} - - -void Echo::changepar(int npar, unsigned char value) -{ - switch(npar) { - case 0: - setvolume(value); - break; - case 1: - setpanning(value); - break; - case 2: - setdelay(value); - break; - case 3: - setlrdelay(value); - break; - case 4: - setlrcross(value); - break; - case 5: - setfb(value); - break; - case 6: - sethidamp(value); - break; - } -} - -unsigned char Echo::getpar(int npar) const -{ - switch(npar) { - case 0: - return Pvolume; - break; - case 1: - return Ppanning; - break; - case 2: - return Pdelay; - break; - case 3: - return Plrdelay; - break; - case 4: - return Plrcross; - break; - case 5: - return Pfb; - break; - case 6: - return Phidamp; - break; - } - return 0; // in case of bogus parameter number -} - diff --git a/plugins/zynaddsubfx/src/Effects/Echo.h b/plugins/zynaddsubfx/src/Effects/Echo.h deleted file mode 100644 index 3701c5c8f..000000000 --- a/plugins/zynaddsubfx/src/Effects/Echo.h +++ /dev/null @@ -1,140 +0,0 @@ -/* - ZynAddSubFX - a software synthesizer - - Echo.h - Echo Effect - Copyright (C) 2002-2005 Nasca Octavian Paul - Author: Nasca Octavian Paul - - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License - as published by the Free Software Foundation. - - 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 (version 2 or later) for more details. - - You should have received a copy of the GNU General Public License (version 2) - along with this program; if not, write to the Free Software Foundation, - Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -*/ - -#ifndef ECHO_H -#define ECHO_H - -#include "../globals.h" -#include "Effect.h" -#include "../Misc/Stereo.h" -#include "../Samples/Sample.h" - -/**Echo Effect*/ -class Echo:public Effect -{ - public: - - /** - * The Constructor For Echo - * @param insertion_ integer to determine if Echo is an insertion effect - * or not - * @param efxoutl_ Effect out Left Channel - * @param efxoutr_ Effect out Right Channel - * @return An initialized Echo Object - */ - Echo(const int &insertion_, - REALTYPE *const efxoutl_, - REALTYPE *const efxoutr_); - - /** - * The destructor - */ - ~Echo(); - - void out(const Stereo &input); - - /** - * Sets the state of Echo to the specified preset - * @param npreset number of chosen preset - */ - void setpreset(unsigned char npreset); - - /** - * Sets the value of the chosen variable - * - * The possible parameters are: - * -# Volume - * -# Panning - * -# Delay - * -# L/R Delay - * -# L/R Crossover - * -# Feedback - * -# Dampening - * @param npar number of chosen parameter - * @param value the new value - */ - void changepar(int npar, unsigned char value); - - /** - * Gets the specified parameter - * - * The possible parameters are - * -# Volume - * -# Panning - * -# Delay - * -# L/R Delay - * -# L/R Crossover - * -# Feedback - * -# Dampening - * @param npar number of chosen parameter - * @return value of parameter - */ - unsigned char getpar(int npar) const; - - int getnumparams(); - - /**Zeros out the state of the Echo*/ - void cleanup(); - - /**\todo This function needs to be implemented or the prototype should be removed*/ - void setdryonly(); - private: - int samplerate; - - //Parameters - char Pvolume; /**<#1 Volume or Dry/Wetness*/ - char Ppanning; /**<#2 Panning*/ - char Pdelay; /**<#3 Delay of the Echo*/ - char Plrdelay; /**<#4 L/R delay difference*/ - char Plrcross; /**<#5 L/R Mixing*/ - char Pfb; /**<#6Feedback*/ - char Phidamp; /**<#7Dampening of the Echo*/ - - void setvolume(unsigned char Pvolume); - void setpanning(unsigned char Ppanning); - void setdelay(unsigned char Pdelay); - void setlrdelay(unsigned char Plrdelay); - void setlrcross(unsigned char Plrcross); - void setfb(unsigned char Pfb); - void sethidamp(unsigned char Phidamp); - - //Real Parameters - REALTYPE panning, lrcross, fb, hidamp; - //Left/Right delay lengths - Stereo delayTime; - REALTYPE lrdelay; - REALTYPE avgDelay; - - void initdelays(); - //2 channel ring buffer - Stereo delay; - Stereo old; - - //position of reading/writing from delaysample - Stereo pos; - //step size for delay buffer - Stereo delta; - Stereo ndelta; -}; - -#endif - diff --git a/plugins/zynaddsubfx/src/Effects/Effect.cpp b/plugins/zynaddsubfx/src/Effects/Effect.cpp deleted file mode 100644 index ab44312ed..000000000 --- a/plugins/zynaddsubfx/src/Effects/Effect.cpp +++ /dev/null @@ -1,36 +0,0 @@ -/* - ZynAddSubFX - a software synthesizer - - Effect.cpp - this class is inherited by the all effects(Reverb, Echo, ..) - Copyright (C) 2002-2005 Nasca Octavian Paul - Author: Nasca Octavian Paul - - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License - as published by the Free Software Foundation. - - 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 (version 2 or later) for more details. - - You should have received a copy of the GNU General Public License (version 2) - along with this program; if not, write to the Free Software Foundation, - Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -*/ - -#include "Effect.h" - -Effect::Effect(bool insertion_, REALTYPE *const efxoutl_, - REALTYPE *const efxoutr_, FilterParams *filterpars_, - const unsigned char &Ppreset_) - :Ppreset(Ppreset_), efxoutl(efxoutl_), efxoutr(efxoutr_), - filterpars(filterpars_), insertion(insertion_) -{} - -void Effect::out(REALTYPE *const smpsl, REALTYPE *const smpsr) -{ - out(Stereo(smpsl,smpsr)); -}; - diff --git a/plugins/zynaddsubfx/src/Effects/Effect.h b/plugins/zynaddsubfx/src/Effects/Effect.h deleted file mode 100644 index eddbbba5c..000000000 --- a/plugins/zynaddsubfx/src/Effects/Effect.h +++ /dev/null @@ -1,105 +0,0 @@ -/* - ZynAddSubFX - a software synthesizer - - Effect.h - this class is inherited by the all effects(Reverb, Echo, ..) - Copyright (C) 2002-2005 Nasca Octavian Paul - Author: Nasca Octavian Paul - - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License - as published by the Free Software Foundation. - - 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 (version 2 or later) for more details. - - You should have received a copy of the GNU General Public License (version 2) - along with this program; if not, write to the Free Software Foundation, - Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -*/ - -#ifndef EFFECT_H -#define EFFECT_H - -#include "../Misc/Util.h" -#include "../globals.h" -#include "../Params/FilterParams.h" -#include "../Misc/Stereo.h" - - -/**this class is inherited by the all effects(Reverb, Echo, ..)*/ -class Effect -{ - public: - /** - * Effect Constructor - * @param insertion_ 1 when it is an insertion Effect and 0 when it - * is not an insertion Effect - * @param efxoutl_ Effect output buffer Left channel - * @param efxoutr_ Effect output buffer Right channel - * @param filterpars_ pointer to FilterParams array - * @param Ppreset_ chosen preset - * @return Initialized Effect object*/ - Effect(bool insertion_, REALTYPE *const efxoutl_, - REALTYPE *const efxoutr_, FilterParams *filterpars_, - const unsigned char &Ppreset_); - /**Deconstructor - * - * Deconstructs the Effect and releases any resouces that it has - * allocated for itself*/ - virtual ~Effect() {} - /** - * Choose a preset - * @param npreset number of chosen preset*/ - virtual void setpreset(unsigned char npreset) = 0; - /**Change parameter npar to value - * @param npar chosen parameter - * @param value chosen new value*/ - virtual void changepar(int npar, unsigned char value) = 0; - /**Get the value of parameter npar - * @param npar chosen parameter - * @return the value of the parameter in an unsigned char or 0 if it - * does not exist*/ - virtual unsigned char getpar(int npar) const = 0; - /**Output result of effect based on the given buffers - * - * This method should result in the effect generating its results - * and placing them into the efxoutl and efxoutr buffers. - * Every Effect should overide this method. - * - * @param smpsl Input buffer for the Left channel - * @param smpsr Input buffer for the Right channel - */ - void out(REALTYPE *const smpsl, REALTYPE *const smpsr); - virtual void out(const Stereo &smp) = 0; - /**Reset the state of the effect*/ - virtual void cleanup() {} - /**This is only used for EQ (for user interface)*/ - virtual REALTYPE getfreqresponse(REALTYPE freq) { - return freq; - } - - unsigned char Ppreset; /***/ - - REALTYPE outvolume;/** -#include - -#include "EffectLFO.h" - - -EffectLFO::EffectLFO() -{ - xl = 0.0; - xr = 0.0; - Pfreq = 40; - Prandomness = 0; - PLFOtype = 0; - Pstereo = 96; - - updateparams(); - - ampl1 = (1 - lfornd) + lfornd * RND; - ampl2 = (1 - lfornd) + lfornd * RND; - ampr1 = (1 - lfornd) + lfornd * RND; - ampr2 = (1 - lfornd) + lfornd * RND; -} - -EffectLFO::~EffectLFO() -{} - - -/* - * Update the changed parameters - */ -void EffectLFO::updateparams() -{ - REALTYPE lfofreq = (pow(2, Pfreq / 127.0 * 10.0) - 1.0) * 0.03; - incx = fabs(lfofreq) * (REALTYPE)SOUND_BUFFER_SIZE / (REALTYPE)SAMPLE_RATE; - if(incx > 0.49999999) - incx = 0.499999999; //Limit the Frequency - - lfornd = Prandomness / 127.0; - if(lfornd < 0.0) - lfornd = 0.0; - else - if(lfornd > 1.0) - lfornd = 1.0; - - if(PLFOtype > 1) - PLFOtype = 1; //this has to be updated if more lfo's are added - lfotype = PLFOtype; - - xr = fmod(xl + (Pstereo - 64.0) / 127.0 + 1.0, 1.0); -} - - -/* - * Compute the shape of the LFO - */ -REALTYPE EffectLFO::getlfoshape(REALTYPE x) -{ - REALTYPE out; - switch(lfotype) { - case 1: //EffectLFO_TRIANGLE - if((x > 0.0) && (x < 0.25)) - out = 4.0 * x; - else - if((x > 0.25) && (x < 0.75)) - out = 2 - 4 * x; - else - out = 4.0 * x - 4.0; - break; - /**\todo more to be added here; also ::updateparams() need to be updated (to allow more lfotypes)*/ - default: - out = cos(x * 2 * PI); //EffectLFO_SINE - } - return out; -} - -/* - * LFO output - */ -void EffectLFO::effectlfoout(REALTYPE *outl, REALTYPE *outr) -{ - REALTYPE out; - - out = getlfoshape(xl); - if((lfotype == 0) || (lfotype == 1)) - out *= (ampl1 + xl * (ampl2 - ampl1)); - xl += incx; - if(xl > 1.0) { - xl -= 1.0; - ampl1 = ampl2; - ampl2 = (1.0 - lfornd) + lfornd * RND; - } - *outl = (out + 1.0) * 0.5; - - out = getlfoshape(xr); - if((lfotype == 0) || (lfotype == 1)) - out *= (ampr1 + xr * (ampr2 - ampr1)); - xr += incx; - if(xr > 1.0) { - xr -= 1.0; - ampr1 = ampr2; - ampr2 = (1.0 - lfornd) + lfornd * RND; - } - *outr = (out + 1.0) * 0.5; -} - diff --git a/plugins/zynaddsubfx/src/Effects/EffectLFO.h b/plugins/zynaddsubfx/src/Effects/EffectLFO.h deleted file mode 100644 index cc14d6652..000000000 --- a/plugins/zynaddsubfx/src/Effects/EffectLFO.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - ZynAddSubFX - a software synthesizer - - EffectLFO.h - Stereo LFO used by some effects - Copyright (C) 2002-2005 Nasca Octavian Paul - Author: Nasca Octavian Paul - - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License - as published by the Free Software Foundation. - - 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 (version 2 or later) for more details. - - You should have received a copy of the GNU General Public License (version 2) - along with this program; if not, write to the Free Software Foundation, - Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -*/ - -#ifndef EFFECT_LFO_H -#define EFFECT_LFO_H - -#include "../globals.h" -/**LFO for some of the Effect objects - * \todo see if this should inherit LFO*/ -class EffectLFO -{ - public: - EffectLFO(); - ~EffectLFO(); - void effectlfoout(REALTYPE *outl, REALTYPE *outr); - void updateparams(); - unsigned char Pfreq; - unsigned char Prandomness; - unsigned char PLFOtype; - unsigned char Pstereo; //"64"=0 - private: - REALTYPE getlfoshape(REALTYPE x); - - REALTYPE xl, xr; - REALTYPE incx; - REALTYPE ampl1, ampl2, ampr1, ampr2; //necessary for "randomness" - REALTYPE lfointensity; - REALTYPE lfornd; - char lfotype; /**\todo GET RID OF CHAR (replace with short or enum)*/ -}; - - -#endif - diff --git a/plugins/zynaddsubfx/src/Effects/EffectMgr.cpp b/plugins/zynaddsubfx/src/Effects/EffectMgr.cpp deleted file mode 100644 index eea0e3236..000000000 --- a/plugins/zynaddsubfx/src/Effects/EffectMgr.cpp +++ /dev/null @@ -1,357 +0,0 @@ -/* - ZynAddSubFX - a software synthesizer - - EffectMgr.cpp - Effect manager, an interface betwen the program and effects - Copyright (C) 2002-2005 Nasca Octavian Paul - Author: Nasca Octavian Paul - - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License - as published by the Free Software Foundation. - - 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 (version 2 or later) for more details. - - You should have received a copy of the GNU General Public License (version 2) - along with this program; if not, write to the Free Software Foundation, - Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -*/ - -#include "EffectMgr.h" -#include -using namespace std; - -EffectMgr::EffectMgr(int insertion_, pthread_mutex_t *mutex_) - :insertion(insertion_), - efxoutl(new REALTYPE[SOUND_BUFFER_SIZE]), - efxoutr(new REALTYPE[SOUND_BUFFER_SIZE]), - filterpars(NULL), nefx(0), efx(NULL), mutex(mutex_), dryonly(false) -{ - setpresettype("Peffect"); /**\todo Figure out what this is doing - * , as it might be another leaky abstraction.*/ -// efx=NULL; -// nefx=0; -// insertion=insertion_; -// mutex=mutex_; -// efxoutl=new REALTYPE[SOUND_BUFFER_SIZE]; -// efxoutr=new REALTYPE[SOUND_BUFFER_SIZE]; - for(int i = 0; i < SOUND_BUFFER_SIZE; i++) { - efxoutl[i] = 0.0; - efxoutr[i] = 0.0; - } -// filterpars=NULL; -// dryonly=false; - defaults(); -} - - -EffectMgr::~EffectMgr() -{ - if(efx != NULL) - delete efx; - delete [] efxoutl; - delete [] efxoutr; -} - -void EffectMgr::defaults() -{ - changeeffect(0); - setdryonly(false); -} - -/* - * Change the effect - */ -void EffectMgr::changeeffect(int nefx_) -{ - cleanup(); - if(nefx == nefx_) - return; - nefx = nefx_; - for(int i = 0; i < SOUND_BUFFER_SIZE; i++) { - efxoutl[i] = 0.0; - efxoutr[i] = 0.0; - } - - if(efx != NULL) - delete efx; - switch(nefx) { /**\todo replace leaky abstraction*/ - case 1: - efx = new Reverb(insertion, efxoutl, efxoutr); - break; - case 2: - efx = new Echo(insertion, efxoutl, efxoutr); - break; - case 3: - efx = new Chorus(insertion, efxoutl, efxoutr); - break; - case 4: - efx = new Phaser(insertion, efxoutl, efxoutr); - break; - case 5: - efx = new Alienwah(insertion, efxoutl, efxoutr); - break; - case 6: - efx = new Distorsion(insertion, efxoutl, efxoutr); - break; - case 7: - efx = new EQ(insertion, efxoutl, efxoutr); - break; - case 8: - efx = new DynamicFilter(insertion, efxoutl, efxoutr); - break; - //put more effect here - default: - efx = NULL; - break; //no effect (thru) - } - - if(efx != NULL) - filterpars = efx->filterpars; -} - -/* - * Obtain the effect number - */ -int EffectMgr::geteffect() -{ - return nefx; -} - -/* - * Cleanup the current effect - */ -void EffectMgr::cleanup() -{ - if(efx != NULL) - efx->cleanup(); -} - - -/* - * Get the preset of the current effect - */ - -unsigned char EffectMgr::getpreset() -{ - if(efx != NULL) - return efx->Ppreset; - else - return 0; -} - -/* - * Change the preset of the current effect - */ -void EffectMgr::changepreset_nolock(unsigned char npreset) -{ - if(efx != NULL) - efx->setpreset(npreset); -} - -/* - * Change the preset of the current effect(with thread locking) - */ -void EffectMgr::changepreset(unsigned char npreset) -{ - pthread_mutex_lock(mutex); - changepreset_nolock(npreset); - pthread_mutex_unlock(mutex); -} - - -/* - * Change a parameter of the current effect - */ -void EffectMgr::seteffectpar_nolock(int npar, unsigned char value) -{ - if(efx == NULL) - return; - efx->changepar(npar, value); -} - -/* - * Change a parameter of the current effect (with thread locking) - */ -void EffectMgr::seteffectpar(int npar, unsigned char value) -{ - pthread_mutex_lock(mutex); - seteffectpar_nolock(npar, value); - pthread_mutex_unlock(mutex); -} - -/* - * Get a parameter of the current effect - */ -unsigned char EffectMgr::geteffectpar(int npar) -{ - if(efx == NULL) - return 0; - return efx->getpar(npar); -} - - -/* - * Apply the effect - */ -void EffectMgr::out(REALTYPE *smpsl, REALTYPE *smpsr) -{ - int i; - if(efx == NULL) { - if(insertion == 0) - for(i = 0; i < SOUND_BUFFER_SIZE; i++) { - smpsl[i] = 0.0; - smpsr[i] = 0.0; - efxoutl[i] = 0.0; - efxoutr[i] = 0.0; - } - ; - return; - } - for(i = 0; i < SOUND_BUFFER_SIZE; i++) { - smpsl[i] += denormalkillbuf[i]; - smpsr[i] += denormalkillbuf[i]; - efxoutl[i] = 0.0; - efxoutr[i] = 0.0; - } - efx->out(smpsl, smpsr); - - REALTYPE volume = efx->volume; - - if(nefx == 7) { //this is need only for the EQ effect - /**\todo figure out why*/ - for(i = 0; i < SOUND_BUFFER_SIZE; i++) { - smpsl[i] = efxoutl[i]; - smpsr[i] = efxoutr[i]; - } - return; - } - - //Insertion effect - if(insertion != 0) { - REALTYPE v1, v2; - if(volume < 0.5) { - v1 = 1.0; - v2 = volume * 2.0; - } - else { - v1 = (1.0 - volume) * 2.0; - v2 = 1.0; - } - if((nefx == 1) || (nefx == 2)) - v2 *= v2; //for Reverb and Echo, the wet function is not liniar - - if(dryonly) { //this is used for instrument effect only - for(i = 0; i < SOUND_BUFFER_SIZE; i++) { - smpsl[i] *= v1; - smpsr[i] *= v1; - efxoutl[i] *= v2; - efxoutr[i] *= v2; - } - } - else { //normal instrument/insertion effect - for(i = 0; i < SOUND_BUFFER_SIZE; i++) { - smpsl[i] = smpsl[i] * v1 + efxoutl[i] * v2; - smpsr[i] = smpsr[i] * v1 + efxoutr[i] * v2; - } - } - } - else { //System effect - for(i = 0; i < SOUND_BUFFER_SIZE; i++) { - efxoutl[i] *= 2.0 * volume; - efxoutr[i] *= 2.0 * volume; - smpsl[i] = efxoutl[i]; - smpsr[i] = efxoutr[i]; - } - } -} - -/* - * Get the effect volume for the system effect - */ -REALTYPE EffectMgr::sysefxgetvolume() -{ - if(efx == NULL) - return 1.0; - else - return efx->outvolume; -} - - -/* - * Get the EQ response - */ -REALTYPE EffectMgr::getEQfreqresponse(REALTYPE freq) -{ - if(nefx == 7) - return efx->getfreqresponse(freq); - else - return 0.0; -} - - -void EffectMgr::setdryonly(bool value) -{ - dryonly = value; -} - -void EffectMgr::add2XML(XMLwrapper *xml) -{ - xml->addpar("type", geteffect()); - - if((efx == NULL) || (geteffect() == 0)) - return; - xml->addpar("preset", efx->Ppreset); - - xml->beginbranch("EFFECT_PARAMETERS"); - for(int n = 0; n < 128; n++) { - /**\todo evaluate who should oversee saving - * and loading of parameters*/ - int par = geteffectpar(n); - if(par == 0) - continue; - xml->beginbranch("par_no", n); - xml->addpar("par", par); - xml->endbranch(); - } - if(filterpars != NULL) { - xml->beginbranch("FILTER"); - filterpars->add2XML(xml); - xml->endbranch(); - } - xml->endbranch(); -} - -void EffectMgr::getfromXML(XMLwrapper *xml) -{ - changeeffect(xml->getpar127("type", geteffect())); - - if((efx == NULL) || (geteffect() == 0)) - return; - - efx->Ppreset = xml->getpar127("preset", efx->Ppreset); - - if(xml->enterbranch("EFFECT_PARAMETERS")) { - for(int n = 0; n < 128; n++) { - seteffectpar_nolock(n, 0); //erase effect parameter - if(xml->enterbranch("par_no", n) == 0) - continue; - - int par = geteffectpar(n); - seteffectpar_nolock(n, xml->getpar127("par", par)); - xml->exitbranch(); - } - if(filterpars != NULL) { - if(xml->enterbranch("FILTER")) { - filterpars->getfromXML(xml); - xml->exitbranch(); - } - } - xml->exitbranch(); - } - cleanup(); -} - diff --git a/plugins/zynaddsubfx/src/Effects/EffectMgr.h b/plugins/zynaddsubfx/src/Effects/EffectMgr.h deleted file mode 100644 index 29d6a7a71..000000000 --- a/plugins/zynaddsubfx/src/Effects/EffectMgr.h +++ /dev/null @@ -1,102 +0,0 @@ -/* - ZynAddSubFX - a software synthesizer - - EffectMgr.h - Effect manager, an interface betwen the program and effects - Copyright (C) 2002-2005 Nasca Octavian Paul - Author: Nasca Octavian Paul - - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License - as published by the Free Software Foundation. - - 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 (version 2 or later) for more details. - - You should have received a copy of the GNU General Public License (version 2) - along with this program; if not, write to the Free Software Foundation, - Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#ifndef EFFECTMGR_H -#define EFFECTMGR_H - -#include - -#include "Effect.h" -#include "Reverb.h" -#include "Echo.h" -#include "Chorus.h" -#include "Phaser.h" -#include "Alienwah.h" -#include "Distorsion.h" -#include "EQ.h" -#include "DynamicFilter.h" -#include "../Misc/XMLwrapper.h" -#include "../Params/FilterParams.h" -#include "../Params/Presets.h" - -/**Effect manager, an interface betwen the program and effects*/ -class EffectMgr:public Presets -{ - public: - EffectMgr(int insertion_, pthread_mutex_t *mutex_); - ~EffectMgr(); - - void add2XML(XMLwrapper *xml); - void defaults(); - void getfromXML(XMLwrapper *xml); - - void out(REALTYPE *smpsl, REALTYPE *smpsr); - - void setdryonly(bool value); - - /**get the output(to speakers) volume of the systemeffect*/ - REALTYPE sysefxgetvolume(); - - void cleanup(); /** -#include -#include "Phaser.h" - -using namespace std; - -#define PHASER_LFO_SHAPE 2 -#define ONE_ 0.99999f // To prevent LFO ever reaching 1.0 for filter stability purposes -#define ZERO_ 0.00001f // Same idea as above. - -Phaser::Phaser(const int &insertion_, REALTYPE *efxoutl_, REALTYPE *efxoutr_) - :Effect(insertion_, efxoutl_, efxoutr_, NULL, 0), old(NULL), xn1(NULL), yn1(NULL), diff(0.0), oldgain(0.0), - fb(0.0) -{ - analog_setup(); - setpreset(Ppreset); - cleanup(); -} - -void Phaser::analog_setup() -{ - //model mismatch between JFET devices - offset[0] = -0.2509303f; - offset[1] = 0.9408924f; - offset[2] = 0.998f; - offset[3] = -0.3486182f; - offset[4] = -0.2762545f; - offset[5] = -0.5215785f; - offset[6] = 0.2509303f; - offset[7] = -0.9408924f; - offset[8] = -0.998f; - offset[9] = 0.3486182f; - offset[10] = 0.2762545f; - offset[11] = 0.5215785f; - - barber = 0; //Deactivate barber pole phasing by default - - mis = 1.0f; - Rmin = 625.0f;// 2N5457 typical on resistance at Vgs = 0 - Rmax = 22000.0f;// Resistor parallel to FET - Rmx = Rmin/Rmax; - Rconst = 1.0f + Rmx; // Handle parallel resistor relationship - C = 0.00000005f; // 50 nF - CFs = (float) 2.0f*(float)SAMPLE_RATE*C; - invperiod = 1.0f / ((float) SOUND_BUFFER_SIZE); -} - -Phaser::~Phaser() -{ - if(xn1.l) - delete[] xn1.l; - if(yn1.l) - delete[] yn1.l; - if(xn1.r) - delete[] xn1.r; - if(yn1.r) - delete[] yn1.r; -} - -/* - * Effect output - */ -void Phaser::out(const Stereo &input) -{ - if(Panalog) - AnalogPhase(input); - else - normalPhase(input); -} - -void Phaser::AnalogPhase(const Stereo &input) -{ - Stereo gain(0.0), lfoVal(0.0), mod(0.0), g(0.0), b(0.0), hpf(0.0); - - lfo.effectlfoout(&lfoVal.l, &lfoVal.r); - mod.l = lfoVal.l*width + (depth - 0.5f); - mod.r = lfoVal.r*width + (depth - 0.5f); - - mod.l = limit(mod.l, ZERO_, ONE_); - mod.r = limit(mod.r, ZERO_, ONE_); - - if(Phyper) { - //Triangle wave squared is approximately sin on bottom, tri on top - //Result is exponential sweep more akin to filter in synth with - //exponential generator circuitry. - mod.l *= mod.l; - mod.r *= mod.r; - } - - //g.l,g.r is Vp - Vgs. Typical FET drain-source resistance follows constant/[1-sqrt(Vp - Vgs)] - mod.l = sqrtf(1.0f - mod.l); - mod.r = sqrtf(1.0f - mod.r); - - diff.r = (mod.r - oldgain.r) * invperiod; - diff.l = (mod.l - oldgain.l) * invperiod; - - g = oldgain; - oldgain = mod; - - for (int i = 0; i < SOUND_BUFFER_SIZE; i++) { - g.l += diff.l;// Linear interpolation between LFO samples - g.r += diff.r; - - Stereo xn(input.l[i] * panning, - input.r[i] * (1.0f - panning)); - - if (barber) { - g.l = fmodf((g.l + 0.25f), ONE_); - g.r = fmodf((g.r + 0.25f), ONE_); - } - - xn.l = applyPhase(xn.l, g.l, fb.l, hpf.l, yn1.l, xn1.l); - xn.r = applyPhase(xn.r, g.r, fb.r, hpf.r, yn1.r, xn1.r); - - - fb.l = xn.l * feedback; - fb.r = xn.r * feedback; - efxoutl[i] = xn.l; - efxoutr[i] = xn.r; - } - - if(Poutsub) { - invSignal(efxoutl, SOUND_BUFFER_SIZE); - invSignal(efxoutr, SOUND_BUFFER_SIZE); - } -} - -REALTYPE Phaser::applyPhase(REALTYPE x, REALTYPE g, REALTYPE fb, - REALTYPE &hpf, REALTYPE *yn1, REALTYPE *xn1) -{ - for(int j = 0; j < Pstages; j++) { //Phasing routine - mis = 1.0f + offsetpct*offset[j]; - - //This is symmetrical. - //FET is not, so this deviates slightly, however sym dist. is - //better sounding than a real FET. - float d = (1.0f + 2.0f*(0.25f + g)*hpf*hpf*distortion) * mis; - Rconst = 1.0f + mis*Rmx; - - // This is 1/R. R is being modulated to control filter fc. - float b = (Rconst - g)/ (d*Rmin); - float gain = (CFs - b)/(CFs + b); - yn1[j] = gain * (x + yn1[j]) - xn1[j]; - - //high pass filter: - //Distortion depends on the high-pass part of the AP stage. - hpf = yn1[j] + (1.0f-gain)*xn1[j]; - - xn1[j] = x; - x = yn1[j]; - if (j==1) - x += fb; //Insert feedback after first phase stage - } - return x; -} -void Phaser::normalPhase(const Stereo &input) -{ - Stereo gain(0.0), lfoVal(0.0); - - lfo.effectlfoout(&lfoVal.l, &lfoVal.r); - gain.l = (exp(lfoVal.l * PHASER_LFO_SHAPE) - 1) / (exp(PHASER_LFO_SHAPE) - 1.0); - gain.r = (exp(lfoVal.r * PHASER_LFO_SHAPE) - 1) / (exp(PHASER_LFO_SHAPE) - 1.0); - - gain.l = 1.0 - phase * (1.0 - depth) - (1.0 - phase) * gain.l * depth; - gain.r = 1.0 - phase * (1.0 - depth) - (1.0 - phase) * gain.r * depth; - - gain.l = limit(gain.l, ZERO_, ONE_); - gain.r = limit(gain.r, ZERO_, ONE_); - - for(int i = 0; i < SOUND_BUFFER_SIZE; i++) { - REALTYPE x = (REALTYPE) i / SOUND_BUFFER_SIZE; - REALTYPE x1 = 1.0 - x; - //TODO think about making panning an external feature - Stereo xn(input.l[i] * panning + fb.l, - input.r[i] * (1.0 - panning) + fb.r); - - Stereo g(gain.l * x + oldgain.l * x1, - gain.r * x + oldgain.r * x1); - - xn.l = applyPhase(xn.l, g.l, old.l); - xn.r = applyPhase(xn.r, g.r, old.r); - - //Left/Right crossing - crossover(xn.l, xn.r, lrcross); - - fb.l = xn.l * feedback; - fb.r = xn.r * feedback; - efxoutl[i] = xn.l; - efxoutr[i] = xn.r; - } - - oldgain = gain; - - if(Poutsub) { - invSignal(efxoutl, SOUND_BUFFER_SIZE); - invSignal(efxoutr, SOUND_BUFFER_SIZE); - } -} - -REALTYPE Phaser::applyPhase(REALTYPE x, REALTYPE g, REALTYPE *old) -{ - for(int j = 0; j < Pstages * 2; j++) { //Phasing routine - REALTYPE tmp = old[j]; - old[j] = g * tmp + x; - x = tmp - g *old[j]; - } - return x; -} - -/* - * Cleanup the effect - */ -void Phaser::cleanup() -{ - fb = oldgain = Stereo(0.0); - for(int i = 0; i < Pstages * 2; i++) { - old.l[i] = 0.0; - old.r[i] = 0.0; - } - for(int i = 0; i < Pstages; i++) { - xn1.l[i] = 0.0; - yn1.l[i] = 0.0; - xn1.r[i] = 0.0; - yn1.r[i] = 0.0; - } -} - -/* - * Parameter control - */ -void Phaser::setwidth(unsigned char Pwidth) -{ - this->Pwidth = Pwidth; - width = ((float)Pwidth / 127.0f); -} - -void Phaser::setfb(unsigned char Pfb) -{ - this->Pfb = Pfb; - feedback = (float) (Pfb - 64) / 64.2f; -} - -void Phaser::setvolume(unsigned char Pvolume) -{ - this->Pvolume = Pvolume; - outvolume = Pvolume / 127.0; - if(insertion == 0) - volume = 1.0; - else - volume = outvolume; -} - -void Phaser::setpanning(unsigned char Ppanning) -{ - this->Ppanning = Ppanning; - panning = (float)Ppanning / 127.0; -} - -void Phaser::setlrcross(unsigned char Plrcross) -{ - this->Plrcross = Plrcross; - lrcross = Plrcross / 127.0; -} - -void Phaser::setdistortion(unsigned char Pdistortion) -{ - this->Pdistortion = Pdistortion; - distortion = (float)Pdistortion / 127.0f; -} - -void Phaser::setoffset(unsigned char Poffset) -{ - this->Poffset = Poffset; - offsetpct = (float)Poffset / 127.0f; -} - -void Phaser::setstages(unsigned char Pstages) -{ - if(xn1.l) - delete[] xn1.l; - if(yn1.l) - delete[] yn1.l; - if(xn1.r) - delete[] xn1.r; - if(yn1.r) - delete[] yn1.r; - - - this->Pstages = min(MAX_PHASER_STAGES, (int)Pstages); - - old = Stereo(new REALTYPE[Pstages * 2], - new REALTYPE[Pstages * 2]); - - xn1 = Stereo(new REALTYPE[Pstages], - new REALTYPE[Pstages]); - - yn1 = Stereo(new REALTYPE[Pstages], - new REALTYPE[Pstages]); - - cleanup(); -} - -void Phaser::setphase(unsigned char Pphase) -{ - this->Pphase = Pphase; - phase = (Pphase / 127.0); -} - -void Phaser::setdepth(unsigned char Pdepth) -{ - this->Pdepth = Pdepth; - depth = (float)(Pdepth) / 127.0f; -} - - -void Phaser::setpreset(unsigned char npreset) -{ - const int PRESET_SIZE = 15; - const int NUM_PRESETS = 12; - unsigned char presets[NUM_PRESETS][PRESET_SIZE] = { - //Phaser - //0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 - {64, 64, 36, 0, 0, 64, 110, 64, 1, 0, 0, 20, 0, 0, 0}, - {64, 64, 35, 0, 0, 88, 40, 64, 3, 0, 0, 20, 0, 0, 0}, - {64, 64, 31, 0, 0, 66, 68, 107, 2, 0, 0, 20, 0, 0, 0}, - {39, 64, 22, 0, 0, 66, 67, 10, 5, 0, 1, 20, 0, 0, 0}, - {64, 64, 20, 0, 1, 110, 67, 78, 10, 0, 0, 20, 0, 0, 0}, - {64, 64, 53, 100, 0, 58, 37, 78, 3, 0, 0, 20, 0, 0, 0}, - //APhaser - //0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 - {64, 64, 14, 0, 1, 64, 64, 40, 4, 10, 0, 110, 1, 20, 1}, - {64, 64, 14, 5, 1, 64, 70, 40, 6, 10, 0, 110, 1, 20, 1}, - {64, 64, 9, 0, 0, 64, 60, 40, 8, 10, 0, 40, 0, 20, 1}, - {64, 64, 14, 10, 0, 64, 45, 80, 7, 10, 1, 110, 1, 20, 1}, - {25, 64, 127, 10, 0, 64, 25, 16, 8, 100, 0, 25, 0, 20, 1}, - {64, 64, 1, 10, 1, 64, 70, 40, 12, 10, 0, 110, 1, 20, 1} - }; - if(npreset >= NUM_PRESETS) - npreset = NUM_PRESETS - 1; - for(int n = 0; n < PRESET_SIZE; n++) - changepar(n, presets[npreset][n]); - Ppreset = npreset; -} - - -void Phaser::changepar(int npar, unsigned char value) -{ - switch(npar) { - case 0: - setvolume(value); - break; - case 1: - setpanning(value); - break; - case 2: - lfo.Pfreq = value; - lfo.updateparams(); - break; - case 3: - lfo.Prandomness = value; - lfo.updateparams(); - break; - case 4: - lfo.PLFOtype = value; - lfo.updateparams(); - barber = (2 == value); - break; - case 5: - lfo.Pstereo = value; - lfo.updateparams(); - break; - case 6: - setdepth(value); - break; - case 7: - setfb(value); - break; - case 8: - setstages(value); - break; - case 9: - setlrcross(value); - setoffset(value); - break; - case 10: - Poutsub = min((int)value,1); - break; - case 11: - setphase(value); - setwidth(value); - break; - case 12: - Phyper = min((int)value, 1); - break; - case 13: - setdistortion(value); - break; - case 14: - Panalog = value; - break; - } -} - -unsigned char Phaser::getpar(int npar) const -{ - switch(npar) { - case 0: - return Pvolume; - case 1: - return Ppanning; - case 2: - return lfo.Pfreq; - case 3: - return lfo.Prandomness; - case 4: - return lfo.PLFOtype; - case 5: - return lfo.Pstereo; - case 6: - return Pdepth; - case 7: - return Pfb; - case 8: - return Pstages; - case 9: - return Plrcross; - return Poffset; - case 10: - return Poutsub; - case 11: - return Pphase; - return Pwidth; - case 12: - return Phyper; - case 13: - return Pdistortion; - case 14: - return Panalog; - default: - return 0; - } -} diff --git a/plugins/zynaddsubfx/src/Effects/Phaser.h b/plugins/zynaddsubfx/src/Effects/Phaser.h deleted file mode 100644 index 75ff79173..000000000 --- a/plugins/zynaddsubfx/src/Effects/Phaser.h +++ /dev/null @@ -1,103 +0,0 @@ -/* - ZynAddSubFX - a software synthesizer - - Phaser.h - Phaser effect - Copyright (C) 2002-2005 Nasca Octavian Paul - Copyright (C) 2009-2010 Ryan Billing - Copyright (C) 2010-2010 Mark McCurry - Author: Nasca Octavian Paul - Ryan Billing - Mark McCurry - - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License - as published by the Free Software Foundation. - - 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 (version 2 or later) for more details. - - You should have received a copy of the GNU General Public License (version 2) - along with this program; if not, write to the Free Software Foundation, - Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -*/ - -#ifndef PHASER_H -#define PHASER_H -#include "../globals.h" -#include "Effect.h" -#include "EffectLFO.h" - -#define MAX_PHASER_STAGES 12 - -class Phaser:public Effect -{ - public: - Phaser(const int &insertion_, REALTYPE *efxoutl_, REALTYPE *efxoutr_); - ~Phaser(); - void out(const Stereo &input); - void setpreset(unsigned char npreset); - void changepar(int npar, unsigned char value); - unsigned char getpar(int npar) const; - void cleanup(); - - private: - //Phaser parameters - EffectLFO lfo; //Phaser modulator - unsigned char Pvolume; //Used to set wet/dry mix - unsigned char Ppanning; - unsigned char Pdistortion; //Model distortion added by FET element - unsigned char Pdepth; //Depth of phaser sweep - unsigned char Pwidth; //Phaser width (LFO amplitude) - unsigned char Pfb; //feedback - unsigned char Poffset; //Model mismatch between variable resistors - unsigned char Plrcross; //crossover - unsigned char Pstages; //Number of first-order All-Pass stages - unsigned char Poutsub; //if I wish to subtract the output instead of adding - unsigned char Pphase; - unsigned char Phyper; //lfo^2 -- converts tri into hyper-sine - unsigned char Panalog; - - //Control parameters - void setvolume(unsigned char Pvolume); - void setpanning(unsigned char Ppanning); - void setdepth(unsigned char Pdepth); - void setfb(unsigned char Pfb); - void setdistortion(unsigned char Pdistortion); - void setwidth(unsigned char Pwidth); - void setoffset(unsigned char Poffset); - void setlrcross(unsigned char Plrcross); - void setstages(unsigned char Pstages); - void setphase(unsigned char Pphase); - - //Internal Variables - bool barber; //Barber pole phasing flag - REALTYPE distortion, width, offsetpct; - REALTYPE panning, feedback, depth, lrcross, phase; - Stereo old, xn1, yn1; - Stereo diff, oldgain, fb; - REALTYPE invperiod; - REALTYPE offset[12]; - - float mis; - float Rmin; // 3N5457 typical on resistance at Vgs = 0 - float Rmax; // Resistor parallel to FET - float Rmx; // Rmin/Rmax to avoid division in loop - float Rconst; // Handle parallel resistor relationship - float C; // Capacitor - float CFs; // A constant derived from capacitor and resistor relationships - - void analog_setup(); - void AnalogPhase(const Stereo &input); - //analog case - REALTYPE applyPhase(REALTYPE x, REALTYPE g, REALTYPE fb, - REALTYPE &hpf, REALTYPE *yn1, REALTYPE *xn1); - - void normalPhase(const Stereo &input); - REALTYPE applyPhase(REALTYPE x, REALTYPE g, REALTYPE *old); -}; - -#endif - diff --git a/plugins/zynaddsubfx/src/Effects/Reverb.cpp b/plugins/zynaddsubfx/src/Effects/Reverb.cpp deleted file mode 100644 index 0176fa77e..000000000 --- a/plugins/zynaddsubfx/src/Effects/Reverb.cpp +++ /dev/null @@ -1,551 +0,0 @@ -/* - ZynAddSubFX - a software synthesizer - - Reverb.cpp - Reverberation effect - Copyright (C) 2002-2005 Nasca Octavian Paul - Author: Nasca Octavian Paul - - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License - as published by the Free Software Foundation. - - 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 (version 2 or later) for more details. - - You should have received a copy of the GNU General Public License (version 2) - along with this program; if not, write to the Free Software Foundation, - Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -*/ - -#include -#include "Reverb.h" - -/**\todo: EarlyReflections,Prdelay,Perbalance */ - -Reverb::Reverb(const int &insertion_, REALTYPE *efxoutl_, REALTYPE *efxoutr_) - :Effect(insertion_, efxoutl_, efxoutr_, NULL, 0) -{ - inputbuf = new REALTYPE[SOUND_BUFFER_SIZE]; - - bandwidth = NULL; - - //defaults - Pvolume = 48; - Ppan = 64; - Ptime = 64; - Pidelay = 40; - Pidelayfb = 0; - Prdelay = 0; - Plpf = 127; - Phpf = 0; - Perbalance = 64; - Plohidamp = 80; - Ptype = 1; - Proomsize = 64; - Pbandwidth = 30; - roomsize = 1.0; - rs = 1.0; - - for(int i = 0; i < REV_COMBS * 2; i++) { - comblen[i] = 800 + (int)(RND * 1400); - combk[i] = 0; - lpcomb[i] = 0; - combfb[i] = -0.97; - comb[i] = NULL; - } - - for(int i = 0; i < REV_APS * 2; i++) { - aplen[i] = 500 + (int)(RND * 500); - apk[i] = 0; - ap[i] = NULL; - } - - lpf = NULL; - hpf = NULL; //no filter - idelay = NULL; - - setpreset(Ppreset); - cleanup(); //do not call this before the comb initialisation -} - - -Reverb::~Reverb() -{ - int i; - if(idelay != NULL) - delete [] idelay; - if(hpf != NULL) - delete hpf; - if(lpf != NULL) - delete lpf; - - for(i = 0; i < REV_APS * 2; i++) - delete [] ap[i]; - for(i = 0; i < REV_COMBS * 2; i++) - delete [] comb[i]; - - delete [] inputbuf; - if(bandwidth) - delete bandwidth; -} - -/* - * Cleanup the effect - */ -void Reverb::cleanup() -{ - int i, j; - for(i = 0; i < REV_COMBS * 2; i++) { - lpcomb[i] = 0.0; - for(j = 0; j < comblen[i]; j++) - comb[i][j] = 0.0; - } - - for(i = 0; i < REV_APS * 2; i++) - for(j = 0; j < aplen[i]; j++) - ap[i][j] = 0.0; - - if(idelay != NULL) - for(i = 0; i < idelaylen; i++) - idelay[i] = 0.0; - - if(hpf != NULL) - hpf->cleanup(); - if(lpf != NULL) - lpf->cleanup(); -} - -/* - * Process one channel; 0=left,1=right - */ -void Reverb::processmono(int ch, REALTYPE *output) -{ - int i, j; - REALTYPE fbout, tmp; - /**\todo: implement the high part from lohidamp*/ - - for(j = REV_COMBS * ch; j < REV_COMBS * (ch + 1); j++) { - int ck = combk[j]; - int comblength = comblen[j]; - REALTYPE lpcombj = lpcomb[j]; - - for(i = 0; i < SOUND_BUFFER_SIZE; i++) { - fbout = comb[j][ck] * combfb[j]; - fbout = fbout * (1.0 - lohifb) + lpcombj * lohifb; - lpcombj = fbout; - - comb[j][ck] = inputbuf[i] + fbout; - output[i] += fbout; - - if((++ck) >= comblength) - ck = 0; - } - - combk[j] = ck; - lpcomb[j] = lpcombj; - } - - for(j = REV_APS * ch; j < REV_APS * (1 + ch); j++) { - int ak = apk[j]; - int aplength = aplen[j]; - for(i = 0; i < SOUND_BUFFER_SIZE; i++) { - tmp = ap[j][ak]; - ap[j][ak] = 0.7 * tmp + output[i]; - output[i] = tmp - 0.7 * ap[j][ak]; - if((++ak) >= aplength) - ak = 0; - } - apk[j] = ak; - } -} - -/* - * Effect output - */ -void Reverb::out(const Stereo &smp) -{ - int i; - if((Pvolume == 0) && (insertion != 0)) - return; - - for(i = 0; i < SOUND_BUFFER_SIZE; i++) - inputbuf[i] = (smp.l[i] + smp.r[i]) / 2.0; - - if(idelay != NULL) { - for(i = 0; i < SOUND_BUFFER_SIZE; i++) { - //Initial delay r - REALTYPE tmp = inputbuf[i] + idelay[idelayk] * idelayfb; - inputbuf[i] = idelay[idelayk]; - idelay[idelayk] = tmp; - idelayk++; - if(idelayk >= idelaylen) - idelayk = 0; - } - } - - if(bandwidth) - bandwidth->process(SOUND_BUFFER_SIZE, inputbuf); - - if(lpf != NULL) - lpf->filterout(inputbuf); - if(hpf != NULL) - hpf->filterout(inputbuf); - - processmono(0, efxoutl); //left - processmono(1, efxoutr); //right - - REALTYPE lvol = rs / REV_COMBS * pan; - REALTYPE rvol = rs / REV_COMBS * (1.0 - pan); - if(insertion != 0) { - lvol *= 2; - rvol *= 2; - } - for(int i = 0; i < SOUND_BUFFER_SIZE; i++) { - efxoutl[i] *= lvol; - efxoutr[i] *= rvol; - } -} - - -/* - * Parameter control - */ -void Reverb::setvolume(unsigned char Pvolume) -{ - this->Pvolume = Pvolume; - if(insertion == 0) { - outvolume = pow(0.01, (1.0 - Pvolume / 127.0)) * 4.0; - volume = 1.0; - } - else { - volume = outvolume = Pvolume / 127.0; - if(Pvolume == 0) - cleanup(); - } -} - -void Reverb::setpan(unsigned char Ppan) -{ - this->Ppan = Ppan; - pan = (REALTYPE)Ppan / 127.0; -} - -void Reverb::settime(unsigned char Ptime) -{ - int i; - REALTYPE t; - this->Ptime = Ptime; - t = pow(60.0, (REALTYPE)Ptime / 127.0) - 0.97; - - for(i = 0; i < REV_COMBS * 2; i++) - combfb[i] = - -exp((REALTYPE)comblen[i] / (REALTYPE)SAMPLE_RATE * log(0.001) / t); - //the feedback is negative because it removes the DC -} - -void Reverb::setlohidamp(unsigned char Plohidamp) -{ - if(Plohidamp < 64) - Plohidamp = 64; //remove this when the high part from lohidamp will be added - - this->Plohidamp = Plohidamp; - if(Plohidamp == 64) { - lohidamptype = 0; - lohifb = 0.0; - } - else { - if(Plohidamp < 64) - lohidamptype = 1; - if(Plohidamp > 64) - lohidamptype = 2; - REALTYPE x = fabs((REALTYPE)(Plohidamp - 64) / 64.1); - lohifb = x * x; - } -} - -void Reverb::setidelay(unsigned char Pidelay) -{ - REALTYPE delay; - this->Pidelay = Pidelay; - delay = pow(50 * Pidelay / 127.0, 2) - 1.0; - - if(idelay != NULL) - delete [] idelay; - idelay = NULL; - - idelaylen = (int) (SAMPLE_RATE * delay / 1000); - if(idelaylen > 1) { - idelayk = 0; - idelay = new REALTYPE[idelaylen]; - for(int i = 0; i < idelaylen; i++) - idelay[i] = 0.0; - } -} - -void Reverb::setidelayfb(unsigned char Pidelayfb) -{ - this->Pidelayfb = Pidelayfb; - idelayfb = Pidelayfb / 128.0; -} - -void Reverb::sethpf(unsigned char Phpf) -{ - this->Phpf = Phpf; - if(Phpf == 0) { //No HighPass - if(hpf != NULL) - delete hpf; - hpf = NULL; - } - else { - REALTYPE fr = exp(pow(Phpf / 127.0, 0.5) * log(10000.0)) + 20.0; - if(hpf == NULL) - hpf = new AnalogFilter(3, fr, 1, 0); - else - hpf->setfreq(fr); - } -} - -void Reverb::setlpf(unsigned char Plpf) -{ - this->Plpf = Plpf; - if(Plpf == 127) { //No LowPass - if(lpf != NULL) - delete lpf; - lpf = NULL; - } - else { - REALTYPE fr = exp(pow(Plpf / 127.0, 0.5) * log(25000.0)) + 40; - if(lpf == NULL) - lpf = new AnalogFilter(2, fr, 1, 0); - else - lpf->setfreq(fr); - } -} - -void Reverb::settype(unsigned char Ptype) -{ - const int NUM_TYPES = 3; - const int combtunings[NUM_TYPES][REV_COMBS] = { - //this is unused (for random) - {0, 0, 0, 0, 0, 0, 0, 0 }, - //Freeverb by Jezar at Dreampoint - {1116, 1188, 1277, 1356, 1422, 1491, 1557, 1617 }, - //Freeverb by Jezar at Dreampoint //duplicate - {1116, 1188, 1277, 1356, 1422, 1491, 1557, 1617 } - }; - const int aptunings[NUM_TYPES][REV_APS] = { - //this is unused (for random) - {0, 0, 0, 0 }, - //Freeverb by Jezar at Dreampoint - {225, 341, 441, 556 }, - //Freeverb by Jezar at Dreampoint (duplicate) - {225, 341, 441, 556 } - }; - - if(Ptype >= NUM_TYPES) - Ptype = NUM_TYPES - 1; - this->Ptype = Ptype; - - REALTYPE tmp; - for(int i = 0; i < REV_COMBS * 2; i++) { - if(Ptype == 0) - tmp = 800.0 + (int)(RND * 1400.0); - else - tmp = combtunings[Ptype][i % REV_COMBS]; - tmp *= roomsize; - if(i > REV_COMBS) - tmp += 23.0; - tmp *= SAMPLE_RATE / 44100.0; //adjust the combs according to the samplerate - if(tmp < 10) - tmp = 10; - - comblen[i] = (int) tmp; - combk[i] = 0; - lpcomb[i] = 0; - if(comb[i] != NULL) - delete [] comb[i]; - comb[i] = new REALTYPE[comblen[i]]; - } - - for(int i = 0; i < REV_APS * 2; i++) { - if(Ptype == 0) - tmp = 500 + (int)(RND * 500); - else - tmp = aptunings[Ptype][i % REV_APS]; - tmp *= roomsize; - if(i > REV_APS) - tmp += 23.0; - tmp *= SAMPLE_RATE / 44100.0; //adjust the combs according to the samplerate - if(tmp < 10) - tmp = 10; - aplen[i] = (int) tmp; - apk[i] = 0; - if(ap[i] != NULL) - delete [] ap[i]; - ap[i] = new REALTYPE[aplen[i]]; - } - settime(Ptime); - cleanup(); - if(bandwidth) - delete bandwidth; - bandwidth = NULL; - if(Ptype == 2) { //bandwidth - bandwidth = new Unison(SOUND_BUFFER_SIZE / 4 + 1, 2.0); - bandwidth->set_size(50); - bandwidth->set_base_frequency(1.0); - } -} - -void Reverb::setroomsize(unsigned char Proomsize) -{ - this->Proomsize = Proomsize; - if(Proomsize == 0) - this->Proomsize = 64; //this is because the older versions consider roomsize=0 - roomsize = (this->Proomsize - 64.0) / 64.0; - if(roomsize > 0.0) - roomsize *= 2.0; - roomsize = pow(10.0, roomsize); - rs = sqrt(roomsize); - settype(Ptype); -} - -void Reverb::setbandwidth(unsigned char Pbandwidth) { - this->Pbandwidth = Pbandwidth; - REALTYPE v = Pbandwidth / 127.0; - if(bandwidth) - bandwidth->set_bandwidth(pow(v, 2.0) * 200.0); -} - -void Reverb::setpreset(unsigned char npreset) -{ - const int PRESET_SIZE = 13; - const int NUM_PRESETS = 13; - unsigned char presets[NUM_PRESETS][PRESET_SIZE] = { - //Cathedral1 - {80, 64, 63, 24, 0, 0, 0, 85, 5, 83, 1, 64, 20 }, - //Cathedral2 - {80, 64, 69, 35, 0, 0, 0, 127, 0, 71, 0, 64, 20 }, - //Cathedral3 - {80, 64, 69, 24, 0, 0, 0, 127, 75, 78, 1, 85, 20 }, - //Hall1 - {90, 64, 51, 10, 0, 0, 0, 127, 21, 78, 1, 64, 20 }, - //Hall2 - {90, 64, 53, 20, 0, 0, 0, 127, 75, 71, 1, 64, 20 }, - //Room1 - {100, 64, 33, 0, 0, 0, 0, 127, 0, 106, 0, 30, 20 }, - //Room2 - {100, 64, 21, 26, 0, 0, 0, 62, 0, 77, 1, 45, 20 }, - //Basement - {110, 64, 14, 0, 0, 0, 0, 127, 5, 71, 0, 25, 20 }, - //Tunnel - {85, 80, 84, 20, 42, 0, 0, 51, 0, 78, 1, 105, 20 }, - //Echoed1 - {95, 64, 26, 60, 71, 0, 0, 114, 0, 64, 1, 64, 20 }, - //Echoed2 - {90, 64, 40, 88, 71, 0, 0, 114, 0, 88, 1, 64, 20 }, - //VeryLong1 - {90, 64, 93, 15, 0, 0, 0, 114, 0, 77, 0, 95, 20 }, - //VeryLong2 - {90, 64, 111, 30, 0, 0, 0, 114, 90, 74, 1, 80, 20 } - }; - - if(npreset >= NUM_PRESETS) - npreset = NUM_PRESETS - 1; - for(int n = 0; n < PRESET_SIZE; n++) - changepar(n, presets[npreset][n]); - if(insertion != 0) - changepar(0, presets[npreset][0] / 2); //lower the volume if reverb is insertion effect - Ppreset = npreset; -} - - -void Reverb::changepar(int npar, unsigned char value) -{ - switch(npar) { - case 0: - setvolume(value); - break; - case 1: - setpan(value); - break; - case 2: - settime(value); - break; - case 3: - setidelay(value); - break; - case 4: - setidelayfb(value); - break; -// case 5: setrdelay(value); -// break; -// case 6: seterbalance(value); -// break; - case 7: - setlpf(value); - break; - case 8: - sethpf(value); - break; - case 9: - setlohidamp(value); - break; - case 10: - settype(value); - break; - case 11: - setroomsize(value); - break; - case 12: - setbandwidth(value); - break; - } -} - -unsigned char Reverb::getpar(int npar) const -{ - switch(npar) { - case 0: - return Pvolume; - break; - case 1: - return Ppan; - break; - case 2: - return Ptime; - break; - case 3: - return Pidelay; - break; - case 4: - return Pidelayfb; - break; -// case 5: return(Prdelay); -// break; -// case 6: return(Perbalance); -// break; - case 7: - return Plpf; - break; - case 8: - return Phpf; - break; - case 9: - return Plohidamp; - break; - case 10: - return Ptype; - break; - case 11: - return Proomsize; - break; - case 12: - return Pbandwidth; - break; - } - return 0; //in case of bogus "parameter" -} - diff --git a/plugins/zynaddsubfx/src/Effects/Reverb.h b/plugins/zynaddsubfx/src/Effects/Reverb.h deleted file mode 100644 index e84c56d88..000000000 --- a/plugins/zynaddsubfx/src/Effects/Reverb.h +++ /dev/null @@ -1,135 +0,0 @@ -/* - ZynAddSubFX - a software synthesizer - - Reverb.h - Reverberation effect - Copyright (C) 2002-2009 Nasca Octavian Paul - Author: Nasca Octavian Paul - - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License - as published by the Free Software Foundation. - - 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 (version 2 or later) for more details. - - You should have received a copy of the GNU General Public License (version 2) - along with this program; if not, write to the Free Software Foundation, - Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -*/ - -#ifndef REVERB_H -#define REVERB_H - -#include -#include "../globals.h" -#include "../DSP/AnalogFilter.h" -#include "../DSP/FFTwrapper.h" -#include "../DSP/Unison.h" -#include "Effect.h" - -#define REV_COMBS 8 -#define REV_APS 4 - -/**Creates Reverberation Effects*/ - -class Reverb:public Effect -{ - public: - Reverb(const int &insertion_, REALTYPE *efxoutl_, REALTYPE *efxoutr_); - ~Reverb(); - void out(const Stereo &smp); - void cleanup(); - - void setpreset(unsigned char npreset); - void changepar(int npar, unsigned char value); - unsigned char getpar(int npar) const; - - private: - //Parametrii - /**Amount of the reverb*/ - unsigned char Pvolume; - - /**Left/Right Panning*/ - unsigned char Ppan; - - /**duration of reverb*/ - unsigned char Ptime; - - /**Initial delay*/ - unsigned char Pidelay; - - /**Initial delay feedback*/ - unsigned char Pidelayfb; - - /**delay between ER/Reverbs*/ - unsigned char Prdelay; - - /**EarlyReflections/Reverb Balance*/ - unsigned char Perbalance; - - /**HighPassFilter*/ - unsigned char Plpf; - - /**LowPassFilter*/ - unsigned char Phpf; - - /**Low/HighFrequency Damping - * \todo 0..63 lpf,64=off,65..127=hpf(TODO)*/ - unsigned char Plohidamp; - - /**Reverb type*/ - unsigned char Ptype; - - /**Room Size*/ - unsigned char Proomsize; - - /**Bandwidth */ - unsigned char Pbandwidth; - - //parameter control - void setvolume(unsigned char Pvolume); - void setpan(unsigned char Ppan); - void settime(unsigned char Ptime); - void setlohidamp(unsigned char Plohidamp); - void setidelay(unsigned char Pidelay); - void setidelayfb(unsigned char Pidelayfb); - void sethpf(unsigned char Phpf); - void setlpf(unsigned char Plpf); - void settype(unsigned char Ptype); - void setroomsize(unsigned char Proomsize); - void setbandwidth(unsigned char Pbandwidth); - - REALTYPE pan, erbalance; - //Parameters - int lohidamptype; /**<0=disable,1=highdamp(lowpass),2=lowdamp(highpass)*/ - int idelaylen, rdelaylen; - int idelayk; - REALTYPE lohifb, idelayfb, roomsize, rs; //rs is used to "normalise" the volume according to the roomsize - int comblen[REV_COMBS * 2]; - int aplen[REV_APS * 2]; - Unison *bandwidth; - - //Internal Variables - - REALTYPE *comb[REV_COMBS * 2]; - - int combk[REV_COMBS * 2]; - REALTYPE combfb[REV_COMBS * 2]; /**type) { - case SND_SEQ_EVENT_NOTEON: - cmdtype = MidiNoteON; - cmdchan = midievent->data.note.channel; - cmdparams[0] = midievent->data.note.note; - cmdparams[1] = midievent->data.note.velocity; - break; - case SND_SEQ_EVENT_NOTEOFF: - cmdtype = MidiNoteOFF; - cmdchan = midievent->data.note.channel; - cmdparams[0] = midievent->data.note.note; - break; - case SND_SEQ_EVENT_PITCHBEND: - cmdtype = MidiController; - cmdchan = midievent->data.control.channel; - cmdparams[0] = C_pitchwheel; //Pitch Bend - cmdparams[1] = midievent->data.control.value; - break; - case SND_SEQ_EVENT_CONTROLLER: - cmdtype = MidiController; - cmdchan = midievent->data.control.channel; - cmdparams[0] = getcontroller(midievent->data.control.param); - cmdparams[1] = midievent->data.control.value; - //fprintf(stderr,"t=%d val=%d\n",midievent->data.control.param,midievent->data.control.value); - break; - } -} - - -int ALSAMidiIn::getalsaid() -{ - if(midi_handle) { - snd_seq_client_info_t *seq_info; - snd_seq_client_info_malloc(&seq_info); - snd_seq_get_client_info(midi_handle, seq_info); - int id = snd_seq_client_info_get_client(seq_info); - snd_seq_client_info_free(seq_info); - return id; - } - return -1; -} - diff --git a/plugins/zynaddsubfx/src/Input/ALSAMidiIn.h b/plugins/zynaddsubfx/src/Input/ALSAMidiIn.h deleted file mode 100644 index cea61fb36..000000000 --- a/plugins/zynaddsubfx/src/Input/ALSAMidiIn.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - ZynAddSubFX - a software synthesizer - - ALSAMidiIn.h - Midi input for ALSA (this creates an ALSA virtual port) - Copyright (C) 2002-2005 Nasca Octavian Paul - Author: Nasca Octavian Paul - - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License - as published by the Free Software Foundation. - - 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 (version 2 or later) for more details. - - You should have received a copy of the GNU General Public License (version 2) - along with this program; if not, write to the Free Software Foundation, - Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -*/ - -#ifndef ALSA_MIDI_IN_H -#define ALSA_MIDI_IN_H - -#include -#include "MidiIn.h" - - -/**Midi input for ALSA (this creates an ALSA virtual port)*/ -class ALSAMidiIn:public MidiIn -{ - public: - /**Constructor*/ - ALSAMidiIn(); - /**Destructor*/ - ~ALSAMidiIn(); - - void getmidicmd(MidiCmdType &cmdtype, - unsigned char &cmdchan, - int *cmdparams); - /**Get the ALSA id - * @return ALSA id*/ - int getalsaid(); - - private: - snd_seq_t *midi_handle; -}; - -#endif - diff --git a/plugins/zynaddsubfx/src/Input/CMakeLists.txt b/plugins/zynaddsubfx/src/Input/CMakeLists.txt deleted file mode 100644 index dac041748..000000000 --- a/plugins/zynaddsubfx/src/Input/CMakeLists.txt +++ /dev/null @@ -1,19 +0,0 @@ -set(zynaddsubfx_input_SRCS - MidiIn.cpp - NULLMidiIn.cpp - #OSSMidiIn.cpp #[TODO] get OSS midi detection and - #WINMidiIn.cpp # Win midi detection working -) - -if(AlsaMidiInput) - set(zynaddsubfx_input_SRCS - ${zynaddsubfx_input_SRCS} - ALSAMidiIn.cpp - ) - message(STATUS "Alsa midi input enabled") - set(MIDIINPUT_LIBRARIES ${ASOUND_LIBRARY} PARENT_SCOPE) -endif(AlsaMidiInput) - -add_library(zynaddsubfx_input STATIC - ${zynaddsubfx_input_SRCS} - ) diff --git a/plugins/zynaddsubfx/src/Input/MidiIn.cpp b/plugins/zynaddsubfx/src/Input/MidiIn.cpp deleted file mode 100644 index 3d7c5b230..000000000 --- a/plugins/zynaddsubfx/src/Input/MidiIn.cpp +++ /dev/null @@ -1,96 +0,0 @@ -/* - ZynAddSubFX - a software synthesizer - - MidiIn.cpp - This class is inherited by all the Midi input classes - Copyright (C) 2002-2005 Nasca Octavian Paul - Author: Nasca Octavian Paul - - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License - as published by the Free Software Foundation. - - 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 (version 2 or later) for more details. - - You should have received a copy of the GNU General Public License (version 2) - along with this program; if not, write to the Free Software Foundation, - Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -*/ - -#include "../globals.h" -#include "MidiIn.h" - -int MidiIn::getcontroller(unsigned char b) -{ - /**\todo there might be a better way to do this*/ - int ctl = C_NULL; - switch(b) { - case 1: - ctl = C_modwheel; //Modulation Wheel - break; - case 7: - ctl = C_volume; //Volume - break; - case 10: - ctl = C_panning; //Panning - break; - case 11: - ctl = C_expression; //Expression - break; - case 64: - ctl = C_sustain; //Sustain pedal - break; - case 65: - ctl = C_portamento; //Portamento - break; - case 71: - ctl = C_filterq; //Filter Q (Sound Timbre) - break; - case 74: - ctl = C_filtercutoff; //Filter Cutoff (Brightness) - break; - case 75: - ctl = C_bandwidth; //BandWidth - break; - case 76: - ctl = C_fmamp; //FM amplitude - break; - case 77: - ctl = C_resonance_center; //Resonance Center Frequency - break; - case 78: - ctl = C_resonance_bandwidth; //Resonance Bandwith - break; - case 120: - ctl = C_allsoundsoff; //All Sounds OFF - break; - case 121: - ctl = C_resetallcontrollers; //Reset All Controllers - break; - case 123: - ctl = C_allnotesoff; //All Notes OFF - break; - //RPN and NRPN - case 0x06: - ctl = C_dataentryhi; //Data Entry (Coarse) - break; - case 0x26: - ctl = C_dataentrylo; //Data Entry (Fine) - break; - case 99: - ctl = C_nrpnhi; //NRPN (Coarse) - break; - case 98: - ctl = C_nrpnlo; //NRPN (Fine) - break; - default: - ctl = C_NULL; //unknown controller - //fprintf(stderr,"Controller=%d , par=%d\n",midievent->data.control.param,cmdparams[1]); - break; - } - return ctl; -} - diff --git a/plugins/zynaddsubfx/src/Input/MidiIn.h b/plugins/zynaddsubfx/src/Input/MidiIn.h deleted file mode 100644 index 5d978eaeb..000000000 --- a/plugins/zynaddsubfx/src/Input/MidiIn.h +++ /dev/null @@ -1,52 +0,0 @@ -/* - ZynAddSubFX - a software synthesizer - - MidiIn.h - This class is inherited by all the Midi input classes - Copyright (C) 2002-2005 Nasca Octavian Paul - Author: Nasca Octavian Paul - - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License - as published by the Free Software Foundation. - - 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 (version 2 or later) for more details. - - You should have received a copy of the GNU General Public License (version 2) - along with this program; if not, write to the Free Software Foundation, - Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -*/ - -#ifndef MIDI_IN_H -#define MIDI_IN_H - -#include "../globals.h" - -enum MidiCmdType { - MidiNull, MidiNoteOFF, MidiNoteON, MidiController -}; -#define MP_MAX_BYTES 4000 //in case of loooong SYS_EXes - -/**This class is inherited by all the Midi input classes*/ -class MidiIn -{ - public: - /**Get the command,channel and parameters of the MIDI - * - * \todo make pure virtual - * @param cmdtype the referece to the variable that will store the type - * @param cmdchan the channel for the event - * @param parameters for the event*/ - virtual void getmidicmd(MidiCmdType &cmdtype, - unsigned char &cmdchan, - int *cmdparams) = 0; - int getcontroller(unsigned char b); - protected: - bool inputok; /**<1 if I can read midi bytes from input ports*/ -}; - -#endif - diff --git a/plugins/zynaddsubfx/src/Input/NULLMidiIn.cpp b/plugins/zynaddsubfx/src/Input/NULLMidiIn.cpp deleted file mode 100644 index a9c13acb3..000000000 --- a/plugins/zynaddsubfx/src/Input/NULLMidiIn.cpp +++ /dev/null @@ -1,41 +0,0 @@ -/* - ZynAddSubFX - a software synthesizer - - NULLMidiIn.cpp - a dummy Midi port - Copyright (C) 2002-2005 Nasca Octavian Paul - Author: Nasca Octavian Paul - - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License - as published by the Free Software Foundation. - - 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 (version 2 or later) for more details. - - You should have received a copy of the GNU General Public License (version 2) - along with this program; if not, write to the Free Software Foundation, - Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -*/ - -#include "NULLMidiIn.h" - -NULLMidiIn::NULLMidiIn() -{} - -NULLMidiIn::~NULLMidiIn() -{} - -/* - * Get the midi command,channel and parameters - * It returns MidiNull because it is a dummy driver - */ -void NULLMidiIn::getmidicmd(MidiCmdType &cmdtype, - unsigned char &cmdchan, - int *cmdparams) -{ - cmdtype = MidiNull; -} - diff --git a/plugins/zynaddsubfx/src/Input/NULLMidiIn.h b/plugins/zynaddsubfx/src/Input/NULLMidiIn.h deleted file mode 100644 index 72cef4ad0..000000000 --- a/plugins/zynaddsubfx/src/Input/NULLMidiIn.h +++ /dev/null @@ -1,50 +0,0 @@ -/* - ZynAddSubFX - a software synthesizer - - NULLMidiIn.h - a dummy Midi port - Copyright (C) 2002-2005 Nasca Octavian Paul - Author: Nasca Octavian Paul - - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License - as published by the Free Software Foundation. - - 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 (version 2 or later) for more details. - - You should have received a copy of the GNU General Public License (version 2) - along with this program; if not, write to the Free Software Foundation, - Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -*/ - -#ifndef NULL_MIDI_IN_H -#define NULL_MIDI_IN_H - -#include "MidiIn.h" - - -/**a dummy Midi port*/ -class NULLMidiIn:public MidiIn -{ - public: - /**Dummy Constructor - * \todo see if the default constructor would work here*/ - NULLMidiIn(); - /**Dummy Destructor - * \todo see if the default destructor would work here*/ - ~NULLMidiIn(); - /**Get the midi command,channel and parameters - * It returns MidiNull because it is a dummy driver - */ - void getmidicmd(MidiCmdType &cmdtype, - unsigned char &cmdchan, - int *cmdparams); - - private: -}; - -#endif - diff --git a/plugins/zynaddsubfx/src/Input/OSSMidiIn.cpp b/plugins/zynaddsubfx/src/Input/OSSMidiIn.cpp deleted file mode 100644 index 5a20fb930..000000000 --- a/plugins/zynaddsubfx/src/Input/OSSMidiIn.cpp +++ /dev/null @@ -1,123 +0,0 @@ -/* - ZynAddSubFX - a software synthesizer - - OSSMidiIn.cpp - Midi input for Open Sound System - Copyright (C) 2002-2005 Nasca Octavian Paul - Author: Nasca Octavian Paul - - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License - as published by the Free Software Foundation. - - 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 (version 2 or later) for more details. - - You should have received a copy of the GNU General Public License (version 2) - along with this program; if not, write to the Free Software Foundation, - Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -*/ - -#include -#include -#include -#include -#include -#include -#include - -#include "OSSMidiIn.h" -#include "../Misc/Util.h" - -OSSMidiIn::OSSMidiIn() -{ - inputok = false; - midi_handle = open(config.cfg.LinuxOSSSeqInDev, O_RDONLY, 0); - if(midi_handle != -1) - inputok = true; - - lastmidicmd = 0; - cmdtype = 0; - cmdchan = 0; -} - -OSSMidiIn::~OSSMidiIn() -{ - close(midi_handle); -} - -unsigned char OSSMidiIn::readbyte() -{ - unsigned char tmp[4]; - read(midi_handle, &tmp[0], 1); - while(tmp[0] != SEQ_MIDIPUTC) { - read(midi_handle, &tmp[0], 4); - } - return tmp[1]; -} - -unsigned char OSSMidiIn::getmidibyte() -{ - unsigned char b; - do { - b = readbyte(); - } while(b == 0xfe); //drops the Active Sense Messages - return b; -} - -/* - * Get the midi command,channel and parameters - */ -void OSSMidiIn::getmidicmd(MidiCmdType &cmdtype, - unsigned char &cmdchan, - int *cmdparams) -{ - unsigned char tmp, i; - if(inputok == false) { - cmdtype = MidiNull; - return; - } - i = 0; - if(lastmidicmd == 0) { //asteapta prima data pana cand vine prima comanda midi - while(tmp < 0x80) - tmp = getmidibyte(); - lastmidicmd = tmp; - } - - tmp = getmidibyte(); - - if(tmp >= 0x80) { - lastmidicmd = tmp; - tmp = getmidibyte(); - } - - if((lastmidicmd >= 0x80) && (lastmidicmd <= 0x8f)) { //Note OFF - cmdtype = MidiNoteOFF; - cmdchan = lastmidicmd % 16; - cmdparams[0] = tmp; //note number - } - - if((lastmidicmd >= 0x90) && (lastmidicmd <= 0x9f)) { //Note ON - cmdtype = MidiNoteON; - cmdchan = lastmidicmd % 16; - cmdparams[0] = tmp; //note number - cmdparams[1] = getmidibyte(); //velocity - if(cmdparams[1] == 0) - cmdtype = MidiNoteOFF; //if velocity==0 then is note off - } - if((lastmidicmd >= 0xB0) && (lastmidicmd <= 0xBF)) { //Controllers - cmdtype = MidiController; - cmdchan = lastmidicmd % 16; - cmdparams[0] = getcontroller(tmp); - cmdparams[1] = getmidibyte(); - } - if((lastmidicmd >= 0xE0) && (lastmidicmd <= 0xEF)) { //Pitch Wheel - cmdtype = MidiController; - cmdchan = lastmidicmd % 16; - cmdparams[0] = C_pitchwheel; - cmdparams[1] = (tmp + getmidibyte() * (int) 128) - 8192; //hope this is correct - } -} - diff --git a/plugins/zynaddsubfx/src/Input/OSSMidiIn.h b/plugins/zynaddsubfx/src/Input/OSSMidiIn.h deleted file mode 100644 index a3b56f51b..000000000 --- a/plugins/zynaddsubfx/src/Input/OSSMidiIn.h +++ /dev/null @@ -1,50 +0,0 @@ -/* - ZynAddSubFX - a software synthesizer - - OSSMidiIn.h - Midi input for Open Sound System - Copyright (C) 2002-2005 Nasca Octavian Paul - Author: Nasca Octavian Paul - - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License - as published by the Free Software Foundation. - - 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 (version 2 or later) for more details. - - You should have received a copy of the GNU General Public License (version 2) - along with this program; if not, write to the Free Software Foundation, - Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -*/ - -#ifndef OSS_MIDI_IN_H -#define OSS_MIDI_IN_H - -#include "MidiIn.h" - -class OSSMidiIn:public MidiIn -{ - public: - OSSMidiIn(); - ~OSSMidiIn(); - unsigned char getmidibyte(); - unsigned char readbyte(); - - //Midi parser - void getmidicmd(MidiCmdType &cmdtype, - unsigned char &cmdchan, - int *cmdparams); - unsigned char cmdtype; //the Message Type (noteon,noteof,sysex..) - unsigned char cmdchan; //the channel number - - private: - int midi_handle; - unsigned char lastmidicmd; //last byte (>=80) received from the Midi -}; - - -#endif - diff --git a/plugins/zynaddsubfx/src/Input/WINMidiIn.cpp b/plugins/zynaddsubfx/src/Input/WINMidiIn.cpp deleted file mode 100644 index 65974eec1..000000000 --- a/plugins/zynaddsubfx/src/Input/WINMidiIn.cpp +++ /dev/null @@ -1,94 +0,0 @@ -/* - ZynAddSubFX - a software synthesizer - - WINMidiIn.cpp - Midi input for Windows - Copyright (C) 2002-2005 Nasca Octavian Paul - Author: Nasca Octavian Paul - - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License - as published by the Free Software Foundation. - - 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 (version 2 or later) for more details. - - You should have received a copy of the GNU General Public License (version 2) - along with this program; if not, write to the Free Software Foundation, - Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -*/ - -#include -#include -#include -#include -#include - -#include "WINMidiIn.h" -#include "MidiIn.h" -#include "../Misc/Util.h" - -Master *winmaster; -HMIDIIN winmidiinhandle; -MidiIn midictl; //used to convert the controllers to ZynAddSubFX controllers - -void CALLBACK WinMidiInProc(HMIDIIN hMidiIn, UINT wMsg, DWORD dwInstance, - DWORD dwParam1, DWORD dwParam2) -{ - int midicommand = MidiNull; - if(wMsg == MIM_DATA) { - int cmd, par1, par2; - cmd = dwParam1 & 0xff; - if(cmd == 0xfe) - return; - par1 = (dwParam1 >> 8) & 0xff; - par2 = dwParam1 >> 16; - //printf("%x %x %x\n",cmd,par1,par2);fflush(stdout); - int cmdchan = cmd & 0x0f; - int cmdtype = (cmd >> 4) & 0x0f; - - int tmp = 0; - pthread_mutex_lock(&winmaster->mutex); - switch(cmdtype) { - case (0x8): //noteon - winmaster->NoteOff(cmdchan, par1); - break; - case (0x9): //noteoff - winmaster->NoteOn(cmdchan, par1, par2 & 0xff); - break; - case (0xb): //controller - winmaster->SetController(cmdchan, midictl.getcontroller( - par1), par2 & 0xff); - break; - case (0xe): //pitch wheel - tmp = (par1 + par2 * (long int) 128) - 8192; - winmaster->SetController(cmdchan, C_pitchwheel, tmp); - break; - default: - break; - } - pthread_mutex_unlock(&winmaster->mutex); - } -} - -void InitWinMidi(Master *master_) -{ - winmaster = master_; - - long int result = - midiInOpen(&winmidiinhandle, - config.cfg.WindowsMidiInId, - (DWORD)WinMidiInProc, - 0, - CALLBACK_FUNCTION); - result = midiInStart(winmidiinhandle); -} - -void StopWinMidi() -{ - midiInStop(winmidiinhandle); - midiInClose(winmidiinhandle); -} - diff --git a/plugins/zynaddsubfx/src/Input/WINMidiIn.h b/plugins/zynaddsubfx/src/Input/WINMidiIn.h deleted file mode 100644 index db9fc79d5..000000000 --- a/plugins/zynaddsubfx/src/Input/WINMidiIn.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - ZynAddSubFX - a software synthesizer - - WINMidiIn.h - Midi input for Windows - Copyright (C) 2002-2005 Nasca Octavian Paul - Author: Nasca Octavian Paul - - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License - as published by the Free Software Foundation. - - 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 (version 2 or later) for more details. - - You should have received a copy of the GNU General Public License (version 2) - along with this program; if not, write to the Free Software Foundation, - Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -*/ - -#ifndef WIN_MIDI_IN_H -#define WIN_MIDI_IN_H - - -#include "../Misc/Master.h" - -void InitWinMidi(Master *master_); -void StopWinMidi(); - - -#endif - diff --git a/plugins/zynaddsubfx/src/Misc/Bank.cpp b/plugins/zynaddsubfx/src/Misc/Bank.cpp deleted file mode 100644 index 246a4098a..000000000 --- a/plugins/zynaddsubfx/src/Misc/Bank.cpp +++ /dev/null @@ -1,644 +0,0 @@ -/* - ZynAddSubFX - a software synthesizer - - Bank.h - Instrument Bank - Copyright (C) 2002-2005 Nasca Octavian Paul - Author: Nasca Octavian Paul - - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License - as published by the Free Software Foundation. - - 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 (version 2 or later) for more details. - - You should have received a copy of the GNU General Public License (version 2) - along with this program; if not, write to the Free Software Foundation, - Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -*/ - -#include "Bank.h" -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include "Config.h" - -#define INSTRUMENT_EXTENSION ".xiz" - -//if this file exists into a directory, this make the directory to be considered as a bank, even if it not contains a instrument file -#define FORCE_BANK_DIR_FILE ".bankdir" - -Bank::Bank() -{ - ZERO(defaultinsname, PART_MAX_NAME_LEN); - snprintf(defaultinsname, PART_MAX_NAME_LEN, "%s", " "); - - for(int i = 0; i < BANK_SIZE; i++) { - ins[i].used = false; - ins[i].filename = NULL; - ins[i].info.PADsynth_used = false; - } - dirname = NULL; - clearbank(); - - - - for(int i = 0; i < MAX_NUM_BANKS; i++) { - banks[i].dir = NULL; - banks[i].name = NULL; - } - - bankfiletitle = dirname; - - loadbank(config.cfg.currentBankDir); -} - -Bank::~Bank() -{ - for(int i = 0; i < MAX_NUM_BANKS; i++) { - if(banks[i].dir != NULL) - delete [] banks[i].dir; - if(banks[i].name != NULL) - delete [] banks[i].name; - } - - clearbank(); -} - -/* - * Get the name of an instrument from the bank - */ -char *Bank::getname(unsigned int ninstrument) -{ - if(emptyslot(ninstrument)) - return defaultinsname; - return ins[ninstrument].name; -} - -/* - * Get the numbered name of an instrument from the bank - */ -char *Bank::getnamenumbered(unsigned int ninstrument) -{ - if(emptyslot(ninstrument)) - return defaultinsname; - snprintf(tmpinsname[ninstrument], - PART_MAX_NAME_LEN + 15, - "%d. %s", - ninstrument + 1, - getname(ninstrument)); - return tmpinsname[ninstrument]; -} - -/* - * Changes the name of an instrument (and the filename) - */ -void Bank::setname(unsigned int ninstrument, const char *newname, int newslot) -{ - if(emptyslot(ninstrument)) - return; - - char newfilename[1000 + 1], tmpfilename[100 + 1]; - - ZERO(newfilename, 1001); - ZERO(tmpfilename, 101); - if(newslot >= 0) - snprintf(tmpfilename, 100, "%4d-%s", newslot + 1, newname); - else - snprintf(tmpfilename, 100, "%4d-%s", ninstrument + 1, newname); - - //add the zeroes at the start of filename - for(int i = 0; i < 4; i++) - if(tmpfilename[i] == ' ') - tmpfilename[i] = '0'; - - //make the filenames legal - for(int i = 0; i < (int) strlen(tmpfilename); i++) { - char c = tmpfilename[i]; - if((c >= '0') && (c <= '9')) - continue; - if((c >= 'A') && (c <= 'Z')) - continue; - if((c >= 'a') && (c <= 'z')) - continue; - if((c == '-') || (c == ' ')) - continue; - - tmpfilename[i] = '_'; - } - - snprintf(newfilename, 1000, "%s/%s.xiz", dirname, tmpfilename); - -// printf("rename %s -> %s\n",ins[ninstrument].filename,newfilename);////////////// - - rename(ins[ninstrument].filename, newfilename); - if(ins[ninstrument].filename) - delete [] ins[ninstrument].filename; - ins[ninstrument].filename = new char[strlen(newfilename) + 5]; - snprintf(ins[ninstrument].filename, strlen( - newfilename) + 1, "%s", newfilename); - snprintf(ins[ninstrument].name, PART_MAX_NAME_LEN, "%s", &tmpfilename[5]); -} - -/* - * Check if there is no instrument on a slot from the bank - */ -int Bank::emptyslot(unsigned int ninstrument) -{ - if(ninstrument >= BANK_SIZE) - return 1; - if(ins[ninstrument].filename == NULL) - return 1; - - if(ins[ninstrument].used) - return 0; - else - return 1; -} - -/* - * Removes the instrument from the bank - */ -void Bank::clearslot(unsigned int ninstrument) -{ - if(emptyslot(ninstrument)) - return; - -// printf("remove %s \n",ins[ninstrument].filename);//////////////////////// - - - remove(ins[ninstrument].filename); - deletefrombank(ninstrument); -} - -/* - * Save the instrument to a slot - */ -void Bank::savetoslot(unsigned int ninstrument, Part *part) -{ - clearslot(ninstrument); - - const int maxfilename = 200; - char tmpfilename[maxfilename + 20]; - ZERO(tmpfilename, maxfilename + 20); - - snprintf(tmpfilename, - maxfilename, - "%4d-%s", - ninstrument + 1, - (char *)part->Pname); - - //add the zeroes at the start of filename - for(int i = 0; i < 4; i++) - if(tmpfilename[i] == ' ') - tmpfilename[i] = '0'; - - //make the filenames legal - for(int i = 0; i < (int)strlen(tmpfilename); i++) { - char c = tmpfilename[i]; - if((c >= '0') && (c <= '9')) - continue; - if((c >= 'A') && (c <= 'Z')) - continue; - if((c >= 'a') && (c <= 'z')) - continue; - if((c == '-') || (c == ' ')) - continue; - - tmpfilename[i] = '_'; - } - - strncat(tmpfilename, ".xiz", maxfilename + 10); - - int fnsize = strlen(dirname) + strlen(tmpfilename) + 10; - char *filename = new char[fnsize + 4]; - ZERO(filename, fnsize + 2); - - snprintf(filename, fnsize, "%s/%s", dirname, tmpfilename); - - remove(filename); - part->saveXML(filename); - addtobank(ninstrument, tmpfilename, (char *) part->Pname); - - delete[] filename; -} - -/* - * Loads the instrument from the bank - */ -void Bank::loadfromslot(unsigned int ninstrument, Part *part) -{ - if(emptyslot(ninstrument)) - return; - - part->defaultsinstrument(); - -// printf("load: %s\n",ins[ninstrument].filename); - - part->loadXMLinstrument(ins[ninstrument].filename); -} - - -/* - * Makes current a bank directory - */ -int Bank::loadbank(const char *bankdirname) -{ - DIR *dir = opendir(bankdirname); - clearbank(); - - if(dir == NULL) - return -1; - - if(dirname != NULL) - delete[] dirname; - dirname = new char[strlen(bankdirname) + 1]; - snprintf(dirname, strlen(bankdirname) + 1, "%s", bankdirname); - - bankfiletitle = dirname; - - // printf("loadbank %s/\n",bankdirname); - struct dirent *fn; - - while((fn = readdir(dir))) { - const char *filename = fn->d_name; - - //sa verific daca e si extensia dorita - if(strstr(filename, INSTRUMENT_EXTENSION) == NULL) - continue; - - //verify if the name is like this NNNN-name (where N is a digit) - int no = 0; - unsigned int startname = 0; - - for(unsigned int i = 0; i < 4; i++) { - if(strlen(filename) <= i) - break; - - if((filename[i] >= '0') && (filename[i] <= '9')) { - no = no * 10 + (filename[i] - '0'); - startname++; - } - } - - - if((startname + 1) < strlen(filename)) - startname++; //to take out the "-" - - char name[PART_MAX_NAME_LEN + 1]; - ZERO(name, PART_MAX_NAME_LEN + 1); - snprintf(name, PART_MAX_NAME_LEN, "%s", filename); - - //remove the file extension - for(int i = strlen(name) - 1; i >= 2; i--) { - if(name[i] == '.') { - name[i] = '\0'; - break; - } - } - - if(no != 0) //the instrument position in the bank is found - addtobank(no - 1, filename, &name[startname]); - else - addtobank(-1, filename, name); - ; - } - - - closedir(dir); - - if(dirname != NULL) - sprintf(config.cfg.currentBankDir, "%s", dirname); - ; - - return 0; -} - -/* - * Makes a new bank, put it on a file and makes it current bank - */ -int Bank::newbank(const char *newbankdirname) -{ - int result; - char tmpfilename[MAX_STRING_SIZE]; - char bankdir[MAX_STRING_SIZE]; - snprintf(bankdir, MAX_STRING_SIZE, "%s", config.cfg.bankRootDirList[0]); - - if(((bankdir[strlen(bankdir) - 1]) != '/') - && ((bankdir[strlen(bankdir) - 1]) != '\\')) - strncat(bankdir, "/", MAX_STRING_SIZE - strlen(bankdir) - 1 ); - ; - strncat(bankdir, newbankdirname, MAX_STRING_SIZE - strlen(bankdir) - 1); -#ifdef OS_WINDOWS - result = mkdir(bankdir); -#else - result = mkdir(bankdir, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH); -#endif - if(result < 0) - return -1; - - snprintf(tmpfilename, - MAX_STRING_SIZE, - "%s/%s", - bankdir, - FORCE_BANK_DIR_FILE); -// printf("%s\n",tmpfilename); - FILE *tmpfile = fopen(tmpfilename, "w+"); - fclose(tmpfile); - - return loadbank(bankdir); -} - -/* - * Check if the bank is locked (i.e. the file opened was readonly) - */ -int Bank::locked() -{ - return dirname == NULL; -} - -/* - * Swaps a slot with another - */ -void Bank::swapslot(unsigned int n1, unsigned int n2) -{ - if((n1 == n2) || (locked())) - return; - if(emptyslot(n1) && (emptyslot(n2))) - return; - if(emptyslot(n1)) { //change n1 to n2 in order to make - int tmp = n2; - n2 = n1; - n1 = tmp; - } - - if(emptyslot(n2)) { //this is just a movement from slot1 to slot2 - setname(n1, getname(n1), n2); - ins[n2] = ins[n1]; - ins[n1].used = false; - ins[n1].name[0] = '\0'; - ins[n1].filename = NULL; - ins[n1].info.PADsynth_used = 0; - } - else { //if both slots are used - if(strcmp(ins[n1].name, ins[n2].name) == 0) //change the name of the second instrument if the name are equal - strncat(ins[n2].name, "2", PART_MAX_NAME_LEN); - ; - setname(n1, getname(n1), n2); - setname(n2, getname(n2), n1); - ins_t tmp; - tmp.used = true; - strcpy(tmp.name, ins[n2].name); - char *tmpfilename = ins[n2].filename; - bool padsynth_used = ins[n2].info.PADsynth_used; - - ins[n2] = ins[n1]; - strcpy(ins[n1].name, tmp.name); - ins[n1].filename = tmpfilename; - ins[n1].info.PADsynth_used = padsynth_used; - } -} - - -//a helper function that compares 2 banks[] arrays -int Bank_compar(const void *a, const void *b) -{ - struct Bank::bankstruct *bank1 = (Bank::bankstruct *)a; - struct Bank::bankstruct *bank2 = (Bank::bankstruct *)b; - if(((bank1->name) == NULL) || ((bank2->name) == NULL)) - return 0; - - int result = strcasecmp(bank1->name, bank2->name); - return result < 0; -} - - -/* - * Re-scan for directories containing instrument banks - */ - -void Bank::rescanforbanks() -{ - for(int i = 0; i < MAX_NUM_BANKS; i++) { - if(banks[i].dir != NULL) - delete [] banks[i].dir; - if(banks[i].name != NULL) - delete [] banks[i].name; - banks[i].dir = NULL; - banks[i].name = NULL; - } - - for(int i = 0; i < MAX_BANK_ROOT_DIRS; i++) - if(config.cfg.bankRootDirList[i] != NULL) - scanrootdir(config.cfg.bankRootDirList[i]); - - //sort the banks - for(int j = 0; j < MAX_NUM_BANKS - 1; j++) { - for(int i = j + 1; i < MAX_NUM_BANKS; i++) { - if(Bank_compar(&banks[i], &banks[j])) { - char *tmpname = banks[i].name; - char *tmpdir = banks[i].dir; - - banks[i].name = banks[j].name; - banks[i].dir = banks[j].dir; - - banks[j].name = tmpname; - banks[j].dir = tmpdir; - } - } - } - - //remove duplicate bank names - int dupl = 0; - for(int j = 0; j < MAX_NUM_BANKS - 1; j++) { - for(int i = j + 1; i < MAX_NUM_BANKS; i++) { - if((banks[i].name == NULL) || (banks[j].name == NULL)) - continue; - if(strcmp(banks[i].name, banks[j].name) == 0) { //add a [1] to the first bankname and [n] to others - char *tmpname = banks[i].name; - banks[i].name = new char[strlen(tmpname) + 100]; - sprintf(banks[i].name, "%s[%d]", tmpname, dupl + 2); - delete[] tmpname; - - if(dupl == 0) { - char *tmpname = banks[j].name; - banks[j].name = new char[strlen(tmpname) + 100]; - sprintf(banks[j].name, "%s[1]", tmpname); - delete[] tmpname; - } - - dupl++; - } - else - dupl = 0; - } - } -} - - - -// private stuff - -void Bank::scanrootdir(char *rootdir) -{ -// printf("Scanning root dir:%s\n",rootdir); - DIR *dir = opendir(rootdir); - if(dir == NULL) - return; - - const int maxdirsize = 1000; - struct { - char dir[maxdirsize]; - char name[maxdirsize]; - } bank; - - const char *separator = "/"; - if(strlen(rootdir)) { - char tmp = rootdir[strlen(rootdir) - 1]; - if((tmp == '/') || (tmp == '\\')) - separator = ""; - } - - struct dirent *fn; - while((fn = readdir(dir))) { - const char *dirname = fn->d_name; - if(dirname[0] == '.') - continue; - - snprintf(bank.dir, maxdirsize, "%s%s%s/", rootdir, separator, dirname); - snprintf(bank.name, maxdirsize, "%s", dirname); - //find out if the directory contains at least 1 instrument - bool isbank = false; - - DIR *d = opendir(bank.dir); - if(d == NULL) - continue; - - struct dirent *fname; - - while((fname = readdir(d))) { - if((strstr(fname->d_name, INSTRUMENT_EXTENSION) != NULL) - || (strstr(fname->d_name, FORCE_BANK_DIR_FILE) != NULL)) { - isbank = true; - break; //aici as putea pune in loc de break un update la un counter care imi arata nr. de instrumente din bank - } - } - - closedir(d); - - if(isbank) { - int pos = -1; - for(int i = 1; i < MAX_NUM_BANKS; i++) { //banks[0] e liber intotdeauna - if(banks[i].name == NULL) { - pos = i; - break; - } - } - - if(pos >= 0) { - banks[pos].name = new char[maxdirsize]; - banks[pos].dir = new char[maxdirsize]; - snprintf(banks[pos].name, maxdirsize, "%s", bank.name); - snprintf(banks[pos].dir, maxdirsize, "%s", bank.dir); - } - } - } - - closedir(dir); -} - -void Bank::clearbank() -{ - for(int i = 0; i < BANK_SIZE; i++) - deletefrombank(i); - if(dirname != NULL) - delete[] dirname; - bankfiletitle = NULL; - dirname = NULL; -} - -int Bank::addtobank(int pos, const char *filename, const char *name) -{ - if((pos >= 0) && (pos < BANK_SIZE)) { - if(ins[pos].used) - pos = -1; //force it to find a new free position - } - else - if(pos >= BANK_SIZE) - pos = -1; - - - if(pos < 0) { //find a free position - for(int i = BANK_SIZE - 1; i >= 0; i--) - if(!ins[i].used) { - pos = i; - break; - } - ; - } - - if(pos < 0) - return -1; //the bank is full - - // printf("%s %d\n",filename,pos); - - deletefrombank(pos); - - ins[pos].used = true; - snprintf(ins[pos].name, PART_MAX_NAME_LEN, "%s", name); - - snprintf(tmpinsname[pos], PART_MAX_NAME_LEN + 10, " "); - - int len = strlen(filename) + 1 + strlen(dirname); - ins[pos].filename = new char[len + 2]; - ins[pos].filename[len + 1] = 0; - snprintf(ins[pos].filename, len + 1, "%s/%s", dirname, filename); - - //see if PADsynth is used - if(config.cfg.CheckPADsynth) { - XMLwrapper *xml = new XMLwrapper(); - xml->loadXMLfile(ins[pos].filename); - - ins[pos].info.PADsynth_used = xml->hasPadSynth(); - delete xml; - } - else - ins[pos].info.PADsynth_used = false; - - return 0; -} - -bool Bank::isPADsynth_used(unsigned int ninstrument) -{ - if(config.cfg.CheckPADsynth == 0) - return 0; - else - return ins[ninstrument].info.PADsynth_used; -} - - -void Bank::deletefrombank(int pos) -{ - if((pos < 0) || (pos >= BANK_SIZE)) - return; - ins[pos].used = false; - ZERO(ins[pos].name, PART_MAX_NAME_LEN + 1); - if(ins[pos].filename != NULL) { - delete [] ins[pos].filename; - ins[pos].filename = NULL; - } - - ZERO(tmpinsname[pos], PART_MAX_NAME_LEN + 20); -} - diff --git a/plugins/zynaddsubfx/src/Misc/Bank.h b/plugins/zynaddsubfx/src/Misc/Bank.h deleted file mode 100644 index aa3594648..000000000 --- a/plugins/zynaddsubfx/src/Misc/Bank.h +++ /dev/null @@ -1,108 +0,0 @@ -/* - ZynAddSubFX - a software synthesizer - - Bank.h - Instrument Bank - Copyright (C) 2002-2005 Nasca Octavian Paul - Author: Nasca Octavian Paul - - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License - as published by the Free Software Foundation. - - 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 (version 2 or later) for more details. - - You should have received a copy of the GNU General Public License (version 2) - along with this program; if not, write to the Free Software Foundation, - Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -*/ - -#ifndef BANK_H -#define BANK_H - -#include "../globals.h" -#include "XMLwrapper.h" -#include "Part.h" - -#define BANK_SIZE 160 - -/** - * The max. number of banks that are used - */ -#define MAX_NUM_BANKS 400 - -/**The instrument Bank - * \todo add in strings to replace char* */ -class Bank -{ - public: - /**Constructor*/ - Bank(); - ~Bank(); - char *getname(unsigned int ninstrument); - char *getnamenumbered(unsigned int ninstrument); - void setname(unsigned int ninstrument, const char *newname, int newslot); //if newslot==-1 then this is ignored, else it will be put on that slot - bool isPADsynth_used(unsigned int ninstrument); - - /**returns 0 if the slot is not empty or 1 if the slot is empty - * \todo start using bool before facepalm*/ - int emptyslot(unsigned int ninstrument); - - /**Empties out the selected slot*/ - void clearslot(unsigned int ninstrument); - /**Saves the given Part to slot*/ - void savetoslot(unsigned int ninstrument, Part *part); - /**Loads the given slot into a Part*/ - void loadfromslot(unsigned int ninstrument, Part *part); - - /**Swaps Slots*/ - void swapslot(unsigned int n1, unsigned int n2); - - int loadbank(const char *bankdirname); - int newbank(const char *newbankdirname); - - char *bankfiletitle; //this is shown on the UI of the bank (the title of the window) - int locked(); - - void rescanforbanks(); - - struct bankstruct { - char *dir; - char *name; - }; - - bankstruct banks[MAX_NUM_BANKS]; - - private: - - //it adds a filename to the bank - //if pos is -1 it try to find a position - //returns -1 if the bank is full, or 0 if the instrument was added - int addtobank(int pos, const char *filename, const char *name); - - void deletefrombank(int pos); - - void clearbank(); - - char defaultinsname[PART_MAX_NAME_LEN]; - char tmpinsname[BANK_SIZE][PART_MAX_NAME_LEN + 20]; //this keeps the numbered names - - struct ins_t { - bool used; - char name[PART_MAX_NAME_LEN + 1]; - char *filename; - struct { - bool PADsynth_used; - } info; - } ins[BANK_SIZE]; - - char *dirname; - - void scanrootdir(char *rootdir); //scans a root dir for banks -}; - -#endif - diff --git a/plugins/zynaddsubfx/src/Misc/CMakeLists.txt b/plugins/zynaddsubfx/src/Misc/CMakeLists.txt deleted file mode 100644 index eb68d5805..000000000 --- a/plugins/zynaddsubfx/src/Misc/CMakeLists.txt +++ /dev/null @@ -1,24 +0,0 @@ -if(NOT ("${MXML_INCLUDE_DIR}" STREQUAL "")) - include_directories("${MXML_INCLUDE_DIR}") -endif() - -set(zynaddsubfx_misc_SRCS - Bank.cpp - Config.cpp - Dump.cpp - Master.cpp - Microtonal.cpp - Part.cpp - Util.cpp - QtXmlWrapper.cpp -) - -if (LASH_FOUND) - set(zynaddsubfx_misc_SRCS ${zynaddsubfx_misc_SRCS} LASHClient.cpp) -endif() - -add_library(zynaddsubfx_misc STATIC - ${zynaddsubfx_misc_SRCS} - ) - -target_link_libraries(zynaddsubfx_misc zynaddsubfx_output) diff --git a/plugins/zynaddsubfx/src/Misc/Config.cpp b/plugins/zynaddsubfx/src/Misc/Config.cpp deleted file mode 100644 index a58f64dc6..000000000 --- a/plugins/zynaddsubfx/src/Misc/Config.cpp +++ /dev/null @@ -1,409 +0,0 @@ -/* - ZynAddSubFX - a software synthesizer - - Config.cpp - Configuration file functions - Copyright (C) 2003-2005 Nasca Octavian Paul - Author: Nasca Octavian Paul - - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License - as published by the Free Software Foundation. - - 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 (version 2 or later) for more details. - - You should have received a copy of the GNU General Public License (version 2) - along with this program; if not, write to the Free Software Foundation, - Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -*/ -#include -#include -#include -#include - -#ifdef OS_WINDOWS -#include -#include -#endif - -#include "Config.h" -#include "XMLwrapper.h" - -Config::Config() : - workingDir( NULL ) -{} -void Config::init() -{ - maxstringsize = MAX_STRING_SIZE; //for ui - //defaults - cfg.SampleRate = 44100; - cfg.SoundBufferSize = 256; - cfg.OscilSize = 1024; - cfg.SwapStereo = 0; - - cfg.LinuxOSSWaveOutDev = new char[MAX_STRING_SIZE]; - snprintf(cfg.LinuxOSSWaveOutDev, MAX_STRING_SIZE, "/dev/dsp"); - cfg.LinuxOSSSeqInDev = new char[MAX_STRING_SIZE]; - snprintf(cfg.LinuxOSSSeqInDev, MAX_STRING_SIZE, "/dev/sequencer"); - - cfg.DumpFile = new char[MAX_STRING_SIZE]; - snprintf(cfg.DumpFile, MAX_STRING_SIZE, "zynaddsubfx_dump.txt"); - - cfg.WindowsWaveOutId = 0; - cfg.WindowsMidiInId = 0; - - cfg.BankUIAutoClose = 0; - cfg.DumpNotesToFile = 0; - cfg.DumpAppend = 1; - - cfg.GzipCompression = 3; - - cfg.Interpolation = 0; - cfg.CheckPADsynth = 1; - - cfg.UserInterfaceMode = 0; - cfg.VirKeybLayout = 1; - winwavemax = 1; - winmidimax = 1; -//try to find out how many input midi devices are there -#ifdef WINMIDIIN - winmidimax = midiInGetNumDevs(); - if(winmidimax == 0) - winmidimax = 1; -#endif - winmididevices = new winmidionedevice[winmidimax]; - for(int i = 0; i < winmidimax; i++) { - winmididevices[i].name = new char[MAX_STRING_SIZE]; - for(int j = 0; j < MAX_STRING_SIZE; j++) - winmididevices[i].name[j] = '\0'; - } - - -//get the midi input devices name -#ifdef WINMIDIIN - MIDIINCAPS midiincaps; - for(int i = 0; i < winmidimax; i++) - if(!midiInGetDevCaps(i, &midiincaps, sizeof(MIDIINCAPS))) - snprintf(winmididevices[i].name, - MAX_STRING_SIZE, - "%s", - midiincaps.szPname); - ; -#endif - for(int i = 0; i < MAX_BANK_ROOT_DIRS; i++) - cfg.bankRootDirList[i] = NULL; - cfg.currentBankDir = new char[MAX_STRING_SIZE]; - sprintf(cfg.currentBankDir, "./testbnk"); - - for(int i = 0; i < MAX_BANK_ROOT_DIRS; i++) - cfg.presetsDirList[i] = NULL; - - char filename[MAX_STRING_SIZE]; - getConfigFileName(filename, MAX_STRING_SIZE); - readConfig(filename); - - if(cfg.bankRootDirList[0] == NULL) { -#if defined(OS_LINUX) - //banks - cfg.bankRootDirList[0] = new char[MAX_STRING_SIZE]; - sprintf(cfg.bankRootDirList[0], "~/banks"); - - cfg.bankRootDirList[1] = new char[MAX_STRING_SIZE]; - sprintf(cfg.bankRootDirList[1], "./"); - - cfg.bankRootDirList[2] = new char[MAX_STRING_SIZE]; - sprintf(cfg.bankRootDirList[2], "/usr/share/zynaddsubfx/banks"); - - cfg.bankRootDirList[3] = new char[MAX_STRING_SIZE]; - sprintf(cfg.bankRootDirList[3], "/usr/local/share/zynaddsubfx/banks"); - - cfg.bankRootDirList[4] = new char[MAX_STRING_SIZE]; - sprintf(cfg.bankRootDirList[4], "../banks"); - - cfg.bankRootDirList[5] = new char[MAX_STRING_SIZE]; - sprintf(cfg.bankRootDirList[5], "banks"); - -#else - //banks - cfg.bankRootDirList[0] = new char[MAX_STRING_SIZE]; - sprintf(cfg.bankRootDirList[0], "./"); - -#ifdef VSTAUDIOOUT - cfg.bankRootDirList[1] = new char[MAX_STRING_SIZE]; - sprintf(cfg.bankRootDirList[1], "c:/Program Files/ZynAddSubFX/banks"); -#else - cfg.bankRootDirList[1] = new char[MAX_STRING_SIZE]; - sprintf(cfg.bankRootDirList[1], "../banks"); -#endif - cfg.bankRootDirList[2] = new char[MAX_STRING_SIZE]; - sprintf(cfg.bankRootDirList[2], "banks"); - -#endif - } - - if(cfg.presetsDirList[0] == NULL) { -#if defined(OS_LINUX) - //presets - cfg.presetsDirList[0] = new char[MAX_STRING_SIZE]; - sprintf(cfg.presetsDirList[0], "./"); - - cfg.presetsDirList[1] = new char[MAX_STRING_SIZE]; - sprintf(cfg.presetsDirList[1], "../presets"); - - cfg.presetsDirList[2] = new char[MAX_STRING_SIZE]; - sprintf(cfg.presetsDirList[2], "presets"); - - cfg.presetsDirList[3] = new char[MAX_STRING_SIZE]; - sprintf(cfg.presetsDirList[3], "/usr/share/zynaddsubfx/presets"); - - cfg.presetsDirList[4] = new char[MAX_STRING_SIZE]; - sprintf(cfg.presetsDirList[4], "/usr/local/share/zynaddsubfx/presets"); - -#else - //presets - cfg.presetsDirList[0] = new char[MAX_STRING_SIZE]; - sprintf(cfg.presetsDirList[0], "./"); - -#ifdef VSTAUDIOOUT - cfg.presetsDirList[1] = new char[MAX_STRING_SIZE]; - sprintf(cfg.presetsDirList[1], "c:/Program Files/ZynAddSubFX/presets"); -#else - cfg.presetsDirList[1] = new char[MAX_STRING_SIZE]; - sprintf(cfg.presetsDirList[1], "../presets"); -#endif - - cfg.presetsDirList[2] = new char[MAX_STRING_SIZE]; - sprintf(cfg.presetsDirList[2], "presets"); -#endif - } -} - -Config::~Config() -{ - delete [] cfg.LinuxOSSWaveOutDev; - delete [] cfg.LinuxOSSSeqInDev; - delete [] cfg.DumpFile; - - for(int i = 0; i < winmidimax; i++) - delete [] winmididevices[i].name; - delete [] winmididevices; -} - - -void Config::save() -{ - char filename[MAX_STRING_SIZE]; - getConfigFileName(filename, MAX_STRING_SIZE); - saveConfig(filename); -} - -void Config::clearbankrootdirlist() -{ - for(int i = 0; i < MAX_BANK_ROOT_DIRS; i++) { - if(cfg.bankRootDirList[i] == NULL) - delete (cfg.bankRootDirList[i]); - cfg.bankRootDirList[i] = NULL; - } -} - -void Config::clearpresetsdirlist() -{ - for(int i = 0; i < MAX_BANK_ROOT_DIRS; i++) { - if(cfg.presetsDirList[i] == NULL) - delete (cfg.presetsDirList[i]); - cfg.presetsDirList[i] = NULL; - } -} - -void Config::readConfig(const char *filename) -{ - XMLwrapper *xmlcfg = new XMLwrapper(); - if(xmlcfg->loadXMLfile(filename) < 0) - return; - if(xmlcfg->enterbranch("CONFIGURATION")) { - cfg.SampleRate = xmlcfg->getpar("sample_rate", - cfg.SampleRate, - 4000, - 1024000); - cfg.SoundBufferSize = xmlcfg->getpar("sound_buffer_size", - cfg.SoundBufferSize, - 16, - 8192); - cfg.OscilSize = xmlcfg->getpar("oscil_size", - cfg.OscilSize, - MAX_AD_HARMONICS * 2, - 131072); - cfg.SwapStereo = xmlcfg->getpar("swap_stereo", - cfg.SwapStereo, - 0, - 1); - cfg.BankUIAutoClose = xmlcfg->getpar("bank_window_auto_close", - cfg.BankUIAutoClose, - 0, - 1); - - cfg.DumpNotesToFile = xmlcfg->getpar("dump_notes_to_file", - cfg.DumpNotesToFile, - 0, - 1); - cfg.DumpAppend = xmlcfg->getpar("dump_append", - cfg.DumpAppend, - 0, - 1); - xmlcfg->getparstr("dump_file", cfg.DumpFile, MAX_STRING_SIZE); - - cfg.GzipCompression = xmlcfg->getpar("gzip_compression", - cfg.GzipCompression, - 0, - 9); - - xmlcfg->getparstr("bank_current", cfg.currentBankDir, MAX_STRING_SIZE); - cfg.Interpolation = xmlcfg->getpar("interpolation", - cfg.Interpolation, - 0, - 1); - - cfg.CheckPADsynth = xmlcfg->getpar("check_pad_synth", - cfg.CheckPADsynth, - 0, - 1); - - - cfg.UserInterfaceMode = xmlcfg->getpar("user_interface_mode", - cfg.UserInterfaceMode, - 0, - 2); - cfg.VirKeybLayout = xmlcfg->getpar("virtual_keyboard_layout", - cfg.VirKeybLayout, - 0, - 10); - - //get bankroot dirs - for(int i = 0; i < MAX_BANK_ROOT_DIRS; i++) { - if(xmlcfg->enterbranch("BANKROOT", i)) { - cfg.bankRootDirList[i] = new char[MAX_STRING_SIZE]; - xmlcfg->getparstr("bank_root", - cfg.bankRootDirList[i], - MAX_STRING_SIZE); - xmlcfg->exitbranch(); - } - } - - //get preset root dirs - for(int i = 0; i < MAX_BANK_ROOT_DIRS; i++) { - if(xmlcfg->enterbranch("PRESETSROOT", i)) { - cfg.presetsDirList[i] = new char[MAX_STRING_SIZE]; - xmlcfg->getparstr("presets_root", - cfg.presetsDirList[i], - MAX_STRING_SIZE); - xmlcfg->exitbranch(); - } - } - - //linux stuff - xmlcfg->getparstr("linux_oss_wave_out_dev", - cfg.LinuxOSSWaveOutDev, - MAX_STRING_SIZE); - xmlcfg->getparstr("linux_oss_seq_in_dev", - cfg.LinuxOSSSeqInDev, - MAX_STRING_SIZE); - - //windows stuff - cfg.WindowsWaveOutId = xmlcfg->getpar("windows_wave_out_id", - cfg.WindowsWaveOutId, - 0, - winwavemax); - cfg.WindowsMidiInId = xmlcfg->getpar("windows_midi_in_id", - cfg.WindowsMidiInId, - 0, - winmidimax); - - xmlcfg->exitbranch(); - } - delete (xmlcfg); - - cfg.OscilSize = (int) pow(2, ceil(log(cfg.OscilSize - 1.0) / log(2.0))); -} - -void Config::saveConfig(const char *filename) -{ - XMLwrapper *xmlcfg = new XMLwrapper(); - - xmlcfg->beginbranch("CONFIGURATION"); - - xmlcfg->addpar("sample_rate", cfg.SampleRate); - xmlcfg->addpar("sound_buffer_size", cfg.SoundBufferSize); - xmlcfg->addpar("oscil_size", cfg.OscilSize); - xmlcfg->addpar("swap_stereo", cfg.SwapStereo); - xmlcfg->addpar("bank_window_auto_close", cfg.BankUIAutoClose); - - xmlcfg->addpar("dump_notes_to_file", cfg.DumpNotesToFile); - xmlcfg->addpar("dump_append", cfg.DumpAppend); - xmlcfg->addparstr("dump_file", cfg.DumpFile); - - xmlcfg->addpar("gzip_compression", cfg.GzipCompression); - - xmlcfg->addpar("check_pad_synth", cfg.CheckPADsynth); - - xmlcfg->addparstr("bank_current", cfg.currentBankDir); - - xmlcfg->addpar("user_interface_mode", cfg.UserInterfaceMode); - xmlcfg->addpar("virtual_keyboard_layout", cfg.VirKeybLayout); - - - for(int i = 0; i < MAX_BANK_ROOT_DIRS; i++) - if(cfg.bankRootDirList[i] != NULL) { - xmlcfg->beginbranch("BANKROOT", i); - xmlcfg->addparstr("bank_root", cfg.bankRootDirList[i]); - xmlcfg->endbranch(); - } - ; - - for(int i = 0; i < MAX_BANK_ROOT_DIRS; i++) - if(cfg.presetsDirList[i] != NULL) { - xmlcfg->beginbranch("PRESETSROOT", i); - xmlcfg->addparstr("presets_root", cfg.presetsDirList[i]); - xmlcfg->endbranch(); - } - ; - - xmlcfg->addpar("interpolation", cfg.Interpolation); - - //linux stuff - xmlcfg->addparstr("linux_oss_wave_out_dev", cfg.LinuxOSSWaveOutDev); - xmlcfg->addparstr("linux_oss_seq_in_dev", cfg.LinuxOSSSeqInDev); - - //windows stuff - xmlcfg->addpar("windows_wave_out_id", cfg.WindowsWaveOutId); - xmlcfg->addpar("windows_midi_in_id", cfg.WindowsMidiInId); - - xmlcfg->endbranch(); - - int tmp = cfg.GzipCompression; - cfg.GzipCompression = 0; - xmlcfg->saveXMLfile(filename); - cfg.GzipCompression = tmp; - - delete (xmlcfg); -} - -void Config::getConfigFileName(char *name, int namesize) -{ - name[0] = 0; - if( workingDir != NULL ) - { - snprintf(name, namesize, "%s%s", workingDir, ".zynaddsubfxXML.cfg"); - } - else - { -#ifdef OS_LINUX - snprintf(name, namesize, "%s%s", getenv("HOME"), "/.zynaddsubfxXML.cfg"); -#else - snprintf(name, namesize, "%s", "zynaddsubfxXML.cfg"); -#endif - } -} - diff --git a/plugins/zynaddsubfx/src/Misc/Config.h b/plugins/zynaddsubfx/src/Misc/Config.h deleted file mode 100644 index 45688addc..000000000 --- a/plugins/zynaddsubfx/src/Misc/Config.h +++ /dev/null @@ -1,73 +0,0 @@ -/* - ZynAddSubFX - a software synthesizer - - Config.h - Configuration file functions - Copyright (C) 2003-2005 Nasca Octavian Paul - Author: Nasca Octavian Paul - - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License - as published by the Free Software Foundation. - - 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 (version 2 or later) for more details. - - You should have received a copy of the GNU General Public License (version 2) - along with this program; if not, write to the Free Software Foundation, - Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -*/ - -#ifndef CONFIG_H -#define CONFIG_H -#include "../globals.h" -#define MAX_STRING_SIZE 4000 -#define MAX_BANK_ROOT_DIRS 100 - -/**Configuration file functions*/ -class Config -{ - public: - /** Constructor*/ - Config(); - /** Destructor*/ - ~Config(); - struct { - char *LinuxOSSWaveOutDev, *LinuxOSSSeqInDev; - int SampleRate, SoundBufferSize, OscilSize, SwapStereo; - int WindowsWaveOutId, WindowsMidiInId; - int BankUIAutoClose; - int DumpNotesToFile, DumpAppend; - int GzipCompression; - int Interpolation; - char *DumpFile; - char *bankRootDirList[MAX_BANK_ROOT_DIRS], *currentBankDir; - char *presetsDirList[MAX_BANK_ROOT_DIRS]; - int CheckPADsynth; - int UserInterfaceMode; - int VirKeybLayout; - } cfg; - int winwavemax, winmidimax; //number of wave/midi devices on Windows - int maxstringsize; - - char * workingDir; - - struct winmidionedevice { - char *name; - }; - winmidionedevice *winmididevices; - - void clearbankrootdirlist(); - void clearpresetsdirlist(); - void init(); - void save(); - - private: - void readConfig(const char *filename); - void saveConfig(const char *filename); - void getConfigFileName(char *name, int namesize); -}; -#endif - diff --git a/plugins/zynaddsubfx/src/Misc/Control.h b/plugins/zynaddsubfx/src/Misc/Control.h deleted file mode 100644 index 297e6f0da..000000000 --- a/plugins/zynaddsubfx/src/Misc/Control.h +++ /dev/null @@ -1,100 +0,0 @@ -/* - ZynAddSubFX - a software synthesizer - - Control.h - Defines a variable that can be controled from a frontend - - Copyright (C) 2009 Harald Hvaal - Author: Harald Hvaal - - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License - as published by the Free Software Foundation. - - 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 (version 2 or later) for more details. - - You should have received a copy of the GNU General Public License (version 2) - along with this program; if not, write to the Free Software Foundation, - Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#ifndef _CONTROL_H_ -#define _CONTROL_H_ - -#include - -class Control -{ - public: - /** - * The parent is the logical owner of this control. Parent should only - * be null for the root node. - * The id is a string uniquely identifying this control within the - * context of the parent control. No spaces or dots are allowed in this - * id. - * Children id's are denoted by ., so that one - * can refer to any control in the hierarchy by separating them with - * dots. Example: Main.AddSynth.FrequencyLFO.Amplitude - */ - Control(Control *parent, string id); - - /** - * Will recursively get the XML representation for all the subcontrols. - * Used for saving to file and copy-pasting settings - */ - string getXMLRepresentation(); - - /** - * Set the value of this (and possibly subcomponents as well) based on - * a xml description. - */ - void restoreFromXML(string xml); - - /** - * Register a controluser. This will cause this user to be notified - * whenever the contents of the control changes. - */ - void registerControlUser(ControlUser *user); - - /** - * This should return a string representation of the controls internal - * value - */ - virtual string getStringRepresentation() = 0; -}; - -class FloatControl:public Control -{ - public: - /** - * Set the value of this control. If the ControlUser variable is set, - * then this user will not be updated with the new value. This is to - * avoid setting a value being set back to the source that set it - * (which would be redundant, or possibly causing infinite setValue - * loops). - * NOTE: this function is thread-safe (using a mutex internally) - */ - void setValue(float value, ControlUser *user = NULL); - - /** - * Reimplemented from Control - */ - virtual string getStringRepresentation(); - - float value(); -}; - -class ControlUser -{ - public: - /** - * Pure virtual method, to notify the controluser that the value has - * been changed internally, and needs to be read again. - */ - virtual void controlUpdated(Control *control) = 0; -}; - -#endif /* _CONTROL_H_ */ - diff --git a/plugins/zynaddsubfx/src/Misc/Dump.cpp b/plugins/zynaddsubfx/src/Misc/Dump.cpp deleted file mode 100644 index 492cf57ed..000000000 --- a/plugins/zynaddsubfx/src/Misc/Dump.cpp +++ /dev/null @@ -1,124 +0,0 @@ -/* - ZynAddSubFX - a software synthesizer - - Dump.cpp - It dumps the notes to a text file - - Copyright (C) 2002-2005 Nasca Octavian Paul - Author: Nasca Octavian Paul - - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License - as published by the Free Software Foundation. - - 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 (version 2 or later) for more details. - - You should have received a copy of the GNU General Public License (version 2) - along with this program; if not, write to the Free Software Foundation, - Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ -#include -#include -#include "Util.h" -#include "Dump.h" - -Dump dump; - -Dump::Dump() -{ - file = NULL; - tick = 0; - k = 0; - keyspressed = 0; -} - -Dump::~Dump() -{ - if(file != NULL) { - double duration = (double)tick * (double) SOUND_BUFFER_SIZE - / (double) SAMPLE_RATE; - fprintf( - file, - "\n# statistics: duration = %d seconds; keyspressed = %d\n\n\n\n", - (int) duration, - keyspressed); - fclose(file); - } -} - -void Dump::startnow() -{ - if(file != NULL) - return; //the file is already open - - if(config.cfg.DumpNotesToFile != 0) { - if(config.cfg.DumpAppend != 0) - file = fopen(config.cfg.DumpFile, "a"); - else - file = fopen(config.cfg.DumpFile, "w"); - if(file == NULL) - return; - if(config.cfg.DumpAppend != 0) - fprintf(file, "%s", "#************************************\n"); - - time_t tm = time(NULL); - - fprintf(file, "#date/time = %s\n", ctime(&tm)); - fprintf(file, - "#1 tick = %g milliseconds\n", - SOUND_BUFFER_SIZE * 1000.0 / SAMPLE_RATE); - fprintf(file, "SAMPLERATE = %d\n", SAMPLE_RATE); - fprintf(file, "TICKSIZE = %d #samples\n", SOUND_BUFFER_SIZE); - fprintf(file, "\n\nSTART\n"); - } -} - -void Dump::inctick() -{ - tick++; -} - - -void Dump::dumpnote(char chan, char note, char vel) -{ - if(file == NULL) - return; - if(note == 0) - return; - if(vel == 0) - fprintf(file, "n %d -> %d %d \n", tick, chan, note); //note off - else - fprintf(file, "N %d -> %d %d %d \n", tick, chan, note, vel); //note on - - if(vel != 0) - keyspressed++; -#ifndef JACKAUDIOOUT - if(k++ > 25) { - fflush(file); - k = 0; - } -#endif -} - -void Dump::dumpcontroller(char chan, unsigned int type, int par) -{ - if(file == NULL) - return; - switch(type) { - case C_pitchwheel: - fprintf(file, "P %d -> %d %d\n", tick, chan, par); - break; - default: - fprintf(file, "C %d -> %d %d %d\n", tick, chan, type, par); - break; - } -#ifndef JACKAUDIOOUT - if(k++ > 25) { - fflush(file); - k = 0; - } -#endif -} - diff --git a/plugins/zynaddsubfx/src/Misc/Dump.h b/plugins/zynaddsubfx/src/Misc/Dump.h deleted file mode 100644 index 392fd407b..000000000 --- a/plugins/zynaddsubfx/src/Misc/Dump.h +++ /dev/null @@ -1,64 +0,0 @@ -/* - ZynAddSubFX - a software synthesizer - - Dump.h - It dumps the notes to a text file - - Copyright (C) 2002-2005 Nasca Octavian Paul - Author: Nasca Octavian Paul - - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License - as published by the Free Software Foundation. - - 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 (version 2 or later) for more details. - - You should have received a copy of the GNU General Public License (version 2) - along with this program; if not, write to the Free Software Foundation, - Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ -#ifndef DUMP_H -#define DUMP_H - -#include - -/**Object used to dump the notes into a text file - * \todo see if this object should have knowledge about the file - * that it will write to - * \todo upgrade from stdio to iostream*/ -class Dump -{ - public: - /**Constructor*/ - Dump(); - /**Destructor - * Closes the dumpfile*/ - ~Dump(); - /**Open dumpfile and prepare it for dumps - * \todo see if this fits better in the constructor*/ - void startnow(); - /**Tick the timestamp*/ - void inctick(); - /**Dump Note to dumpfile - * @param chan The channel of the note - * @param note The note - * @param vel The velocity of the note*/ - void dumpnote(char chan, char note, char vel); - /** Dump the Controller - * @param chan The channel of the Controller - * @param type The type - * @param par The value of the controller - * \todo figure out what type is exactly meaning*/ - void dumpcontroller(char chan, unsigned int type, int par); - - private: - FILE *file; - int tick; - int k; //This appears to be a constant used to flush the file - //periodically when JACK is used - int keyspressed; -}; -#endif - diff --git a/plugins/zynaddsubfx/src/Misc/LASHClient.cpp b/plugins/zynaddsubfx/src/Misc/LASHClient.cpp deleted file mode 100644 index 292037791..000000000 --- a/plugins/zynaddsubfx/src/Misc/LASHClient.cpp +++ /dev/null @@ -1,104 +0,0 @@ -/* - ZynAddSubFX - a software synthesizer - - LASHClient.cpp - LASH support - Copyright (C) 2006-2009 Lars Luthman - Author: Lars Luthman - - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License - as published by the Free Software Foundation. - - 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 (version 2 or later) for more details. - - You should have received a copy of the GNU General Public License (version 2) - along with this program; if not, write to the Free Software Foundation, - Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -*/ -#include -#include -#include - -#include "LASHClient.h" - - -LASHClient::LASHClient(int *argc, char ***argv) -{ - client = lash_init(lash_extract_args(argc, argv), "ZynAddSubFX", - LASH_Config_File, LASH_PROTOCOL(2, 0)); -} - - -void LASHClient::setalsaid(int id) -{ - if(lash_enabled(client)) - if(id != -1) - lash_alsa_client_id(client, id); -} - - -void LASHClient::setjackname(const char *name) -{ - if(lash_enabled(client)) - if(name != NULL) { - lash_jack_client_name(client, name); - - lash_event_t *event = lash_event_new_with_type(LASH_Client_Name); - lash_event_set_string(event, name); - lash_send_event(client, event); - } -} - - -LASHClient::Event LASHClient::checkevents(std::string &filename) -{ - if(!lash_enabled(client)) - return NoEvent; - - Event received = NoEvent; - lash_event_t *event; - while(event = lash_get_event(client)) { - // save - if(lash_event_get_type(event) == LASH_Save_File) { - std::cerr << "LASH event: LASH_Save_File" << std::endl; - filename = std::string(lash_event_get_string(event)) - + "/master.xmz"; - received = Save; - break; - } - // restore - else - if(lash_event_get_type(event) == LASH_Restore_File) { - std::cerr << "LASH event: LASH_Restore_File" << std::endl; - filename = std::string(lash_event_get_string(event)) - + "/master.xmz"; - received = Restore; - break; - } - // quit - else - if(lash_event_get_type(event) == LASH_Quit) { - std::cerr << "LASH event: LASH_Quit" << std::endl; - received = Quit; - break; - } - - lash_event_destroy(event); - } - return received; -} - - -void LASHClient::confirmevent(Event event) -{ - if(event == Save) - lash_send_event(client, lash_event_new_with_type(LASH_Save_File)); - else - if(event == Restore) - lash_send_event(client, lash_event_new_with_type(LASH_Restore_File)); -} - diff --git a/plugins/zynaddsubfx/src/Misc/LASHClient.h b/plugins/zynaddsubfx/src/Misc/LASHClient.h deleted file mode 100644 index cf50295da..000000000 --- a/plugins/zynaddsubfx/src/Misc/LASHClient.h +++ /dev/null @@ -1,66 +0,0 @@ -/* - ZynAddSubFX - a software synthesizer - - LASHClient.h - LASH support - Copyright (C) 2006-2009 Lars Luthman - Author: Lars Luthman - - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License - as published by the Free Software Foundation. - - 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 (version 2 or later) for more details. - - You should have received a copy of the GNU General Public License (version 2) - along with this program; if not, write to the Free Software Foundation, - Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -*/ -#ifndef LASHClient_h -#define LASHClient_h - -#include -#include -#include - - -/** This class wraps up some functions for initialising and polling - * the LASH daemon. - * \todo fix indentation nonconformism - * \todo see why there is no destructor*/ -class LASHClient -{ - public: - /**Enum to represent the LASH events that are currently handled*/ - enum Event { - Save, - Restore, - Quit, - NoEvent - }; - - /** Constructor - * @param argc number of arguments - * @param argv the text arguments*/ - LASHClient(int *argc, char ***argv); - - /**set the ALSA id - * @param id new ALSA id*/ - void setalsaid(int id); - /**Set the JACK name - * @param name the new name*/ - void setjackname(const char *name); - Event checkevents(std::string &filename); - void confirmevent(Event event); - - private: - - lash_client_t *client; -}; - - -#endif - diff --git a/plugins/zynaddsubfx/src/Misc/Master.cpp b/plugins/zynaddsubfx/src/Misc/Master.cpp deleted file mode 100644 index fa5e1b003..000000000 --- a/plugins/zynaddsubfx/src/Misc/Master.cpp +++ /dev/null @@ -1,828 +0,0 @@ -/* - ZynAddSubFX - a software synthesizer - - Master.cpp - It sends Midi Messages to Parts, receives samples from parts, - process them with system/insertion effects and mix them - Copyright (C) 2002-2005 Nasca Octavian Paul - Author: Nasca Octavian Paul - - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License - as published by the Free Software Foundation. - - 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 (version 2 or later) for more details. - - You should have received a copy of the GNU General Public License (version 2) - along with this program; if not, write to the Free Software Foundation, - Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -*/ - -#include "Master.h" - -#include -#include -#include - -#include - -Master::Master() -{ - swaplr = 0; - - pthread_mutex_init(&mutex, NULL); - fft = new FFTwrapper(OSCIL_SIZE); - - tmpmixl = new REALTYPE[SOUND_BUFFER_SIZE]; - tmpmixr = new REALTYPE[SOUND_BUFFER_SIZE]; - audiooutl = new REALTYPE[SOUND_BUFFER_SIZE]; - audiooutr = new REALTYPE[SOUND_BUFFER_SIZE]; - - ksoundbuffersample = -1; //this is only time when this is -1; this means that the GetAudioOutSamples was never called - ksoundbuffersamplelow = 0.0; - oldsamplel = 0.0; - oldsampler = 0.0; - shutup = 0; - for(int npart = 0; npart < NUM_MIDI_PARTS; npart++) { - vuoutpeakpart[npart] = 1e-9; - fakepeakpart[npart] = 0; - } - - for(int i = 0; i < SOUND_BUFFER_SIZE; i++) { - audiooutl[i] = 0.0; - audiooutr[i] = 0.0; - } - - for(int npart = 0; npart < NUM_MIDI_PARTS; npart++) - part[npart] = new Part(µtonal, fft, &mutex); - - - - //Insertion Effects init - for(int nefx = 0; nefx < NUM_INS_EFX; nefx++) - insefx[nefx] = new EffectMgr(1, &mutex); - - //System Effects init - for(int nefx = 0; nefx < NUM_SYS_EFX; nefx++) - sysefx[nefx] = new EffectMgr(0, &mutex); - ; - - - defaults(); -} - -void Master::defaults() -{ - volume = 1.0; - setPvolume(80); - setPkeyshift(64); - - for(int npart = 0; npart < NUM_MIDI_PARTS; npart++) { - part[npart]->defaults(); - part[npart]->Prcvchn = npart % NUM_MIDI_CHANNELS; - } - - partonoff(0, 1); //enable the first part - - for(int nefx = 0; nefx < NUM_INS_EFX; nefx++) { - insefx[nefx]->defaults(); - Pinsparts[nefx] = -1; - } - - //System Effects init - for(int nefx = 0; nefx < NUM_SYS_EFX; nefx++) { - sysefx[nefx]->defaults(); - for(int npart = 0; npart < NUM_MIDI_PARTS; npart++) - //if (nefx==0) setPsysefxvol(npart,nefx,64); - //else - setPsysefxvol(npart, nefx, 0); - ; - for(int nefxto = 0; nefxto < NUM_SYS_EFX; nefxto++) - setPsysefxsend(nefx, nefxto, 0); - } - -// sysefx[0]->changeeffect(1); - microtonal.defaults(); - ShutUp(); -} - -/* - * Note On Messages (velocity=0 for NoteOff) - */ -void Master::NoteOn(unsigned char chan, - unsigned char note, - unsigned char velocity) -{ - dump.dumpnote(chan, note, velocity); - - noteon(chan, note, velocity); -} - -/* - * Internal Note On (velocity=0 for NoteOff) - */ -void Master::noteon(unsigned char chan, - unsigned char note, - unsigned char velocity) -{ - int npart; - if(velocity != 0) { - for(npart = 0; npart < NUM_MIDI_PARTS; npart++) { - if(chan == part[npart]->Prcvchn) { - fakepeakpart[npart] = velocity * 2; - if(part[npart]->Penabled != 0) - part[npart]->NoteOn(note, velocity, keyshift); - } - } - } - else - this->NoteOff(chan, note); - ; - HDDRecorder.triggernow(); -} - -/* - * Note Off Messages - */ -void Master::NoteOff(unsigned char chan, unsigned char note) -{ - dump.dumpnote(chan, note, 0); - - noteoff(chan, note); -} - -/* - * Internal Note Off - */ -void Master::noteoff(unsigned char chan, unsigned char note) -{ - int npart; - for(npart = 0; npart < NUM_MIDI_PARTS; npart++) - if((chan == part[npart]->Prcvchn) && (part[npart]->Penabled != 0)) - part[npart]->NoteOff(note); - ; -} - -/* - * Controllers - */ -void Master::SetController(unsigned char chan, unsigned int type, int par) -{ - dump.dumpcontroller(chan, type, par); - - setcontroller(chan, type, par); -} - -/* - * Internal Controllers - */ -void Master::setcontroller(unsigned char chan, unsigned int type, int par) -{ - if((type == C_dataentryhi) || (type == C_dataentrylo) - || (type == C_nrpnhi) || (type == C_nrpnlo)) { //Process RPN and NRPN by the Master (ignore the chan) - ctl.setparameternumber(type, par); - - int parhi = -1, parlo = -1, valhi = -1, vallo = -1; - if(ctl.getnrpn(&parhi, &parlo, &valhi, &vallo) == 0) //this is NRPN - //fprintf(stderr,"rcv. NRPN: %d %d %d %d\n",parhi,parlo,valhi,vallo); - switch(parhi) { - case 0x04: //System Effects - if(parlo < NUM_SYS_EFX) - sysefx[parlo]->seteffectpar_nolock(valhi, vallo); - ; - break; - case 0x08: //Insertion Effects - if(parlo < NUM_INS_EFX) - insefx[parlo]->seteffectpar_nolock(valhi, vallo); - ; - break; - } - ; - } - else { //other controllers - for(int npart = 0; npart < NUM_MIDI_PARTS; npart++) //Send the controller to all part assigned to the channel - if((chan == part[npart]->Prcvchn) && (part[npart]->Penabled != 0)) - part[npart]->SetController(type, par); - ; - - if(type == C_allsoundsoff) { //cleanup insertion/system FX - for(int nefx = 0; nefx < NUM_SYS_EFX; ++nefx) - sysefx[nefx]->cleanup(); - for(int nefx = 0; nefx < NUM_INS_EFX; ++nefx) - insefx[nefx]->cleanup(); - } - } -} - - -/* - * Enable/Disable a part - */ -void Master::partonoff(int npart, int what) -{ - if(npart >= NUM_MIDI_PARTS) - return; - if(what == 0) { //disable part - fakepeakpart[npart] = 0; - part[npart]->Penabled = 0; - part[npart]->cleanup(); - for(int nefx = 0; nefx < NUM_INS_EFX; nefx++) { - if(Pinsparts[nefx] == npart) - insefx[nefx]->cleanup(); - ; - } - } - else { //enabled - part[npart]->Penabled = 1; - fakepeakpart[npart] = 0; - } -} - -/* - * Master audio out (the final sound) - */ -void Master::AudioOut(REALTYPE *outl, REALTYPE *outr) -{ - int i, npart, nefx; - - /* //test!!!!!!!!!!!!! se poate bloca aici (mutex) - if (seq.play){ - int type,par1,par2,again,midichan; - int ntrack=1; - // do{ - again=seq.getevent(ntrack,&midichan,&type,&par1,&par2); - if (type>0) { - // printf("aaa\n"); - - if (type==1){//note_on or note_off - if (par2!=0) NoteOn(midichan,par1,par2); - else NoteOff(midichan,par1); - }; - }; - // } while (again); - }; - */ - - -// printf("zzzz\n"); - - - //Swaps the Left channel with Right Channel (if it is asked for) - if(swaplr != 0) { - REALTYPE *tmp = outl; - outl = outr; - outr = tmp; - } - - //clean up the output samples - for(i = 0; i < SOUND_BUFFER_SIZE; i++) { - outl[i] = 0.0; - outr[i] = 0.0; - } - - //Compute part samples and store them part[npart]->partoutl,partoutr - for(npart = 0; npart < NUM_MIDI_PARTS; npart++) - if(part[npart]->Penabled != 0) - part[npart]->ComputePartSmps(); - - //Insertion effects - for(nefx = 0; nefx < NUM_INS_EFX; nefx++) { - if(Pinsparts[nefx] >= 0) { - int efxpart = Pinsparts[nefx]; - if(part[efxpart]->Penabled != 0) - insefx[nefx]->out(part[efxpart]->partoutl, - part[efxpart]->partoutr); - } - } - - - //Apply the part volumes and pannings (after insertion effects) - for(npart = 0; npart < NUM_MIDI_PARTS; npart++) { - if(part[npart]->Penabled == 0) - continue; - - REALTYPE newvol_l = part[npart]->volume; - REALTYPE newvol_r = part[npart]->volume; - REALTYPE oldvol_l = part[npart]->oldvolumel; - REALTYPE oldvol_r = part[npart]->oldvolumer; - REALTYPE pan = part[npart]->panning; - if(pan < 0.5) - newvol_l *= pan * 2.0; - else - newvol_r *= (1.0 - pan) * 2.0; - - if(ABOVE_AMPLITUDE_THRESHOLD(oldvol_l, newvol_l) - || ABOVE_AMPLITUDE_THRESHOLD(oldvol_r, newvol_r)) { //the volume or the panning has changed and needs interpolation - for(i = 0; i < SOUND_BUFFER_SIZE; i++) { - REALTYPE vol_l = INTERPOLATE_AMPLITUDE(oldvol_l, - newvol_l, - i, - SOUND_BUFFER_SIZE); - REALTYPE vol_r = INTERPOLATE_AMPLITUDE(oldvol_r, - newvol_r, - i, - SOUND_BUFFER_SIZE); - part[npart]->partoutl[i] *= vol_l; - part[npart]->partoutr[i] *= vol_r; - } - part[npart]->oldvolumel = newvol_l; - part[npart]->oldvolumer = newvol_r; - } - else { - for(i = 0; i < SOUND_BUFFER_SIZE; i++) { //the volume did not changed - part[npart]->partoutl[i] *= newvol_l; - part[npart]->partoutr[i] *= newvol_r; - } - } - } - - - //System effects - for(nefx = 0; nefx < NUM_SYS_EFX; nefx++) { - if(sysefx[nefx]->geteffect() == 0) - continue; //the effect is disabled - - //Clean up the samples used by the system effects - for(i = 0; i < SOUND_BUFFER_SIZE; i++) { - tmpmixl[i] = 0.0; - tmpmixr[i] = 0.0; - } - - //Mix the channels according to the part settings about System Effect - for(npart = 0; npart < NUM_MIDI_PARTS; npart++) { - //skip if the part has no output to effect - if(Psysefxvol[nefx][npart] == 0) - continue; - - //skip if the part is disabled - if(part[npart]->Penabled == 0) - continue; - - //the output volume of each part to system effect - REALTYPE vol = sysefxvol[nefx][npart]; - for(i = 0; i < SOUND_BUFFER_SIZE; i++) { - tmpmixl[i] += part[npart]->partoutl[i] * vol; - tmpmixr[i] += part[npart]->partoutr[i] * vol; - } - } - - // system effect send to next ones - for(int nefxfrom = 0; nefxfrom < nefx; nefxfrom++) { - if(Psysefxsend[nefxfrom][nefx] != 0) { - REALTYPE v = sysefxsend[nefxfrom][nefx]; - for(i = 0; i < SOUND_BUFFER_SIZE; i++) { - tmpmixl[i] += sysefx[nefxfrom]->efxoutl[i] * v; - tmpmixr[i] += sysefx[nefxfrom]->efxoutr[i] * v; - } - } - } - - sysefx[nefx]->out(tmpmixl, tmpmixr); - - //Add the System Effect to sound output - REALTYPE outvol = sysefx[nefx]->sysefxgetvolume(); - for(i = 0; i < SOUND_BUFFER_SIZE; i++) { - outl[i] += tmpmixl[i] * outvol; - outr[i] += tmpmixr[i] * outvol; - } - } - - //Mix all parts - for(npart = 0; npart < NUM_MIDI_PARTS; npart++) { - for(i = 0; i < SOUND_BUFFER_SIZE; i++) { //the volume did not changed - outl[i] += part[npart]->partoutl[i]; - outr[i] += part[npart]->partoutr[i]; - } - } - - //Insertion effects for Master Out - for(nefx = 0; nefx < NUM_INS_EFX; nefx++) - if(Pinsparts[nefx] == -2) - insefx[nefx]->out(outl, outr); - ; - - //Master Volume - for(i = 0; i < SOUND_BUFFER_SIZE; i++) { - outl[i] *= volume; - outr[i] *= volume; - } - - //Peak computation (for vumeters) - vuoutpeakl = 1e-12; - vuoutpeakr = 1e-12; - for(i = 0; i < SOUND_BUFFER_SIZE; i++) { - if(fabs(outl[i]) > vuoutpeakl) - vuoutpeakl = fabs(outl[i]); - if(fabs(outr[i]) > vuoutpeakr) - vuoutpeakr = fabs(outr[i]); - } - if((vuoutpeakl > 1.0) || (vuoutpeakr > 1.0)) - vuclipped = 1; - if(vumaxoutpeakl < vuoutpeakl) - vumaxoutpeakl = vuoutpeakl; - if(vumaxoutpeakr < vuoutpeakr) - vumaxoutpeakr = vuoutpeakr; - - //RMS Peak computation (for vumeters) - vurmspeakl = 1e-12; - vurmspeakr = 1e-12; - for(i = 0; i < SOUND_BUFFER_SIZE; i++) { - vurmspeakl += outl[i] * outl[i]; - vurmspeakr += outr[i] * outr[i]; - } - vurmspeakl = sqrt(vurmspeakl / SOUND_BUFFER_SIZE); - vurmspeakr = sqrt(vurmspeakr / SOUND_BUFFER_SIZE); - - //Part Peak computation (for Part vumeters or fake part vumeters) - for(npart = 0; npart < NUM_MIDI_PARTS; npart++) { - vuoutpeakpart[npart] = 1.0e-12; - if(part[npart]->Penabled != 0) { - REALTYPE *outl = part[npart]->partoutl, - *outr = part[npart]->partoutr; - for(i = 0; i < SOUND_BUFFER_SIZE; i++) { - REALTYPE tmp = fabs(outl[i] + outr[i]); - if(tmp > vuoutpeakpart[npart]) - vuoutpeakpart[npart] = tmp; - } - vuoutpeakpart[npart] *= volume; - } - else - if(fakepeakpart[npart] > 1) - fakepeakpart[npart]--; - ; - } - - - //Shutup if it is asked (with fade-out) - if(shutup != 0) { - for(i = 0; i < SOUND_BUFFER_SIZE; i++) { - REALTYPE tmp = - (SOUND_BUFFER_SIZE - i) / (REALTYPE) SOUND_BUFFER_SIZE; - outl[i] *= tmp; - outr[i] *= tmp; - } - ShutUp(); - } - - //update the LFO's time - LFOParams::time++; - - if(HDDRecorder.recording()) - HDDRecorder.recordbuffer(outl, outr); - dump.inctick(); -} - -void Master::GetAudioOutSamples(int nsamples, - int samplerate, - REALTYPE *outl, - REALTYPE *outr) -{ - if(ksoundbuffersample == -1) { //first time - AudioOut(&audiooutl[0], &audiooutr[0]); - ksoundbuffersample = 0; - } - - - if(samplerate == SAMPLE_RATE) { //no resample - int ksample = 0; - while(ksample < nsamples) { - outl[ksample] = audiooutl[ksoundbuffersample]; - outr[ksample] = audiooutr[ksoundbuffersample]; - - ksample++; - ksoundbuffersample++; - if(ksoundbuffersample >= SOUND_BUFFER_SIZE) { - AudioOut(&audiooutl[0], &audiooutr[0]); - ksoundbuffersample = 0; - } - } - } - else { //Resample - int ksample = 0; - REALTYPE srinc = SAMPLE_RATE / (REALTYPE)samplerate; - - while(ksample < nsamples) { - if(ksoundbuffersample != 0) { - outl[ksample] = audiooutl[ksoundbuffersample] - * ksoundbuffersamplelow - + audiooutl[ksoundbuffersample - - 1] * (1.0 - ksoundbuffersamplelow); - outr[ksample] = audiooutr[ksoundbuffersample] - * ksoundbuffersamplelow - + audiooutr[ksoundbuffersample - - 1] * (1.0 - ksoundbuffersamplelow); - } - else { - outl[ksample] = audiooutl[ksoundbuffersample] - * ksoundbuffersamplelow - + oldsamplel * (1.0 - ksoundbuffersamplelow); - outr[ksample] = audiooutr[ksoundbuffersample] - * ksoundbuffersamplelow - + oldsampler * (1.0 - ksoundbuffersamplelow); - } - - ksample++; - - ksoundbuffersamplelow += srinc; - if(ksoundbuffersamplelow >= 1.0) { - ksoundbuffersample += (int) floor(ksoundbuffersamplelow); - ksoundbuffersamplelow = ksoundbuffersamplelow - floor( - ksoundbuffersamplelow); - } - - if(ksoundbuffersample >= SOUND_BUFFER_SIZE) { - oldsamplel = audiooutl[SOUND_BUFFER_SIZE - 1]; - oldsampler = audiooutr[SOUND_BUFFER_SIZE - 1]; - AudioOut(&audiooutl[0], &audiooutr[0]); - ksoundbuffersample = 0; - } - } - } -} - - -Master::~Master() -{ - for(int npart = 0; npart < NUM_MIDI_PARTS; npart++) - delete part[npart]; - for(int nefx = 0; nefx < NUM_INS_EFX; nefx++) - delete insefx[nefx]; - for(int nefx = 0; nefx < NUM_SYS_EFX; nefx++) - delete sysefx[nefx]; - - delete [] audiooutl; - delete [] audiooutr; - delete [] tmpmixl; - delete [] tmpmixr; - delete (fft); - - pthread_mutex_destroy(&mutex); -} - - -/* - * Parameter control - */ -void Master::setPvolume(char Pvolume_) -{ - Pvolume = Pvolume_; - volume = dB2rap((Pvolume - 96.0) / 96.0 * 40.0); -} - -void Master::setPkeyshift(char Pkeyshift_) -{ - Pkeyshift = Pkeyshift_; - keyshift = (int)Pkeyshift - 64; -} - - -void Master::setPsysefxvol(int Ppart, int Pefx, char Pvol) -{ - Psysefxvol[Pefx][Ppart] = Pvol; - sysefxvol[Pefx][Ppart] = pow(0.1, (1.0 - Pvol / 96.0) * 2.0); -} - -void Master::setPsysefxsend(int Pefxfrom, int Pefxto, char Pvol) -{ - Psysefxsend[Pefxfrom][Pefxto] = Pvol; - sysefxsend[Pefxfrom][Pefxto] = pow(0.1, (1.0 - Pvol / 96.0) * 2.0); -} - - -/* - * Panic! (Clean up all parts and effects) - */ -void Master::ShutUp() -{ - for(int npart = 0; npart < NUM_MIDI_PARTS; npart++) { - part[npart]->cleanup(); - fakepeakpart[npart] = 0; - } - for(int nefx = 0; nefx < NUM_INS_EFX; nefx++) - insefx[nefx]->cleanup(); - for(int nefx = 0; nefx < NUM_SYS_EFX; nefx++) - sysefx[nefx]->cleanup(); - vuresetpeaks(); - shutup = 0; -} - - -/* - * Reset peaks and clear the "cliped" flag (for VU-meter) - */ -void Master::vuresetpeaks() -{ - vuoutpeakl = 1e-9; - vuoutpeakr = 1e-9; - vumaxoutpeakl = 1e-9; - vumaxoutpeakr = 1e-9; - vuclipped = 0; -} - - - -void Master::applyparameters() -{ - for(int npart = 0; npart < NUM_MIDI_PARTS; npart++) - part[npart]->applyparameters(); - ; -} - -void Master::add2XML(XMLwrapper *xml) -{ - xml->addpar("volume", Pvolume); - xml->addpar("key_shift", Pkeyshift); - xml->addparbool("nrpn_receive", ctl.NRPN.receive); - - xml->beginbranch("MICROTONAL"); - microtonal.add2XML(xml); - xml->endbranch(); - - for(int npart = 0; npart < NUM_MIDI_PARTS; npart++) { - xml->beginbranch("PART", npart); - part[npart]->add2XML(xml); - xml->endbranch(); - } - - xml->beginbranch("SYSTEM_EFFECTS"); - for(int nefx = 0; nefx < NUM_SYS_EFX; nefx++) { - xml->beginbranch("SYSTEM_EFFECT", nefx); - xml->beginbranch("EFFECT"); - sysefx[nefx]->add2XML(xml); - xml->endbranch(); - - for(int pefx = 0; pefx < NUM_MIDI_PARTS; pefx++) { - xml->beginbranch("VOLUME", pefx); - xml->addpar("vol", Psysefxvol[nefx][pefx]); - xml->endbranch(); - } - - for(int tonefx = nefx + 1; tonefx < NUM_SYS_EFX; tonefx++) { - xml->beginbranch("SENDTO", tonefx); - xml->addpar("send_vol", Psysefxsend[nefx][tonefx]); - xml->endbranch(); - } - - - xml->endbranch(); - } - xml->endbranch(); - - xml->beginbranch("INSERTION_EFFECTS"); - for(int nefx = 0; nefx < NUM_INS_EFX; nefx++) { - xml->beginbranch("INSERTION_EFFECT", nefx); - xml->addpar("part", Pinsparts[nefx]); - - xml->beginbranch("EFFECT"); - insefx[nefx]->add2XML(xml); - xml->endbranch(); - xml->endbranch(); - } - - xml->endbranch(); -} - - -int Master::getalldata(char **data) -{ - XMLwrapper *xml = new XMLwrapper(); - - xml->beginbranch("MASTER"); - - pthread_mutex_lock(&mutex); - add2XML(xml); - pthread_mutex_unlock(&mutex); - - xml->endbranch(); - - *data = xml->getXMLdata(); - delete (xml); - return strlen(*data) + 1; -} - -void Master::putalldata(char *data, int size) -{ - XMLwrapper *xml = new XMLwrapper(); - if(!xml->putXMLdata(data)) { - delete (xml); - return; - } - - if(xml->enterbranch("MASTER") == 0) - return; - - pthread_mutex_lock(&mutex); - getfromXML(xml); - pthread_mutex_unlock(&mutex); - - xml->exitbranch(); - - delete (xml); -} - -int Master::saveXML(const char *filename) -{ - XMLwrapper *xml = new XMLwrapper(); - - xml->beginbranch("MASTER"); - add2XML(xml); - xml->endbranch(); - - int result = xml->saveXMLfile(filename); - delete (xml); - return result; -} - - - -int Master::loadXML(const char *filename) -{ - XMLwrapper *xml = new XMLwrapper(); - if(xml->loadXMLfile(filename) < 0) { - delete (xml); - return -1; - } - - if(xml->enterbranch("MASTER") == 0) - return -10; - getfromXML(xml); - xml->exitbranch(); - - delete (xml); - return 0; -} - -void Master::getfromXML(XMLwrapper *xml) -{ - setPvolume(xml->getpar127("volume", Pvolume)); - setPkeyshift(xml->getpar127("key_shift", Pkeyshift)); - ctl.NRPN.receive = xml->getparbool("nrpn_receive", ctl.NRPN.receive); - - - part[0]->Penabled = 0; - for(int npart = 0; npart < NUM_MIDI_PARTS; npart++) { - if(xml->enterbranch("PART", npart) == 0) - continue; - part[npart]->getfromXML(xml); - xml->exitbranch(); - } - - if(xml->enterbranch("MICROTONAL")) { - microtonal.getfromXML(xml); - xml->exitbranch(); - } - - sysefx[0]->changeeffect(0); - if(xml->enterbranch("SYSTEM_EFFECTS")) { - for(int nefx = 0; nefx < NUM_SYS_EFX; nefx++) { - if(xml->enterbranch("SYSTEM_EFFECT", nefx) == 0) - continue; - if(xml->enterbranch("EFFECT")) { - sysefx[nefx]->getfromXML(xml); - xml->exitbranch(); - } - - for(int partefx = 0; partefx < NUM_MIDI_PARTS; partefx++) { - if(xml->enterbranch("VOLUME", partefx) == 0) - continue; - setPsysefxvol(partefx, nefx, - xml->getpar127("vol", Psysefxvol[partefx][nefx])); - xml->exitbranch(); - } - - for(int tonefx = nefx + 1; tonefx < NUM_SYS_EFX; tonefx++) { - if(xml->enterbranch("SENDTO", tonefx) == 0) - continue; - setPsysefxsend(nefx, tonefx, - xml->getpar127("send_vol", - Psysefxsend[nefx][tonefx])); - xml->exitbranch(); - } - xml->exitbranch(); - } - xml->exitbranch(); - } - - - if(xml->enterbranch("INSERTION_EFFECTS")) { - for(int nefx = 0; nefx < NUM_INS_EFX; nefx++) { - if(xml->enterbranch("INSERTION_EFFECT", nefx) == 0) - continue; - Pinsparts[nefx] = xml->getpar("part", - Pinsparts[nefx], - -2, - NUM_MIDI_PARTS); - if(xml->enterbranch("EFFECT")) { - insefx[nefx]->getfromXML(xml); - xml->exitbranch(); - } - xml->exitbranch(); - } - - xml->exitbranch(); - } -} - diff --git a/plugins/zynaddsubfx/src/Misc/Master.h b/plugins/zynaddsubfx/src/Misc/Master.h deleted file mode 100644 index eb4752245..000000000 --- a/plugins/zynaddsubfx/src/Misc/Master.h +++ /dev/null @@ -1,177 +0,0 @@ -/* - ZynAddSubFX - a software synthesizer - - Master.h - It sends Midi Messages to Parts, receives samples from parts, - process them with system/insertion effects and mix them - Copyright (C) 2002-2005 Nasca Octavian Paul - Author: Nasca Octavian Paul - - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License - as published by the Free Software Foundation. - - 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 (version 2 or later) for more details. - - You should have received a copy of the GNU General Public License (version 2) - along with this program; if not, write to the Free Software Foundation, - Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -*/ - -#ifndef MASTER_H -#define MASTER_H - -#include "../globals.h" -#include "../Effects/EffectMgr.h" -#include "Part.h" -#include "../Output/Recorder.h" -#include "Microtonal.h" - -#include "Bank.h" -#include "Dump.h" -#include "../Seq/Sequencer.h" -#include "XMLwrapper.h" - -extern Dump dump; -/** It sends Midi Messages to Parts, receives samples from parts, - * process them with system/insertion effects and mix them */ -class Master -{ - public: - /** Constructor*/ - Master(); - /** Destructor*/ - ~Master(); - - /**Saves all settings to a XML file - * @return 0 for ok or <0 if there is an error*/ - int saveXML(const char *filename); - - /**This adds the parameters to the XML data*/ - void add2XML(XMLwrapper *xml); - - void defaults(); - - - /**loads all settings from a XML file - * @return 0 for ok or -1 if there is an error*/ - int loadXML(const char *filename); - void applyparameters(); - - void getfromXML(XMLwrapper *xml); - - /**get all data to a newly allocated array (used for VST) - * @return the datasize*/ - int getalldata(char **data); - /**put all data from the *data array to zynaddsubfx parameters (used for VST)*/ - void putalldata(char *data, int size); - - - - //Midi IN - void NoteOn(unsigned char chan, - unsigned char note, - unsigned char velocity); - void NoteOff(unsigned char chan, unsigned char note); - void SetController(unsigned char chan, unsigned int type, int par); - //void NRPN... - - - void ShutUp(); - int shutup; - - /**Audio Output*/ - void AudioOut(REALTYPE *outl, REALTYPE *outr); - /**Audio Output (for callback mode). This allows the program to be controled by an external program*/ - void GetAudioOutSamples(int nsamples, - int samplerate, - REALTYPE *outl, - REALTYPE *outr); - - - void partonoff(int npart, int what); - - /**parts \todo see if this can be made to be dynamic*/ - Part *part[NUM_MIDI_PARTS]; - - //parameters - unsigned char Pvolume; - unsigned char Pkeyshift; - unsigned char Psysefxvol[NUM_SYS_EFX][NUM_MIDI_PARTS]; - unsigned char Psysefxsend[NUM_SYS_EFX][NUM_SYS_EFX]; - - //parameters control - void setPvolume(char Pvolume_); - void setPkeyshift(char Pkeyshift_); - void setPsysefxvol(int Ppart, int Pefx, char Pvol); - void setPsysefxsend(int Pefxfrom, int Pefxto, char Pvol); - - //effects - EffectMgr *sysefx[NUM_SYS_EFX]; //system - EffectMgr *insefx[NUM_INS_EFX]; //insertion -// void swapcopyeffects(int what,int type,int neff1,int neff2); - - //HDD recorder - Recorder HDDRecorder; - - //part that's apply the insertion effect; -1 to disable - short int Pinsparts[NUM_INS_EFX]; - - //peaks for VU-meter - void vuresetpeaks(); - REALTYPE vuoutpeakl, vuoutpeakr, vumaxoutpeakl, vumaxoutpeakr, - vurmspeakl, vurmspeakr; - int vuclipped; - - //peaks for part VU-meters - REALTYPE vuoutpeakpart[NUM_MIDI_PARTS]; - unsigned char fakepeakpart[NUM_MIDI_PARTS]; //this is used to compute the "peak" when the part is disabled - - Controller ctl; - int swaplr; //1 if L and R are swapped - - //Sequencer - Sequencer seq; - - //other objects - Microtonal microtonal; - Bank bank; - - FFTwrapper *fft; - pthread_mutex_t mutex; - - private: - REALTYPE volume; - REALTYPE sysefxvol[NUM_SYS_EFX][NUM_MIDI_PARTS]; - REALTYPE sysefxsend[NUM_SYS_EFX][NUM_SYS_EFX]; - - //Temporary mixing samples for part samples which is sent to system effect - REALTYPE *tmpmixl; - REALTYPE *tmpmixr; - - - int keyshift; - - //Audio Output samples (if it used GetAudioOutSamples - eg. for Jack output; elsewhere is unused) - REALTYPE *audiooutl; - REALTYPE *audiooutr; - - int ksoundbuffersample; //this is used to know if there is need to call AudioOut by GetAudioOutSamples method - REALTYPE ksoundbuffersamplelow; //this is used for resampling (eg. if Jack samplerate!= SAMPLE_RATE) - REALTYPE oldsamplel, oldsampler; //this is used for resampling - - //These are called by the NoteOn, NoteOff,SetController (which are from external sources like MIDI, Virtual Keyboard) - //and are called by internal parts of the program (like sequencer) - void noteon(unsigned char chan, - unsigned char note, - unsigned char velocity); - void noteoff(unsigned char chan, unsigned char note); - void setcontroller(unsigned char chan, unsigned int type, int par); -}; - - -#endif - diff --git a/plugins/zynaddsubfx/src/Misc/Microtonal.cpp b/plugins/zynaddsubfx/src/Misc/Microtonal.cpp deleted file mode 100644 index cae9aa9d9..000000000 --- a/plugins/zynaddsubfx/src/Misc/Microtonal.cpp +++ /dev/null @@ -1,687 +0,0 @@ -/* - ZynAddSubFX - a software synthesizer - - Microtonal.cpp - Tuning settings and microtonal capabilities - Copyright (C) 2002-2005 Nasca Octavian Paul - Author: Nasca Octavian Paul - - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License - as published by the Free Software Foundation. - - 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 (version 2 or later) for more details. - - You should have received a copy of the GNU General Public License (version 2) - along with this program; if not, write to the Free Software Foundation, - Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -*/ - -#include -#include -#include "Microtonal.h" - -#define MAX_LINE_SIZE 80 - -Microtonal::Microtonal() -{ - Pname = new unsigned char[MICROTONAL_MAX_NAME_LEN]; - Pcomment = new unsigned char[MICROTONAL_MAX_NAME_LEN]; - defaults(); -} - -void Microtonal::defaults() -{ - Pinvertupdown = 0; - Pinvertupdowncenter = 60; - octavesize = 12; - Penabled = 0; - PAnote = 69; - PAfreq = 440.0; - Pscaleshift = 64; - - Pfirstkey = 0; - Plastkey = 127; - Pmiddlenote = 60; - Pmapsize = 12; - Pmappingenabled = 0; - - for(int i = 0; i < 128; i++) - Pmapping[i] = i; - - for(int i = 0; i < MAX_OCTAVE_SIZE; i++) { - octave[i].tuning = tmpoctave[i].tuning = pow( - 2, - (i % octavesize - + 1) / 12.0); - octave[i].type = tmpoctave[i].type = 1; - octave[i].x1 = tmpoctave[i].x1 = (i % octavesize + 1) * 100; - octave[i].x2 = tmpoctave[i].x2 = 0; - } - octave[11].type = 2; - octave[11].x1 = 2; - octave[11].x2 = 1; - for(int i = 0; i < MICROTONAL_MAX_NAME_LEN; i++) { - Pname[i] = '\0'; - Pcomment[i] = '\0'; - } - snprintf((char *) Pname, MICROTONAL_MAX_NAME_LEN, "12tET"); - snprintf((char *) Pcomment, - MICROTONAL_MAX_NAME_LEN, - "Equal Temperament 12 notes per octave"); - Pglobalfinedetune = 64; -} - -Microtonal::~Microtonal() -{ - delete [] Pname; - delete [] Pcomment; -} - -/* - * Get the size of the octave - */ -unsigned char Microtonal::getoctavesize() const -{ - if(Penabled != 0) - return octavesize; - else - return 12; -} - -/* - * Get the frequency according the note number - */ -REALTYPE Microtonal::getnotefreq(int note, int keyshift) const -{ - // in this function will appears many times things like this: - // var=(a+b*100)%b - // I had written this way because if I use var=a%b gives unwanted results when a<0 - // This is the same with divisions. - - if((Pinvertupdown != 0) && ((Pmappingenabled == 0) || (Penabled == 0))) - note = (int) Pinvertupdowncenter * 2 - note; - - //compute global fine detune - REALTYPE globalfinedetunerap = pow(2.0, (Pglobalfinedetune - 64.0) / 1200.0); //-64.0 .. 63.0 cents - - if(Penabled == 0) - return pow(2.0, - (note - PAnote - + keyshift) / 12.0) * PAfreq * globalfinedetunerap; //12tET - - int scaleshift = - ((int)Pscaleshift - 64 + (int) octavesize * 100) % octavesize; - - //compute the keyshift - REALTYPE rap_keyshift = 1.0; - if(keyshift != 0) { - int kskey = (keyshift + (int)octavesize * 100) % octavesize; - int ksoct = (keyshift + (int)octavesize * 100) / octavesize - 100; - rap_keyshift = (kskey == 0) ? (1.0) : (octave[kskey - 1].tuning); - rap_keyshift *= pow(octave[octavesize - 1].tuning, ksoct); - } - - //if the mapping is enabled - if(Pmappingenabled != 0) { - if((note < Pfirstkey) || (note > Plastkey)) - return -1.0; - //Compute how many mapped keys are from middle note to reference note - //and find out the proportion between the freq. of middle note and "A" note - int tmp = PAnote - Pmiddlenote, minus = 0; - if(tmp < 0) { - tmp = -tmp; - minus = 1; - } - int deltanote = 0; - for(int i = 0; i < tmp; i++) - if(Pmapping[i % Pmapsize] >= 0) - deltanote++; - REALTYPE rap_anote_middlenote = - (deltanote == - 0) ? (1.0) : (octave[(deltanote - 1) % octavesize].tuning); - if(deltanote != 0) - rap_anote_middlenote *= - pow(octave[octavesize - 1].tuning, (deltanote - 1) / octavesize); - if(minus != 0) - rap_anote_middlenote = 1.0 / rap_anote_middlenote; - - //Convert from note (midi) to degree (note from the tunning) - int degoct = - (note - (int)Pmiddlenote + (int) Pmapsize - * 200) / (int)Pmapsize - 200; - int degkey = (note - Pmiddlenote + (int)Pmapsize * 100) % Pmapsize; - degkey = Pmapping[degkey]; - if(degkey < 0) - return -1.0; //this key is not mapped - - //invert the keyboard upside-down if it is asked for - //TODO: do the right way by using Pinvertupdowncenter - if(Pinvertupdown != 0) { - degkey = octavesize - degkey - 1; - degoct = -degoct; - } - //compute the frequency of the note - degkey = degkey + scaleshift; - degoct += degkey / octavesize; - degkey %= octavesize; - - REALTYPE freq = (degkey == 0) ? (1.0) : octave[degkey - 1].tuning; - freq *= pow(octave[octavesize - 1].tuning, degoct); - freq *= PAfreq / rap_anote_middlenote; - freq *= globalfinedetunerap; - if(scaleshift != 0) - freq /= octave[scaleshift - 1].tuning; - return freq * rap_keyshift; - } - else { //if the mapping is disabled - int nt = note - PAnote + scaleshift; - int ntkey = (nt + (int)octavesize * 100) % octavesize; - int ntoct = (nt - ntkey) / octavesize; - - REALTYPE oct = octave[octavesize - 1].tuning; - REALTYPE freq = - octave[(ntkey + octavesize - 1) % octavesize].tuning *pow(oct, - ntoct) - * PAfreq; - if(ntkey == 0) - freq /= oct; - if(scaleshift != 0) - freq /= octave[scaleshift - 1].tuning; -// fprintf(stderr,"note=%d freq=%.3f cents=%d\n",note,freq,(int)floor(log(freq/PAfreq)/log(2.0)*1200.0+0.5)); - freq *= globalfinedetunerap; - return freq * rap_keyshift; - } -} - -bool Microtonal::operator==(const Microtonal µ) const -{ - return !(*this != micro); -} - -bool Microtonal::operator!=(const Microtonal µ) const -{ - //A simple macro to test equality MiCRotonal EQuals (not the perfect - //approach, but good enough) -#define MCREQ(x) if(x != micro.x) \ - return true; - - //for floats -#define FMCREQ(x) if(!((x < micro.x + 0.0001) && (x > micro.x - 0.0001))) \ - return true; - - MCREQ(Pinvertupdown); - MCREQ(Pinvertupdowncenter); - MCREQ(octavesize); - MCREQ(Penabled); - MCREQ(PAnote); - FMCREQ(PAfreq); - MCREQ(Pscaleshift); - - MCREQ(Pfirstkey); - MCREQ(Plastkey); - MCREQ(Pmiddlenote); - MCREQ(Pmapsize); - MCREQ(Pmappingenabled); - - for(int i = 0; i < 128; i++) - MCREQ(Pmapping[i]); - - for(int i = 0; i < octavesize; i++) { - FMCREQ(octave[i].tuning); - MCREQ(octave[i].type); - MCREQ(octave[i].x1); - MCREQ(octave[i].x2); - } - if(strcmp((const char *)this->Pname, (const char *)micro.Pname)) - return true; - if(strcmp((const char *)this->Pcomment, (const char *)micro.Pcomment)) - return true; - MCREQ(Pglobalfinedetune); - return false; - - //undefine macros, as they are no longer needed -#undef MCREQ -#undef FMCREQ -} - - -/* - * Convert a line to tunings; returns -1 if it ok - */ -int Microtonal::linetotunings(unsigned int nline, const char *line) -{ - int x1 = -1, x2 = -1, type = -1; - REALTYPE x = -1.0, tmp, tuning = 1.0; - if(strstr(line, "/") == NULL) { - if(strstr(line, ".") == NULL) { // M case (M=M/1) - sscanf(line, "%d", &x1); - x2 = 1; - type = 2; //division - } - else { // float number case - sscanf(line, "%f", &x); - if(x < 0.000001) - return 1; - type = 1; //float type(cents) - } - } - else { // M/N case - sscanf(line, "%d/%d", &x1, &x2); - if((x1 < 0) || (x2 < 0)) - return 1; - if(x2 == 0) - x2 = 1; - type = 2; //division - } - - if(x1 <= 0) - x1 = 1; //not allow zero frequency sounds (consider 0 as 1) - - //convert to float if the number are too big - if((type == 2) - && ((x1 > (128 * 128 * 128 - 1)) || (x2 > (128 * 128 * 128 - 1)))) { - type = 1; - x = ((REALTYPE) x1) / x2; - } - switch(type) { - case 1: - x1 = (int) floor(x); - tmp = fmod(x, 1.0); - x2 = (int) (floor(tmp * 1e6)); - tuning = pow(2.0, x / 1200.0); - break; - case 2: - x = ((REALTYPE)x1) / x2; - tuning = x; - break; - } - - tmpoctave[nline].tuning = tuning; - tmpoctave[nline].type = type; - tmpoctave[nline].x1 = x1; - tmpoctave[nline].x2 = x2; - - return -1; //ok -} - -/* - * Convert the text to tunnings - */ -int Microtonal::texttotunings(const char *text) -{ - unsigned int i, k = 0, nl = 0; - char *lin; - lin = new char[MAX_LINE_SIZE + 1]; - while(k < strlen(text)) { - for(i = 0; i < MAX_LINE_SIZE; i++) { - lin[i] = text[k++]; - if(lin[i] < 0x20) - break; - } - lin[i] = '\0'; - if(strlen(lin) == 0) - continue; - int err = linetotunings(nl, lin); - if(err != -1) { - delete [] lin; - return nl; //Parse error - } - nl++; - } - delete [] lin; - if(nl > MAX_OCTAVE_SIZE) - nl = MAX_OCTAVE_SIZE; - if(nl == 0) - return -2; //the input is empty - octavesize = nl; - for(i = 0; i < octavesize; i++) { - octave[i].tuning = tmpoctave[i].tuning; - octave[i].type = tmpoctave[i].type; - octave[i].x1 = tmpoctave[i].x1; - octave[i].x2 = tmpoctave[i].x2; - } - return -1; //ok -} - -/* - * Convert the text to mapping - */ -void Microtonal::texttomapping(const char *text) -{ - unsigned int i, k = 0; - char *lin; - lin = new char[MAX_LINE_SIZE + 1]; - for(i = 0; i < 128; i++) - Pmapping[i] = -1; - int tx = 0; - while(k < strlen(text)) { - for(i = 0; i < MAX_LINE_SIZE; i++) { - lin[i] = text[k++]; - if(lin[i] < 0x20) - break; - } - lin[i] = '\0'; - if(strlen(lin) == 0) - continue; - - int tmp = 0; - if(sscanf(lin, "%d", &tmp) == 0) - tmp = -1; - if(tmp < -1) - tmp = -1; - Pmapping[tx] = tmp; - - if((tx++) > 127) - break; - } - delete [] lin; - - if(tx == 0) - tx = 1; - Pmapsize = tx; -} - -/* - * Convert tunning to text line - */ -void Microtonal::tuningtoline(int n, char *line, int maxn) -{ - if((n > octavesize) || (n > MAX_OCTAVE_SIZE)) { - line[0] = '\0'; - return; - } - if(octave[n].type == 1) - snprintf(line, maxn, "%d.%06d", octave[n].x1, octave[n].x2); - if(octave[n].type == 2) - snprintf(line, maxn, "%d/%d", octave[n].x1, octave[n].x2); -} - - -int Microtonal::loadline(FILE *file, char *line) -{ - do { - if(fgets(line, 500, file) == 0) - return 1; - } while(line[0] == '!'); - return 0; -} -/* - * Loads the tunnings from a scl file - */ -int Microtonal::loadscl(const char *filename) -{ - FILE *file = fopen(filename, "r"); - char tmp[500]; - fseek(file, 0, SEEK_SET); - //loads the short description - if(loadline(file, &tmp[0]) != 0) - return 2; - for(int i = 0; i < 500; i++) - if(tmp[i] < 32) - tmp[i] = 0; - snprintf((char *) Pname, MICROTONAL_MAX_NAME_LEN, "%s", tmp); - snprintf((char *) Pcomment, MICROTONAL_MAX_NAME_LEN, "%s", tmp); - //loads the number of the notes - if(loadline(file, &tmp[0]) != 0) - return 2; - int nnotes = MAX_OCTAVE_SIZE; - sscanf(&tmp[0], "%d", &nnotes); - if(nnotes > MAX_OCTAVE_SIZE) - return 2; - //load the tunnings - for(int nline = 0; nline < nnotes; nline++) { - if(loadline(file, &tmp[0]) != 0) - return 2; - linetotunings(nline, &tmp[0]); - } - fclose(file); - - octavesize = nnotes; - for(int i = 0; i < octavesize; i++) { - octave[i].tuning = tmpoctave[i].tuning; - octave[i].type = tmpoctave[i].type; - octave[i].x1 = tmpoctave[i].x1; - octave[i].x2 = tmpoctave[i].x2; - } - - return 0; -} - -/* - * Loads the mapping from a kbm file - */ -int Microtonal::loadkbm(const char *filename) -{ - FILE *file = fopen(filename, "r"); - int x; - char tmp[500]; - - fseek(file, 0, SEEK_SET); - //loads the mapsize - if(loadline(file, &tmp[0]) != 0) - return 2; - if(sscanf(&tmp[0], "%d", &x) == 0) - return 2; - if(x < 1) - x = 0; - if(x > 127) - x = 127; //just in case... - Pmapsize = x; - //loads first MIDI note to retune - if(loadline(file, &tmp[0]) != 0) - return 2; - if(sscanf(&tmp[0], "%d", &x) == 0) - return 2; - if(x < 1) - x = 0; - if(x > 127) - x = 127; //just in case... - Pfirstkey = x; - //loads last MIDI note to retune - if(loadline(file, &tmp[0]) != 0) - return 2; - if(sscanf(&tmp[0], "%d", &x) == 0) - return 2; - if(x < 1) - x = 0; - if(x > 127) - x = 127; //just in case... - Plastkey = x; - //loads last the middle note where scale fro scale degree=0 - if(loadline(file, &tmp[0]) != 0) - return 2; - if(sscanf(&tmp[0], "%d", &x) == 0) - return 2; - if(x < 1) - x = 0; - if(x > 127) - x = 127; //just in case... - Pmiddlenote = x; - //loads the reference note - if(loadline(file, &tmp[0]) != 0) - return 2; - if(sscanf(&tmp[0], "%d", &x) == 0) - return 2; - if(x < 1) - x = 0; - if(x > 127) - x = 127; //just in case... - PAnote = x; - //loads the reference freq. - if(loadline(file, &tmp[0]) != 0) - return 2; - REALTYPE tmpPAfreq = 440.0; - if(sscanf(&tmp[0], "%f", &tmpPAfreq) == 0) - return 2; - PAfreq = tmpPAfreq; - - //the scale degree(which is the octave) is not loaded, it is obtained by the tunnings with getoctavesize() method - if(loadline(file, &tmp[0]) != 0) - return 2; - - //load the mappings - if(Pmapsize != 0) { - for(int nline = 0; nline < Pmapsize; nline++) { - if(loadline(file, &tmp[0]) != 0) - return 2; - if(sscanf(&tmp[0], "%d", &x) == 0) - x = -1; - Pmapping[nline] = x; - } - Pmappingenabled = 1; - } - else { - Pmappingenabled = 0; - Pmapping[0] = 0; - Pmapsize = 1; - } - fclose(file); - - return 0; -} - - - -void Microtonal::add2XML(XMLwrapper *xml) const -{ - xml->addparstr("name", (char *) Pname); - xml->addparstr("comment", (char *) Pcomment); - - xml->addparbool("invert_up_down", Pinvertupdown); - xml->addpar("invert_up_down_center", Pinvertupdowncenter); - - xml->addparbool("enabled", Penabled); - xml->addpar("global_fine_detune", Pglobalfinedetune); - - xml->addpar("a_note", PAnote); - xml->addparreal("a_freq", PAfreq); - - if((Penabled == 0) && (xml->minimal)) - return; - - xml->beginbranch("SCALE"); - xml->addpar("scale_shift", Pscaleshift); - xml->addpar("first_key", Pfirstkey); - xml->addpar("last_key", Plastkey); - xml->addpar("middle_note", Pmiddlenote); - - xml->beginbranch("OCTAVE"); - xml->addpar("octave_size", octavesize); - for(int i = 0; i < octavesize; i++) { - xml->beginbranch("DEGREE", i); - if(octave[i].type == 1) - xml->addparreal("cents", octave[i].tuning); - ; - if(octave[i].type == 2) { - xml->addpar("numerator", octave[i].x1); - xml->addpar("denominator", octave[i].x2); - } - xml->endbranch(); - } - xml->endbranch(); - - xml->beginbranch("KEYBOARD_MAPPING"); - xml->addpar("map_size", Pmapsize); - xml->addpar("mapping_enabled", Pmappingenabled); - for(int i = 0; i < Pmapsize; i++) { - xml->beginbranch("KEYMAP", i); - xml->addpar("degree", Pmapping[i]); - xml->endbranch(); - } - - xml->endbranch(); - xml->endbranch(); -} - -void Microtonal::getfromXML(XMLwrapper *xml) -{ - xml->getparstr("name", (char *) Pname, MICROTONAL_MAX_NAME_LEN); - xml->getparstr("comment", (char *) Pcomment, MICROTONAL_MAX_NAME_LEN); - - Pinvertupdown = xml->getparbool("invert_up_down", Pinvertupdown); - Pinvertupdowncenter = xml->getpar127("invert_up_down_center", - Pinvertupdowncenter); - - Penabled = xml->getparbool("enabled", Penabled); - Pglobalfinedetune = xml->getpar127("global_fine_detune", Pglobalfinedetune); - - PAnote = xml->getpar127("a_note", PAnote); - PAfreq = xml->getparreal("a_freq", PAfreq, 1.0, 10000.0); - - if(xml->enterbranch("SCALE")) { - Pscaleshift = xml->getpar127("scale_shift", Pscaleshift); - Pfirstkey = xml->getpar127("first_key", Pfirstkey); - Plastkey = xml->getpar127("last_key", Plastkey); - Pmiddlenote = xml->getpar127("middle_note", Pmiddlenote); - - if(xml->enterbranch("OCTAVE")) { - octavesize = xml->getpar127("octave_size", octavesize); - for(int i = 0; i < octavesize; i++) { - if(xml->enterbranch("DEGREE", i) == 0) - continue; - octave[i].x2 = 0; - octave[i].tuning = xml->getparreal("cents", octave[i].tuning); - octave[i].x1 = xml->getpar127("numerator", octave[i].x1); - octave[i].x2 = xml->getpar127("denominator", octave[i].x2); - - if(octave[i].x2 != 0) - octave[i].type = 2; - else - octave[i].type = 1; - - xml->exitbranch(); - } - xml->exitbranch(); - } - - if(xml->enterbranch("KEYBOARD_MAPPING")) { - Pmapsize = xml->getpar127("map_size", Pmapsize); - Pmappingenabled = xml->getpar127("mapping_enabled", Pmappingenabled); - for(int i = 0; i < Pmapsize; i++) { - if(xml->enterbranch("KEYMAP", i) == 0) - continue; - Pmapping[i] = xml->getpar127("degree", Pmapping[i]); - xml->exitbranch(); - } - xml->exitbranch(); - } - xml->exitbranch(); - } -} - - - -int Microtonal::saveXML(const char *filename) const -{ - XMLwrapper *xml = new XMLwrapper(); - - xml->beginbranch("MICROTONAL"); - add2XML(xml); - xml->endbranch(); - - int result = xml->saveXMLfile(filename); - delete (xml); - return result; -} - -int Microtonal::loadXML(const char *filename) -{ - XMLwrapper *xml = new XMLwrapper(); - if(xml->loadXMLfile(filename) < 0) { - delete (xml); - return -1; - } - - if(xml->enterbranch("MICROTONAL") == 0) - return -10; - getfromXML(xml); - xml->exitbranch(); - - delete (xml); - return 0; -} - diff --git a/plugins/zynaddsubfx/src/Misc/Microtonal.h b/plugins/zynaddsubfx/src/Misc/Microtonal.h deleted file mode 100644 index c7fd7c200..000000000 --- a/plugins/zynaddsubfx/src/Misc/Microtonal.h +++ /dev/null @@ -1,135 +0,0 @@ -/* - ZynAddSubFX - a software synthesizer - - Microtonal.h - Tuning settings and microtonal capabilities - Copyright (C) 2002-2005 Nasca Octavian Paul - Author: Nasca Octavian Paul - - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License - as published by the Free Software Foundation. - - 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 (version 2 or later) for more details. - - You should have received a copy of the GNU General Public License (version 2) - along with this program; if not, write to the Free Software Foundation, - Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -*/ - -#ifndef MICROTONAL_H -#define MICROTONAL_H - -#include "../globals.h" -#include "XMLwrapper.h" - -#define MAX_OCTAVE_SIZE 128 -#define MICROTONAL_MAX_NAME_LEN 120 - -#include - - -/**Tuning settings and microtonal capabilities*/ -class Microtonal -{ - public: - /**Constructor*/ - Microtonal(); - /**Destructor*/ - ~Microtonal(); - void defaults(); - /**Calculates the frequency for a given note - */ - REALTYPE getnotefreq(int note, int keyshift) const; - - - //Parameters - /**if the keys are inversed (the pitch is lower to keys from the right direction)*/ - unsigned char Pinvertupdown; - - /**the central key of the inversion*/ - unsigned char Pinvertupdowncenter; - - /**0 for 12 key temperate scale, 1 for microtonal*/ - unsigned char Penabled; - - /**the note of "A" key*/ - unsigned char PAnote; - - /**the frequency of the "A" note*/ - REALTYPE PAfreq; - - /**if the scale is "tuned" to a note, you can tune to other note*/ - unsigned char Pscaleshift; - - //first and last key (to retune) - unsigned char Pfirstkey; - unsigned char Plastkey; - - /**The middle note where scale degree 0 is mapped to*/ - unsigned char Pmiddlenote; - - /**Map size*/ - unsigned char Pmapsize; - - /**Mapping ON/OFF*/ - unsigned char Pmappingenabled; - /**Mapping (keys)*/ - short int Pmapping[128]; - - /**Fine detune to be applied to all notes*/ - unsigned char Pglobalfinedetune; - - // Functions - /** Return the current octave size*/ - unsigned char getoctavesize() const; - /**Convert tunning to string*/ - void tuningtoline(int n, char *line, int maxn); - /**load the tunnings from a .scl file*/ - int loadscl(const char *filename); - /**load the mapping from .kbm file*/ - int loadkbm(const char *filename); - /**Load text into the internal tunings - * - *\todo better description*/ - int texttotunings(const char *text); - /**Load text into the internal mappings - * - *\todo better description*/ - void texttomapping(const char *text); - - /**Name of Microtonal tuning*/ - unsigned char *Pname; - /**Comment about the tuning*/ - unsigned char *Pcomment; - - void add2XML(XMLwrapper *xml) const; - void getfromXML(XMLwrapper *xml); - int saveXML(const char *filename) const; - int loadXML(const char *filename); - - //simple operators primarily for debug - bool operator==(const Microtonal µ) const; - bool operator!=(const Microtonal µ) const; - - private: - int linetotunings(unsigned int nline, const char *line); - int loadline(FILE *file, char *line); //loads a line from the text file, while ignoring the lines beggining with "!" - unsigned char octavesize; - struct { - unsigned char type; //1 for cents or 2 for division - - // the real tuning (eg. +1.05946 for one halftone) - // or 2.0 for one octave - REALTYPE tuning; - - //the real tunning is x1/x2 - unsigned int x1, x2; - } octave[MAX_OCTAVE_SIZE], tmpoctave[MAX_OCTAVE_SIZE]; -}; - -#endif - diff --git a/plugins/zynaddsubfx/src/Misc/Part.cpp b/plugins/zynaddsubfx/src/Misc/Part.cpp deleted file mode 100644 index e54c85891..000000000 --- a/plugins/zynaddsubfx/src/Misc/Part.cpp +++ /dev/null @@ -1,1370 +0,0 @@ -/* - ZynAddSubFX - a software synthesizer - - Part.cpp - Part implementation - Copyright (C) 2002-2005 Nasca Octavian Paul - Author: Nasca Octavian Paul - - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License - as published by the Free Software Foundation. - - 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 (version 2 or later) for more details. - - You should have received a copy of the GNU General Public License (version 2) - along with this program; if not, write to the Free Software Foundation, - Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -*/ - -#include "Part.h" -#include "Microtonal.h" -#include -#include -#include - -Part::Part(Microtonal *microtonal_, FFTwrapper *fft_, pthread_mutex_t *mutex_) -{ - microtonal = microtonal_; - fft = fft_; - mutex = mutex_; - partoutl = new REALTYPE [SOUND_BUFFER_SIZE]; - partoutr = new REALTYPE [SOUND_BUFFER_SIZE]; - tmpoutl = new REALTYPE [SOUND_BUFFER_SIZE]; - tmpoutr = new REALTYPE [SOUND_BUFFER_SIZE]; - - for(int n = 0; n < NUM_KIT_ITEMS; n++) { - kit[n].Pname = new unsigned char [PART_MAX_NAME_LEN]; - kit[n].adpars = NULL; - kit[n].subpars = NULL; - kit[n].padpars = NULL; - } - - kit[0].adpars = new ADnoteParameters(fft); - kit[0].subpars = new SUBnoteParameters(); - kit[0].padpars = new PADnoteParameters(fft, mutex); -// ADPartParameters=kit[0].adpars; -// SUBPartParameters=kit[0].subpars; - - //Part's Insertion Effects init - for(int nefx = 0; nefx < NUM_PART_EFX; nefx++) { - partefx[nefx] = new EffectMgr(1, mutex); - Pefxbypass[nefx] = false; - } - - for(int n = 0; n < NUM_PART_EFX + 1; n++) { - partfxinputl[n] = new REALTYPE [SOUND_BUFFER_SIZE]; - partfxinputr[n] = new REALTYPE [SOUND_BUFFER_SIZE]; - } - - killallnotes = 0; - oldfreq = -1.0; - - int i, j; - for(i = 0; i < POLIPHONY; i++) { - partnote[i].status = KEY_OFF; - partnote[i].note = -1; - partnote[i].itemsplaying = 0; - for(j = 0; j < NUM_KIT_ITEMS; j++) { - partnote[i].kititem[j].adnote = NULL; - partnote[i].kititem[j].subnote = NULL; - partnote[i].kititem[j].padnote = NULL; - } - partnote[i].time = 0; - } - cleanup(); - - Pname = new unsigned char [PART_MAX_NAME_LEN]; - - oldvolumel = oldvolumer = 0.5; - lastnote = -1; - lastpos = 0; // lastpos will store previously used NoteOn(...)'s pos. - lastlegatomodevalid = false; // To store previous legatomodevalid value. - - - defaults(); -} - -void Part::defaults() -{ - Penabled = 0; - Pminkey = 0; - Pmaxkey = 127; - Pnoteon = 1; - Ppolymode = 1; - Plegatomode = 0; - setPvolume(96); - Pkeyshift = 64; - Prcvchn = 0; - setPpanning(64); - Pvelsns = 64; - Pveloffs = 64; - Pkeylimit = 15; - defaultsinstrument(); - ctl.defaults(); -} - -void Part::defaultsinstrument() -{ - ZERO(Pname, PART_MAX_NAME_LEN); - - info.Ptype = 0; - ZERO(info.Pauthor, MAX_INFO_TEXT_SIZE + 1); - ZERO(info.Pcomments, MAX_INFO_TEXT_SIZE + 1); - - Pkitmode = 0; - Pdrummode = 0; - - for(int n = 0; n < NUM_KIT_ITEMS; n++) { - kit[n].Penabled = 0; - kit[n].Pmuted = 0; - kit[n].Pminkey = 0; - kit[n].Pmaxkey = 127; - kit[n].Padenabled = 0; - kit[n].Psubenabled = 0; - kit[n].Ppadenabled = 0; - ZERO(kit[n].Pname, PART_MAX_NAME_LEN); - kit[n].Psendtoparteffect = 0; - if(n != 0) - setkititemstatus(n, 0); - } - kit[0].Penabled = 1; - kit[0].Padenabled = 1; - kit[0].adpars->defaults(); - kit[0].subpars->defaults(); - kit[0].padpars->defaults(); - - for(int nefx = 0; nefx < NUM_PART_EFX; nefx++) { - partefx[nefx]->defaults(); - Pefxroute[nefx] = 0; //route to next effect - } -} - - - -/* - * Cleanup the part - */ -void Part::cleanup() -{ - for(int k = 0; k < POLIPHONY; k++) - KillNotePos(k); - for(int i = 0; i < SOUND_BUFFER_SIZE; i++) { - partoutl[i] = denormalkillbuf[i]; - partoutr[i] = denormalkillbuf[i]; - tmpoutl[i] = 0.0; - tmpoutr[i] = 0.0; - } - ctl.resetall(); - for(int nefx = 0; nefx < NUM_PART_EFX; nefx++) - partefx[nefx]->cleanup(); - for(int n = 0; n < NUM_PART_EFX + 1; n++) { - for(int i = 0; i < SOUND_BUFFER_SIZE; i++) { - partfxinputl[n][i] = denormalkillbuf[i]; - partfxinputr[n][i] = denormalkillbuf[i]; - } - } -} - -Part::~Part() -{ - cleanup(); - for(int n = 0; n < NUM_KIT_ITEMS; n++) { - if(kit[n].adpars != NULL) - delete (kit[n].adpars); - if(kit[n].subpars != NULL) - delete (kit[n].subpars); - if(kit[n].padpars != NULL) - delete (kit[n].padpars); - kit[n].adpars = NULL; - kit[n].subpars = NULL; - kit[n].padpars = NULL; - delete [] kit[n].Pname; - } - - delete [] Pname; - delete [] partoutl; - delete [] partoutr; - delete [] tmpoutl; - delete [] tmpoutr; - for(int nefx = 0; nefx < NUM_PART_EFX; nefx++) - delete (partefx[nefx]); - for(int n = 0; n < NUM_PART_EFX + 1; n++) { - delete [] partfxinputl[n]; - delete [] partfxinputr[n]; - } -} - -/* - * Note On Messages - */ -void Part::NoteOn(unsigned char note, - unsigned char velocity, - int masterkeyshift) -{ - int i, pos; - - // Legato and MonoMem used vars: - int posb = POLIPHONY - 1; // Just a dummy initial value. - bool legatomodevalid = false; //true when legato mode is determined applicable. - bool doinglegato = false; // true when we determined we do a legato note. - bool ismonofirstnote = false; /*(In Mono/Legato) true when we determined - no other notes are held down or sustained.*/ - int lastnotecopy = lastnote; //Useful after lastnote has been changed. - - if(Pnoteon == 0) - return; - if((note < Pminkey) || (note > Pmaxkey)) - return; - - // MonoMem stuff: - if(Ppolymode == 0) { // If Poly is off - monomemnotes.push_back(note); // Add note to the list. - monomem[note].velocity = velocity; // Store this note's velocity. - monomem[note].mkeyshift = masterkeyshift; /* Store masterkeyshift too, - I'm not sure why though... */ - if((partnote[lastpos].status != KEY_PLAYING) - && (partnote[lastpos].status != KEY_RELASED_AND_SUSTAINED)) - ismonofirstnote = true; // No other keys are held or sustained. - } - else - // Poly mode is On so just make sure the list is empty. - if(not monomemnotes.empty()) - monomemnotes.clear(); - - lastnote = note; - - pos = -1; - for(i = 0; i < POLIPHONY; i++) { - if(partnote[i].status == KEY_OFF) { - pos = i; - break; - } - } - - if((Plegatomode != 0) && (Pdrummode == 0)) { - if(Ppolymode != 0) { - fprintf( - stderr, - "ZynAddSubFX WARNING: Poly and Legato modes are both On, that should not happen ! ... Disabling Legato mode ! - (Part.cpp::NoteOn(..))\n"); - Plegatomode = 0; - } - else { - // Legato mode is on and applicable. - legatomodevalid = true; - if((not ismonofirstnote) && (lastlegatomodevalid)) { - // At least one other key is held or sustained, and the - // previous note was played while in valid legato mode. - doinglegato = true; // So we'll do a legato note. - pos = lastpos; // A legato note uses same pos as previous.. - posb = lastposb; // .. same goes for posb. - } - else { - // Legato mode is valid, but this is only a first note. - for(i = 0; i < POLIPHONY; i++) - if((partnote[i].status == KEY_PLAYING) - || (partnote[i].status == KEY_RELASED_AND_SUSTAINED)) - RelaseNotePos(i); - - // Set posb - posb = (pos + 1) % POLIPHONY; //We really want it (if the following fails) - for(i = 0; i < POLIPHONY; i++) - if((partnote[i].status == KEY_OFF) && (pos != i)) { - posb = i; - break; - } - } - lastposb = posb; // Keep a trace of used posb - } - } - else // Legato mode is either off or non-applicable. - if(Ppolymode == 0) { //if the mode is 'mono' turn off all other notes - for(i = 0; i < POLIPHONY; i++) - if(partnote[i].status == KEY_PLAYING) - RelaseNotePos(i); - RelaseSustainedKeys(); - } - lastlegatomodevalid = legatomodevalid; - - if(pos == -1) - //test - fprintf(stderr, - "%s", - "NOTES TOO MANY (> POLIPHONY) - (Part.cpp::NoteOn(..))\n"); - else { - //start the note - partnote[pos].status = KEY_PLAYING; - partnote[pos].note = note; - if(legatomodevalid) { - partnote[posb].status = KEY_PLAYING; - partnote[posb].note = note; - } - - //this computes the velocity sensing of the part - REALTYPE vel = VelF(velocity / 127.0, Pvelsns); - - //compute the velocity offset - vel += (Pveloffs - 64.0) / 64.0; - if(vel < 0.0) - vel = 0.0; - else - if(vel > 1.0) - vel = 1.0; - - //compute the keyshift - int partkeyshift = (int)Pkeyshift - 64; - int keyshift = masterkeyshift + partkeyshift; - - //initialise note frequency - REALTYPE notebasefreq; - if(Pdrummode == 0) { - notebasefreq = microtonal->getnotefreq(note, keyshift); - if(notebasefreq < 0.0) - return; //the key is no mapped - } - else - notebasefreq = 440.0 * pow(2.0, (note - 69.0) / 12.0); - ; - - //Portamento - if(oldfreq < 1.0) - oldfreq = notebasefreq; //this is only the first note is played - - // For Mono/Legato: Force Portamento Off on first - // notes. That means it is required that the previous note is - // still held down or sustained for the Portamento to activate - // (that's like Legato). - int portamento = 0; - if((Ppolymode != 0) || (not ismonofirstnote)) - // I added a third argument to the - // ctl.initportamento(...) function to be able - // to tell it if we're doing a legato note. - portamento = ctl.initportamento(oldfreq, notebasefreq, doinglegato); - - if(portamento != 0) - ctl.portamento.noteusing = pos; - oldfreq = notebasefreq; - - lastpos = pos; // Keep a trace of used pos. - - if(doinglegato) { - // Do Legato note - if(Pkitmode == 0) { // "normal mode" legato note - if((kit[0].Padenabled != 0) - && (partnote[pos].kititem[0].adnote != NULL) - && (partnote[posb].kititem[0].adnote != NULL)) { - partnote[pos].kititem[0].adnote->ADlegatonote(notebasefreq, - vel, - portamento, - note, - true); //'true' is to tell it it's being called from here. - partnote[posb].kititem[0].adnote->ADlegatonote(notebasefreq, - vel, - portamento, - note, - true); - } - - if((kit[0].Psubenabled != 0) - && (partnote[pos].kititem[0].subnote != NULL) - && (partnote[posb].kititem[0].subnote != NULL)) { - partnote[pos].kititem[0].subnote->SUBlegatonote( - notebasefreq, - vel, - portamento, - note, - true); - partnote[posb].kititem[0].subnote->SUBlegatonote( - notebasefreq, - vel, - portamento, - note, - true); - } - - if((kit[0].Ppadenabled != 0) - && (partnote[pos].kititem[0].padnote != NULL) - && (partnote[posb].kititem[0].padnote != NULL)) { - partnote[pos].kititem[0].padnote->PADlegatonote( - notebasefreq, - vel, - portamento, - note, - true); - partnote[posb].kititem[0].padnote->PADlegatonote( - notebasefreq, - vel, - portamento, - note, - true); - } - } - else { // "kit mode" legato note - int ci = 0; - for(int item = 0; item < NUM_KIT_ITEMS; item++) { - if(kit[item].Pmuted != 0) - continue; - if((note < kit[item].Pminkey) || (note > kit[item].Pmaxkey)) - continue; - - if((lastnotecopy < kit[item].Pminkey) - || (lastnotecopy > kit[item].Pmaxkey)) - continue; // We will not perform legato across 2 key regions. - - partnote[pos].kititem[ci].sendtoparteffect = - (kit[item].Psendtoparteffect < - NUM_PART_EFX ? kit[item].Psendtoparteffect : NUM_PART_EFX); //if this parameter is 127 for "unprocessed" - partnote[posb].kititem[ci].sendtoparteffect = - (kit[item].Psendtoparteffect < - NUM_PART_EFX ? kit[item].Psendtoparteffect : NUM_PART_EFX); - - if((kit[item].Padenabled != 0) && (kit[item].adpars != NULL) - && (partnote[pos].kititem[ci].adnote != NULL) - && (partnote[posb].kititem[ci].adnote != NULL)) { - partnote[pos].kititem[ci].adnote->ADlegatonote( - notebasefreq, - vel, - portamento, - note, - true); - partnote[posb].kititem[ci].adnote->ADlegatonote( - notebasefreq, - vel, - portamento, - note, - true); - } - if((kit[item].Psubenabled != 0) - && (kit[item].subpars != NULL) - && (partnote[pos].kititem[ci].subnote != NULL) - && (partnote[posb].kititem[ci].subnote != NULL)) { - partnote[pos].kititem[ci].subnote->SUBlegatonote( - notebasefreq, - vel, - portamento, - note, - true); - partnote[posb].kititem[ci].subnote->SUBlegatonote( - notebasefreq, - vel, - portamento, - note, - true); - } - if((kit[item].Ppadenabled != 0) - && (kit[item].padpars != NULL) - && (partnote[pos].kititem[ci].padnote != NULL) - && (partnote[posb].kititem[ci].padnote != NULL)) { - partnote[pos].kititem[ci].padnote->PADlegatonote( - notebasefreq, - vel, - portamento, - note, - true); - partnote[posb].kititem[ci].padnote->PADlegatonote( - notebasefreq, - vel, - portamento, - note, - true); - } - - if((kit[item].adpars != NULL) - || (kit[item].subpars != NULL) - || (kit[item].padpars != NULL)) { - ci++; - if(((kit[item].Padenabled != 0) - || (kit[item].Psubenabled != 0) - || (kit[item].Ppadenabled != 0)) && (Pkitmode == 2)) - break; - } - } - if(ci == 0) { - // No legato were performed at all, so pretend nothing happened: - monomemnotes.pop_back(); // Remove last note from the list. - lastnote = lastnotecopy; // Set lastnote back to previous value. - } - } - return; // Ok, Legato note done, return. - } - - partnote[pos].itemsplaying = 0; - if(legatomodevalid) - partnote[posb].itemsplaying = 0; - - if(Pkitmode == 0) { //init the notes for the "normal mode" - partnote[pos].kititem[0].sendtoparteffect = 0; - if(kit[0].Padenabled != 0) - partnote[pos].kititem[0].adnote = new ADnote(kit[0].adpars, - &ctl, - notebasefreq, - vel, - portamento, - note, - false); - if(kit[0].Psubenabled != 0) - partnote[pos].kititem[0].subnote = new SUBnote(kit[0].subpars, - &ctl, - notebasefreq, - vel, - portamento, - note, - false); - if(kit[0].Ppadenabled != 0) - partnote[pos].kititem[0].padnote = new PADnote(kit[0].padpars, - &ctl, - notebasefreq, - vel, - portamento, - note, - false); - if((kit[0].Padenabled != 0) || (kit[0].Psubenabled != 0) - || (kit[0].Ppadenabled != 0)) - partnote[pos].itemsplaying++; - - // Spawn another note (but silent) if legatomodevalid==true - if(legatomodevalid) { - partnote[posb].kititem[0].sendtoparteffect = 0; - if(kit[0].Padenabled != 0) - partnote[posb].kititem[0].adnote = new ADnote(kit[0].adpars, - &ctl, - notebasefreq, - vel, - portamento, - note, - true); //true for silent. - if(kit[0].Psubenabled != 0) - partnote[posb].kititem[0].subnote = new SUBnote( - kit[0].subpars, - &ctl, - notebasefreq, - vel, - portamento, - note, - true); - if(kit[0].Ppadenabled != 0) - partnote[posb].kititem[0].padnote = new PADnote( - kit[0].padpars, - &ctl, - notebasefreq, - vel, - portamento, - note, - true); - if((kit[0].Padenabled != 0) || (kit[0].Psubenabled != 0) - || (kit[0].Ppadenabled != 0)) - partnote[posb].itemsplaying++; - } - } - else { //init the notes for the "kit mode" - for(int item = 0; item < NUM_KIT_ITEMS; item++) { - if(kit[item].Pmuted != 0) - continue; - if((note < kit[item].Pminkey) || (note > kit[item].Pmaxkey)) - continue; - - int ci = partnote[pos].itemsplaying; //ci=current item - - partnote[pos].kititem[ci].sendtoparteffect = - (kit[item].Psendtoparteffect < NUM_PART_EFX ? - kit[item]. - Psendtoparteffect : NUM_PART_EFX); //if this parameter is 127 for "unprocessed" - - if((kit[item].adpars != NULL) && ((kit[item].Padenabled) != 0)) - partnote[pos].kititem[ci].adnote = new ADnote( - kit[item].adpars, - &ctl, - notebasefreq, - vel, - portamento, - note, - false); - - if((kit[item].subpars != NULL) && ((kit[item].Psubenabled) != 0)) - partnote[pos].kititem[ci].subnote = new SUBnote( - kit[item].subpars, - &ctl, - notebasefreq, - vel, - portamento, - note, - false); - - if((kit[item].padpars != NULL) && ((kit[item].Ppadenabled) != 0)) - partnote[pos].kititem[ci].padnote = new PADnote( - kit[item].padpars, - &ctl, - notebasefreq, - vel, - portamento, - note, - false); - - // Spawn another note (but silent) if legatomodevalid==true - if(legatomodevalid) { - partnote[posb].kititem[ci].sendtoparteffect = - (kit[item].Psendtoparteffect < - NUM_PART_EFX ? kit[item].Psendtoparteffect : NUM_PART_EFX); //if this parameter is 127 for "unprocessed" - - if((kit[item].adpars != NULL) - && ((kit[item].Padenabled) != 0)) - partnote[posb].kititem[ci].adnote = new ADnote( - kit[item].adpars, - &ctl, - notebasefreq, - vel, - portamento, - note, - true); //true for silent. - if((kit[item].subpars != NULL) - && ((kit[item].Psubenabled) != 0)) - partnote[posb].kititem[ci].subnote = - new SUBnote(kit[item].subpars, - &ctl, - notebasefreq, - vel, - portamento, - note, - true); - if((kit[item].padpars != NULL) - && ((kit[item].Ppadenabled) != 0)) - partnote[posb].kititem[ci].padnote = - new PADnote(kit[item].padpars, - &ctl, - notebasefreq, - vel, - portamento, - note, - true); - - if((kit[item].adpars != NULL) || (kit[item].subpars != NULL)) - partnote[posb].itemsplaying++; - } - - if((kit[item].adpars != NULL) || (kit[item].subpars != NULL)) { - partnote[pos].itemsplaying++; - if(((kit[item].Padenabled != 0) - || (kit[item].Psubenabled != 0) - || (kit[item].Ppadenabled != 0)) - && (Pkitmode == 2)) - break; - } - } - } - } - - //this only relase the keys if there is maximum number of keys allowed - setkeylimit(Pkeylimit); -} - -/* - * Note Off Messages - */ -void Part::NoteOff(unsigned char note) //relase the key -{ - int i; - - // This note is released, so we remove it from the list. - if(not monomemnotes.empty()) - monomemnotes.remove(note); - - for(i = POLIPHONY - 1; i >= 0; i--) //first note in, is first out if there are same note multiple times - if((partnote[i].status == KEY_PLAYING) && (partnote[i].note == note)) { - if(ctl.sustain.sustain == 0) { //the sustain pedal is not pushed - if((Ppolymode == 0) && (not monomemnotes.empty())) - MonoMemRenote(); // To play most recent still held note. - else - RelaseNotePos(i); - /// break; - } - else //the sustain pedal is pushed - partnote[i].status = KEY_RELASED_AND_SUSTAINED; - } -} - -/* - * Controllers - */ -void Part::SetController(unsigned int type, int par) -{ - switch(type) { - case C_pitchwheel: - ctl.setpitchwheel(par); - break; - case C_expression: - ctl.setexpression(par); - setPvolume(Pvolume); //update the volume - break; - case C_portamento: - ctl.setportamento(par); - break; - case C_panning: - ctl.setpanning(par); - setPpanning(Ppanning); //update the panning - break; - case C_filtercutoff: - ctl.setfiltercutoff(par); - break; - case C_filterq: - ctl.setfilterq(par); - break; - case C_bandwidth: - ctl.setbandwidth(par); - break; - case C_modwheel: - ctl.setmodwheel(par); - break; - case C_fmamp: - ctl.setfmamp(par); - break; - case C_volume: - ctl.setvolume(par); - if(ctl.volume.receive != 0) - volume = ctl.volume.volume; - else - setPvolume(Pvolume); - break; - case C_sustain: - ctl.setsustain(par); - if(ctl.sustain.sustain == 0) - RelaseSustainedKeys(); - break; - case C_allsoundsoff: - AllNotesOff(); //Panic - break; - case C_resetallcontrollers: - ctl.resetall(); - RelaseSustainedKeys(); - if(ctl.volume.receive != 0) - volume = ctl.volume.volume; - else - setPvolume(Pvolume); - setPvolume(Pvolume); //update the volume - setPpanning(Ppanning); //update the panning - - for(int item = 0; item < NUM_KIT_ITEMS; item++) { - if(kit[item].adpars == NULL) - continue; - kit[item].adpars->GlobalPar.Reson-> - sendcontroller(C_resonance_center, 1.0); - - kit[item].adpars->GlobalPar.Reson-> - sendcontroller(C_resonance_bandwidth, 1.0); - } - //more update to add here if I add controllers - break; - case C_allnotesoff: - RelaseAllKeys(); - break; - case C_resonance_center: - ctl.setresonancecenter(par); - for(int item = 0; item < NUM_KIT_ITEMS; item++) { - if(kit[item].adpars == NULL) - continue; - kit[item].adpars->GlobalPar.Reson-> - sendcontroller(C_resonance_center, ctl.resonancecenter.relcenter); - } - break; - case C_resonance_bandwidth: - ctl.setresonancebw(par); - kit[0].adpars->GlobalPar.Reson-> - sendcontroller(C_resonance_bandwidth, ctl.resonancebandwidth.relbw); - break; - } -} -/* - * Relase the sustained keys - */ - -void Part::RelaseSustainedKeys() -{ - // Let's call MonoMemRenote() on some conditions: - if((Ppolymode == 0) && (not monomemnotes.empty())) - if(monomemnotes.back() != lastnote) // Sustain controller manipulation would cause repeated same note respawn without this check. - MonoMemRenote(); // To play most recent still held note. - - for(int i = 0; i < POLIPHONY; i++) - if(partnote[i].status == KEY_RELASED_AND_SUSTAINED) - RelaseNotePos(i); -} - -/* - * Relase all keys - */ - -void Part::RelaseAllKeys() -{ - for(int i = 0; i < POLIPHONY; i++) - if((partnote[i].status != KEY_RELASED) - && (partnote[i].status != KEY_OFF)) //thanks to Frank Neumann - RelaseNotePos(i); - ; -} - -// Call NoteOn(...) with the most recent still held key as new note -// (Made for Mono/Legato). -void Part::MonoMemRenote() -{ - unsigned char mmrtempnote = monomemnotes.back(); // Last list element. - monomemnotes.pop_back(); // We remove it, will be added again in NoteOn(...). - if(Pnoteon == 0) - RelaseNotePos(lastpos); - else - NoteOn(mmrtempnote, monomem[mmrtempnote].velocity, - monomem[mmrtempnote].mkeyshift); -} - -/* - * Release note at position - */ -void Part::RelaseNotePos(int pos) -{ - for(int j = 0; j < NUM_KIT_ITEMS; j++) { - if(partnote[pos].kititem[j].adnote != NULL) - if(partnote[pos].kititem[j].adnote) - partnote[pos].kititem[j].adnote->relasekey(); - - if(partnote[pos].kititem[j].subnote != NULL) - if(partnote[pos].kititem[j].subnote != NULL) - partnote[pos].kititem[j].subnote->relasekey(); - - if(partnote[pos].kititem[j].padnote != NULL) - if(partnote[pos].kititem[j].padnote) - partnote[pos].kititem[j].padnote->relasekey(); - } - partnote[pos].status = KEY_RELASED; -} - - -/* - * Kill note at position - */ -void Part::KillNotePos(int pos) -{ - partnote[pos].status = KEY_OFF; - partnote[pos].note = -1; - partnote[pos].time = 0; - partnote[pos].itemsplaying = 0; - - for(int j = 0; j < NUM_KIT_ITEMS; j++) { - if(partnote[pos].kititem[j].adnote != NULL) { - delete (partnote[pos].kititem[j].adnote); - partnote[pos].kititem[j].adnote = NULL; - } - if(partnote[pos].kititem[j].subnote != NULL) { - delete (partnote[pos].kititem[j].subnote); - partnote[pos].kititem[j].subnote = NULL; - } - if(partnote[pos].kititem[j].padnote != NULL) { - delete (partnote[pos].kititem[j].padnote); - partnote[pos].kititem[j].padnote = NULL; - } - } - if(pos == ctl.portamento.noteusing) { - ctl.portamento.noteusing = -1; - ctl.portamento.used = 0; - } -} - - -/* - * Set Part's key limit - */ -void Part::setkeylimit(unsigned char Pkeylimit) -{ - this->Pkeylimit = Pkeylimit; - int keylimit = Pkeylimit; - if(keylimit == 0) - keylimit = POLIPHONY - 5; - - //release old keys if the number of notes>keylimit - if(Ppolymode != 0) { - int notecount = 0; - for(int i = 0; i < POLIPHONY; i++) - if((partnote[i].status == KEY_PLAYING) - || (partnote[i].status == KEY_RELASED_AND_SUSTAINED)) - notecount++; - ; - int oldestnotepos = -1, maxtime = 0; - if(notecount > keylimit) { //find out the oldest note - for(int i = 0; i < POLIPHONY; i++) { - if(((partnote[i].status == KEY_PLAYING) - || (partnote[i].status == KEY_RELASED_AND_SUSTAINED)) - && (partnote[i].time > maxtime)) { - maxtime = partnote[i].time; - oldestnotepos = i; - } - } - } - if(oldestnotepos != -1) - RelaseNotePos(oldestnotepos); - } -} - - -/* - * Prepare all notes to be turned off - */ -void Part::AllNotesOff() -{ - killallnotes = 1; -} - - -/* - * Compute Part samples and store them in the partoutl[] and partoutr[] - */ -void Part::ComputePartSmps() -{ - int i, k; - int noteplay; //0 if there is nothing activated - for(int nefx = 0; nefx < NUM_PART_EFX + 1; nefx++) { - for(i = 0; i < SOUND_BUFFER_SIZE; i++) { - partfxinputl[nefx][i] = 0.0; - partfxinputr[nefx][i] = 0.0; - } - } - - for(k = 0; k < POLIPHONY; k++) { - if(partnote[k].status == KEY_OFF) - continue; - noteplay = 0; - partnote[k].time++; - //get the sampledata of the note and kill it if it's finished - - for(int item = 0; item < partnote[k].itemsplaying; item++) { - int sendcurrenttofx = partnote[k].kititem[item].sendtoparteffect; - - ADnote *adnote = partnote[k].kititem[item].adnote; - SUBnote *subnote = partnote[k].kititem[item].subnote; - PADnote *padnote = partnote[k].kititem[item].padnote; - //get from the ADnote - if(adnote != NULL) { - noteplay++; - if(adnote->ready != 0) - adnote->noteout(&tmpoutl[0], &tmpoutr[0]); - else - for(i = 0; i < SOUND_BUFFER_SIZE; i++) { - tmpoutl[i] = 0.0; - tmpoutr[i] = 0.0; - } - ; - if(adnote->finished() != 0) { - delete (adnote); - partnote[k].kititem[item].adnote = NULL; - } - for(i = 0; i < SOUND_BUFFER_SIZE; i++) { //add the ADnote to part(mix) - partfxinputl[sendcurrenttofx][i] += tmpoutl[i]; - partfxinputr[sendcurrenttofx][i] += tmpoutr[i]; - } - } - //get from the SUBnote - if(subnote != NULL) { - noteplay++; - if(subnote->ready != 0) - subnote->noteout(&tmpoutl[0], &tmpoutr[0]); - else - for(i = 0; i < SOUND_BUFFER_SIZE; i++) { - tmpoutl[i] = 0.0; - tmpoutr[i] = 0.0; - } - ; - - for(i = 0; i < SOUND_BUFFER_SIZE; i++) { //add the SUBnote to part(mix) - partfxinputl[sendcurrenttofx][i] += tmpoutl[i]; - partfxinputr[sendcurrenttofx][i] += tmpoutr[i]; - } - if(subnote->finished() != 0) { - delete (subnote); - partnote[k].kititem[item].subnote = NULL; - } - } - //get from the PADnote - if(padnote != NULL) { - noteplay++; - if(padnote->ready != 0) - padnote->noteout(&tmpoutl[0], &tmpoutr[0]); - else - for(i = 0; i < SOUND_BUFFER_SIZE; i++) { - tmpoutl[i] = 0.0; - tmpoutr[i] = 0.0; - } - ; - if(padnote->finished() != 0) { - delete (padnote); - partnote[k].kititem[item].padnote = NULL; - } - for(i = 0; i < SOUND_BUFFER_SIZE; i++) { //add the PADnote to part(mix) - partfxinputl[sendcurrenttofx][i] += tmpoutl[i]; - partfxinputr[sendcurrenttofx][i] += tmpoutr[i]; - } - } - } - //Kill note if there is no synth on that note - if(noteplay == 0) - KillNotePos(k); - } - - - //Apply part's effects and mix them - for(int nefx = 0; nefx < NUM_PART_EFX; nefx++) { - if(!Pefxbypass[nefx]) { - partefx[nefx]->out(partfxinputl[nefx], partfxinputr[nefx]); - if(Pefxroute[nefx] == 2) { - for(i = 0; i < SOUND_BUFFER_SIZE; i++) { - partfxinputl[nefx + 1][i] += partefx[nefx]->efxoutl[i]; - partfxinputr[nefx + 1][i] += partefx[nefx]->efxoutr[i]; - } - } - } - int routeto = ((Pefxroute[nefx] == 0) ? nefx + 1 : NUM_PART_EFX); - for(i = 0; i < SOUND_BUFFER_SIZE; i++) { - partfxinputl[routeto][i] += partfxinputl[nefx][i]; - partfxinputr[routeto][i] += partfxinputr[nefx][i]; - } - } - for(i = 0; i < SOUND_BUFFER_SIZE; i++) { - partoutl[i] = partfxinputl[NUM_PART_EFX][i]; - partoutr[i] = partfxinputr[NUM_PART_EFX][i]; - } - - //Kill All Notes if killallnotes!=0 - if(killallnotes != 0) { - for(i = 0; i < SOUND_BUFFER_SIZE; i++) { - REALTYPE tmp = - (SOUND_BUFFER_SIZE - i) / (REALTYPE) SOUND_BUFFER_SIZE; - partoutl[i] *= tmp; - partoutr[i] *= tmp; - tmpoutl[i] = 0.0; - tmpoutr[i] = 0.0; - } - for(int k = 0; k < POLIPHONY; k++) - KillNotePos(k); - killallnotes = 0; - for(int nefx = 0; nefx < NUM_PART_EFX; nefx++) - partefx[nefx]->cleanup(); - ; - } - ctl.updateportamento(); -} - -/* - * Parameter control - */ -void Part::setPvolume(char Pvolume_) -{ - Pvolume = Pvolume_; - volume = dB2rap((Pvolume - 96.0) / 96.0 * 40.0) * ctl.expression.relvolume; -} - -void Part::setPpanning(char Ppanning_) -{ - Ppanning = Ppanning_; - panning = Ppanning / 127.0 + ctl.panning.pan; - if(panning < 0.0) - panning = 0.0; - else - if(panning > 1.0) - panning = 1.0; -} - -/* - * Enable or disable a kit item - */ -void Part::setkititemstatus(int kititem, int Penabled_) -{ - if((kititem == 0) || (kititem >= NUM_KIT_ITEMS)) - return; //nonexistent kit item and the first kit item is always enabled - kit[kititem].Penabled = Penabled_; - - bool resetallnotes = false; - if(Penabled_ == 0) { - if(kit[kititem].adpars != NULL) - delete (kit[kititem].adpars); - if(kit[kititem].subpars != NULL) - delete (kit[kititem].subpars); - if(kit[kititem].padpars != NULL) { - delete (kit[kititem].padpars); - resetallnotes = true; - } - kit[kititem].adpars = NULL; - kit[kititem].subpars = NULL; - kit[kititem].padpars = NULL; - kit[kititem].Pname[0] = '\0'; - } - else { - if(kit[kititem].adpars == NULL) - kit[kititem].adpars = new ADnoteParameters(fft); - if(kit[kititem].subpars == NULL) - kit[kititem].subpars = new SUBnoteParameters(); - if(kit[kititem].padpars == NULL) - kit[kititem].padpars = new PADnoteParameters(fft, mutex); - } - - if(resetallnotes) - for(int k = 0; k < POLIPHONY; k++) - KillNotePos(k); -} - - - -void Part::add2XMLinstrument(XMLwrapper *xml) -{ - xml->beginbranch("INFO"); - xml->addparstr("name", (char *)Pname); - xml->addparstr("author", (char *)info.Pauthor); - xml->addparstr("comments", (char *)info.Pcomments); - xml->addpar("type", info.Ptype); - xml->endbranch(); - - - xml->beginbranch("INSTRUMENT_KIT"); - xml->addpar("kit_mode", Pkitmode); - xml->addparbool("drum_mode", Pdrummode); - - for(int i = 0; i < NUM_KIT_ITEMS; i++) { - xml->beginbranch("INSTRUMENT_KIT_ITEM", i); - xml->addparbool("enabled", kit[i].Penabled); - if(kit[i].Penabled != 0) { - xml->addparstr("name", (char *)kit[i].Pname); - - xml->addparbool("muted", kit[i].Pmuted); - xml->addpar("min_key", kit[i].Pminkey); - xml->addpar("max_key", kit[i].Pmaxkey); - - xml->addpar("send_to_instrument_effect", kit[i].Psendtoparteffect); - - xml->addparbool("add_enabled", kit[i].Padenabled); - if((kit[i].Padenabled != 0) && (kit[i].adpars != NULL)) { - xml->beginbranch("ADD_SYNTH_PARAMETERS"); - kit[i].adpars->add2XML(xml); - xml->endbranch(); - } - - xml->addparbool("sub_enabled", kit[i].Psubenabled); - if((kit[i].Psubenabled != 0) && (kit[i].subpars != NULL)) { - xml->beginbranch("SUB_SYNTH_PARAMETERS"); - kit[i].subpars->add2XML(xml); - xml->endbranch(); - } - - xml->addparbool("pad_enabled", kit[i].Ppadenabled); - if((kit[i].Ppadenabled != 0) && (kit[i].padpars != NULL)) { - xml->beginbranch("PAD_SYNTH_PARAMETERS"); - kit[i].padpars->add2XML(xml); - xml->endbranch(); - } - } - xml->endbranch(); - } - xml->endbranch(); - - xml->beginbranch("INSTRUMENT_EFFECTS"); - for(int nefx = 0; nefx < NUM_PART_EFX; nefx++) { - xml->beginbranch("INSTRUMENT_EFFECT", nefx); - xml->beginbranch("EFFECT"); - partefx[nefx]->add2XML(xml); - xml->endbranch(); - - xml->addpar("route", Pefxroute[nefx]); - partefx[nefx]->setdryonly(Pefxroute[nefx] == 2); - xml->addparbool("bypass", Pefxbypass[nefx]); - xml->endbranch(); - } - xml->endbranch(); -} - - -void Part::add2XML(XMLwrapper *xml) -{ - //parameters - xml->addparbool("enabled", Penabled); - if((Penabled == 0) && (xml->minimal)) - return; - - xml->addpar("volume", Pvolume); - xml->addpar("panning", Ppanning); - - xml->addpar("min_key", Pminkey); - xml->addpar("max_key", Pmaxkey); - xml->addpar("key_shift", Pkeyshift); - xml->addpar("rcv_chn", Prcvchn); - - xml->addpar("velocity_sensing", Pvelsns); - xml->addpar("velocity_offset", Pveloffs); - - xml->addparbool("note_on", Pnoteon); - xml->addparbool("poly_mode", Ppolymode); - xml->addpar("legato_mode", Plegatomode); - xml->addpar("key_limit", Pkeylimit); - - xml->beginbranch("INSTRUMENT"); - add2XMLinstrument(xml); - xml->endbranch(); - - xml->beginbranch("CONTROLLER"); - ctl.add2XML(xml); - xml->endbranch(); -} - -int Part::saveXML(char *filename) -{ - XMLwrapper *xml; - xml = new XMLwrapper(); - - xml->beginbranch("INSTRUMENT"); - add2XMLinstrument(xml); - xml->endbranch(); - - int result = xml->saveXMLfile(filename); - delete (xml); - return result; -} - -int Part::loadXMLinstrument(const char *filename) -{ - XMLwrapper *xml = new XMLwrapper(); - if(xml->loadXMLfile(filename) < 0) { - delete (xml); - return -1; - } - - if(xml->enterbranch("INSTRUMENT") == 0) - return -10; - getfromXMLinstrument(xml); - xml->exitbranch(); - - delete (xml); - return 0; -} - - -void Part::applyparameters() -{ - for(int n = 0; n < NUM_KIT_ITEMS; n++) - if((kit[n].padpars != NULL) && (kit[n].Ppadenabled != 0)) - kit[n].padpars->applyparameters(true); - ; -} - -void Part::getfromXMLinstrument(XMLwrapper *xml) -{ - if(xml->enterbranch("INFO")) { - xml->getparstr("name", (char *)Pname, PART_MAX_NAME_LEN); - xml->getparstr("author", (char *)info.Pauthor, MAX_INFO_TEXT_SIZE); - xml->getparstr("comments", (char *)info.Pcomments, MAX_INFO_TEXT_SIZE); - info.Ptype = xml->getpar("type", info.Ptype, 0, 16); - - xml->exitbranch(); - } - - if(xml->enterbranch("INSTRUMENT_KIT")) { - Pkitmode = xml->getpar127("kit_mode", Pkitmode); - Pdrummode = xml->getparbool("drum_mode", Pdrummode); - - setkititemstatus(0, 0); - for(int i = 0; i < NUM_KIT_ITEMS; i++) { - if(xml->enterbranch("INSTRUMENT_KIT_ITEM", i) == 0) - continue; - setkititemstatus(i, xml->getparbool("enabled", kit[i].Penabled)); - if(kit[i].Penabled == 0) { - xml->exitbranch(); - continue; - } - - xml->getparstr("name", (char *)kit[i].Pname, PART_MAX_NAME_LEN); - - kit[i].Pmuted = xml->getparbool("muted", kit[i].Pmuted); - kit[i].Pminkey = xml->getpar127("min_key", kit[i].Pminkey); - kit[i].Pmaxkey = xml->getpar127("max_key", kit[i].Pmaxkey); - - kit[i].Psendtoparteffect = xml->getpar127( - "send_to_instrument_effect", - kit[i].Psendtoparteffect); - - kit[i].Padenabled = xml->getparbool("add_enabled", - kit[i].Padenabled); - if(xml->enterbranch("ADD_SYNTH_PARAMETERS")) { - kit[i].adpars->getfromXML(xml); - xml->exitbranch(); - } - - kit[i].Psubenabled = xml->getparbool("sub_enabled", - kit[i].Psubenabled); - if(xml->enterbranch("SUB_SYNTH_PARAMETERS")) { - kit[i].subpars->getfromXML(xml); - xml->exitbranch(); - } - - kit[i].Ppadenabled = xml->getparbool("pad_enabled", - kit[i].Ppadenabled); - if(xml->enterbranch("PAD_SYNTH_PARAMETERS")) { - kit[i].padpars->getfromXML(xml); - xml->exitbranch(); - } - - xml->exitbranch(); - } - - xml->exitbranch(); - } - - - if(xml->enterbranch("INSTRUMENT_EFFECTS")) { - for(int nefx = 0; nefx < NUM_PART_EFX; nefx++) { - if(xml->enterbranch("INSTRUMENT_EFFECT", nefx) == 0) - continue; - if(xml->enterbranch("EFFECT")) { - partefx[nefx]->getfromXML(xml); - xml->exitbranch(); - } - - Pefxroute[nefx] = xml->getpar("route", - Pefxroute[nefx], - 0, - NUM_PART_EFX); - partefx[nefx]->setdryonly(Pefxroute[nefx] == 2); - Pefxbypass[nefx] = xml->getparbool("bypass", Pefxbypass[nefx]); - xml->exitbranch(); - } - xml->exitbranch(); - } -} - -void Part::getfromXML(XMLwrapper *xml) -{ - Penabled = xml->getparbool("enabled", Penabled); - - setPvolume(xml->getpar127("volume", Pvolume)); - setPpanning(xml->getpar127("panning", Ppanning)); - - Pminkey = xml->getpar127("min_key", Pminkey); - Pmaxkey = xml->getpar127("max_key", Pmaxkey); - Pkeyshift = xml->getpar127("key_shift", Pkeyshift); - Prcvchn = xml->getpar127("rcv_chn", Prcvchn); - - Pvelsns = xml->getpar127("velocity_sensing", Pvelsns); - Pveloffs = xml->getpar127("velocity_offset", Pveloffs); - - Pnoteon = xml->getparbool("note_on", Pnoteon); - Ppolymode = xml->getparbool("poly_mode", Ppolymode); - Plegatomode = xml->getparbool("legato_mode", Plegatomode); //older versions - if(!Plegatomode) - Plegatomode = xml->getpar127("legato_mode", Plegatomode); - Pkeylimit = xml->getpar127("key_limit", Pkeylimit); - - - if(xml->enterbranch("INSTRUMENT")) { - getfromXMLinstrument(xml); - xml->exitbranch(); - } - - if(xml->enterbranch("CONTROLLER")) { - ctl.getfromXML(xml); - xml->exitbranch(); - } -} - diff --git a/plugins/zynaddsubfx/src/Misc/Part.h b/plugins/zynaddsubfx/src/Misc/Part.h deleted file mode 100644 index 66169e3e3..000000000 --- a/plugins/zynaddsubfx/src/Misc/Part.h +++ /dev/null @@ -1,206 +0,0 @@ -/* - ZynAddSubFX - a software synthesizer - - Part.h - Part implementation - Copyright (C) 2002-2005 Nasca Octavian Paul - Author: Nasca Octavian Paul - - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License - as published by the Free Software Foundation. - - 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 (version 2 or later) for more details. - - You should have received a copy of the GNU General Public License (version 2) - along with this program; if not, write to the Free Software Foundation, - Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -*/ - -#ifndef PART_H -#define PART_H - -#define MAX_INFO_TEXT_SIZE 1000 - -#include "../globals.h" -#include "../Params/ADnoteParameters.h" -#include "../Params/SUBnoteParameters.h" -#include "../Params/PADnoteParameters.h" -#include "../Synth/ADnote.h" -#include "../Synth/SUBnote.h" -#include "../Synth/PADnote.h" -#include "../Params/Controller.h" -#include "../Misc/Microtonal.h" -#include "../DSP/FFTwrapper.h" -#include "../Effects/EffectMgr.h" -#include "XMLwrapper.h" - -#include // For the monomemnotes list. - -/** Part implementation*/ -class Part -{ - public: - /**Constructor - * @param microtonal_ Pointer to the microtonal object - * @param fft_ Pointer to the FFTwrapper - * @param mutex_ Pointer to the master pthread_mutex_t*/ - Part(Microtonal *microtonal_, FFTwrapper *fft_, pthread_mutex_t *mutex_); - /**Destructor*/ - ~Part(); - - // Midi commands implemented - void NoteOn(unsigned char note, - unsigned char velocity, - int masterkeyshift); - void NoteOff(unsigned char note); - void AllNotesOff(); //panic - void SetController(unsigned int type, int par); - void RelaseSustainedKeys(); //this is called when the sustain pedal is relased - void RelaseAllKeys(); //this is called on AllNotesOff controller - - /* The synthesizer part output */ - void ComputePartSmps(); //Part output - - //instrumentonly: 0 - save all, 1 - save only instrumnet, 2 - save only instrument without the name(used in bank) - - - //saves the instrument settings to a XML file - //returns 0 for ok or <0 if there is an error - int saveXML(char *filename); - int loadXMLinstrument(const char *filename); - - void add2XML(XMLwrapper *xml); - void add2XMLinstrument(XMLwrapper *xml); - - void defaults(); - void defaultsinstrument(); - - void applyparameters(); - - void getfromXML(XMLwrapper *xml); - void getfromXMLinstrument(XMLwrapper *xml); - - void cleanup(); - -// ADnoteParameters *ADPartParameters; -// SUBnoteParameters *SUBPartParameters; - - //the part's kit - struct { - unsigned char Penabled, Pmuted, Pminkey, Pmaxkey; - unsigned char *Pname; - unsigned char Padenabled, Psubenabled, Ppadenabled; - unsigned char Psendtoparteffect; - ADnoteParameters *adpars; - SUBnoteParameters *subpars; - PADnoteParameters *padpars; - } kit[NUM_KIT_ITEMS]; - - - //Part parameters - void setkeylimit(unsigned char Pkeylimit); - void setkititemstatus(int kititem, int Penabled_); - - unsigned char Penabled; /** monomemnotes; // A list to remember held notes. - struct { - unsigned char velocity; - int mkeyshift; // I'm not sure masterkeyshift should be remembered. - } monomem[256]; /* 256 is to cover all possible note values. - monomem[] is used in conjunction with the list to - store the velocity and masterkeyshift values of a - given note (the list only store note values). - For example 'monomem[note].velocity' would be the - velocity value of the note 'note'. - */ - - PartNotes partnote[POLIPHONY]; - - REALTYPE *tmpoutl; //used to get the note - REALTYPE *tmpoutr; - - REALTYPE oldfreq; //this is used for portamento - Microtonal *microtonal; - FFTwrapper *fft; -}; - -#endif - diff --git a/plugins/zynaddsubfx/src/Misc/QtXmlWrapper.cpp b/plugins/zynaddsubfx/src/Misc/QtXmlWrapper.cpp deleted file mode 100644 index a329e043a..000000000 --- a/plugins/zynaddsubfx/src/Misc/QtXmlWrapper.cpp +++ /dev/null @@ -1,550 +0,0 @@ -/* - * QtXmlWrapper.cpp - a QtXml based XML backend for ZynAddSubxFX - * - * Copyright (c) 2009 Tobias Doerffel - * - * This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net - * - * 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. - * - */ - -/* File derived from QtXmlWrapper.C: */ -/* - ZynAddSubFX - a software synthesizer - - QtXmlWrapper.C - XML wrapper - Copyright (C) 2003-2005 Nasca Octavian Paul - Copyright (C) 2009-2009 Mark McCurry - Author: Nasca Octavian Paul - Mark McCurry - - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License - as published by the Free Software Foundation. - - 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 (version 2 or later) for more details. - - You should have received a copy of the GNU General Public License (version 2) - along with this program; if not, write to the Free Software Foundation, - Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -*/ - -#include -#include -#include "QtXmlWrapper.h" -#include -#include -#include -#include -#include "lmmsconfig.h" -#include "../globals.h" -#include "Util.h" - - -struct XmlData -{ - XmlData() : - m_doc( "ZynAddSubFX-data" ) - { - } - QDomDocument m_doc; - QDomElement m_node; - QDomElement m_info; - - QDomElement addparams( const char *name, unsigned int params, ... ); -} ; - - - -QtXmlWrapper::QtXmlWrapper() : - d( new XmlData ) -{ - version.Major = 2; - version.Minor = 4; - version.Revision = 1; - - minimal = true; - - d->m_node = d->m_doc.createElement( "ZynAddSubFX-data" ); - d->m_node.setAttribute( "version-major", QString::number( version.Major ) ); - d->m_node.setAttribute( "version-minor", QString::number( version.Minor ) ); - d->m_node.setAttribute( "version-revision", QString::number( version.Revision ) ); - d->m_node.setAttribute( "ZynAddSubFX-author", "Nasca Octavian Paul" ); - d->m_doc.appendChild( d->m_node ); - - //make the empty branch that will contain the information parameters - d->m_info = d->addparams("INFORMATION", 0); - - //save zynaddsubfx specifications - beginbranch("BASE_PARAMETERS"); - addpar("max_midi_parts", NUM_MIDI_PARTS); - addpar("max_kit_items_per_instrument", NUM_KIT_ITEMS); - - addpar("max_system_effects", NUM_SYS_EFX); - addpar("max_insertion_effects", NUM_INS_EFX); - addpar("max_instrument_effects", NUM_PART_EFX); - - addpar("max_addsynth_voices", NUM_VOICES); - endbranch(); -} - - - - -QtXmlWrapper::~QtXmlWrapper() -{ - delete d; -} - - - - -void QtXmlWrapper::setPadSynth(bool enabled) -{ - /**@bug this might create multiple nodes when only one is needed*/ - QDomElement oldNode = d->m_node; - d->m_node = d->m_info; - //Info storing - addparbool("PADsynth_used", enabled); - d->m_node = oldNode; -} - -QDomElement findElement( QDomElement root, const QString & tagname, const QString & attrname, - const QString & attrval ) -{ - QDomNodeList list = root.elementsByTagName( tagname ); - for( int i = 0; i < list.size(); ++i ) - { - QDomNode n = list.at( i ); - if( n.isElement() ) - { - QDomElement e = n.toElement(); - if( e.hasAttribute( attrname ) && e.attribute( attrname ) == attrval ) - { - return e; - } - } - } - - return QDomElement(); -} - - - - -bool QtXmlWrapper::hasPadSynth() const -{ - /**Right now this has a copied implementation of setparbool, so this should - * be reworked as XMLwrapper evolves*/ - QDomElement tmp = d->m_doc.elementsByTagName( "INFORMATION" ).at( 0 ).toElement(); - QDomElement parameter = findElement( tmp, "par_bool", "name", "PADsynth_used" ); - if( !parameter.isNull() ) - { - const QString val = parameter.attribute( "value" ).toLower(); - return val[0] == 'y'; - } - return false; -} - - -/* SAVE XML members */ - -int QtXmlWrapper::saveXMLfile(const std::string &filename) const -{ - char *xmldata = getXMLdata(); - if(xmldata == NULL) - return -2; - - int compression = config.cfg.GzipCompression; - int result = dosavefile(filename.c_str(), compression, xmldata); - - delete[] xmldata; - return result; -} - - -char *QtXmlWrapper::getXMLdata() const -{ - QString xml = d->m_doc.toString( 1 ); - return qstrdup( xml.toUtf8().constData() ); -} - - -int QtXmlWrapper::dosavefile(const char *filename, - int compression, - const char *xmldata) const -{ - if(compression == 0) { - FILE *file; - file = fopen(filename, "w"); - if(file == NULL) - return -1; - fputs(xmldata, file); - fclose(file); - } - else { - if(compression > 9) - compression = 9; - if(compression < 1) - compression = 1; - char options[10]; - snprintf(options, 10, "wb%d", compression); - - gzFile gzfile; - gzfile = gzopen(filename, options); - if(gzfile == NULL) - return -1; - gzputs(gzfile, xmldata); - gzclose(gzfile); - } - - return 0; -} - - - -void QtXmlWrapper::addpar(const std::string &name, int val) -{ - d->addparams("par", 2, "name", name.c_str(), "value", stringFrom( - val).c_str()); -} - -void QtXmlWrapper::addparreal(const std::string &name, REALTYPE val) -{ - d->addparams("par_real", 2, "name", name.c_str(), "value", - stringFrom(val).c_str()); -} - -void QtXmlWrapper::addparbool(const std::string &name, int val) -{ - if(val != 0) - d->addparams("par_bool", 2, "name", name.c_str(), "value", "yes"); - else - d->addparams("par_bool", 2, "name", name.c_str(), "value", "no"); -} - -void QtXmlWrapper::addparstr(const std::string &name, const std::string &val) -{ - QDomElement e = d->m_doc.createElement( "string" ); - e.setAttribute( "name", name.c_str() ); - e.appendChild( d->m_doc.createTextNode( val.c_str() ) ); - d->m_node.appendChild( e ); -} - - -void QtXmlWrapper::beginbranch(const std::string &name) -{ - d->m_node = d->addparams(name.c_str(), 0); -} - -void QtXmlWrapper::beginbranch(const std::string &name, int id) -{ - d->m_node = d->addparams(name.c_str(), 1, "id", stringFrom(id).c_str()); -} - -void QtXmlWrapper::endbranch() -{ - d->m_node = d->m_node.parentNode().toElement(); -} - - - -/* LOAD XML members */ - -int QtXmlWrapper::loadXMLfile(const std::string &filename) -{ - const char *xmldata = doloadfile(filename.c_str()); - if(xmldata == NULL) - { - qDebug() << "QtXmlWrapper::loadXMLfile(): empty data"; - return -1; //the file could not be loaded or uncompressed - } - - QByteArray b( xmldata ); - while( !b.isEmpty() && b[0] != '<' ) - { - // remove first blank line - b.remove( 0, 1 ); - } - - if( !d->m_doc.setContent( b ) ) - { - qDebug() << "QtXmlWrapper::loadXMLfile(): could not set document content"; - delete[] xmldata; - return -2; - } - delete[] xmldata; - - d->m_node = d->m_doc.elementsByTagName( "ZynAddSubFX-data" ).at( 0 ).toElement(); - if( d->m_node.isNull() || !d->m_node.isElement() ) - { - qDebug() << "QtXmlWrapper::loadXMLfile(): missing root node"; - return -3; //the XML doesnt embbed zynaddsubfx data - } - QDomElement root = d->m_node.toElement(); - //fetch version information - version.Major = root.attribute( "version-major").toInt(); - version.Minor = root.attribute( "version-minor").toInt(); - version.Revision = root.attribute( "version-revision").toInt(); - - return 0; -} - - -char *QtXmlWrapper::doloadfile(const std::string &filename) const -{ - char *xmldata = NULL; - gzFile gzfile = gzopen(filename.c_str(), "rb"); - - if(gzfile != NULL) { //The possibly compressed file opened - std::stringstream strBuf; //reading stream - const int bufSize = 500; //fetch size - char fetchBuf[bufSize + 1]; //fetch buffer - int read = 0; //chars read in last fetch - - fetchBuf[bufSize] = 0; //force null termination - - while(bufSize == (read = gzread(gzfile, fetchBuf, bufSize))) - strBuf << fetchBuf; - - fetchBuf[read] = 0; //Truncate last partial read - strBuf << fetchBuf; - - gzclose(gzfile); - - //Place data in output format - std::string tmp = strBuf.str(); - xmldata = new char[tmp.size() + 1]; - strncpy(xmldata, tmp.c_str(), tmp.size() + 1); - } - - return xmldata; -} - -bool QtXmlWrapper::putXMLdata(const char *xmldata) -{ - d->m_doc.setContent( QString::fromUtf8( xmldata ) ); - - d->m_node = d->m_doc.elementsByTagName( "ZynAddSubFX-data" ).at( 0 ).toElement(); - if( d->m_node.isNull() ) - { - return false; - } - - return true; -} - - - -int QtXmlWrapper::enterbranch(const std::string &name) -{ - QDomElement tmp = d->m_node.firstChildElement( name.c_str() ); - if( tmp.isNull() ) - { - return 0; - } - - d->m_node = tmp; - - return 1; -} - -int QtXmlWrapper::enterbranch(const std::string &name, int id) -{ - QDomElement tmp = findElement( d->m_node, name.c_str(), - "id", QString::number( id ) ); - if( tmp.isNull() ) - { - return 0; - } - - d->m_node = tmp; - - return 1; -} - - -void QtXmlWrapper::exitbranch() -{ - d->m_node = d->m_node.parentNode().toElement(); -} - - -int QtXmlWrapper::getbranchid(int min, int max) const -{ - if( !d->m_node.isElement() ) - { - return min; - } - QDomElement tmp = d->m_node.toElement(); - if( !tmp.hasAttribute( "id" ) ) - { - return min; - } - int id = tmp.attribute( "id" ).toInt(); - if((min == 0) && (max == 0)) - return id; - - if(id < min) - id = min; - else - if(id > max) - id = max; - - return id; -} - -int QtXmlWrapper::getpar(const std::string &name, int defaultpar, int min, - int max) const -{ - QDomElement tmp = findElement( d->m_node, "par", "name", name.c_str() ); - if( tmp.isNull() || !tmp.hasAttribute( "value" ) ) - { - return defaultpar; - } - - int val = tmp.attribute( "value" ).toInt(); - if(val < min) - val = min; - else - if(val > max) - val = max; - - return val; -} - -int QtXmlWrapper::getpar127(const std::string &name, int defaultpar) const -{ - return getpar(name, defaultpar, 0, 127); -} - -int QtXmlWrapper::getparbool(const std::string &name, int defaultpar) const -{ - QDomElement tmp = findElement( d->m_node, "par_bool", "name", name.c_str() ); - if( tmp.isNull() || !tmp.hasAttribute( "value" ) ) - { - return defaultpar; - } - - const QString val = tmp.attribute( "value" ).toLower(); - if( val[0] == 'y' ) - { - return 1; - } - return 0; -} - -void QtXmlWrapper::getparstr(const std::string &name, char *par, int maxstrlen) const -{ - ZERO(par, maxstrlen); - QDomNode tmp = findElement( d->m_node, "string", "name", name.c_str() ); - if( tmp.isNull() || !tmp.hasChildNodes() ) - { - return; - } - - tmp = tmp.firstChild(); - if( tmp.nodeType() == QDomNode::ElementNode ) - { - snprintf(par, maxstrlen, "%s", tmp.toElement().tagName().toUtf8().constData() ); - return; - } - if( tmp.nodeType() == QDomNode::TextNode ) - { - snprintf(par, maxstrlen, "%s", tmp.toText().data().toUtf8().constData() ); - return; - } -} - -std::string QtXmlWrapper::getparstr(const std::string &name, - const std::string &defaultpar) const -{ - QDomNode tmp = findElement( d->m_node, "string", "name", name.c_str() ); - if( tmp.isNull() || !tmp.hasChildNodes() ) - { - return defaultpar; - } - - tmp = tmp.firstChild(); - if( tmp.nodeType() == QDomNode::ElementNode && !tmp.toElement().tagName().isEmpty() ) - { - return tmp.toElement().tagName().toUtf8().constData(); - } - if( tmp.nodeType() == QDomNode::TextNode && !tmp.toText().data().isEmpty() ) - { - return tmp.toText().data().toUtf8().constData(); - } - - return defaultpar; -} - -REALTYPE QtXmlWrapper::getparreal(const char *name, REALTYPE defaultpar) const -{ - QDomElement tmp = findElement( d->m_node, "par_real", "name", name ); - if( tmp.isNull() || !tmp.hasAttribute( "value" ) ) - { - return defaultpar; - } - - return tmp.attribute( "value" ).toFloat(); -} - -REALTYPE QtXmlWrapper::getparreal(const char *name, - REALTYPE defaultpar, - REALTYPE min, - REALTYPE max) const -{ - REALTYPE result = getparreal(name, defaultpar); - - if(result < min) - result = min; - else - if(result > max) - result = max; - return result; -} - - -/** Private members **/ - -QDomElement XmlData::addparams(const char *name, unsigned int params, - ...) -{ - /**@todo make this function send out a good error message if something goes - * wrong**/ - QDomElement element = m_doc.createElement( name ); - m_node.appendChild( element ); - - if(params) { - va_list variableList; - va_start(variableList, params); - - const char *ParamName; - const char *ParamValue; - while(params--) { - ParamName = va_arg(variableList, const char *); - ParamValue = va_arg(variableList, const char *); - element.setAttribute( ParamName, ParamValue); - } - } - return element; -} - diff --git a/plugins/zynaddsubfx/src/Misc/QtXmlWrapper.h b/plugins/zynaddsubfx/src/Misc/QtXmlWrapper.h deleted file mode 100644 index 0f478dd97..000000000 --- a/plugins/zynaddsubfx/src/Misc/QtXmlWrapper.h +++ /dev/null @@ -1,125 +0,0 @@ -/* - * QtXmlWrapper.h - a QtXml based XML backend for ZynAddSubxFX - * - * Copyright (c) 2009 Tobias Doerffel - * - * This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net - * - * 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. - * - */ - -/* File derived from XMLwrapper.h: */ -/* - ZynAddSubFX - a software synthesizer - - XMLwrapper.h - XML wrapper - Copyright (C) 2003-2005 Nasca Octavian Paul - Copyright (C) 2009-2009 Mark McCurry - Author: Nasca Octavian Paul - Mark McCurry - - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License - as published by the Free Software Foundation. - - 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 (version 2 or later) for more details. - - You should have received a copy of the GNU General Public License (version 2) - along with this program; if not, write to the Free Software Foundation, - Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -*/ - -#ifndef QT_XML_WRAPPER_H -#define QT_XML_WRAPPER_H - -#include "../globals.h" - -#include -#include -#include -#include - -#define QtXmlWrapper XMLwrapper - -struct XmlData; - -class QtXmlWrapper -{ -public: - QtXmlWrapper(); - ~QtXmlWrapper(); - - int saveXMLfile( const std::string & filename ) const; - int loadXMLfile( const std::string & filename ); - - char *getXMLdata() const; - bool putXMLdata( const char *xmldata ); - - void addpar( const std::string & name, int val ); - void addparreal( const std::string & name, REALTYPE val); - void addparbool( const std::string & name, int val ); - void addparstr( const std::string & name, const std::string & val ); - - void beginbranch( const std::string & name ); - void beginbranch( const std::string & name, int id ); - void endbranch(); - - - int enterbranch( const std::string & name ); - int enterbranch( const std::string & name, int id ); - void exitbranch(); - int getbranchid( int min, int max ) const; - - int getpar( const std::string & name, int defaultpar, int min, int max ) const; - int getpar127( const std::string & name, int defaultpar ) const; - int getparbool( const std::string & name, int defaultpar ) const; - - void getparstr( const std::string & name, char * par, int maxstrlen ) const; - std::string getparstr( const std::string & name, const std::string & defaultpar ) const; - REALTYPE getparreal( const char * name, REALTYPE defaultpar ) const; - - REALTYPE getparreal(const char *name, REALTYPE defaultpar, REALTYPE min, REALTYPE max) const; - - bool minimal; /** -Stereo::Stereo(const T &left, const T &right) - :l(left), r(right) -{} - -template -Stereo::Stereo(const T &val) - :l(val), r(val) -{} - -template -Stereo &Stereo::operator=(const Stereo &nstr) -{ - l = nstr.l; - r = nstr.r; - return *this; -} - diff --git a/plugins/zynaddsubfx/src/Misc/Stereo.h b/plugins/zynaddsubfx/src/Misc/Stereo.h deleted file mode 100644 index 06ee63c80..000000000 --- a/plugins/zynaddsubfx/src/Misc/Stereo.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - ZynAddSubFX - a software synthesizer - - Stereo.h - Object for storing a pair of objects - Copyright (C) 2009-2009 Mark McCurry - Author: Mark McCurry - - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License - as published by the Free Software Foundation. - - 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 (version 2 or later) for more details. - - You should have received a copy of the GNU General Public License (version 2) - along with this program; if not, write to the Free Software Foundation, - Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ -#ifndef STEREO_H -#define STEREO_H - -template -struct Stereo -{ - public: - Stereo(const T &left, const T &right); - - /**Initializes Stereo with left and right set to val - * @param val the value for both channels*/ - Stereo(const T &val); - ~Stereo() {} - - Stereo &operator=(const Stereo &smp); - - //data - T l, r; -}; -#include "Stereo.cpp" -#endif - diff --git a/plugins/zynaddsubfx/src/Misc/Util.cpp b/plugins/zynaddsubfx/src/Misc/Util.cpp deleted file mode 100644 index a7ea4328d..000000000 --- a/plugins/zynaddsubfx/src/Misc/Util.cpp +++ /dev/null @@ -1,130 +0,0 @@ -/* - ZynAddSubFX - a software synthesizer - - Util.cpp - Miscellaneous functions - Copyright (C) 2002-2005 Nasca Octavian Paul - Author: Nasca Octavian Paul - - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License - as published by the Free Software Foundation. - - 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 (version 2 or later) for more details. - - You should have received a copy of the GNU General Public License (version 2) - along with this program; if not, write to the Free Software Foundation, - Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -*/ - -#include "Util.h" -#include -#include - -#include -#include -#include -#include -#include -#include - -int SAMPLE_RATE = 44100; -int SOUND_BUFFER_SIZE = 256; -int OSCIL_SIZE = 1024; - -Config config; -REALTYPE *denormalkillbuf; - - -/* - * Transform the velocity according the scaling parameter (velocity sensing) - */ -REALTYPE VelF(REALTYPE velocity, unsigned char scaling) -{ - REALTYPE x; - x = pow(VELOCITY_MAX_SCALE, (64.0 - scaling) / 64.0); - if((scaling == 127) || (velocity > 0.99)) - return 1.0; - else - return pow(velocity, x); -} - -/* - * Get the detune in cents - */ -REALTYPE getdetune(unsigned char type, - unsigned short int coarsedetune, - unsigned short int finedetune) -{ - REALTYPE det = 0.0, octdet = 0.0, cdet = 0.0, findet = 0.0; - //Get Octave - int octave = coarsedetune / 1024; - if(octave >= 8) - octave -= 16; - octdet = octave * 1200.0; - - //Coarse and fine detune - int cdetune = coarsedetune % 1024; - if(cdetune > 512) - cdetune -= 1024; - - int fdetune = finedetune - 8192; - - switch(type) { -// case 1: is used for the default (see below) - case 2: - cdet = fabs(cdetune * 10.0); - findet = fabs(fdetune / 8192.0) * 10.0; - break; - case 3: - cdet = fabs(cdetune * 100); - findet = pow(10, fabs(fdetune / 8192.0) * 3.0) / 10.0 - 0.1; - break; - case 4: - cdet = fabs(cdetune * 701.95500087); //perfect fifth - findet = (pow(2, fabs(fdetune / 8192.0) * 12.0) - 1.0) / 4095 * 1200; - break; - //case ...: need to update N_DETUNE_TYPES, if you'll add more - default: - cdet = fabs(cdetune * 50.0); - findet = fabs(fdetune / 8192.0) * 35.0; //almost like "Paul's Sound Designer 2" - break; - } - if(finedetune < 8192) - findet = -findet; - if(cdetune < 0) - cdet = -cdet; - - det = octdet + cdet + findet; - return det; -} - - -bool fileexists(const char *filename) -{ - struct stat tmp; - int result = stat(filename, &tmp); - if(result >= 0) - return true; - - return false; -} - -void invSignal(REALTYPE *sig, size_t len) -{ - for(unsigned int i = 0; i < len; i++) - sig[i] *= -1.0f; -} - -void crossover(REALTYPE &a, REALTYPE &b, REALTYPE crossover) -{ - REALTYPE tmpa = a; - REALTYPE tmpb = b; - a = tmpa * (1.0 - crossover) + tmpb * crossover; - b = tmpb * (1.0 - crossover) + tmpa * crossover; -} - - diff --git a/plugins/zynaddsubfx/src/Misc/Util.h b/plugins/zynaddsubfx/src/Misc/Util.h deleted file mode 100644 index d77f457f4..000000000 --- a/plugins/zynaddsubfx/src/Misc/Util.h +++ /dev/null @@ -1,84 +0,0 @@ -/* - ZynAddSubFX - a software synthesizer - - Util.h - Miscellaneous functions - Copyright (C) 2002-2005 Nasca Octavian Paul - Author: Nasca Octavian Paul - - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License - as published by the Free Software Foundation. - - 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 (version 2 or later) for more details. - - You should have received a copy of the GNU General Public License (version 2) - along with this program; if not, write to the Free Software Foundation, - Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -*/ - -#ifndef UTIL_H -#define UTIL_H - -#include -#include -#include -#include "../globals.h" -#include "Config.h" - -//Velocity Sensing function -extern REALTYPE VelF(REALTYPE velocity, unsigned char scaling); - -bool fileexists(const char *filename); - -#define N_DETUNE_TYPES 4 //the number of detune types -extern REALTYPE getdetune(unsigned char type, - unsigned short int coarsedetune, - unsigned short int finedetune); - -extern REALTYPE *denormalkillbuf; /** -std::string stringFrom(T x) -{ - std::stringstream ss; - ss << x; - return ss.str(); -} - -template -std::string stringFrom(REALTYPE x) -{ - char buf[64]; - sprintf( buf, "%f", x ); - return buf; -} - - -template -T stringTo(const char *x) -{ - std::string str = x != NULL ? x : "0"; //should work for the basic float/int - std::stringstream ss(str); - T ans; - ss >> ans; - return ans; -} - -template -T limit(T val, T min, T max) -{ - return (val < min ? min : (val > max ? max : val)); -} - -#endif - diff --git a/plugins/zynaddsubfx/src/Misc/XMLwrapper.cpp b/plugins/zynaddsubfx/src/Misc/XMLwrapper.cpp deleted file mode 100644 index d3750c47e..000000000 --- a/plugins/zynaddsubfx/src/Misc/XMLwrapper.cpp +++ /dev/null @@ -1,617 +0,0 @@ -/* - ZynAddSubFX - a software synthesizer - - XMLwrapper.cpp - XML wrapper - Copyright (C) 2003-2005 Nasca Octavian Paul - Copyright (C) 2009-2009 Mark McCurry - Author: Nasca Octavian Paul - Mark McCurry - - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License - as published by the Free Software Foundation. - - 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 (version 2 or later) for more details. - - You should have received a copy of the GNU General Public License (version 2) - along with this program; if not, write to the Free Software Foundation, - Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -*/ - -#include "XMLwrapper.h" -#include -#include -#include -#include -#include -#include -#include - -#include "../globals.h" -#include "Util.h" - -using namespace std; - -int xml_k = 0; -bool verbose = false; - -const char *XMLwrapper_whitespace_callback(mxml_node_t *node, int where) -{ - const char *name = node->value.element.name; - - if((where == MXML_WS_BEFORE_OPEN) && (!strcmp(name, "?xml"))) - return NULL; - if((where == MXML_WS_BEFORE_CLOSE) && (!strcmp(name, "string"))) - return NULL; - - if((where == MXML_WS_BEFORE_OPEN) || (where == MXML_WS_BEFORE_CLOSE)) - /* const char *tmp=node->value.element.name; - if (tmp!=NULL) { - if ((strstr(tmp,"par")!=tmp)&&(strstr(tmp,"string")!=tmp)) { - printf("%s ",tmp); - if (where==MXML_WS_BEFORE_OPEN) xml_k++; - if (where==MXML_WS_BEFORE_CLOSE) xml_k--; - if (xml_k>=STACKSIZE) xml_k=STACKSIZE-1; - if (xml_k<0) xml_k=0; - printf("%d\n",xml_k); - printf("\n"); - }; - - }; - int i=0; - for (i=1;i(mxmlFindElement( - const_cast(node), - const_cast(top), - name, attr, value, descend)); -} - -//temporary const overload of mxmlElementGetAttr -const char *mxmlElementGetAttr(const mxml_node_t *node, const char *name) -{ - return mxmlElementGetAttr(const_cast(node), name); -} - -XMLwrapper::XMLwrapper() -{ - version.Major = 2; - version.Minor = 4; - version.Revision = 1; - - minimal = true; - - node = tree = mxmlNewElement(MXML_NO_PARENT, - "?xml version=\"1.0\" encoding=\"UTF-8\"?"); - /* for mxml 2.1 (and older) - tree=mxmlNewElement(MXML_NO_PARENT,"?xml"); - mxmlElementSetAttr(tree,"version","1.0"); - mxmlElementSetAttr(tree,"encoding","UTF-8"); - */ - - mxml_node_t *doctype = mxmlNewElement(tree, "!DOCTYPE"); - mxmlElementSetAttr(doctype, "ZynAddSubFX-data", NULL); - - node = root = addparams("ZynAddSubFX-data", 4, - "version-major", stringFrom( - version.Major).c_str(), - "version-minor", stringFrom( - version.Minor).c_str(), - "version-revision", - stringFrom(version.Revision).c_str(), - "ZynAddSubFX-author", "Nasca Octavian Paul"); - - //make the empty branch that will contain the information parameters - info = addparams("INFORMATION", 0); - - //save zynaddsubfx specifications - beginbranch("BASE_PARAMETERS"); - addpar("max_midi_parts", NUM_MIDI_PARTS); - addpar("max_kit_items_per_instrument", NUM_KIT_ITEMS); - - addpar("max_system_effects", NUM_SYS_EFX); - addpar("max_insertion_effects", NUM_INS_EFX); - addpar("max_instrument_effects", NUM_PART_EFX); - - addpar("max_addsynth_voices", NUM_VOICES); - endbranch(); -} - -XMLwrapper::~XMLwrapper() -{ - if(tree != NULL) - mxmlDelete(tree); -} - -void XMLwrapper::setPadSynth(bool enabled) -{ - /**@bug this might create multiple nodes when only one is needed*/ - mxml_node_t *oldnode = node; - node = info; - //Info storing - addparbool("PADsynth_used", enabled); - node = oldnode; -} - -bool XMLwrapper::hasPadSynth() const -{ - /**Right now this has a copied implementation of setparbool, so this should - * be reworked as XMLwrapper evolves*/ - mxml_node_t *tmp = mxmlFindElement(tree, - tree, - "INFORMATION", - NULL, - NULL, - MXML_DESCEND); - - mxml_node_t *parameter = mxmlFindElement(tmp, - tmp, - "par_bool", - "name", - "PADsynth_used", - MXML_DESCEND_FIRST); - if(parameter == NULL) //no information availiable - return false; - - const char *strval = mxmlElementGetAttr(parameter, "value"); - if(strval == NULL) //no information available - return false; - - if((strval[0] == 'Y') || (strval[0] == 'y')) - return true; - else - return false; -} - - -/* SAVE XML members */ - -int XMLwrapper::saveXMLfile(const string &filename) const -{ - char *xmldata = getXMLdata(); - if(xmldata == NULL) - return -2; - - int compression = config.cfg.GzipCompression; - int result = dosavefile(filename.c_str(), compression, xmldata); - - free(xmldata); - return result; -} - -char *XMLwrapper::getXMLdata() const -{ - xml_k = 0; - - char *xmldata = mxmlSaveAllocString(tree, XMLwrapper_whitespace_callback); - - return xmldata; -} - - -int XMLwrapper::dosavefile(const char *filename, - int compression, - const char *xmldata) const -{ - if(compression == 0) { - FILE *file; - file = fopen(filename, "w"); - if(file == NULL) - return -1; - fputs(xmldata, file); - fclose(file); - } - else { - if(compression > 9) - compression = 9; - if(compression < 1) - compression = 1; - char options[10]; - snprintf(options, 10, "wb%d", compression); - - gzFile gzfile; - gzfile = gzopen(filename, options); - if(gzfile == NULL) - return -1; - gzputs(gzfile, xmldata); - gzclose(gzfile); - } - - return 0; -} - - - -void XMLwrapper::addpar(const string &name, int val) -{ - addparams("par", 2, "name", name.c_str(), "value", stringFrom( - val).c_str()); -} - -void XMLwrapper::addparreal(const string &name, REALTYPE val) -{ - addparams("par_real", 2, "name", name.c_str(), "value", - stringFrom(val).c_str()); -} - -void XMLwrapper::addparbool(const string &name, int val) -{ - if(val != 0) - addparams("par_bool", 2, "name", name.c_str(), "value", "yes"); - else - addparams("par_bool", 2, "name", name.c_str(), "value", "no"); -} - -void XMLwrapper::addparstr(const string &name, const string &val) -{ - mxml_node_t *element = mxmlNewElement(node, "string"); - mxmlElementSetAttr(element, "name", name.c_str()); - mxmlNewText(element, 0, val.c_str()); -} - - -void XMLwrapper::beginbranch(const string &name) -{ - if(verbose) - cout << "beginbranch()" << name << endl; - node = addparams(name.c_str(), 0); -} - -void XMLwrapper::beginbranch(const string &name, int id) -{ - if(verbose) - cout << "beginbranch(" << id << ")" << name << endl; - node = addparams(name.c_str(), 1, "id", stringFrom(id).c_str()); -} - -void XMLwrapper::endbranch() -{ - if(verbose) - cout << "endbranch()" << node << "-" << node->value.element.name - << " To " - << node->parent << "-" << node->parent->value.element.name << endl; - node = node->parent; -} - - - -/* LOAD XML members */ - -int XMLwrapper::loadXMLfile(const string &filename) -{ - if(tree != NULL) - mxmlDelete(tree); - tree = NULL; - - const char *xmldata = doloadfile(filename.c_str()); - if(xmldata == NULL) - return -1; //the file could not be loaded or uncompressed - - root = tree = mxmlLoadString(NULL, xmldata, MXML_OPAQUE_CALLBACK); - - delete [] xmldata; - - if(tree == NULL) - return -2; //this is not XML - - - node = root = mxmlFindElement(tree, - tree, - "ZynAddSubFX-data", - NULL, - NULL, - MXML_DESCEND); - if(root == NULL) - return -3; //the XML doesnt embbed zynaddsubfx data - - //fetch version information - version.Major = stringTo(mxmlElementGetAttr(root, "version-major")); - version.Minor = stringTo(mxmlElementGetAttr(root, "version-minor")); - version.Revision = - stringTo(mxmlElementGetAttr(root, "version-revision")); - - if(verbose) - cout << "loadXMLfile() version: " << version.Major << '.' - << version.Minor << '.' << version.Revision << endl; - - - return 0; -} - - -char *XMLwrapper::doloadfile(const string &filename) const -{ - char *xmldata = NULL; - gzFile gzfile = gzopen(filename.c_str(), "rb"); - - if(gzfile != NULL) { //The possibly compressed file opened - stringstream strBuf; //reading stream - const int bufSize = 500; //fetch size - char fetchBuf[bufSize + 1]; //fetch buffer - int read = 0; //chars read in last fetch - - fetchBuf[bufSize] = 0; //force null termination - - while(bufSize == (read = gzread(gzfile, fetchBuf, bufSize))) - strBuf << fetchBuf; - - fetchBuf[read] = 0; //Truncate last partial read - strBuf << fetchBuf; - - gzclose(gzfile); - - //Place data in output format - string tmp = strBuf.str(); - xmldata = new char[tmp.size() + 1]; - strncpy(xmldata, tmp.c_str(), tmp.size() + 1); - } - - return xmldata; -} - -bool XMLwrapper::putXMLdata(const char *xmldata) -{ - if(tree != NULL) - mxmlDelete(tree); - - tree = NULL; - if(xmldata == NULL) - return false; - - root = tree = mxmlLoadString(NULL, xmldata, MXML_OPAQUE_CALLBACK); - if(tree == NULL) - return false; - - node = root = mxmlFindElement(tree, - tree, - "ZynAddSubFX-data", - NULL, - NULL, - MXML_DESCEND); - if(root == NULL) - return false; - - return true; -} - - - -int XMLwrapper::enterbranch(const string &name) -{ - if(verbose) - cout << "enterbranch() " << name << endl; - mxml_node_t *tmp = mxmlFindElement(node, node, - name.c_str(), NULL, NULL, - MXML_DESCEND_FIRST); - if(tmp == NULL) - return 0; - - node = tmp; - return 1; -} - -int XMLwrapper::enterbranch(const string &name, int id) -{ - if(verbose) - cout << "enterbranch(" << id << ") " << name << endl; - mxml_node_t *tmp = mxmlFindElement(node, node, - name.c_str(), "id", stringFrom( - id).c_str(), MXML_DESCEND_FIRST); - if(tmp == NULL) - return 0; - - node = tmp; - return 1; -} - - -void XMLwrapper::exitbranch() -{ - if(verbose) - cout << "exitbranch()" << node << "-" << node->value.element.name - << " To " - << node->parent << "-" << node->parent->value.element.name << endl; - node = node->parent; -} - - -int XMLwrapper::getbranchid(int min, int max) const -{ - int id = stringTo(mxmlElementGetAttr(node, "id")); - if((min == 0) && (max == 0)) - return id; - - if(id < min) - id = min; - else - if(id > max) - id = max; - - return id; -} - -int XMLwrapper::getpar(const string &name, int defaultpar, int min, - int max) const -{ - const mxml_node_t *tmp = mxmlFindElement(node, - node, - "par", - "name", - name.c_str(), - MXML_DESCEND_FIRST); - - if(tmp == NULL) - return defaultpar; - - const char *strval = mxmlElementGetAttr(tmp, "value"); - if(strval == NULL) - return defaultpar; - - int val = stringTo(strval); - if(val < min) - val = min; - else - if(val > max) - val = max; - - return val; -} - -int XMLwrapper::getpar127(const string &name, int defaultpar) const -{ - return getpar(name, defaultpar, 0, 127); -} - -int XMLwrapper::getparbool(const string &name, int defaultpar) const -{ - const mxml_node_t *tmp = mxmlFindElement(node, - node, - "par_bool", - "name", - name.c_str(), - MXML_DESCEND_FIRST); - - if(tmp == NULL) - return defaultpar; - - const char *strval = mxmlElementGetAttr(tmp, "value"); - if(strval == NULL) - return defaultpar; - - if((strval[0] == 'Y') || (strval[0] == 'y')) - return 1; - else - return 0; -} - -void XMLwrapper::getparstr(const string &name, char *par, int maxstrlen) const -{ - ZERO(par, maxstrlen); - const mxml_node_t *tmp = mxmlFindElement(node, - node, - "string", - "name", - name.c_str(), - MXML_DESCEND_FIRST); - - if(tmp == NULL) - return; - if(tmp->child == NULL) - return; - if(tmp->child->type == MXML_OPAQUE) { - snprintf(par, maxstrlen, "%s", tmp->child->value.element.name); - return; - } - if((tmp->child->type == MXML_TEXT) - && (tmp->child->value.text.string != NULL)) { - snprintf(par, maxstrlen, "%s", tmp->child->value.text.string); - return; - } -} - -string XMLwrapper::getparstr(const string &name, - const std::string &defaultpar) const -{ - const mxml_node_t *tmp = mxmlFindElement(node, - node, - "string", - "name", - name.c_str(), - MXML_DESCEND_FIRST); - - if((tmp == NULL) || (tmp->child == NULL)) - return defaultpar; - - if((tmp->child->type == MXML_OPAQUE) - && (tmp->child->value.element.name != NULL)) - return tmp->child->value.element.name; - - if((tmp->child->type == MXML_TEXT) - && (tmp->child->value.text.string != NULL)) - return tmp->child->value.text.string; - - return defaultpar; -} - -REALTYPE XMLwrapper::getparreal(const char *name, REALTYPE defaultpar) const -{ - const mxml_node_t *tmp = mxmlFindElement(node, - node, - "par_real", - "name", - name, - MXML_DESCEND_FIRST); - if(tmp == NULL) - return defaultpar; - - const char *strval = mxmlElementGetAttr(tmp, "value"); - if(strval == NULL) - return defaultpar; - - return stringTo(strval); -} - -REALTYPE XMLwrapper::getparreal(const char *name, - REALTYPE defaultpar, - REALTYPE min, - REALTYPE max) const -{ - REALTYPE result = getparreal(name, defaultpar); - - if(result < min) - result = min; - else - if(result > max) - result = max; - return result; -} - - -/** Private members **/ - -mxml_node_t *XMLwrapper::addparams(const char *name, unsigned int params, - ...) const -{ - /**@todo make this function send out a good error message if something goes - * wrong**/ - mxml_node_t *element = mxmlNewElement(node, name); - - if(params) { - va_list variableList; - va_start(variableList, params); - - const char *ParamName; - const char *ParamValue; - while(params--) { - ParamName = va_arg(variableList, const char *); - ParamValue = va_arg(variableList, const char *); - if(verbose) - cout << "addparams()[" << params << "]=" << name << " " - << ParamName << "=\"" << ParamValue << "\"" << endl; - mxmlElementSetAttr(element, ParamName, ParamValue); - } - } - return element; -} - diff --git a/plugins/zynaddsubfx/src/Misc/XMLwrapper.h b/plugins/zynaddsubfx/src/Misc/XMLwrapper.h deleted file mode 100644 index 997ac933b..000000000 --- a/plugins/zynaddsubfx/src/Misc/XMLwrapper.h +++ /dev/null @@ -1,275 +0,0 @@ -/* - ZynAddSubFX - a software synthesizer - - XMLwrapper.h - XML wrapper - Copyright (C) 2003-2005 Nasca Octavian Paul - Copyright (C) 2009-2009 Mark McCurry - Author: Nasca Octavian Paul - Mark McCurry - - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License - as published by the Free Software Foundation. - - 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 (version 2 or later) for more details. - - You should have received a copy of the GNU General Public License (version 2) - along with this program; if not, write to the Free Software Foundation, - Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -*/ - -#if 1 -#include "QtXmlWrapper.h" -#else -#include -#include -#ifndef REALTYPE -#define REALTYPE float -#endif - -#ifndef XML_WRAPPER_H -#define XML_WRAPPER_H - -/**Mxml wrapper*/ -class XMLwrapper -{ - public: - /** - * Constructor. - * Will Construct the object and fill in top level branch - * */ - XMLwrapper(); - - /**Destructor*/ - ~XMLwrapper(); - - /** - * Saves the XML to a file. - * @param filename the name of the destination file. - * @returns 0 if ok or -1 if the file cannot be saved. - */ - int saveXMLfile(const std::string &filename) const; - - /** - * Return XML tree as a string. - * Note: The string must be freed with free() to deallocate - * @returns a newly allocated NULL terminated string of the XML data. - */ - char *getXMLdata() const; - - /** - * Add simple parameter. - * @param name The name of the mXML node. - * @param val The string value of the mXml node - */ - void addpar(const std::string &name, int val); - - /** - * Adds a realtype parameter. - * @param name The name of the mXML node. - * @param val The REALTYPE value of the node. - */ - void addparreal(const std::string &name, REALTYPE val); - - /** - * Add boolean parameter. - * \todo Fix this reverse boolean logic. - * @param name The name of the mXML node. - * @param val The boolean value of the node (0->"yes";else->"no"). - */ - void addparbool(const std::string &name, int val); - - /** - * Add string parameter. - * @param name The name of the mXML node. - * @param val The string value of the node. - */ - void addparstr(const std::string &name, const std::string &val); - - /** - * Create a new branch. - * @param name Name of new branch - * @see void endbranch() - */ - void beginbranch(const std::string &name); - /** - * Create a new branch. - * @param name Name of new branch - * @param id "id" value of branch - * @see void endbranch() - */ - void beginbranch(const std::string &name, int id); - - /**Closes new branches. - * This must be called to exit each branch created by beginbranch( ). - * @see void beginbranch(const std::string &name) - * @see void beginbranch(const std::string &name, int id) - */ - void endbranch(); - - /** - * Loads file into XMLwrapper. - * @param filename file to be loaded - * @returns 0 if ok or -1 if the file cannot be loaded - */ - int loadXMLfile(const std::string &filename); - - /** - * Loads string into XMLwrapper. - * @param xmldata NULL terminated string of XML data. - * @returns true if successful. - */ - bool putXMLdata(const char *xmldata); - - /** - * Enters the branch. - * @param name Name of branch. - * @returns 1 if is ok, or 0 otherwise. - */ - int enterbranch(const std::string &name); - - /** - * Enter into the branch \c name with id \c id. - * @param name Name of branch. - * @param id Value of branch's "id". - * @returns 1 if is ok, or 0 otherwise. - */ - int enterbranch(const std::string &name, int id); - - /**Exits from a branch*/ - void exitbranch(); - - /**Get the the branch_id and limits it between the min and max. - * if min==max==0, it will not limit it - * if there isn't any id, will return min - * this must be called only imediately after enterbranch() - */ - int getbranchid(int min, int max) const; - - /** - * Returns the integer value stored in node name. - * It returns the integer value between the limits min and max. - * If min==max==0, then the value will not be limited. - * If there is no location named name, then defaultpar will be returned. - * @param name The parameter name. - * @param defaultpar The default value if the real value is not found. - * @param min The minimum return value. - * @param max The maximum return value. - */ - int getpar(const std::string &name, int defaultpar, int min, - int max) const; - - /** - * Returns the integer value stored in the node with range [0,127]. - * @param name The parameter name. - * @param defaultpar The default value if the real value is not found. - */ - int getpar127(const std::string &name, int defaultpar) const; - - /** - * Returns the boolean value stored in the node. - * @param name The parameter name. - * @param defaultpar The default value if the real value is not found. - */ - int getparbool(const std::string &name, int defaultpar) const; - - /** - * Get the string value stored in the node. - * @param name The parameter name. - * @param par Pointer to destination string - * @param maxstrlen Max string length for destination - */ - void getparstr(const std::string &name, char *par, int maxstrlen) const; - - /** - * Get the string value stored in the node. - * @param name The parameter name. - * @param defaultpar The default value if the real value is not found. - */ - std::string getparstr(const std::string &name, - const std::string &defaultpar) const; - - /** - * Returns the real value stored in the node. - * @param name The parameter name. - * @param defaultpar The default value if the real value is not found. - */ - REALTYPE getparreal(const char *name, REALTYPE defaultpar) const; - - /** - * Returns the real value stored in the node. - * @param name The parameter name. - * @param defaultpar The default value if the real value is not found. - * @param min The minimum value - * @param max The maximum value - */ - REALTYPE getparreal(const char *name, - REALTYPE defaultpar, - REALTYPE min, - REALTYPE max) const; - - bool minimal; /** - * - * @param name The name of the xml node - * @param params The number of the attributes - * @param ... const char * pairs that are in the format attribute_name, - * attribute_value - */ - mxml_node_t *addparams(const char *name, unsigned int params, - ...) const; - - /**@todo keep these numbers up to date*/ - struct { - int Major; /** -#include "DSSIaudiooutput.h" -#include "../Misc/Config.h" -#include "../Misc/Bank.h" -#include - -// -// Static stubs for LADSPA member functions -// -// LADSPA is essentially a C handle based API; This plug-in implementation is -// a C++ OO one so we need stub functions to map from C API calls to C++ object -// method calls. -void DSSIaudiooutput::stub_connectPort(LADSPA_Handle instance, unsigned long port, LADSPA_Data * data) -{ - getInstance(instance)->connectPort(port, data); -} - -void DSSIaudiooutput::stub_activate(LADSPA_Handle instance) -{ - getInstance(instance)->activate(); -} - -void DSSIaudiooutput::stub_run(LADSPA_Handle instance, unsigned long sample_count) -{ - getInstance(instance)->run(sample_count); -} - -void DSSIaudiooutput::stub_deactivate(LADSPA_Handle instance) -{ - getInstance(instance)->deactivate(); -} - - -void DSSIaudiooutput::stub_cleanup(LADSPA_Handle instance) -{ - DSSIaudiooutput* plugin_instance = getInstance(instance); - plugin_instance->cleanup(); - delete plugin_instance; -} - - -const LADSPA_Descriptor *ladspa_descriptor(unsigned long index) -{ - return DSSIaudiooutput::getLadspaDescriptor(index); -} - -// -// Static stubs for DSSI member functions -// -// DSSI is essentially a C handle based API; This plug-in implementation is -// a C++ OO one so we need stub functions to map from C API calls to C++ object -// method calls. -const DSSI_Program_Descriptor* DSSIaudiooutput::stub_getProgram (LADSPA_Handle instance, unsigned long index) -{ - return getInstance(instance)->getProgram(index); -} - -void DSSIaudiooutput::stub_selectProgram(LADSPA_Handle instance, unsigned long bank, unsigned long program) -{ - getInstance(instance)->selectProgram(bank, program); -} - -int DSSIaudiooutput::stub_getMidiControllerForPort(LADSPA_Handle instance, unsigned long port) -{ - return getInstance(instance)->getMidiControllerForPort(port); -} - -void DSSIaudiooutput::stub_runSynth(LADSPA_Handle instance, unsigned long sample_count, - snd_seq_event_t *events, unsigned long event_count) -{ - getInstance(instance)->runSynth(sample_count, events, event_count); -} - -const DSSI_Descriptor *dssi_descriptor(unsigned long index) -{ - return DSSIaudiooutput::getDssiDescriptor(index); -} - -// -// LADSPA member functions -// - -/** - * Instantiates a plug-in. - * - * This LADSPA member function instantiates a plug-in. - * Note that instance initialisation should generally occur in - * activate() rather than here. - * - * Zyn Implementation - * ------------------ - * This implementation creates a C++ class object and hides its pointer - * in the handle by type casting. - * - * @param descriptor [in] the descriptor for this plug-in - * @param s_rate [in] the sample rate - * @return the plug-in instance handle if successful else NULL - */ -LADSPA_Handle DSSIaudiooutput::instantiate(const LADSPA_Descriptor * descriptor, unsigned long s_rate) -{ - if(descriptor->UniqueID == dssiDescriptor->LADSPA_Plugin->UniqueID) - { - return (LADSPA_Handle)(new DSSIaudiooutput(s_rate)); - } - else - { - return NULL; - } -} - -/** - * Connects a port on an instantiated plug-in. - * - * This LADSPA member function connects a port on an instantiated plug-in to a - * memory location at which a block of data for the port will be read/written. - * The data location is expected to be an array of LADSPA_Data for audio ports - * or a single LADSPA_Data value for control ports. Memory issues will be - * managed by the host. The plug-in must read/write the data at these locations - * every time run() or run_adding() is called and the data present at the time - * of this connection call should not be considered meaningful. - * - * Zyn Implementation - * ------------------ - * The buffer pointers are stored as member variables - * - * @param port [in] the port to be connected - * @param data [in] the data buffer to write to / read from - */ -void DSSIaudiooutput::connectPort(unsigned long port, LADSPA_Data * data) -{ - switch (port) { - case 0: - outl = data; - break; - case 1: - outr = data; - break; - } -} - -/** - * Initialises a plug-in instance and activates it for use. - * - * This LADSPA member function initialises a plug-in instance and activates it - * for use. This is separated from instantiate() to aid real-time support and - * so that hosts can reinitialise a plug-in instance by calling deactivate() and - * then activate(). In this case the plug-in instance must reset all state - * information dependent on the history of the plug-in instance except for any - * data locations provided by connect_port() and any gain set by - * set_run_adding_gain(). - * - * Zyn Implementation - * ------------------ - * Currently this does nothing; Care must be taken as to code placed here as - * too much code here seems to cause time-out problems in jack-dssi-host. -*/ -void DSSIaudiooutput::activate() -{ -} - -/** - * Runs an instance of a plug-in for a block. - * - * This LADSPA member function runs an instance of a plug-in for a block. - * Note that if an activate() function exists then it must be called before - * run() or run_adding(). If deactivate() is called for a plug-in instance then - * the plug-in instance may not be reused until activate() has been called again. - * - * Zyn Implementation - * ------------------ - * This is a LADSPA function that does not process any MIDI events; it is hence - * implemented by simply calling runSynth() with an empty event list. - * - * @param sample_count [in] the block size (in samples) for which the plug-in instance may run - */ -void DSSIaudiooutput::run(unsigned long sample_count) -{ - runSynth(sample_count,NULL,(unsigned long)0); -} - -/** - * Counterpart to activate(). - * - * This LADSPA member function is the counterpart to activate() (see above). - * Deactivation is not similar to pausing as the plug-in instance will be - * reinitialised when activate() is called to reuse it. - * - * Zyn Implementation - * ------------------ - * Currently this function does nothing. - */ -void DSSIaudiooutput::deactivate() -{ - -} - -/** - * Deletes a plug-in instance that is no longer required. - * - * LADSPA member function; once an instance of a plug-in has been finished with - * it can be deleted using this function. The instance handle ceases to be - * valid after this call. - * - * If activate() was called for a plug-in instance then a corresponding call to - * deactivate() must be made before cleanup() is called. - * - * Zyn Implementation - * ------------------ - * Currently cleanup is deferred to the destructor that is invoked after cleanup() - */ -void DSSIaudiooutput::cleanup() -{ -} - -/** - * Initial entry point for the LADSPA plug-in library. - * - * This LADSPA function is the initial entry point for the plug-in library. - * The LADSPA host looks for this entry point in each shared library object it - * finds and then calls the function to enumerate the plug-ins within the - * library. - * - * Zyn Implementation - * ------------------ - * As the Zyn plug-in is a DSSI plug-in, the LADSPA descriptor is embedded inside - * the DSSI descriptor, which is created by DSSIaudiooutput::initDssiDescriptor() - * statically when the library is loaded. This function then merely returns a pointer - * to that embedded descriptor. - * - * @param index [in] the index number of the plug-in within the library. - * @return if index is in range, a pointer to the plug-in descriptor is returned, else NULL - */ -const LADSPA_Descriptor* DSSIaudiooutput::getLadspaDescriptor(unsigned long index) -{ - if(index > 0 || dssiDescriptor == NULL) - return NULL; - else - return dssiDescriptor->LADSPA_Plugin; -} - -// -// DSSI member functions -// - -/** - * Provides a description of a program available on this synth. - * - * This DSSI member function pointer provides a description of a program (named - * preset sound) available on this synth. - * - * Zyn Implementation - * ------------------ - * The instruments in all Zyn's bank directories, as shown by the `instrument - * -> show instrument bank` command, are enumerated to the host by this - * function, allowing access to all those instruments. - * The first time an instrument is requested, the bank it is in and any - * unmapped ones preceding that are mapped; all the instruments names and - * filenames from those banks are stored in the programMap member variable for - * later use. This is done on demand in this way, rather than up front in one - * go because loading all the instrument names in one go can lead to timeouts - * and zombies. - * - * @param index [in] index into the plug-in's list of - * programs, not a program number as represented by the Program - * field of the DSSI_Program_Descriptor. (This distinction is - * needed to support synths that use non-contiguous program or - * bank numbers.) - * @return a DSSI_Program_Descriptor pointer that is - * guaranteed to be valid only until the next call to get_program, - * deactivate, or configure, on the same plug-in instance, or NULL if index is out of range. - */ -const DSSI_Program_Descriptor* DSSIaudiooutput::getProgram (unsigned long index) -{ - static DSSI_Program_Descriptor retVal; - - /* Make sure we have the list of banks loaded */ - initBanks(); - - /* Make sure that the bank containing the instrument has been mapped */ - while (index >= programMap.size() && mapNextBank()) - /* DO NOTHING MORE */; - - if(index >= programMap.size()) - { - /* No more instruments */ - return NULL; - } - else - { - /* OK, return the instrument */ - retVal.Name = programMap[index].name.c_str(); - retVal.Program = programMap[index].program; - retVal.Bank = programMap[index].bank; - return &retVal; - } -} - -/** - * Selects a new program for this synth. - * - * This DSSI member function selects a new program for this synth. The program - * change will take effect immediately at the start of the next run_synth() - * call. An invalid bank / instrument combination is ignored. - * - * Zyn Implementation - * ------------------ - * the banks and instruments are as shown in the `instrument -> show instrument - * bank` command in Zyn. The bank no is a 1-based index into the list of banks - * Zyn loads and shows in the drop down and the program number is the - * instrument within that bank. - * - * @param bank [in] the bank number to select - * @param program [in] the program number within the bank to select - */ -void DSSIaudiooutput::selectProgram(unsigned long bank, unsigned long program) -{ - initBanks(); -// cerr << "selectProgram(" << (bank & 0x7F) << ':' << ((bank >> 7) & 0x7F) << "," << program << ")" << '\n'; - if(bank < MAX_NUM_BANKS && program < BANK_SIZE) - { - char* bankdir = master->bank.banks[ bank ].dir; - if(bankdir != NULL) - { - pthread_mutex_lock(&master->mutex); - - /* We have to turn off the CheckPADsynth functionality, else - * the program change takes way too long and we get timeouts - * and hence zombies (!) */ - int save = config.cfg.CheckPADsynth; - config.cfg.CheckPADsynth = 0; - - /* Load the bank... */ - master->bank.loadbank(bankdir); - - /* restore the CheckPADsynth flag */ - config.cfg.CheckPADsynth = save; - - /* Now load the instrument... */ - master->bank.loadfromslot((unsigned int)program, master->part[0]); - - pthread_mutex_unlock(&master->mutex); - } - } -} - -/** - * Returns the MIDI controller number or NRPN for a input control port - * - * This DSSI member function returns the MIDI controller number or NRPN that - * should be mapped to the given input control port. If the given port should - * not have any MIDI controller mapped to it, the function will return DSSI_NONE. - * The behaviour of this function is undefined if the given port - * number does not correspond to an input control port. - * - * Zyn Implementation - * ------------------ - * Currently Zyn does not define any controller ports, but may do in the future. - * - * @param port [in] the input controller port - * @return the CC and NRPN values shifted and ORed together. - */ -int DSSIaudiooutput::getMidiControllerForPort(unsigned long port) -{ - return DSSI_NONE; -} - -/** - * Runs the synth for a block. - * - * This DSSI member function runs the synth for a block. This is identical in - * function to the LADSPA run() function, except that it also supplies events - * to the synth. - * - * Zyn Implementation - * ------------------ - * Zyn implements synthesis in Master::GetAudioOutSamples; runSynth calls this - * function in chunks delimited by the sample_count and the frame indexes in - * the events block, calling the appropriate NoteOn, NoteOff and SetController - * members of Master to process the events supplied between each chunk. - * - * @param sample_count [in] the block size (in samples) for which the synth - * instance may run. - * @param events [in] The Events pointer points to a block of ALSA - * sequencer events, used to communicate MIDI and related events to the synth. - * Each event must be timestamped relative to the start of the block, - * (mis)using the ALSA "tick time" field as a frame count. The host is - * responsible for ensuring that events with differing timestamps are already - * ordered by time. Must not include NOTE (only NOTE_ON / NOTE_OFF), LSB or MSB - * events. - * @param event_count [in] the number of entries in the `events` block - */ -void DSSIaudiooutput::runSynth(unsigned long sample_count, snd_seq_event_t *events, unsigned long event_count) -{ - unsigned long from_frame = 0; - unsigned long event_index = 0; - unsigned long next_event_frame = 0; - unsigned long to_frame = 0; - pthread_mutex_lock(&master->mutex); - - do { - /* Find the time of the next event, if any */ - if(events == NULL || event_index >= event_count) - next_event_frame = ULONG_MAX; - else - next_event_frame = events[event_index].time.tick; - - /* find the end of the sub-sample to be processed this time round... */ - /* if the next event falls within the desired sample interval... */ - if(next_event_frame < sample_count && next_event_frame >= to_frame) - /* set the end to be at that event */ - to_frame = next_event_frame; - else - /* ...else go for the whole remaining sample */ - to_frame = sample_count; - if(from_frameGetAudioOutSamples(to_frame - from_frame, (int)sampleRate, &(outl[from_frame]), &(outr[from_frame])); - // next sub-sample please... - from_frame = to_frame; - } - - // Now process any event(s) at the current timing point - while(events != NULL && event_index < event_count && events[event_index].time.tick == to_frame) - { - if(events[event_index].type == SND_SEQ_EVENT_NOTEON) - { - master->NoteOn(events[event_index].data.note.channel, events[event_index].data.note.note, events[event_index].data.note.velocity); - } - else if(events[event_index].type == SND_SEQ_EVENT_NOTEOFF) - { - master->NoteOff(events[event_index].data.note.channel, events[event_index].data.note.note); - } - else if(events[event_index].type == SND_SEQ_EVENT_CONTROLLER) - { - master->SetController(events[event_index].data.control.channel, events[event_index].data.control.param, events[event_index].data.control.value); - } - else - { - } - event_index++; - } - - // Keep going until we have the desired total length of sample... - } while(to_frame < sample_count); - - pthread_mutex_unlock(&master->mutex); -} - -/** - * Initial entry point for the DSSI plug-in library. - * - * This DSSI function is the initial entry point for the plug-in library. - * The DSSI host looks for this entry point in each shared library object it - * finds and then calls the function to enumerate the plug-ins within the - * library. - * - * Zyn Implementation - * ------------------ - * The descriptor is created statically by DSSIaudiooutput::initDssiDescriptor() - * when the plug-in library is loaded. This function merely returns a pointer to - * that descriptor. - * - * @param index [in] the index number of the plug-in within the library. - * @return if index is in range, a pointer to the plug-in descriptor is returned, else NULL - */ -const DSSI_Descriptor* DSSIaudiooutput::getDssiDescriptor(unsigned long index) -{ - if(index > 0 || dssiDescriptor == NULL) - return NULL; - else - return dssiDescriptor; -} - -// -// Internal member functions -// - -// Initialise the DSSI descriptor, statically: -DSSI_Descriptor* DSSIaudiooutput::dssiDescriptor = DSSIaudiooutput::initDssiDescriptor(); - -/** - * Initializes the DSSI (and LADSPA) descriptor, returning it is an object. - */ -DSSI_Descriptor* DSSIaudiooutput::initDssiDescriptor() -{ - DSSI_Descriptor* newDssiDescriptor = new DSSI_Descriptor; - - LADSPA_PortDescriptor* newPortDescriptors; - char** newPortNames; - LADSPA_PortRangeHint* newPortRangeHints; - - if (newDssiDescriptor) - { - LADSPA_Descriptor* newLadspaDescriptor = new LADSPA_Descriptor; - if (newLadspaDescriptor) - { - newLadspaDescriptor->UniqueID = 100; - newLadspaDescriptor->Label = "ZASF"; - newLadspaDescriptor->Properties = 0; - newLadspaDescriptor->Name = "ZynAddSubFX"; - newLadspaDescriptor->Maker = "Nasca Octavian Paul "; - newLadspaDescriptor->Copyright = "GNU General Public License v.2"; - newLadspaDescriptor->PortCount = 2; - - newPortNames = new char *[newLadspaDescriptor->PortCount]; - newPortNames[0] = "Output L"; - newPortNames[1] = "Output R"; - newLadspaDescriptor->PortNames = newPortNames; - - newPortDescriptors = new LADSPA_PortDescriptor[newLadspaDescriptor->PortCount]; - newPortDescriptors[0] = LADSPA_PORT_OUTPUT | LADSPA_PORT_AUDIO; - newPortDescriptors[1] = LADSPA_PORT_OUTPUT | LADSPA_PORT_AUDIO; - newLadspaDescriptor->PortDescriptors = newPortDescriptors; - - newPortRangeHints = new LADSPA_PortRangeHint[newLadspaDescriptor->PortCount]; - newPortRangeHints[0].HintDescriptor = 0; - newPortRangeHints[1].HintDescriptor = 0; - newLadspaDescriptor->PortRangeHints = newPortRangeHints; - - newLadspaDescriptor->activate = stub_activate; - newLadspaDescriptor->cleanup = stub_cleanup; - newLadspaDescriptor->connect_port = stub_connectPort; - newLadspaDescriptor->deactivate = stub_deactivate; - newLadspaDescriptor->instantiate = instantiate; - newLadspaDescriptor->run = stub_run; - newLadspaDescriptor->run_adding = NULL; - newLadspaDescriptor->set_run_adding_gain = NULL; - } - newDssiDescriptor->LADSPA_Plugin = newLadspaDescriptor; - newDssiDescriptor->DSSI_API_Version = 1; - newDssiDescriptor->configure = NULL; - newDssiDescriptor->get_program = stub_getProgram; - newDssiDescriptor->get_midi_controller_for_port = stub_getMidiControllerForPort; - newDssiDescriptor->select_program = stub_selectProgram; - newDssiDescriptor->run_synth = stub_runSynth; - newDssiDescriptor->run_synth_adding = NULL; - newDssiDescriptor->run_multiple_synths = NULL; - newDssiDescriptor->run_multiple_synths_adding = NULL; - } - - dssiDescriptor = newDssiDescriptor; - - return dssiDescriptor; -} - -/** - * Converts a LADSPA / DSSI handle into a DSSIaudiooutput instance. - * - * @param instance [in] - * @return the instance - */ -DSSIaudiooutput* DSSIaudiooutput::getInstance(LADSPA_Handle instance) -{ - return (DSSIaudiooutput*)(instance); -} - -/** - * The private sole constructor for the DSSIaudiooutput class. - * - * Only ever called via instantiate(). - * @param sampleRate [in] the sample rate to be used by the synth. - * @return - */ -DSSIaudiooutput::DSSIaudiooutput(unsigned long sampleRate) -{ - this->sampleRate = sampleRate; - this->banksInited = false; - - config.init(); - - srand(time(NULL)); - denormalkillbuf=new REALTYPE [SOUND_BUFFER_SIZE]; - for (int i=0;imaster = new Master(); -} - -/** - * The destructor for the DSSIaudiooutput class - * @return - */ -DSSIaudiooutput::~DSSIaudiooutput() -{ -} - -/** - * Ensures the list of bank (directories) has been initialised. - */ -void DSSIaudiooutput::initBanks(void) -{ - if(!banksInited) - { - pthread_mutex_lock(&master->mutex); - master->bank.rescanforbanks(); - banksInited = true; - pthread_mutex_unlock(&master->mutex); - } -} - -/** - * constructor for the internally used ProgramDescriptor class - * - * @param _bank [in] bank number - * @param _program [in] program number - * @param _name [in] instrument / sample name - * @return - */ -DSSIaudiooutput::ProgramDescriptor::ProgramDescriptor(unsigned long _bank, unsigned long _program, char* _name) : - bank(_bank), program(_program), name(_name) -{ -} - -/** - * The map of programs available; held as a single shared statically allocated object. - */ -vector DSSIaudiooutput::programMap = vector(); - -/** - * Index controlling the map of banks - */ -long DSSIaudiooutput::bankNoToMap = 1; - -/** - * Queries and maps the next available bank of instruments. - * - * If the program index requested to getProgram() lies beyond the banks mapped to date, - * this member function is called to map the next one. - * @return true if a new bank has been found and mapped, else false. - */ -bool DSSIaudiooutput::mapNextBank() -{ - pthread_mutex_lock(&master->mutex); - Bank& bank = master->bank; - bool retval; - if(bankNoToMap >= MAX_NUM_BANKS || bank.banks[bankNoToMap].dir == NULL) - { - retval = false; - } - else - { - bank.loadbank(bank.banks[bankNoToMap].dir); - for(unsigned long instrument = 0; instrument < BANK_SIZE; instrument++) - { - char* insName = bank.getname(instrument); - if(insName != NULL && insName[0] != '\0' && insName[0] != ' ') - { - programMap.push_back(ProgramDescriptor(bankNoToMap,instrument,insName)); - } - } - bankNoToMap ++; - retval = true; - } - pthread_mutex_unlock(&master->mutex); - return retval; -} diff --git a/plugins/zynaddsubfx/src/Output/DSSIaudiooutput.h b/plugins/zynaddsubfx/src/Output/DSSIaudiooutput.h deleted file mode 100644 index 076367a72..000000000 --- a/plugins/zynaddsubfx/src/Output/DSSIaudiooutput.h +++ /dev/null @@ -1,111 +0,0 @@ -/* - ZynAddSubFX - a software synthesizer - - VSTaudiooutput.h - Audio output for VST - Copyright (C) 2002 Nasca Octavian Paul - Author: Nasca Octavian Paul - - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License - as published by the Free Software Foundation. - - 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 (version 2 or later) for more details. - - You should have received a copy of the GNU General Public License (version 2) - along with this program; if not, write to the Free Software Foundation, - Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -*/ -#ifndef VST_AUDIO_OUTPUT_H -#define VST_AUDIO_OUTPUT_H - -#include - -#include "../globals.h" -#include "../Misc/Master.h" - -#include -#include -#include - -class DSSIaudiooutput -{ -public: - // - // Static stubs for LADSPA member functions - // - static void stub_connectPort(LADSPA_Handle instance, unsigned long port, LADSPA_Data * data); - static void stub_activate(LADSPA_Handle instance); - static void stub_run(LADSPA_Handle instance, unsigned long sample_count); - static void stub_deactivate(LADSPA_Handle Instance); - static void stub_cleanup(LADSPA_Handle instance); - - // - // Static stubs for DSSI member functions - // - static const DSSI_Program_Descriptor* stub_getProgram (LADSPA_Handle instance, unsigned long Index); - static void stub_selectProgram(LADSPA_Handle instance, unsigned long bank, unsigned long program); - static int stub_getMidiControllerForPort(LADSPA_Handle instance, unsigned long port); - static void stub_runSynth(LADSPA_Handle instance, unsigned long sample_count, - snd_seq_event_t *events, unsigned long event_count); - - /* - * LADSPA member functions - */ - static LADSPA_Handle instantiate(const LADSPA_Descriptor * descriptor, unsigned long s_rate); - void connectPort(unsigned long port, LADSPA_Data * data); - void activate(); - void run(unsigned long sample_count); - void deactivate(); - void cleanup(); - static const LADSPA_Descriptor* getLadspaDescriptor(unsigned long index); - - /* - * DSSI member functions - */ - const DSSI_Program_Descriptor* getProgram (unsigned long Index); - void selectProgram(unsigned long bank, unsigned long program); - int getMidiControllerForPort(unsigned long port); - void runSynth(unsigned long sample_count, snd_seq_event_t *events, unsigned long event_count); - static const DSSI_Descriptor* getDssiDescriptor(unsigned long index); - - struct ProgramDescriptor - { - unsigned long bank; - unsigned long program; - string name; - ProgramDescriptor(unsigned long _bank, unsigned long _program, char* _name); - }; - -private: - - DSSIaudiooutput(unsigned long sampleRate); - ~DSSIaudiooutput(); - static DSSI_Descriptor* initDssiDescriptor(); - static DSSIaudiooutput* getInstance(LADSPA_Handle instance); - void initBanks(); - bool mapNextBank(); - - LADSPA_Data *outl; - LADSPA_Data *outr; - long sampleRate; - Master* master; - static DSSI_Descriptor* dssiDescriptor; - static string bankDirNames[]; - static - vector programMap; - - /** - * Flag controlling the list of bank directories - */ - bool banksInited; - - static - long bankNoToMap; -}; - -#endif - diff --git a/plugins/zynaddsubfx/src/Output/JACK_RTaudiooutput.cpp b/plugins/zynaddsubfx/src/Output/JACK_RTaudiooutput.cpp deleted file mode 100644 index 2e63e659b..000000000 --- a/plugins/zynaddsubfx/src/Output/JACK_RTaudiooutput.cpp +++ /dev/null @@ -1,229 +0,0 @@ -/* - ZynAddSubFX - a software synthesizer - - JACKaudiooutput.cpp - Audio output for JACK - Copyright (C) 2002 Nasca Octavian Paul - Author: Nasca Octavian Paul - - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License - as published by the Free Software Foundation. - - 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 (version 2 or later) for more details. - - You should have received a copy of the GNU General Public License (version 2) - along with this program; if not, write to the Free Software Foundation, - Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -*/ - -#include -#include -#include -#include - - -extern "C" -{ -#include -}; -#include "JACKaudiooutput.h" - -Master *jackmaster; -jack_client_t *jackclient; -jack_port_t *outport_left, *outport_right; -jack_ringbuffer_t *rb = NULL; - -REALTYPE *jackoutl, *jackoutr; -int jackfinish = 0; - -void *thread_blocked(void *arg); -int jackprocess(jack_nframes_t nframes, void *arg); -int jacksrate(jack_nframes_t nframes, void *arg); -void jackshutdown(void *arg); - -pthread_cond_t more_data = PTHREAD_COND_INITIALIZER; -pthread_mutex_t zyn_thread_lock = PTHREAD_MUTEX_INITIALIZER; - -pthread_t bthr; - - -bool JACKaudiooutputinit(Master *master_) -{ - jackmaster = master_; - jackclient = 0; - char tmpstr[100]; - - jackoutl = new REALTYPE [SOUND_BUFFER_SIZE]; - jackoutr = new REALTYPE [SOUND_BUFFER_SIZE]; - - int rbbufsize = SOUND_BUFFER_SIZE * sizeof(REALTYPE) * 2 * 2; - printf("%d\n", rbbufsize); - rb = jack_ringbuffer_create(rbbufsize); - for(int i = 0; i < rbbufsize; i++) - rb->buf[i] = 0.0; - - - for(int i = 0; i < 15; i++) { - if(i != 0) - snprintf(tmpstr, 100, "ZynAddSubFX_%d", i); - else - snprintf(tmpstr, 100, "ZynAddSubFX"); - jackclient = jack_client_new(tmpstr); - if(jackclient != 0) - break; - } - - if(jackclient == 0) { - fprintf( - stderr, - "\nERROR: Cannot make a jack client (possible reasons: JACK server is not running or jackd is launched by root and zynaddsubfx by another user.).\n\n\n"); - return false; - } - - fprintf(stderr, - "Internal SampleRate = %d\nJack Output SampleRate= %d\n", - SAMPLE_RATE, - jack_get_sample_rate(jackclient)); - if((unsigned int)jack_get_sample_rate(jackclient) != - (unsigned int) SAMPLE_RATE) - fprintf(stderr, - "It is recomanded that the both samplerates to be equal.\n"); - - jack_set_process_callback(jackclient, jackprocess, 0); - jack_set_sample_rate_callback(jackclient, jacksrate, 0); - jack_on_shutdown(jackclient, jackshutdown, 0); - - outport_left = jack_port_register(jackclient, - "out_1", - JACK_DEFAULT_AUDIO_TYPE, - JackPortIsOutput | JackPortIsTerminal, - 0); - outport_right = jack_port_register(jackclient, - "out_2", - JACK_DEFAULT_AUDIO_TYPE, - JackPortIsOutput | JackPortIsTerminal, - 0); - - if(jack_activate(jackclient)) { - fprintf(stderr, "Cannot activate jack client\n"); - return false; - } - - pthread_create(&bthr, NULL, thread_blocked, NULL); - - /* - jack_connect(jackclient,jack_port_name(outport_left),"alsa_pcm:out_1"); - jack_connect(jackclient,jack_port_name(outport_right),"alsa_pcm:out_2"); - */ - - return true; -} - -void *thread_blocked(void *arg) -{ - int datasize = SOUND_BUFFER_SIZE * sizeof(REALTYPE); - - //try to get realtime - sched_param sc; - sc.sched_priority = 50; - int err = sched_setscheduler(0, SCHED_FIFO, &sc); - - pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL); - pthread_mutex_lock(&zyn_thread_lock); - - while(jackfinish == 0) { - while(jack_ringbuffer_write_space(rb) >= datasize) { - pthread_mutex_lock(&jackmaster->mutex); - jackmaster->GetAudioOutSamples(SOUND_BUFFER_SIZE, - jack_get_sample_rate(jackclient), - jackoutl, - jackoutr); - pthread_mutex_unlock(&jackmaster->mutex); - - jack_ringbuffer_write(rb, (char *) jackoutl, datasize); - jack_ringbuffer_write(rb, (char *) jackoutr, datasize); - } - pthread_cond_wait(&more_data, &zyn_thread_lock); - } - pthread_mutex_unlock(&zyn_thread_lock); - - return 0; -} - - -int jackprocess(jack_nframes_t nframes, void *arg) -{ - jack_default_audio_sample_t *outl = - (jack_default_audio_sample_t *) jack_port_get_buffer(outport_left, - nframes); - jack_default_audio_sample_t *outr = - (jack_default_audio_sample_t *) jack_port_get_buffer(outport_right, - nframes); - - int datasize = nframes * sizeof(REALTYPE); - int incoming_datasize = SOUND_BUFFER_SIZE * sizeof(REALTYPE); - int data_read = 0; - - - if(jack_ringbuffer_read_space(rb) >= (2 * incoming_datasize)) { - if(datasize > incoming_datasize) { - data_read = 0; - while(data_read < datasize) { - jack_ringbuffer_read(rb, (char *) outl + data_read, datasize); - jack_ringbuffer_read(rb, (char *) outr + data_read, datasize); - data_read += incoming_datasize; - } - } - else - if(datasize == incoming_datasize) { - jack_ringbuffer_read(rb, (char *) outl, datasize); - jack_ringbuffer_read(rb, (char *) outr, datasize); - } - else {} - } - else { //the ringbuffer is empty or there are too small amount of samples in it - for(int i = 0; i < nframes; i++) { - outl[i] = 0.0; - outr[i] = 0.0; - } - } - /* if (jack_ringbuffer_read_space(rb)>=datasize){ - jack_ringbuffer_read(rb, (char *) outl,datasize); - jack_ringbuffer_read(rb, (char *) outr,datasize); - } else {//the ringbuffer is empty or there are too small amount of samples in it - for (int i=0;i -#include -#include "JACKaudiooutput.h" - -Master *jackmaster; -jack_client_t *jackclient; -char jackname[100]; -jack_port_t *outport_left, *outport_right, *midi_inport; - -int jackprocess(jack_nframes_t nframes, void *arg); -int jacksrate(jack_nframes_t nframes, void *arg); -void jackshutdown(void *arg); - -bool JACKaudiooutputinit(Master *master_) -{ - jackmaster = master_; - jackclient = 0; - - for(int i = 0; i < 15; i++) { - if(i != 0) - snprintf(jackname, 100, "ZynAddSubFX_%d", i); - else - snprintf(jackname, 100, "ZynAddSubFX"); - jackclient = jack_client_new(jackname); - if(jackclient != 0) - break; - } - - if(jackclient == 0) { - fprintf( - stderr, - "\nERROR: Cannot make a jack client (possible reasons: JACK server is not running or jackd is launched by root and zynaddsubfx by another user.).\n"); - return false; - } - - fprintf(stderr, - "Internal SampleRate = %d\nJack Output SampleRate= %d\n", - SAMPLE_RATE, - jack_get_sample_rate(jackclient)); - if((unsigned int)jack_get_sample_rate(jackclient) != - (unsigned int) SAMPLE_RATE) - fprintf(stderr, - "It is recomanded that the both samplerates to be equal.\n"); - - jack_set_process_callback(jackclient, jackprocess, 0); - jack_set_sample_rate_callback(jackclient, jacksrate, 0); - jack_on_shutdown(jackclient, jackshutdown, 0); - - outport_left = jack_port_register(jackclient, - "out_1", - JACK_DEFAULT_AUDIO_TYPE, - JackPortIsOutput | JackPortIsTerminal, - 0); - outport_right = jack_port_register(jackclient, - "out_2", - JACK_DEFAULT_AUDIO_TYPE, - JackPortIsOutput | JackPortIsTerminal, - 0); - midi_inport = jack_port_register(jackclient, - "midi_input", - JACK_DEFAULT_MIDI_TYPE, - JackPortIsInput | JackPortIsTerminal, - 0); - - if(jack_activate(jackclient)) { - fprintf(stderr, "Cannot activate jack client\n"); - return false; - } - - /* - jack_connect(jackclient,jack_port_name(outport_left),"alsa_pcm:out_1"); - jack_connect(jackclient,jack_port_name(outport_right),"alsa_pcm:out_2"); - */ - return true; -} - -int jackprocess(jack_nframes_t nframes, void *arg) -{ - jack_default_audio_sample_t *outl = - (jack_default_audio_sample_t *) jack_port_get_buffer(outport_left, - nframes); - jack_default_audio_sample_t *outr = - (jack_default_audio_sample_t *) jack_port_get_buffer(outport_right, - nframes); - - if(!pthread_mutex_trylock(&jackmaster->mutex)) { - JACKhandlemidi(nframes); - jackmaster->GetAudioOutSamples(nframes, jack_get_sample_rate( - jackclient), outl, outr); - pthread_mutex_unlock(&jackmaster->mutex); - } - else { - memset(outl, 0, sizeof(jack_default_audio_sample_t) * nframes); - memset(outr, 0, sizeof(jack_default_audio_sample_t) * nframes); - } - - return 0; -} - -void JACKfinish() -{ - jack_client_close(jackclient); -} - -int jacksrate(jack_nframes_t nframes, void *arg) -{ - return 0; -} - -void jackshutdown(void *arg) -{} - - -void JACKhandlemidi(unsigned long frames) -{ - // We must have the master mutex before we run this function - - // XXX This is really nasty, not only do we lose the sample accuracy of - // JACK MIDI, but any accuracy at all below the buffer size - - void *midi_buf = jack_port_get_buffer(midi_inport, frames); - jack_midi_event_t jack_midi_event; - jack_nframes_t event_index = 0; - unsigned char *midi_data; - unsigned char type, chan; - - while(jack_midi_event_get(&jack_midi_event, midi_buf, - event_index++) == 0) { - midi_data = jack_midi_event.buffer; - type = midi_data[0] & 0xF0; - chan = midi_data[0] & 0x0F; - - switch(type) { - case 0x80: /* note-off */ - jackmaster->NoteOff(chan, midi_data[1]); - break; - - case 0x90: /* note-on */ - jackmaster->NoteOn(chan, midi_data[1], midi_data[2]); - break; - - case 0xB0: /* controller */ - jackmaster->SetController(chan, midi_data[1], midi_data[2]); - break; - - case 0xE0: /* pitch bend */ - jackmaster->SetController(chan, C_pitchwheel, - ((midi_data[2] << 7) | midi_data[1])); - break; - - /* XXX TODO: handle MSB/LSB controllers and RPNs and NRPNs */ - } - } -} - - -const char *JACKgetname() -{ - if(jackclient != NULL) - return jackname; - return NULL; -} - diff --git a/plugins/zynaddsubfx/src/Output/JACKaudiooutput.h b/plugins/zynaddsubfx/src/Output/JACKaudiooutput.h deleted file mode 100644 index afc5e5b7f..000000000 --- a/plugins/zynaddsubfx/src/Output/JACKaudiooutput.h +++ /dev/null @@ -1,48 +0,0 @@ -/* - ZynAddSubFX - a software synthesizer - - JACKaudiooutput.h - Audio output for JACK - Copyright (C) 2002 Nasca Octavian Paul - Author: Nasca Octavian Paul - - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License - as published by the Free Software Foundation. - - 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 (version 2 or later) for more details. - - You should have received a copy of the GNU General Public License (version 2) - along with this program; if not, write to the Free Software Foundation, - Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -*/ -#ifndef JACK_AUDIO_OUTPUT_H -#define JACK_AUDIO_OUTPUT_H - -#include - -#include "../globals.h" -#include "../Misc/Master.h" - - -#if (REALTYPE != jack_default_audio_sample_t) -#error \ - "The internal sample datatype of ZynAddSubFX and the datatype of jack differs. \ - In order to compile ZynAddSubFX the 'REALTYPE' and 'jack_default_audio_sample_t' must be equal. \ - Set the 'REALTYPE' data type (which is defined in 'globals.h') to what is defined \ - in the file types.h from jack include directory as 'jack_default_audio_sample_t' (as float or double)." -#endif - - - - -bool JACKaudiooutputinit(Master *master_); -void JACKfinish(); -void JACKhandlemidi(unsigned long frames); -const char *JACKgetname(); - -#endif - diff --git a/plugins/zynaddsubfx/src/Output/OSSaudiooutput.cpp b/plugins/zynaddsubfx/src/Output/OSSaudiooutput.cpp deleted file mode 100644 index f6c6b3f0f..000000000 --- a/plugins/zynaddsubfx/src/Output/OSSaudiooutput.cpp +++ /dev/null @@ -1,128 +0,0 @@ -/* - ZynAddSubFX - a software synthesizer - - OSSaudiooutput.cpp - Audio output for Open Sound System - Copyright (C) 2002-2005 Nasca Octavian Paul - Author: Nasca Octavian Paul - - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License - as published by the Free Software Foundation. - - 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 (version 2 or later) for more details. - - You should have received a copy of the GNU General Public License (version 2) - along with this program; if not, write to the Free Software Foundation, - Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -*/ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "OSSaudiooutput.h" -#include "../Misc/Util.h" -#include "../globals.h" -using namespace std; - -OSSaudiooutput::OSSaudiooutput() -{ - int i; - int snd_bitsize = 16; - snd_fragment = 0x00080009; //fragment size (?) - snd_stereo = 1; //stereo - snd_format = AFMT_S16_LE; - snd_samplerate = SAMPLE_RATE; - playing_until.tv_sec = 0; - playing_until.tv_usec = 0; - - smps = new short int[SOUND_BUFFER_SIZE * 2]; - for(i = 0; i < SOUND_BUFFER_SIZE * 2; i++) - smps[i] = 0; - - snd_handle = open(config.cfg.LinuxOSSWaveOutDev, O_WRONLY, 0); - if(snd_handle == -1) { - cerr << "ERROR - I can't open the "; - cerr << config.cfg.LinuxOSSWaveOutDev << '.' << endl; - return; - } - ioctl(snd_handle, SNDCTL_DSP_RESET, NULL); - - ioctl(snd_handle, SNDCTL_DSP_SETFMT, &snd_format); - ioctl(snd_handle, SNDCTL_DSP_STEREO, &snd_stereo); - ioctl(snd_handle, SNDCTL_DSP_SPEED, &snd_samplerate); - ioctl(snd_handle, SNDCTL_DSP_SAMPLESIZE, &snd_bitsize); - ioctl(snd_handle, SNDCTL_DSP_SETFRAGMENT, &snd_fragment); -} - - -/* - * Output the samples to the soundcard - * The samples are bigger than -1.0 and smaller 1.0 - */ -void OSSaudiooutput::OSSout(REALTYPE *smp_left, REALTYPE *smp_right) -{ - int i; - REALTYPE l, r; - if(snd_handle < 0) { //output could not be opened - struct timeval now; - int remaining; - gettimeofday(&now, NULL); - if((playing_until.tv_usec == 0) && (playing_until.tv_sec == 0)) { - playing_until.tv_usec = now.tv_usec; - playing_until.tv_sec = now.tv_sec; - } - else { - remaining = (playing_until.tv_usec - now.tv_usec) - + (playing_until.tv_sec - now.tv_sec) * 1000000; - if(remaining > 10000) //Don't sleep() less than 10ms. - //This will add latency... - usleep(remaining - 10000); - if(remaining < 0) - cerr << "WARNING - too late" << endl; - } - playing_until.tv_usec += SOUND_BUFFER_SIZE * 1000000 / SAMPLE_RATE; - if(remaining < 0) - playing_until.tv_usec -= remaining; - playing_until.tv_sec += playing_until.tv_usec / 1000000; - playing_until.tv_usec %= 1000000; - return; - } - - for(i = 0; i < SOUND_BUFFER_SIZE; i++) { - l = smp_left[i]; - r = smp_right[i]; - - if(l < -1.0) - l = -1.0; - else - if(l > 1.0) - l = 1.0; - if(r < -1.0) - r = -1.0; - else - if(r > 1.0) - r = 1.0; - - smps[i * 2] = (short int) (l * 32767.0); - smps[i * 2 + 1] = (short int) (r * 32767.0); - } - write(snd_handle, smps, SOUND_BUFFER_SIZE * 4); // *2 because is 16 bit, again * 2 because is stereo -} - - -OSSaudiooutput::~OSSaudiooutput() -{ - close(snd_handle); - delete [] smps; -} - diff --git a/plugins/zynaddsubfx/src/Output/OSSaudiooutput.h b/plugins/zynaddsubfx/src/Output/OSSaudiooutput.h deleted file mode 100644 index 28da1cfaf..000000000 --- a/plugins/zynaddsubfx/src/Output/OSSaudiooutput.h +++ /dev/null @@ -1,50 +0,0 @@ -/* - ZynAddSubFX - a software synthesizer - - OSSaudiooutput.h - Audio output for Open Sound System - Copyright (C) 2002-2005 Nasca Octavian Paul - Author: Nasca Octavian Paul - - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License - as published by the Free Software Foundation. - - 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 (version 2 or later) for more details. - - You should have received a copy of the GNU General Public License (version 2) - along with this program; if not, write to the Free Software Foundation, - Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -*/ - -#ifndef OSS_AUDIO_OUTPUT_H -#define OSS_AUDIO_OUTPUT_H - -#include -#include "../globals.h" - -class OSSaudiooutput -{ - public: - OSSaudiooutput(); - ~OSSaudiooutput(); - - //the out is [-1.0 .. 1.0] - /* smp_left[] and smp_right[] has the size of SOUND_BUFFER_SIZE */ - void OSSout(REALTYPE *smp_left, REALTYPE *smp_right); - private: - int snd_handle; - int snd_fragment; - int snd_stereo; - int snd_format; - int snd_samplerate; - struct timeval playing_until; - - short int *smps; //Samples to be sent to soundcard -}; - -#endif - diff --git a/plugins/zynaddsubfx/src/Output/PAaudiooutput.cpp b/plugins/zynaddsubfx/src/Output/PAaudiooutput.cpp deleted file mode 100644 index bfd84cca9..000000000 --- a/plugins/zynaddsubfx/src/Output/PAaudiooutput.cpp +++ /dev/null @@ -1,80 +0,0 @@ -/* - ZynAddSubFX - a software synthesizer - - PAaudiooutput.cpp - Audio output for PortAudio - Copyright (C) 2002 Nasca Octavian Paul - Author: Nasca Octavian Paul - - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License - as published by the Free Software Foundation. - - 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 (version 2 or later) for more details. - - You should have received a copy of the GNU General Public License (version 2) - along with this program; if not, write to the Free Software Foundation, - Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -*/ - -#include "PAaudiooutput.h" - -Master *PAmaster; -PaStream *stream; -REALTYPE *outl, *outr; - -int PAprocess(void *inputBuffer, void *outputBuffer, - unsigned long framesPerBuffer, - PaTimestamp outTime, void *userData) -{ - if(framesPerBuffer != SOUND_BUFFER_SIZE) { - fprintf( - stderr, - "Bug: PAudioOutput::PAprocess SOUND_BUFFER_SIZE!=framesPerBuffer"); - fprintf(stderr, "%d %d\n", framesPerBuffer, SOUND_BUFFER_SIZE); - } - - pthread_mutex_lock(&PAmaster->mutex); - PAmaster->GetAudioOutSamples(SOUND_BUFFER_SIZE, SAMPLE_RATE, outl, outr); - pthread_mutex_unlock(&PAmaster->mutex); - - float *out = (float *)outputBuffer; - - for(int i = 0; i < framesPerBuffer; i++) { - if(i >= SOUND_BUFFER_SIZE) - break; //this should never happens, except only when framesPerBuffer!>SOUND_BUFFER_SIZE - out[i * 2] = outl[i]; - out[i * 2 + 1] = outr[i]; - } - - return 0; -} - -void PAaudiooutputinit(Master *master_) -{ - PAmaster = master_; - outl = new REALTYPE [SOUND_BUFFER_SIZE]; - outr = new REALTYPE [SOUND_BUFFER_SIZE]; - Pa_Initialize(); - Pa_OpenDefaultStream(&stream, - 0, - 2, - paFloat32, - SAMPLE_RATE, - SOUND_BUFFER_SIZE, - 0, - PAprocess, - NULL); - Pa_StartStream(stream); -} - -void PAfinish() -{ - Pa_StopStream(stream); - delete (outl); - delete (outr); -} - diff --git a/plugins/zynaddsubfx/src/Output/PAaudiooutput.h b/plugins/zynaddsubfx/src/Output/PAaudiooutput.h deleted file mode 100644 index 942011d57..000000000 --- a/plugins/zynaddsubfx/src/Output/PAaudiooutput.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - ZynAddSubFX - a software synthesizer - - PAaudiooutput.h - Audio output for PortAudio - Copyright (C) 2002 Nasca Octavian Paul - Author: Nasca Octavian Paul - - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License - as published by the Free Software Foundation. - - 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 (version 2 or later) for more details. - - You should have received a copy of the GNU General Public License (version 2) - along with this program; if not, write to the Free Software Foundation, - Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -*/ -#ifndef PA_AUDIO_OUTPUT_H -#define PA_AUDIO_OUTPUT_H - -#include - -#include "../globals.h" -#include "../Misc/Master.h" - -void PAaudiooutputinit(Master *master_); -void PAfinish(); - -#endif - diff --git a/plugins/zynaddsubfx/src/Output/Recorder.cpp b/plugins/zynaddsubfx/src/Output/Recorder.cpp deleted file mode 100644 index 244047ce8..000000000 --- a/plugins/zynaddsubfx/src/Output/Recorder.cpp +++ /dev/null @@ -1,113 +0,0 @@ -/* - ZynAddSubFX - a software synthesizer - - Recorder.cpp - Records sound to a file - Copyright (C) 2002-2005 Nasca Octavian Paul - Author: Nasca Octavian Paul - - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License - as published by the Free Software Foundation. - - 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 (version 2 or later) for more details. - - You should have received a copy of the GNU General Public License (version 2) - along with this program; if not, write to the Free Software Foundation, - Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -*/ - -#include -#include "Recorder.h" - -Recorder::Recorder() -{ - recordbuf_16bit = new short int [SOUND_BUFFER_SIZE * 2]; - status = 0; - notetrigger = 0; - for(int i = 0; i < SOUND_BUFFER_SIZE * 2; i++) - recordbuf_16bit[i] = 0; -} - -Recorder::~Recorder() -{ - if(recording() == 1) - stop(); - delete [] recordbuf_16bit; -} - -int Recorder::preparefile(std::string filename_, int overwrite) -{ - if(!overwrite) { - struct stat fileinfo; - int statr; - statr = stat(filename_.c_str(), &fileinfo); - if(statr == 0) //file exists - return 1; - } - - if(!wav.newfile(filename_, SAMPLE_RATE, 2)) - return 2; - - status = 1; //ready - - return 0; -} - -void Recorder::start() -{ - notetrigger = 0; - status = 2; //recording -} - -void Recorder::stop() -{ - wav.close(); - status = 0; -} - -void Recorder::pause() -{ - status = 0; -} - -int Recorder::recording() -{ - if((status == 2) && (notetrigger != 0)) - return 1; - else - return 0; -} - -void Recorder::recordbuffer(REALTYPE *outl, REALTYPE *outr) -{ - int tmp; - if(status != 2) - return; - for(int i = 0; i < SOUND_BUFFER_SIZE; i++) { - tmp = (int)(outl[i] * 32767.0); - if(tmp < -32768) - tmp = -32768; - if(tmp > 32767) - tmp = 32767; - recordbuf_16bit[i * 2] = tmp; - - tmp = (int)(outr[i] * 32767.0); - if(tmp < -32768) - tmp = -32768; - if(tmp > 32767) - tmp = 32767; - recordbuf_16bit[i * 2 + 1] = tmp; - } - wav.write_stereo_samples(SOUND_BUFFER_SIZE, recordbuf_16bit); -} - -void Recorder::triggernow() -{ - if(status == 2) - notetrigger = 1; -} - diff --git a/plugins/zynaddsubfx/src/Output/Recorder.h b/plugins/zynaddsubfx/src/Output/Recorder.h deleted file mode 100644 index 997ed3783..000000000 --- a/plugins/zynaddsubfx/src/Output/Recorder.h +++ /dev/null @@ -1,57 +0,0 @@ -/* - ZynAddSubFX - a software synthesizer - - Recorder.h - Records sound to a file - Copyright (C) 2002-2005 Nasca Octavian Paul - Author: Nasca Octavian Paul - - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License - as published by the Free Software Foundation. - - 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 (version 2 or later) for more details. - - You should have received a copy of the GNU General Public License (version 2) - along with this program; if not, write to the Free Software Foundation, - Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -*/ - -#ifndef RECORDER_H -#define RECORDER_H -#include -#include "../globals.h" -#include "WAVaudiooutput.h" - -/**Records sound to a file*/ -class Recorder -{ - public: - - Recorder(); - ~Recorder(); - int preparefile(std::string filename_, int overwrite); //returns 1 if the file exists - void start(); - void stop(); - void pause(); - int recording(); - void triggernow(); - void recordbuffer(REALTYPE *outl, REALTYPE *outr); - - /** Status: - * 0 - not ready(no file selected), - * 1 - ready - * 2 - recording */ - int status; - - private: - WAVaudiooutput wav; - short int *recordbuf_16bit; - int notetrigger; -}; - -#endif - diff --git a/plugins/zynaddsubfx/src/Output/VSTaudiooutput.cpp b/plugins/zynaddsubfx/src/Output/VSTaudiooutput.cpp deleted file mode 100644 index 494a127c0..000000000 --- a/plugins/zynaddsubfx/src/Output/VSTaudiooutput.cpp +++ /dev/null @@ -1,68 +0,0 @@ -/* - ZynAddSubFX - a software synthesizer - - VSTaudiooutput.cpp - Audio output for VST - Copyright (C) 2002 Nasca Octavian Paul - Author: Nasca Octavian Paul - - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License - as published by the Free Software Foundation. - - 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 (version 2 or later) for more details. - - You should have received a copy of the GNU General Public License (version 2) - along with this program; if not, write to the Free Software Foundation, - Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -*/ -#include -#include "VSTaudiooutput.h" - -//the constructor and the destructor are defined in main.cpp - -void VSTSynth::process(float **inputs, float **outputs, long sampleframes) -{ - float *outl = outputs[0]; - float *outr = outputs[1]; - pthread_mutex_lock(&vmaster->mutex); - vmaster->GetAudioOutSamples(sampleframes, (int) getSampleRate(), outl, outr); - pthread_mutex_unlock(&vmaster->mutex); -} - -void VSTSynth::processReplacing(float **inputs, - float **outputs, - long sampleframes) -{ - process(inputs, outputs, sampleframes); -} - -long int VSTSynth::canDo(char *txt) -{ - if(strcmp(txt, "receiveVstEvents") == 0) - return 1; - if(strcmp(txt, "receiveVstMidiEvent") == 0) - return 1; - return -1; -} - -bool VSTSynth::getVendorString(char *txt) -{ - strcpy(txt, "Nasca O. Paul"); - return true; -} - -bool VSTSynth::getProductString(char *txt) -{ - strcpy(txt, "ZynAddSubFX"); - return true; -} - -void VSTSynth::resume() -{ - wantEvents(); -} - diff --git a/plugins/zynaddsubfx/src/Output/VSTaudiooutput.h b/plugins/zynaddsubfx/src/Output/VSTaudiooutput.h deleted file mode 100644 index 1fe0afd13..000000000 --- a/plugins/zynaddsubfx/src/Output/VSTaudiooutput.h +++ /dev/null @@ -1,60 +0,0 @@ -/* - ZynAddSubFX - a software synthesizer - - VSTaudiooutput.h - Audio output for VST - Copyright (C) 2002 Nasca Octavian Paul - Author: Nasca Octavian Paul - - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License - as published by the Free Software Foundation. - - 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 (version 2 or later) for more details. - - You should have received a copy of the GNU General Public License (version 2) - along with this program; if not, write to the Free Software Foundation, - Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -*/ -#ifndef VST_AUDIO_OUTPUT_H -#define VST_AUDIO_OUTPUT_H - -#include - -#include "../globals.h" -#include "../Misc/Master.h" -#include "../UI/MasterUI.h" - -#include "../../../vstsdk2/source/common/audioeffectx.h" - -class VSTSynth:public AudioEffectX -{ - public: - VSTSynth(audioMasterCallback audioMaster); - ~VSTSynth(); - - virtual void process(float **inputs, float **outputs, long sampleframes); - virtual void processReplacing(float **inputs, - float **outputs, - long sampleframes); - virtual long processEvents(VstEvents *events); //this is used for Midi input - virtual long int canDo(char *txt); - virtual bool getVendorString(char *txt); - virtual bool getProductString(char *txt); - virtual void resume(); - - virtual long getChunk(void **data, bool isPreset = false); - virtual long setChunk(void *data, long size, bool isPreset = false); - - MasterUI *ui; - int Pexitprogram; - - Master *vmaster; - pthread_t thr; -}; - -#endif - diff --git a/plugins/zynaddsubfx/src/Output/WAVaudiooutput.cpp b/plugins/zynaddsubfx/src/Output/WAVaudiooutput.cpp deleted file mode 100644 index cc1f87c0e..000000000 --- a/plugins/zynaddsubfx/src/Output/WAVaudiooutput.cpp +++ /dev/null @@ -1,101 +0,0 @@ -/* - Copyright (C) 2006 Nasca Octavian Paul - Author: Nasca Octavian Paul - - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License - as published by the Free Software Foundation. - - 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 (version 2) for more details. - - You should have received a copy of the GNU General Public License (version 2) - along with this program; if not, write to the Free Software Foundation, - Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#include -#include -#include "WAVaudiooutput.h" -using namespace std; - -WAVaudiooutput::WAVaudiooutput() -{ - file = NULL; - sampleswritten = 0; - samplerate = 44100; -} - -WAVaudiooutput::~WAVaudiooutput() -{ - close(); -} - -bool WAVaudiooutput::newfile(string filename, int samplerate, int channels) -{ - /**\todo Move this into the Constructor*/ - close(); //inchide un posibil fisier existent - file = fopen(filename.c_str(), "w"); - if(!file) - return false; - this->samplerate = samplerate; - this->channels = channels; - sampleswritten = 0; - char tmp[44]; - fwrite(tmp, 1, 44, file); - return true; -} - -void WAVaudiooutput::close() -{ - if(file) { - unsigned int chunksize; - rewind(file); - - fwrite("RIFF", 4, 1, file); - chunksize = sampleswritten * 4 + 36; - fwrite(&chunksize, 4, 1, file); - - fwrite("WAVEfmt ", 8, 1, file); - chunksize = 16; - fwrite(&chunksize, 4, 1, file); - unsigned short int formattag = 1; //uncompresed wave - fwrite(&formattag, 2, 1, file); - unsigned short int nchannels = channels; //stereo - fwrite(&nchannels, 2, 1, file); - unsigned int samplerate_ = samplerate; //samplerate - fwrite(&samplerate_, 4, 1, file); - unsigned int bytespersec = samplerate * 2 * channels; //bytes/sec - fwrite(&bytespersec, 4, 1, file); - unsigned short int blockalign = 2 * channels; //2 channels * 16 bits/8 - fwrite(&blockalign, 2, 1, file); - unsigned short int bitspersample = 16; - fwrite(&bitspersample, 2, 1, file); - - fwrite("data", 4, 1, file); - chunksize = sampleswritten * blockalign; - fwrite(&chunksize, 4, 1, file); - - fclose(file); - file = NULL; - } -} - -void WAVaudiooutput::write_stereo_samples(int nsmps, short int *smps) -{ - if(!file) - return; - fwrite(smps, nsmps, 4, file); - sampleswritten += nsmps; -} - -void WAVaudiooutput::write_mono_samples(int nsmps, short int *smps) -{ - if(!file) - return; - fwrite(smps, nsmps, 2, file); - sampleswritten += nsmps; -} - diff --git a/plugins/zynaddsubfx/src/Output/WAVaudiooutput.h b/plugins/zynaddsubfx/src/Output/WAVaudiooutput.h deleted file mode 100644 index 193fb19f3..000000000 --- a/plugins/zynaddsubfx/src/Output/WAVaudiooutput.h +++ /dev/null @@ -1,43 +0,0 @@ -/* - - Copyright (C) 2008 Nasca Octavian Paul - Author: Nasca Octavian Paul - - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License - as published by the Free Software Foundation. - - 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 (version 2) for more details. - - You should have received a copy of the GNU General Public License (version 2) - along with this program; if not, write to the Free Software Foundation, - Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#ifndef WAVOUTPUT_H -#define WAVOUTPUT_H -#include - -class WAVaudiooutput -{ - public: - WAVaudiooutput(); - ~WAVaudiooutput(); - - bool newfile(std::string filename, int samplerate, int channels); - void close(); - - void write_mono_samples(int nsmps, short int *smps); - void write_stereo_samples(int nsmps, short int *smps); - - private: - int sampleswritten; - int samplerate; - int channels; - FILE *file; -}; -#endif - diff --git a/plugins/zynaddsubfx/src/Params/ADnoteParameters.cpp b/plugins/zynaddsubfx/src/Params/ADnoteParameters.cpp deleted file mode 100644 index 91f3449f1..000000000 --- a/plugins/zynaddsubfx/src/Params/ADnoteParameters.cpp +++ /dev/null @@ -1,840 +0,0 @@ -/* - ZynAddSubFX - a software synthesizer - - ADnoteParameters.cpp - Parameters for ADnote (ADsynth) - Copyright (C) 2002-2005 Nasca Octavian Paul - Author: Nasca Octavian Paul - - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License - as published by the Free Software Foundation. - - 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 (version 2 or later) for more details. - - You should have received a copy of the GNU General Public License (version 2) - along with this program; if not, write to the Free Software Foundation, - Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -*/ - -#include -#include -#include - -#include "ADnoteParameters.h" -int ADnote_unison_sizes[] = -{1, 2, 3, 4, 5, 6, 8, 10, 12, 15, 20, 25, 30, 40, 50, 0}; - -ADnoteParameters::ADnoteParameters(FFTwrapper *fft_) - :PresetsArray() -{ - setpresettype("Padsyth"); - fft = fft_; - - GlobalPar.FreqEnvelope = new EnvelopeParams(0, 0); - GlobalPar.FreqEnvelope->ASRinit(64, 50, 64, 60); - GlobalPar.FreqLfo = new LFOParams(70, 0, 64, 0, 0, 0, 0, 0); - - GlobalPar.AmpEnvelope = new EnvelopeParams(64, 1); - GlobalPar.AmpEnvelope->ADSRinit_dB(0, 40, 127, 25); - GlobalPar.AmpLfo = new LFOParams(80, 0, 64, 0, 0, 0, 0, 1); - - GlobalPar.GlobalFilter = new FilterParams(2, 94, 40); - GlobalPar.FilterEnvelope = new EnvelopeParams(0, 1); - GlobalPar.FilterEnvelope->ADSRinit_filter(64, 40, 64, 70, 60, 64); - GlobalPar.FilterLfo = new LFOParams(80, 0, 64, 0, 0, 0, 0, 2); - GlobalPar.Reson = new Resonance(); - - for(int nvoice = 0; nvoice < NUM_VOICES; nvoice++) - EnableVoice(nvoice); - - defaults(); -} - -void ADnoteParameters::defaults() -{ - //Default Parameters - /* Frequency Global Parameters */ - GlobalPar.PStereo = 1; //stereo - GlobalPar.PDetune = 8192; //zero - GlobalPar.PCoarseDetune = 0; - GlobalPar.PDetuneType = 1; - GlobalPar.FreqEnvelope->defaults(); - GlobalPar.FreqLfo->defaults(); - GlobalPar.PBandwidth = 64; - - /* Amplitude Global Parameters */ - GlobalPar.PVolume = 90; - GlobalPar.PPanning = 64; //center - GlobalPar.PAmpVelocityScaleFunction = 64; - GlobalPar.AmpEnvelope->defaults(); - GlobalPar.AmpLfo->defaults(); - GlobalPar.PPunchStrength = 0; - GlobalPar.PPunchTime = 60; - GlobalPar.PPunchStretch = 64; - GlobalPar.PPunchVelocitySensing = 72; - GlobalPar.Hrandgrouping = 0; - - /* Filter Global Parameters*/ - GlobalPar.PFilterVelocityScale = 64; - GlobalPar.PFilterVelocityScaleFunction = 64; - GlobalPar.GlobalFilter->defaults(); - GlobalPar.FilterEnvelope->defaults(); - GlobalPar.FilterLfo->defaults(); - GlobalPar.Reson->defaults(); - - - for(int nvoice = 0; nvoice < NUM_VOICES; nvoice++) - defaults(nvoice); - ; - VoicePar[0].Enabled = 1; -} - -/* - * Defaults a voice - */ -void ADnoteParameters::defaults(int n) -{ - int nvoice = n; - VoicePar[nvoice].Enabled = 0; - - VoicePar[nvoice].Unison_size = 1; - VoicePar[nvoice].Unison_frequency_spread = 60; - VoicePar[nvoice].Unison_stereo_spread = 64; - VoicePar[nvoice].Unison_vibratto = 64; - VoicePar[nvoice].Unison_vibratto_speed = 64; - VoicePar[nvoice].Unison_invert_phase = 0; - - VoicePar[nvoice].Type = 0; - VoicePar[nvoice].Pfixedfreq = 0; - VoicePar[nvoice].PfixedfreqET = 0; - VoicePar[nvoice].Presonance = 1; - VoicePar[nvoice].Pfilterbypass = 0; - VoicePar[nvoice].Pextoscil = -1; - VoicePar[nvoice].PextFMoscil = -1; - VoicePar[nvoice].Poscilphase = 64; - VoicePar[nvoice].PFMoscilphase = 64; - VoicePar[nvoice].PDelay = 0; - VoicePar[nvoice].PVolume = 100; - VoicePar[nvoice].PVolumeminus = 0; - VoicePar[nvoice].PPanning = 64; //center - VoicePar[nvoice].PDetune = 8192; //8192=0 - VoicePar[nvoice].PCoarseDetune = 0; - VoicePar[nvoice].PDetuneType = 0; - VoicePar[nvoice].PFreqLfoEnabled = 0; - VoicePar[nvoice].PFreqEnvelopeEnabled = 0; - VoicePar[nvoice].PAmpEnvelopeEnabled = 0; - VoicePar[nvoice].PAmpLfoEnabled = 0; - VoicePar[nvoice].PAmpVelocityScaleFunction = 127; - VoicePar[nvoice].PFilterEnabled = 0; - VoicePar[nvoice].PFilterEnvelopeEnabled = 0; - VoicePar[nvoice].PFilterLfoEnabled = 0; - VoicePar[nvoice].PFMEnabled = 0; - - //I use the internal oscillator (-1) - VoicePar[nvoice].PFMVoice = -1; - - VoicePar[nvoice].PFMVolume = 90; - VoicePar[nvoice].PFMVolumeDamp = 64; - VoicePar[nvoice].PFMDetune = 8192; - VoicePar[nvoice].PFMCoarseDetune = 0; - VoicePar[nvoice].PFMDetuneType = 0; - VoicePar[nvoice].PFMFreqEnvelopeEnabled = 0; - VoicePar[nvoice].PFMAmpEnvelopeEnabled = 0; - VoicePar[nvoice].PFMVelocityScaleFunction = 64; - - VoicePar[nvoice].OscilSmp->defaults(); - VoicePar[nvoice].FMSmp->defaults(); - - VoicePar[nvoice].AmpEnvelope->defaults(); - VoicePar[nvoice].AmpLfo->defaults(); - - VoicePar[nvoice].FreqEnvelope->defaults(); - VoicePar[nvoice].FreqLfo->defaults(); - - VoicePar[nvoice].VoiceFilter->defaults(); - VoicePar[nvoice].FilterEnvelope->defaults(); - VoicePar[nvoice].FilterLfo->defaults(); - - VoicePar[nvoice].FMFreqEnvelope->defaults(); - VoicePar[nvoice].FMAmpEnvelope->defaults(); -} - - - -/* - * Init the voice parameters - */ -void ADnoteParameters::EnableVoice(int nvoice) -{ - VoicePar[nvoice].OscilSmp = new OscilGen(fft, GlobalPar.Reson); - VoicePar[nvoice].FMSmp = new OscilGen(fft, NULL); - - VoicePar[nvoice].AmpEnvelope = new EnvelopeParams(64, 1); - VoicePar[nvoice].AmpEnvelope->ADSRinit_dB(0, 100, 127, 100); - VoicePar[nvoice].AmpLfo = new LFOParams(90, 32, 64, 0, 0, 30, 0, 1); - - VoicePar[nvoice].FreqEnvelope = new EnvelopeParams(0, 0); - VoicePar[nvoice].FreqEnvelope->ASRinit(30, 40, 64, 60); - VoicePar[nvoice].FreqLfo = new LFOParams(50, 40, 0, 0, 0, 0, 0, 0); - - VoicePar[nvoice].VoiceFilter = new FilterParams(2, 50, 60); - VoicePar[nvoice].FilterEnvelope = new EnvelopeParams(0, 0); - VoicePar[nvoice].FilterEnvelope->ADSRinit_filter(90, 70, 40, 70, 10, 40); - VoicePar[nvoice].FilterLfo = new LFOParams(50, 20, 64, 0, 0, 0, 0, 2); - - VoicePar[nvoice].FMFreqEnvelope = new EnvelopeParams(0, 0); - VoicePar[nvoice].FMFreqEnvelope->ASRinit(20, 90, 40, 80); - VoicePar[nvoice].FMAmpEnvelope = new EnvelopeParams(64, 1); - VoicePar[nvoice].FMAmpEnvelope->ADSRinit(80, 90, 127, 100); -} - -/* - * Get the Multiplier of the fine detunes of the voices - */ -REALTYPE ADnoteParameters::getBandwidthDetuneMultiplier() -{ - REALTYPE bw = (GlobalPar.PBandwidth - 64.0) / 64.0; - bw = pow(2.0, bw * pow(fabs(bw), 0.2) * 5.0); - - return bw; -} - -/* - * Get the unison spread in cents for a voice - */ - -REALTYPE ADnoteParameters::getUnisonFrequencySpreadCents(int nvoice) { - REALTYPE unison_spread = VoicePar[nvoice].Unison_frequency_spread / 127.0; - unison_spread = pow(unison_spread * 2.0, 2.0) * 50.0; //cents - return unison_spread; -} - -/* - * Kill the voice - */ -void ADnoteParameters::KillVoice(int nvoice) -{ - delete (VoicePar[nvoice].OscilSmp); - delete (VoicePar[nvoice].FMSmp); - - delete (VoicePar[nvoice].AmpEnvelope); - delete (VoicePar[nvoice].AmpLfo); - - delete (VoicePar[nvoice].FreqEnvelope); - delete (VoicePar[nvoice].FreqLfo); - - delete (VoicePar[nvoice].VoiceFilter); - delete (VoicePar[nvoice].FilterEnvelope); - delete (VoicePar[nvoice].FilterLfo); - - delete (VoicePar[nvoice].FMFreqEnvelope); - delete (VoicePar[nvoice].FMAmpEnvelope); -} - -ADnoteParameters::~ADnoteParameters() -{ - delete (GlobalPar.FreqEnvelope); - delete (GlobalPar.FreqLfo); - delete (GlobalPar.AmpEnvelope); - delete (GlobalPar.AmpLfo); - delete (GlobalPar.GlobalFilter); - delete (GlobalPar.FilterEnvelope); - delete (GlobalPar.FilterLfo); - delete (GlobalPar.Reson); - - for(int nvoice = 0; nvoice < NUM_VOICES; nvoice++) - KillVoice(nvoice); - ; -} - -int ADnoteParameters::get_unison_size_index(int nvoice) { - int index = 0; - if(nvoice >= NUM_VOICES) - return 0; - int unison = VoicePar[nvoice].Unison_size; - - while(1) { - if(ADnote_unison_sizes[index] >= unison) - return index; - ; - if(ADnote_unison_sizes[index] == 0) - return index - 1; - ; - index++; - } - return 0; -} - -void ADnoteParameters::set_unison_size_index(int nvoice, int index) { - int unison = 1; - for(int i = 0; i <= index; i++) { - unison = ADnote_unison_sizes[i]; - if(unison == 0) { - unison = ADnote_unison_sizes[i - 1]; - break; - } - } - - VoicePar[nvoice].Unison_size = unison; -} - - - -void ADnoteParameters::add2XMLsection(XMLwrapper *xml, int n) -{ - int nvoice = n; - if(nvoice >= NUM_VOICES) - return; - - int oscilused = 0, fmoscilused = 0; //if the oscil or fmoscil are used by another voice - - for(int i = 0; i < NUM_VOICES; i++) { - if(VoicePar[i].Pextoscil == nvoice) - oscilused = 1; - if(VoicePar[i].PextFMoscil == nvoice) - fmoscilused = 1; - } - - xml->addparbool("enabled", VoicePar[nvoice].Enabled); - if(((VoicePar[nvoice].Enabled == 0) && (oscilused == 0) - && (fmoscilused == 0)) && (xml->minimal)) - return; - - - xml->addpar("type", VoicePar[nvoice].Type); - - xml->addpar("unison_size", VoicePar[nvoice].Unison_size); - xml->addpar("unison_frequency_spread", - VoicePar[nvoice].Unison_frequency_spread); - xml->addpar("unison_stereo_spread", VoicePar[nvoice].Unison_stereo_spread); - xml->addpar("unison_vibratto", VoicePar[nvoice].Unison_vibratto); - xml->addpar("unison_vibratto_speed", VoicePar[nvoice].Unison_vibratto_speed); - xml->addpar("unison_invert_phase", VoicePar[nvoice].Unison_invert_phase); - - xml->addpar("delay", VoicePar[nvoice].PDelay); - xml->addparbool("resonance", VoicePar[nvoice].Presonance); - - xml->addpar("ext_oscil", VoicePar[nvoice].Pextoscil); - xml->addpar("ext_fm_oscil", VoicePar[nvoice].PextFMoscil); - - xml->addpar("oscil_phase", VoicePar[nvoice].Poscilphase); - xml->addpar("oscil_fm_phase", VoicePar[nvoice].PFMoscilphase); - - xml->addparbool("filter_enabled", VoicePar[nvoice].PFilterEnabled); - xml->addparbool("filter_bypass", VoicePar[nvoice].Pfilterbypass); - - xml->addpar("fm_enabled", VoicePar[nvoice].PFMEnabled); - - xml->beginbranch("OSCIL"); - VoicePar[nvoice].OscilSmp->add2XML(xml); - xml->endbranch(); - - - xml->beginbranch("AMPLITUDE_PARAMETERS"); - xml->addpar("panning", VoicePar[nvoice].PPanning); - xml->addpar("volume", VoicePar[nvoice].PVolume); - xml->addparbool("volume_minus", VoicePar[nvoice].PVolumeminus); - xml->addpar("velocity_sensing", VoicePar[nvoice].PAmpVelocityScaleFunction); - - xml->addparbool("amp_envelope_enabled", - VoicePar[nvoice].PAmpEnvelopeEnabled); - if((VoicePar[nvoice].PAmpEnvelopeEnabled != 0) || (!xml->minimal)) { - xml->beginbranch("AMPLITUDE_ENVELOPE"); - VoicePar[nvoice].AmpEnvelope->add2XML(xml); - xml->endbranch(); - } - xml->addparbool("amp_lfo_enabled", VoicePar[nvoice].PAmpLfoEnabled); - if((VoicePar[nvoice].PAmpLfoEnabled != 0) || (!xml->minimal)) { - xml->beginbranch("AMPLITUDE_LFO"); - VoicePar[nvoice].AmpLfo->add2XML(xml); - xml->endbranch(); - } - xml->endbranch(); - - xml->beginbranch("FREQUENCY_PARAMETERS"); - xml->addparbool("fixed_freq", VoicePar[nvoice].Pfixedfreq); - xml->addpar("fixed_freq_et", VoicePar[nvoice].PfixedfreqET); - xml->addpar("detune", VoicePar[nvoice].PDetune); - xml->addpar("coarse_detune", VoicePar[nvoice].PCoarseDetune); - xml->addpar("detune_type", VoicePar[nvoice].PDetuneType); - - xml->addparbool("freq_envelope_enabled", - VoicePar[nvoice].PFreqEnvelopeEnabled); - if((VoicePar[nvoice].PFreqEnvelopeEnabled != 0) || (!xml->minimal)) { - xml->beginbranch("FREQUENCY_ENVELOPE"); - VoicePar[nvoice].FreqEnvelope->add2XML(xml); - xml->endbranch(); - } - xml->addparbool("freq_lfo_enabled", VoicePar[nvoice].PFreqLfoEnabled); - if((VoicePar[nvoice].PFreqLfoEnabled != 0) || (!xml->minimal)) { - xml->beginbranch("FREQUENCY_LFO"); - VoicePar[nvoice].FreqLfo->add2XML(xml); - xml->endbranch(); - } - xml->endbranch(); - - - if((VoicePar[nvoice].PFilterEnabled != 0) || (!xml->minimal)) { - xml->beginbranch("FILTER_PARAMETERS"); - xml->beginbranch("FILTER"); - VoicePar[nvoice].VoiceFilter->add2XML(xml); - xml->endbranch(); - - xml->addparbool("filter_envelope_enabled", - VoicePar[nvoice].PFilterEnvelopeEnabled); - if((VoicePar[nvoice].PFilterEnvelopeEnabled != 0) || (!xml->minimal)) { - xml->beginbranch("FILTER_ENVELOPE"); - VoicePar[nvoice].FilterEnvelope->add2XML(xml); - xml->endbranch(); - } - - xml->addparbool("filter_lfo_enabled", - VoicePar[nvoice].PFilterLfoEnabled); - if((VoicePar[nvoice].PFilterLfoEnabled != 0) || (!xml->minimal)) { - xml->beginbranch("FILTER_LFO"); - VoicePar[nvoice].FilterLfo->add2XML(xml); - xml->endbranch(); - } - xml->endbranch(); - } - - if((VoicePar[nvoice].PFMEnabled != 0) || (fmoscilused != 0) - || (!xml->minimal)) { - xml->beginbranch("FM_PARAMETERS"); - xml->addpar("input_voice", VoicePar[nvoice].PFMVoice); - - xml->addpar("volume", VoicePar[nvoice].PFMVolume); - xml->addpar("volume_damp", VoicePar[nvoice].PFMVolumeDamp); - xml->addpar("velocity_sensing", - VoicePar[nvoice].PFMVelocityScaleFunction); - - xml->addparbool("amp_envelope_enabled", - VoicePar[nvoice].PFMAmpEnvelopeEnabled); - if((VoicePar[nvoice].PFMAmpEnvelopeEnabled != 0) || (!xml->minimal)) { - xml->beginbranch("AMPLITUDE_ENVELOPE"); - VoicePar[nvoice].FMAmpEnvelope->add2XML(xml); - xml->endbranch(); - } - xml->beginbranch("MODULATOR"); - xml->addpar("detune", VoicePar[nvoice].PFMDetune); - xml->addpar("coarse_detune", VoicePar[nvoice].PFMCoarseDetune); - xml->addpar("detune_type", VoicePar[nvoice].PFMDetuneType); - - xml->addparbool("freq_envelope_enabled", - VoicePar[nvoice].PFMFreqEnvelopeEnabled); - if((VoicePar[nvoice].PFMFreqEnvelopeEnabled != 0) || (!xml->minimal)) { - xml->beginbranch("FREQUENCY_ENVELOPE"); - VoicePar[nvoice].FMFreqEnvelope->add2XML(xml); - xml->endbranch(); - } - - xml->beginbranch("OSCIL"); - VoicePar[nvoice].FMSmp->add2XML(xml); - xml->endbranch(); - - xml->endbranch(); - xml->endbranch(); - } -} - - -void ADnoteParameters::add2XML(XMLwrapper *xml) -{ - xml->addparbool("stereo", GlobalPar.PStereo); - - xml->beginbranch("AMPLITUDE_PARAMETERS"); - xml->addpar("volume", GlobalPar.PVolume); - xml->addpar("panning", GlobalPar.PPanning); - xml->addpar("velocity_sensing", GlobalPar.PAmpVelocityScaleFunction); - xml->addpar("punch_strength", GlobalPar.PPunchStrength); - xml->addpar("punch_time", GlobalPar.PPunchTime); - xml->addpar("punch_stretch", GlobalPar.PPunchStretch); - xml->addpar("punch_velocity_sensing", GlobalPar.PPunchVelocitySensing); - xml->addpar("harmonic_randomness_grouping", GlobalPar.Hrandgrouping); - - xml->beginbranch("AMPLITUDE_ENVELOPE"); - GlobalPar.AmpEnvelope->add2XML(xml); - xml->endbranch(); - - xml->beginbranch("AMPLITUDE_LFO"); - GlobalPar.AmpLfo->add2XML(xml); - xml->endbranch(); - xml->endbranch(); - - xml->beginbranch("FREQUENCY_PARAMETERS"); - xml->addpar("detune", GlobalPar.PDetune); - - xml->addpar("coarse_detune", GlobalPar.PCoarseDetune); - xml->addpar("detune_type", GlobalPar.PDetuneType); - - xml->addpar("bandwidth", GlobalPar.PBandwidth); - - xml->beginbranch("FREQUENCY_ENVELOPE"); - GlobalPar.FreqEnvelope->add2XML(xml); - xml->endbranch(); - - xml->beginbranch("FREQUENCY_LFO"); - GlobalPar.FreqLfo->add2XML(xml); - xml->endbranch(); - xml->endbranch(); - - - xml->beginbranch("FILTER_PARAMETERS"); - xml->addpar("velocity_sensing_amplitude", GlobalPar.PFilterVelocityScale); - xml->addpar("velocity_sensing", GlobalPar.PFilterVelocityScaleFunction); - - xml->beginbranch("FILTER"); - GlobalPar.GlobalFilter->add2XML(xml); - xml->endbranch(); - - xml->beginbranch("FILTER_ENVELOPE"); - GlobalPar.FilterEnvelope->add2XML(xml); - xml->endbranch(); - - xml->beginbranch("FILTER_LFO"); - GlobalPar.FilterLfo->add2XML(xml); - xml->endbranch(); - xml->endbranch(); - - xml->beginbranch("RESONANCE"); - GlobalPar.Reson->add2XML(xml); - xml->endbranch(); - - for(int nvoice = 0; nvoice < NUM_VOICES; nvoice++) { - xml->beginbranch("VOICE", nvoice); - add2XMLsection(xml, nvoice); - xml->endbranch(); - } -} - - -void ADnoteParameters::getfromXML(XMLwrapper *xml) -{ - GlobalPar.PStereo = xml->getparbool("stereo", GlobalPar.PStereo); - - if(xml->enterbranch("AMPLITUDE_PARAMETERS")) { - GlobalPar.PVolume = xml->getpar127("volume", GlobalPar.PVolume); - GlobalPar.PPanning = xml->getpar127("panning", GlobalPar.PPanning); - GlobalPar.PAmpVelocityScaleFunction = xml->getpar127( - "velocity_sensing", - GlobalPar. - PAmpVelocityScaleFunction); - - GlobalPar.PPunchStrength = xml->getpar127("punch_strength", - GlobalPar.PPunchStrength); - GlobalPar.PPunchTime = xml->getpar127("punch_time", - GlobalPar.PPunchTime); - GlobalPar.PPunchStretch = xml->getpar127("punch_stretch", - GlobalPar.PPunchStretch); - GlobalPar.PPunchVelocitySensing = xml->getpar127( - "punch_velocity_sensing", - GlobalPar.PPunchVelocitySensing); - GlobalPar.Hrandgrouping = xml->getpar127( - "harmonic_randomness_grouping", - GlobalPar.Hrandgrouping); - - if(xml->enterbranch("AMPLITUDE_ENVELOPE")) { - GlobalPar.AmpEnvelope->getfromXML(xml); - xml->exitbranch(); - } - - if(xml->enterbranch("AMPLITUDE_LFO")) { - GlobalPar.AmpLfo->getfromXML(xml); - xml->exitbranch(); - } - - xml->exitbranch(); - } - - if(xml->enterbranch("FREQUENCY_PARAMETERS")) { - GlobalPar.PDetune = xml->getpar("detune", - GlobalPar.PDetune, - 0, - 16383); - GlobalPar.PCoarseDetune = xml->getpar("coarse_detune", - GlobalPar.PCoarseDetune, - 0, - 16383); - GlobalPar.PDetuneType = xml->getpar127("detune_type", - GlobalPar.PDetuneType); - - GlobalPar.PBandwidth = xml->getpar127("bandwidth", - GlobalPar.PBandwidth); - - xml->enterbranch("FREQUENCY_ENVELOPE"); - GlobalPar.FreqEnvelope->getfromXML(xml); - xml->exitbranch(); - - xml->enterbranch("FREQUENCY_LFO"); - GlobalPar.FreqLfo->getfromXML(xml); - xml->exitbranch(); - - xml->exitbranch(); - } - - - if(xml->enterbranch("FILTER_PARAMETERS")) { - GlobalPar.PFilterVelocityScale = xml->getpar127( - "velocity_sensing_amplitude", - GlobalPar.PFilterVelocityScale); - GlobalPar.PFilterVelocityScaleFunction = xml->getpar127( - "velocity_sensing", - GlobalPar.PFilterVelocityScaleFunction); - - xml->enterbranch("FILTER"); - GlobalPar.GlobalFilter->getfromXML(xml); - xml->exitbranch(); - - xml->enterbranch("FILTER_ENVELOPE"); - GlobalPar.FilterEnvelope->getfromXML(xml); - xml->exitbranch(); - - xml->enterbranch("FILTER_LFO"); - GlobalPar.FilterLfo->getfromXML(xml); - xml->exitbranch(); - xml->exitbranch(); - } - - if(xml->enterbranch("RESONANCE")) { - GlobalPar.Reson->getfromXML(xml); - xml->exitbranch(); - } - - for(int nvoice = 0; nvoice < NUM_VOICES; nvoice++) { - VoicePar[nvoice].Enabled = 0; - if(xml->enterbranch("VOICE", nvoice) == 0) - continue; - getfromXMLsection(xml, nvoice); - xml->exitbranch(); - } -} - -void ADnoteParameters::getfromXMLsection(XMLwrapper *xml, int n) -{ - int nvoice = n; - if(nvoice >= NUM_VOICES) - return; - - VoicePar[nvoice].Enabled = xml->getparbool("enabled", 0); - - VoicePar[nvoice].Unison_size = - xml->getpar127("unison_size", VoicePar[nvoice].Unison_size); - VoicePar[nvoice].Unison_frequency_spread = xml->getpar127( - "unison_frequency_spread", - VoicePar[nvoice].Unison_frequency_spread); - VoicePar[nvoice].Unison_stereo_spread = xml->getpar127( - "unison_stereo_spread", - VoicePar[nvoice].Unison_stereo_spread); - VoicePar[nvoice].Unison_vibratto = xml->getpar127( - "unison_vibratto", - VoicePar[nvoice]. - Unison_vibratto); - VoicePar[nvoice].Unison_vibratto_speed = xml->getpar127( - "unison_vibratto_speed", - VoicePar[nvoice].Unison_vibratto_speed); - VoicePar[nvoice].Unison_invert_phase = xml->getpar127( - "unison_invert_phase", - VoicePar[nvoice].Unison_invert_phase); - - VoicePar[nvoice].Type = xml->getpar127("type", - VoicePar[nvoice].Type); - VoicePar[nvoice].PDelay = xml->getpar127("delay", - VoicePar[nvoice].PDelay); - VoicePar[nvoice].Presonance = - xml->getparbool("resonance", VoicePar[nvoice].Presonance); - - VoicePar[nvoice].Pextoscil = xml->getpar("ext_oscil", - -1, - -1, - nvoice - 1); - VoicePar[nvoice].PextFMoscil = xml->getpar("ext_fm_oscil", - -1, - -1, - nvoice - 1); - - VoicePar[nvoice].Poscilphase = - xml->getpar127("oscil_phase", VoicePar[nvoice].Poscilphase); - VoicePar[nvoice].PFMoscilphase = xml->getpar127( - "oscil_fm_phase", - VoicePar[nvoice]. - PFMoscilphase); - - VoicePar[nvoice].PFilterEnabled = xml->getparbool( - "filter_enabled", - VoicePar[nvoice]. - PFilterEnabled); - VoicePar[nvoice].Pfilterbypass = xml->getparbool( - "filter_bypass", - VoicePar[nvoice]. - Pfilterbypass); - - VoicePar[nvoice].PFMEnabled = - xml->getpar127("fm_enabled", VoicePar[nvoice].PFMEnabled); - - if(xml->enterbranch("OSCIL")) { - VoicePar[nvoice].OscilSmp->getfromXML(xml); - xml->exitbranch(); - } - - - if(xml->enterbranch("AMPLITUDE_PARAMETERS")) { - VoicePar[nvoice].PPanning = - xml->getpar127("panning", VoicePar[nvoice].PPanning); - VoicePar[nvoice].PVolume = - xml->getpar127("volume", VoicePar[nvoice].PVolume); - VoicePar[nvoice].PVolumeminus = xml->getparbool( - "volume_minus", - VoicePar[nvoice]. - PVolumeminus); - VoicePar[nvoice].PAmpVelocityScaleFunction = xml->getpar127( - "velocity_sensing", - VoicePar[nvoice].PAmpVelocityScaleFunction); - - VoicePar[nvoice].PAmpEnvelopeEnabled = xml->getparbool( - "amp_envelope_enabled", - VoicePar[nvoice].PAmpEnvelopeEnabled); - if(xml->enterbranch("AMPLITUDE_ENVELOPE")) { - VoicePar[nvoice].AmpEnvelope->getfromXML(xml); - xml->exitbranch(); - } - - VoicePar[nvoice].PAmpLfoEnabled = xml->getparbool( - "amp_lfo_enabled", - VoicePar[nvoice]. - PAmpLfoEnabled); - if(xml->enterbranch("AMPLITUDE_LFO")) { - VoicePar[nvoice].AmpLfo->getfromXML(xml); - xml->exitbranch(); - } - xml->exitbranch(); - } - - if(xml->enterbranch("FREQUENCY_PARAMETERS")) { - VoicePar[nvoice].Pfixedfreq = - xml->getparbool("fixed_freq", VoicePar[nvoice].Pfixedfreq); - VoicePar[nvoice].PfixedfreqET = xml->getpar127( - "fixed_freq_et", - VoicePar[nvoice]. - PfixedfreqET); - - - VoicePar[nvoice].PDetune = xml->getpar("detune", - VoicePar[nvoice].PDetune, - 0, - 16383); - - VoicePar[nvoice].PCoarseDetune = - xml->getpar("coarse_detune", - VoicePar[nvoice].PCoarseDetune, - 0, - 16383); - VoicePar[nvoice].PDetuneType = xml->getpar127( - "detune_type", - VoicePar[nvoice]. - PDetuneType); - - VoicePar[nvoice].PFreqEnvelopeEnabled = xml->getparbool( - "freq_envelope_enabled", - VoicePar[nvoice].PFreqEnvelopeEnabled); - if(xml->enterbranch("FREQUENCY_ENVELOPE")) { - VoicePar[nvoice].FreqEnvelope->getfromXML(xml); - xml->exitbranch(); - } - - VoicePar[nvoice].PFreqLfoEnabled = xml->getparbool( - "freq_lfo_enabled", - VoicePar[nvoice]. - PFreqLfoEnabled); - if(xml->enterbranch("FREQUENCY_LFO")) { - VoicePar[nvoice].FreqLfo->getfromXML(xml); - xml->exitbranch(); - } - xml->exitbranch(); - } - - if(xml->enterbranch("FILTER_PARAMETERS")) { - if(xml->enterbranch("FILTER")) { - VoicePar[nvoice].VoiceFilter->getfromXML(xml); - xml->exitbranch(); - } - - VoicePar[nvoice].PFilterEnvelopeEnabled = xml->getparbool( - "filter_envelope_enabled", - VoicePar[nvoice].PFilterEnvelopeEnabled); - if(xml->enterbranch("FILTER_ENVELOPE")) { - VoicePar[nvoice].FilterEnvelope->getfromXML(xml); - xml->exitbranch(); - } - - VoicePar[nvoice].PFilterLfoEnabled = xml->getparbool( - "filter_lfo_enabled", - VoicePar[nvoice].PFilterLfoEnabled); - if(xml->enterbranch("FILTER_LFO")) { - VoicePar[nvoice].FilterLfo->getfromXML(xml); - xml->exitbranch(); - } - xml->exitbranch(); - } - - if(xml->enterbranch("FM_PARAMETERS")) { - VoicePar[nvoice].PFMVoice = - xml->getpar("input_voice", - VoicePar[nvoice].PFMVoice, - -1, - nvoice - 1); - - VoicePar[nvoice].PFMVolume = - xml->getpar127("volume", VoicePar[nvoice].PFMVolume); - VoicePar[nvoice].PFMVolumeDamp = xml->getpar127( - "volume_damp", - VoicePar[nvoice]. - PFMVolumeDamp); - VoicePar[nvoice].PFMVelocityScaleFunction = xml->getpar127( - "velocity_sensing", - VoicePar[nvoice].PFMVelocityScaleFunction); - - VoicePar[nvoice].PFMAmpEnvelopeEnabled = xml->getparbool( - "amp_envelope_enabled", - VoicePar[nvoice].PFMAmpEnvelopeEnabled); - if(xml->enterbranch("AMPLITUDE_ENVELOPE")) { - VoicePar[nvoice].FMAmpEnvelope->getfromXML(xml); - xml->exitbranch(); - } - - if(xml->enterbranch("MODULATOR")) { - VoicePar[nvoice].PFMDetune = - xml->getpar("detune", VoicePar[nvoice].PFMDetune, 0, 16383); - VoicePar[nvoice].PFMCoarseDetune = xml->getpar( - "coarse_detune", - VoicePar[nvoice]. - PFMCoarseDetune, - 0, - 16383); - VoicePar[nvoice].PFMDetuneType = xml->getpar127( - "detune_type", - VoicePar[nvoice]. - PFMDetuneType); - - VoicePar[nvoice].PFMFreqEnvelopeEnabled = xml->getparbool( - "freq_envelope_enabled", - VoicePar[nvoice].PFMFreqEnvelopeEnabled); - if(xml->enterbranch("FREQUENCY_ENVELOPE")) { - VoicePar[nvoice].FMFreqEnvelope->getfromXML(xml); - xml->exitbranch(); - } - - if(xml->enterbranch("OSCIL")) { - VoicePar[nvoice].FMSmp->getfromXML(xml); - xml->exitbranch(); - } - - xml->exitbranch(); - } - xml->exitbranch(); - } -} - diff --git a/plugins/zynaddsubfx/src/Params/ADnoteParameters.h b/plugins/zynaddsubfx/src/Params/ADnoteParameters.h deleted file mode 100644 index e63efcff3..000000000 --- a/plugins/zynaddsubfx/src/Params/ADnoteParameters.h +++ /dev/null @@ -1,307 +0,0 @@ -/* - ZynAddSubFX - a software synthesizer - - ADnoteParameters.h - Parameters for ADnote (ADsynth) - Copyright (C) 2002-2005 Nasca Octavian Paul - Author: Nasca Octavian Paul - - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License - as published by the Free Software Foundation. - - 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 (version 2 or later) for more details. - - You should have received a copy of the GNU General Public License (version 2) - along with this program; if not, write to the Free Software Foundation, - Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -*/ - -#ifndef AD_NOTE_PARAMETERS_H -#define AD_NOTE_PARAMETERS_H - - -#include "../globals.h" -#include "EnvelopeParams.h" -#include "LFOParams.h" -#include "FilterParams.h" -#include "../Synth/OscilGen.h" -#include "../Synth/Resonance.h" -#include "../Misc/Util.h" -#include "../Misc/XMLwrapper.h" -#include "../DSP/FFTwrapper.h" -#include "PresetsArray.h" - -enum FMTYPE { - NONE, MORPH, RING_MOD, PHASE_MOD, FREQ_MOD, PITCH_MOD -}; -extern int ADnote_unison_sizes[]; - -/*****************************************************************/ -/* GLOBAL PARAMETERS */ -/*****************************************************************/ - -struct ADnoteGlobalParam { - /* The instrument type - MONO/STEREO - If the mode is MONO, the panning of voices are not used - Stereo=1, Mono=0. */ - - unsigned char PStereo; - - - /****************************************** - * FREQUENCY GLOBAL PARAMETERS * - ******************************************/ - unsigned short int PDetune; //fine detune - unsigned short int PCoarseDetune; //coarse detune+octave - unsigned char PDetuneType; //detune type - - unsigned char PBandwidth; //how much the relative fine detunes of the voices are changed - - EnvelopeParams *FreqEnvelope; //Frequency Envelope - - LFOParams *FreqLfo; //Frequency LFO - - /******************************************** - * AMPLITUDE GLOBAL PARAMETERS * - ********************************************/ - - /* Panning - 0 - random - 1 - left - 64 - center - 127 - right */ - unsigned char PPanning; - - unsigned char PVolume; - - unsigned char PAmpVelocityScaleFunction; - - EnvelopeParams *AmpEnvelope; - - LFOParams *AmpLfo; - - unsigned char PPunchStrength, PPunchTime, PPunchStretch, - PPunchVelocitySensing; - - /****************************************** - * FILTER GLOBAL PARAMETERS * - ******************************************/ - FilterParams *GlobalFilter; - - // filter velocity sensing - unsigned char PFilterVelocityScale; - - // filter velocity sensing - unsigned char PFilterVelocityScaleFunction; - - EnvelopeParams *FilterEnvelope; - - LFOParams *FilterLfo; - - // RESONANCE - Resonance *Reson; - - //how the randomness is applied to the harmonics on more voices using the same oscillator - unsigned char Hrandgrouping; -}; - - - -/***********************************************************/ -/* VOICE PARAMETERS */ -/***********************************************************/ -struct ADnoteVoiceParam { - /** If the voice is enabled */ - unsigned char Enabled; - - /** How many subvoices are used in this voice */ - unsigned char Unison_size; - - /** How subvoices are spread */ - unsigned char Unison_frequency_spread; - - /** Stereo spread of the subvoices*/ - unsigned char Unison_stereo_spread; - - /** Vibratto of the subvoices (which makes the unison more "natural")*/ - unsigned char Unison_vibratto; - - /** Medium speed of the vibratto of the subvoices*/ - unsigned char Unison_vibratto_speed; - - /** Unison invert phase */ - unsigned char Unison_invert_phase; //0=none,1=random,2=50%,3=33%,4=25% - - /** Type of the voice (0=Sound,1=Noise)*/ - unsigned char Type; - - /** Voice Delay */ - unsigned char PDelay; - - /** If the resonance is enabled for this voice */ - unsigned char Presonance; - - // What external oscil should I use, -1 for internal OscilSmp&FMSmp - short int Pextoscil, PextFMoscil; - // it is not allowed that the externoscil,externFMoscil => current voice - - // oscillator phases - unsigned char Poscilphase, PFMoscilphase; - - // filter bypass - unsigned char Pfilterbypass; - - /** Voice oscillator */ - OscilGen *OscilSmp; - - /********************************** - * FREQUENCY PARAMETERS * - **********************************/ - - /** If the base frequency is fixed to 440 Hz*/ - unsigned char Pfixedfreq; - - /* Equal temperate (this is used only if the Pfixedfreq is enabled) - If this parameter is 0, the frequency is fixed (to 440 Hz); - if this parameter is 64, 1 MIDI halftone -> 1 frequency halftone */ - unsigned char PfixedfreqET; - - /** Fine detune */ - unsigned short int PDetune; - - /** Coarse detune + octave */ - unsigned short int PCoarseDetune; - - /** Detune type */ - unsigned char PDetuneType; - - /* Frequency Envelope */ - unsigned char PFreqEnvelopeEnabled; - EnvelopeParams *FreqEnvelope; - - /* Frequency LFO */ - unsigned char PFreqLfoEnabled; - LFOParams *FreqLfo; - - - /*************************** - * AMPLITUDE PARAMETERS * - ***************************/ - - /* Panning 0 - random - 1 - left - 64 - center - 127 - right - The Panning is ignored if the instrument is mono */ - unsigned char PPanning; - - /* Voice Volume */ - unsigned char PVolume; - - /* If the Volume negative */ - unsigned char PVolumeminus; - - /* Velocity sensing */ - unsigned char PAmpVelocityScaleFunction; - - /* Amplitude Envelope */ - unsigned char PAmpEnvelopeEnabled; - EnvelopeParams *AmpEnvelope; - - /* Amplitude LFO */ - unsigned char PAmpLfoEnabled; - LFOParams *AmpLfo; - - - - /************************* - * FILTER PARAMETERS * - *************************/ - - /* Voice Filter */ - unsigned char PFilterEnabled; - FilterParams *VoiceFilter; - - /* Filter Envelope */ - unsigned char PFilterEnvelopeEnabled; - EnvelopeParams *FilterEnvelope; - - /* LFO Envelope */ - unsigned char PFilterLfoEnabled; - LFOParams *FilterLfo; - - /**************************** - * MODULLATOR PARAMETERS * - ****************************/ - - /* Modullator Parameters (0=off,1=Morph,2=RM,3=PM,4=FM.. */ - unsigned char PFMEnabled; - - /* Voice that I use as modullator instead of FMSmp. - It is -1 if I use FMSmp(default). - It maynot be equal or bigger than current voice */ - short int PFMVoice; - - /* Modullator oscillator */ - OscilGen *FMSmp; - - /* Modullator Volume */ - unsigned char PFMVolume; - - /* Modullator damping at higher frequencies */ - unsigned char PFMVolumeDamp; - - /* Modullator Velocity Sensing */ - unsigned char PFMVelocityScaleFunction; - - /* Fine Detune of the Modullator*/ - unsigned short int PFMDetune; - - /* Coarse Detune of the Modullator */ - unsigned short int PFMCoarseDetune; - - /* The detune type */ - unsigned char PFMDetuneType; - - /* Frequency Envelope of the Modullator */ - unsigned char PFMFreqEnvelopeEnabled; - EnvelopeParams *FMFreqEnvelope; - - /* Frequency Envelope of the Modullator */ - unsigned char PFMAmpEnvelopeEnabled; - EnvelopeParams *FMAmpEnvelope; -}; - -class ADnoteParameters : public PresetsArray -{ - public: - ADnoteParameters(FFTwrapper *fft_); - ~ADnoteParameters(); - - ADnoteGlobalParam GlobalPar; - ADnoteVoiceParam VoicePar[NUM_VOICES]; - - void defaults(); - void add2XML(XMLwrapper *xml); - void getfromXML(XMLwrapper *xml); - - REALTYPE getBandwidthDetuneMultiplier(); - REALTYPE getUnisonFrequencySpreadCents(int nvoice); - int get_unison_size_index(int nvoice); - void set_unison_size_index(int nvoice, int index); - private: - void defaults(int n); //n is the nvoice - - void EnableVoice(int nvoice); - void KillVoice(int nvoice); - FFTwrapper *fft; - - void add2XMLsection(XMLwrapper *xml, int n); - void getfromXMLsection(XMLwrapper *xml, int n); -}; - -#endif - diff --git a/plugins/zynaddsubfx/src/Params/CMakeLists.txt b/plugins/zynaddsubfx/src/Params/CMakeLists.txt deleted file mode 100644 index 670fcf26d..000000000 --- a/plugins/zynaddsubfx/src/Params/CMakeLists.txt +++ /dev/null @@ -1,19 +0,0 @@ -set(zynaddsubfx_params_SRCS - ADnoteParameters.cpp - Controller.cpp - EnvelopeParams.cpp - FilterParams.cpp - LFOParams.cpp - PADnoteParameters.cpp - Presets.cpp - PresetsArray.cpp - PresetsStore.cpp - SUBnoteParameters.cpp - -) - -add_library(zynaddsubfx_params STATIC - ${zynaddsubfx_params_SRCS} - ) - -target_link_libraries(zynaddsubfx_params)# ${ASOUND_LIBRARY}) diff --git a/plugins/zynaddsubfx/src/Params/Controller.cpp b/plugins/zynaddsubfx/src/Params/Controller.cpp deleted file mode 100644 index e3fb70d8c..000000000 --- a/plugins/zynaddsubfx/src/Params/Controller.cpp +++ /dev/null @@ -1,415 +0,0 @@ -/* - ZynAddSubFX - a software synthesizer - - Controller.cpp - (Midi) Controllers implementation - Copyright (C) 2002-2005 Nasca Octavian Paul - Author: Nasca Octavian Paul - - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License - as published by the Free Software Foundation. - - 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 (version 2 or later) for more details. - - You should have received a copy of the GNU General Public License (version 2) - along with this program; if not, write to the Free Software Foundation, - Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -*/ - -#include "Controller.h" -#include -#include - -Controller::Controller() -{ - defaults(); - resetall(); -} - -Controller::~Controller() -{} - -void Controller::defaults() -{ - setpitchwheelbendrange(100); //2 halftones - expression.receive = 1; - panning.depth = 64; - filtercutoff.depth = 64; - filterq.depth = 64; - bandwidth.depth = 64; - bandwidth.exponential = 0; - modwheel.depth = 80; - modwheel.exponential = 0; - fmamp.receive = 1; - volume.receive = 1; - sustain.receive = 1; - NRPN.receive = 1; - - portamento.portamento = 0; - portamento.used = 0; - portamento.proportional = 0; - portamento.propRate = 80; - portamento.propDepth = 90; - portamento.receive = 1; - portamento.time = 64; - portamento.updowntimestretch = 64; - portamento.pitchthresh = 3; - portamento.pitchthreshtype = 1; - portamento.noteusing = -1; - resonancecenter.depth = 64; - resonancebandwidth.depth = 64; - - initportamento(440.0, 440.0, false); // Now has a third argument - setportamento(0); -} - -void Controller::resetall() -{ - setpitchwheel(0); //center - setexpression(127); - setpanning(64); - setfiltercutoff(64); - setfilterq(64); - setbandwidth(64); - setmodwheel(64); - setfmamp(127); - setvolume(127); - setsustain(0); - setresonancecenter(64); - setresonancebw(64); - - //reset the NRPN - NRPN.parhi = -1; - NRPN.parlo = -1; - NRPN.valhi = -1; - NRPN.vallo = -1; -} - -void Controller::setpitchwheel(int value) -{ - pitchwheel.data = value; - REALTYPE cents = value / 8192.0; - cents *= pitchwheel.bendrange; - pitchwheel.relfreq = pow(2, cents / 1200.0); - //fprintf(stderr,"%ld %ld -> %.3f\n",pitchwheel.bendrange,pitchwheel.data,pitchwheel.relfreq);fflush(stderr); -} - -void Controller::setpitchwheelbendrange(unsigned short int value) -{ - pitchwheel.bendrange = value; -} - -void Controller::setexpression(int value) -{ - expression.data = value; - if(expression.receive != 0) - expression.relvolume = value / 127.0; - else - expression.relvolume = 1.0; -} - -void Controller::setpanning(int value) -{ - panning.data = value; - panning.pan = (value / 128.0 - 0.5) * (panning.depth / 64.0); -} - -void Controller::setfiltercutoff(int value) -{ - filtercutoff.data = value; - filtercutoff.relfreq = - (value - 64.0) * filtercutoff.depth / 4096.0 * 3.321928; //3.3219..=ln2(10) -} - -void Controller::setfilterq(int value) -{ - filterq.data = value; - filterq.relq = pow(30.0, (value - 64.0) / 64.0 * (filterq.depth / 64.0)); -} - -void Controller::setbandwidth(int value) -{ - bandwidth.data = value; - if(bandwidth.exponential == 0) { - REALTYPE tmp = pow(25.0, pow(bandwidth.depth / 127.0, 1.5)) - 1.0; - if((value < 64) && (bandwidth.depth >= 64)) - tmp = 1.0; - bandwidth.relbw = (value / 64.0 - 1.0) * tmp + 1.0; - if(bandwidth.relbw < 0.01) - bandwidth.relbw = 0.01; - } - else - bandwidth.relbw = - pow(25.0, (value - 64.0) / 64.0 * (bandwidth.depth / 64.0)); - ; -} - -void Controller::setmodwheel(int value) -{ - modwheel.data = value; - if(modwheel.exponential == 0) { - REALTYPE tmp = pow(25.0, pow(modwheel.depth / 127.0, 1.5) * 2.0) / 25.0; - if((value < 64) && (modwheel.depth >= 64)) - tmp = 1.0; - modwheel.relmod = (value / 64.0 - 1.0) * tmp + 1.0; - if(modwheel.relmod < 0.0) - modwheel.relmod = 0.0; - } - else - modwheel.relmod = - pow(25.0, (value - 64.0) / 64.0 * (modwheel.depth / 80.0)); -} - -void Controller::setfmamp(int value) -{ - fmamp.data = value; - fmamp.relamp = value / 127.0; - if(fmamp.receive != 0) - fmamp.relamp = value / 127.0; - else - fmamp.relamp = 1.0; -} - -void Controller::setvolume(int value) -{ - volume.data = value; - if(volume.receive != 0) - volume.volume = pow(0.1, (127 - value) / 127.0 * 2.0); - else - volume.volume = 1.0; -} - -void Controller::setsustain(int value) -{ - sustain.data = value; - if(sustain.receive != 0) - sustain.sustain = ((value < 64) ? 0 : 1); - else - sustain.sustain = 0; -} - -void Controller::setportamento(int value) -{ - portamento.data = value; - if(portamento.receive != 0) - portamento.portamento = ((value < 64) ? 0 : 1); -} - -int Controller::initportamento(REALTYPE oldfreq, - REALTYPE newfreq, - bool legatoflag) -{ - portamento.x = 0.0; - - if(legatoflag) { // Legato in progress - if(portamento.portamento == 0) - return 0; - } - else // No legato, do the original if...return - if((portamento.used != 0) || (portamento.portamento == 0)) - return 0; - ; - - REALTYPE portamentotime = pow(100.0, portamento.time / 127.0) / 50.0; //portamento time in seconds - - if(portamento.proportional) { - //If there is a min(float,float) and a max(float,float) then they - //could be used here - //Linear functors could also make this nicer - if(oldfreq > newfreq) //2 is the center of propRate - portamentotime *= - pow(oldfreq / newfreq / (portamento.propRate / 127.0 * 3 + .05), - (portamento.propDepth / 127.0 * 1.6 + .2)); - else //1 is the center of propDepth - portamentotime *= - pow(newfreq / oldfreq / (portamento.propRate / 127.0 * 3 + .05), - (portamento.propDepth / 127.0 * 1.6 + .2)); - } - - if((portamento.updowntimestretch >= 64) && (newfreq < oldfreq)) { - if(portamento.updowntimestretch == 127) - return 0; - portamentotime *= pow(0.1, (portamento.updowntimestretch - 64) / 63.0); - } - if((portamento.updowntimestretch < 64) && (newfreq > oldfreq)) { - if(portamento.updowntimestretch == 0) - return 0; - portamentotime *= pow(0.1, (64.0 - portamento.updowntimestretch) / 64.0); - } - - //printf("%f->%f : Time %f\n",oldfreq,newfreq,portamentotime); - - portamento.dx = SOUND_BUFFER_SIZE / (portamentotime * SAMPLE_RATE); - portamento.origfreqrap = oldfreq / newfreq; - - REALTYPE tmprap = ((portamento.origfreqrap > 1.0) ? - (portamento.origfreqrap) : - (1.0 / portamento.origfreqrap)); - - REALTYPE thresholdrap = pow(2.0, portamento.pitchthresh / 12.0); - if((portamento.pitchthreshtype == 0) && (tmprap - 0.00001 > thresholdrap)) - return 0; - if((portamento.pitchthreshtype == 1) && (tmprap + 0.00001 < thresholdrap)) - return 0; - - portamento.used = 1; - portamento.freqrap = portamento.origfreqrap; - return 1; -} - -void Controller::updateportamento() -{ - if(portamento.used == 0) - return; - - portamento.x += portamento.dx; - if(portamento.x > 1.0) { - portamento.x = 1.0; - portamento.used = 0; - } - portamento.freqrap = - (1.0 - portamento.x) * portamento.origfreqrap + portamento.x; -} - - -void Controller::setresonancecenter(int value) -{ - resonancecenter.data = value; - resonancecenter.relcenter = - pow(3.0, (value - 64.0) / 64.0 * (resonancecenter.depth / 64.0)); -} -void Controller::setresonancebw(int value) -{ - resonancebandwidth.data = value; - resonancebandwidth.relbw = - pow(1.5, (value - 64.0) / 64.0 * (resonancebandwidth.depth / 127.0)); -} - - -//Returns 0 if there is NRPN or 1 if there is not -int Controller::getnrpn(int *parhi, int *parlo, int *valhi, int *vallo) -{ - if(NRPN.receive == 0) - return 1; - if((NRPN.parhi < 0) || (NRPN.parlo < 0) || (NRPN.valhi < 0) - || (NRPN.vallo < 0)) - return 1; - - *parhi = NRPN.parhi; - *parlo = NRPN.parlo; - *valhi = NRPN.valhi; - *vallo = NRPN.vallo; - return 0; -} - - -void Controller::setparameternumber(unsigned int type, int value) -{ - switch(type) { - case C_nrpnhi: - NRPN.parhi = value; - NRPN.valhi = -1; - NRPN.vallo = -1; //clear the values - break; - case C_nrpnlo: - NRPN.parlo = value; - NRPN.valhi = -1; - NRPN.vallo = -1; //clear the values - break; - case C_dataentryhi: - if((NRPN.parhi >= 0) && (NRPN.parlo >= 0)) - NRPN.valhi = value; - break; - case C_dataentrylo: - if((NRPN.parhi >= 0) && (NRPN.parlo >= 0)) - NRPN.vallo = value; - break; - } -} - - - -void Controller::add2XML(XMLwrapper *xml) -{ - xml->addpar("pitchwheel_bendrange", pitchwheel.bendrange); - - xml->addparbool("expression_receive", expression.receive); - xml->addpar("panning_depth", panning.depth); - xml->addpar("filter_cutoff_depth", filtercutoff.depth); - xml->addpar("filter_q_depth", filterq.depth); - xml->addpar("bandwidth_depth", bandwidth.depth); - xml->addpar("mod_wheel_depth", modwheel.depth); - xml->addparbool("mod_wheel_exponential", modwheel.exponential); - xml->addparbool("fm_amp_receive", fmamp.receive); - xml->addparbool("volume_receive", volume.receive); - xml->addparbool("sustain_receive", sustain.receive); - - xml->addparbool("portamento_receive", portamento.receive); - xml->addpar("portamento_time", portamento.time); - xml->addpar("portamento_pitchthresh", portamento.pitchthresh); - xml->addpar("portamento_pitchthreshtype", portamento.pitchthreshtype); - xml->addpar("portamento_portamento", portamento.portamento); - xml->addpar("portamento_updowntimestretch", portamento.updowntimestretch); - xml->addpar("portamento_proportional", portamento.proportional); - xml->addpar("portamento_proprate", portamento.propRate); - xml->addpar("portamento_propdepth", portamento.propDepth); - - xml->addpar("resonance_center_depth", resonancecenter.depth); - xml->addpar("resonance_bandwidth_depth", resonancebandwidth.depth); -} - -void Controller::getfromXML(XMLwrapper *xml) -{ - pitchwheel.bendrange = xml->getpar("pitchwheel_bendrange", - pitchwheel.bendrange, - -6400, - 6400); - - expression.receive = xml->getparbool("expression_receive", - expression.receive); - panning.depth = xml->getpar127("panning_depth", panning.depth); - filtercutoff.depth = xml->getpar127("filter_cutoff_depth", - filtercutoff.depth); - filterq.depth = xml->getpar127("filter_q_depth", filterq.depth); - bandwidth.depth = xml->getpar127("bandwidth_depth", bandwidth.depth); - modwheel.depth = xml->getpar127("mod_wheel_depth", modwheel.depth); - modwheel.exponential = xml->getparbool("mod_wheel_exponential", - modwheel.exponential); - fmamp.receive = xml->getparbool("fm_amp_receive", - fmamp.receive); - volume.receive = xml->getparbool("volume_receive", - volume.receive); - sustain.receive = xml->getparbool("sustain_receive", - sustain.receive); - - portamento.receive = xml->getparbool("portamento_receive", - portamento.receive); - portamento.time = xml->getpar127("portamento_time", - portamento.time); - portamento.pitchthresh = xml->getpar127("portamento_pitchthresh", - portamento.pitchthresh); - portamento.pitchthreshtype = xml->getpar127("portamento_pitchthreshtype", - portamento.pitchthreshtype); - portamento.portamento = xml->getpar127("portamento_portamento", - portamento.portamento); - portamento.updowntimestretch = xml->getpar127( - "portamento_updowntimestretch", - portamento.updowntimestretch); - portamento.proportional = xml->getpar127("portamento_proportional", - portamento.proportional); - portamento.propRate = xml->getpar127("portamento_proprate", - portamento.propRate); - portamento.propDepth = xml->getpar127("portamento_propdepth", - portamento.propDepth); - - - resonancecenter.depth = xml->getpar127("resonance_center_depth", - resonancecenter.depth); - resonancebandwidth.depth = xml->getpar127("resonance_bandwidth_depth", - resonancebandwidth.depth); -} - diff --git a/plugins/zynaddsubfx/src/Params/Controller.h b/plugins/zynaddsubfx/src/Params/Controller.h deleted file mode 100644 index 86a4badbb..000000000 --- a/plugins/zynaddsubfx/src/Params/Controller.h +++ /dev/null @@ -1,221 +0,0 @@ -/* - ZynAddSubFX - a software synthesizer - - Controller.h - (Midi) Controllers implementation - Copyright (C) 2002-2005 Nasca Octavian Paul - Author: Nasca Octavian Paul - - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License - as published by the Free Software Foundation. - - 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 (version 2 or later) for more details. - - You should have received a copy of the GNU General Public License (version 2) - along with this program; if not, write to the Free Software Foundation, - Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -*/ - - -#ifndef CONTROLLER_H -#define CONTROLLER_H - -#include "../globals.h" -#include "../Misc/XMLwrapper.h" - -/**(Midi) Controllers implementation*/ -class Controller -{ - public: - Controller(); - ~Controller(); - void resetall(); - - void add2XML(XMLwrapper *xml); - void defaults(); - void getfromXML(XMLwrapper *xml); - - //Controllers functions - void setpitchwheel(int value); - void setpitchwheelbendrange(unsigned short int value); - void setexpression(int value); - void setpanning(int value); - void setfiltercutoff(int value); - void setfilterq(int value); - void setbandwidth(int value); - void setmodwheel(int value); - void setfmamp(int value); - void setvolume(int value); - void setsustain(int value); - /**Enable or disable portamento - * @param value 0-127 MIDI value (greater than 64 enables)*/ - void setportamento(int value); - void setresonancecenter(int value); - void setresonancebw(int value); - - - void setparameternumber(unsigned int type, int value); //used for RPN and NRPN's - int getnrpn(int *parhi, int *parlo, int *valhi, int *vallo); - - /** - * Initialize a portamento - * - * @param oldfreq Starting frequency of the portamento (Hz) - * @param newfreq Ending frequency of the portamento (Hz) - * @param legatoflag true when legato is in progress, false otherwise - * @returns 1 if properly initialized, 0 otherwise*/ - int initportamento(REALTYPE oldfreq, REALTYPE newfreq, bool legatoflag); - /**Update portamento's freqrap to next value based upon dx*/ - void updateportamento(); - - // Controllers values - struct { //Pitch Wheel - int data; - short int bendrange; //bendrange is in cents - REALTYPE relfreq; //the relative frequency (default is 1.0) - } pitchwheel; - - struct { //Expression - int data; - REALTYPE relvolume; - unsigned char receive; - } expression; - - struct { //Panning - int data; - REALTYPE pan; - unsigned char depth; - } panning; - - - struct { //Filter cutoff - int data; - REALTYPE relfreq; - unsigned char depth; - } filtercutoff; - - struct { //Filter Q - int data; - REALTYPE relq; - unsigned char depth; - } filterq; - - struct { //Bandwidth - int data; - REALTYPE relbw; - unsigned char depth; - unsigned char exponential; - } bandwidth; - - struct { //Modulation Wheel - int data; - REALTYPE relmod; - unsigned char depth; - unsigned char exponential; - } modwheel; - - struct { //FM amplitude - int data; - REALTYPE relamp; - unsigned char receive; - } fmamp; - - struct { //Volume - int data; - REALTYPE volume; - unsigned char receive; - } volume; - - struct { //Sustain - int data, sustain; - unsigned char receive; - } sustain; - - struct { /** - -#include -#include -#include "EnvelopeParams.h" - -EnvelopeParams::EnvelopeParams(unsigned char Penvstretch_, - unsigned char Pforcedrelease_):Presets() -{ - int i; - - PA_dt = 10; - PD_dt = 10; - PR_dt = 10; - PA_val = 64; - PD_val = 64; - PS_val = 64; - PR_val = 64; - - for(i = 0; i < MAX_ENVELOPE_POINTS; i++) { - Penvdt[i] = 32; - Penvval[i] = 64; - } - Penvdt[0] = 0; //no used - Penvsustain = 1; - Penvpoints = 1; - Envmode = 1; - Penvstretch = Penvstretch_; - Pforcedrelease = Pforcedrelease_; - Pfreemode = 1; - Plinearenvelope = 0; - - store2defaults(); -} - -EnvelopeParams::~EnvelopeParams() -{} - -REALTYPE EnvelopeParams::getdt(char i) -{ - REALTYPE result = (pow(2.0, Penvdt[(int)i] / 127.0 * 12.0) - 1.0) * 10.0; //miliseconds - return result; -} - - -/* - * ADSR/ASR... initialisations - */ -void EnvelopeParams::ADSRinit(char A_dt, char D_dt, char S_val, char R_dt) -{ - setpresettype("Penvamplitude"); - Envmode = 1; - PA_dt = A_dt; - PD_dt = D_dt; - PS_val = S_val; - PR_dt = R_dt; - Pfreemode = 0; - converttofree(); - - store2defaults(); -} - -void EnvelopeParams::ADSRinit_dB(char A_dt, char D_dt, char S_val, char R_dt) -{ - setpresettype("Penvamplitude"); - Envmode = 2; - PA_dt = A_dt; - PD_dt = D_dt; - PS_val = S_val; - PR_dt = R_dt; - Pfreemode = 0; - converttofree(); - - store2defaults(); -} - -void EnvelopeParams::ASRinit(char A_val, char A_dt, char R_val, char R_dt) -{ - setpresettype("Penvfrequency"); - Envmode = 3; - PA_val = A_val; - PA_dt = A_dt; - PR_val = R_val; - PR_dt = R_dt; - Pfreemode = 0; - converttofree(); - - store2defaults(); -} - -void EnvelopeParams::ADSRinit_filter(char A_val, - char A_dt, - char D_val, - char D_dt, - char R_dt, - char R_val) -{ - setpresettype("Penvfilter"); - Envmode = 4; - PA_val = A_val; - PA_dt = A_dt; - PD_val = D_val; - PD_dt = D_dt; - PR_dt = R_dt; - PR_val = R_val; - Pfreemode = 0; - converttofree(); - store2defaults(); -} - -void EnvelopeParams::ASRinit_bw(char A_val, char A_dt, char R_val, char R_dt) -{ - setpresettype("Penvbandwidth"); - Envmode = 5; - PA_val = A_val; - PA_dt = A_dt; - PR_val = R_val; - PR_dt = R_dt; - Pfreemode = 0; - converttofree(); - store2defaults(); -} - -/* - * Convert the Envelope to freemode - */ -void EnvelopeParams::converttofree() -{ - switch(Envmode) { - case 1: - Penvpoints = 4; - Penvsustain = 2; - Penvval[0] = 0; - Penvdt[1] = PA_dt; - Penvval[1] = 127; - Penvdt[2] = PD_dt; - Penvval[2] = PS_val; - Penvdt[3] = PR_dt; - Penvval[3] = 0; - break; - case 2: - Penvpoints = 4; - Penvsustain = 2; - Penvval[0] = 0; - Penvdt[1] = PA_dt; - Penvval[1] = 127; - Penvdt[2] = PD_dt; - Penvval[2] = PS_val; - Penvdt[3] = PR_dt; - Penvval[3] = 0; - break; - case 3: - Penvpoints = 3; - Penvsustain = 1; - Penvval[0] = PA_val; - Penvdt[1] = PA_dt; - Penvval[1] = 64; - Penvdt[2] = PR_dt; - Penvval[2] = PR_val; - break; - case 4: - Penvpoints = 4; - Penvsustain = 2; - Penvval[0] = PA_val; - Penvdt[1] = PA_dt; - Penvval[1] = PD_val; - Penvdt[2] = PD_dt; - Penvval[2] = 64; - Penvdt[3] = PR_dt; - Penvval[3] = PR_val; - break; - case 5: - Penvpoints = 3; - Penvsustain = 1; - Penvval[0] = PA_val; - Penvdt[1] = PA_dt; - Penvval[1] = 64; - Penvdt[2] = PR_dt; - Penvval[2] = PR_val; - break; - } -} - - - - -void EnvelopeParams::add2XML(XMLwrapper *xml) -{ - xml->addparbool("free_mode", Pfreemode); - xml->addpar("env_points", Penvpoints); - xml->addpar("env_sustain", Penvsustain); - xml->addpar("env_stretch", Penvstretch); - xml->addparbool("forced_release", Pforcedrelease); - xml->addparbool("linear_envelope", Plinearenvelope); - xml->addpar("A_dt", PA_dt); - xml->addpar("D_dt", PD_dt); - xml->addpar("R_dt", PR_dt); - xml->addpar("A_val", PA_val); - xml->addpar("D_val", PD_val); - xml->addpar("S_val", PS_val); - xml->addpar("R_val", PR_val); - - if((Pfreemode != 0) || (!xml->minimal)) { - for(int i = 0; i < Penvpoints; i++) { - xml->beginbranch("POINT", i); - if(i != 0) - xml->addpar("dt", Penvdt[i]); - xml->addpar("val", Penvval[i]); - xml->endbranch(); - } - } -} - - - -void EnvelopeParams::getfromXML(XMLwrapper *xml) -{ - Pfreemode = xml->getparbool("free_mode", Pfreemode); - Penvpoints = xml->getpar127("env_points", Penvpoints); - Penvsustain = xml->getpar127("env_sustain", Penvsustain); - Penvstretch = xml->getpar127("env_stretch", Penvstretch); - Pforcedrelease = xml->getparbool("forced_release", Pforcedrelease); - Plinearenvelope = xml->getparbool("linear_envelope", Plinearenvelope); - - PA_dt = xml->getpar127("A_dt", PA_dt); - PD_dt = xml->getpar127("D_dt", PD_dt); - PR_dt = xml->getpar127("R_dt", PR_dt); - PA_val = xml->getpar127("A_val", PA_val); - PD_val = xml->getpar127("D_val", PD_val); - PS_val = xml->getpar127("S_val", PS_val); - PR_val = xml->getpar127("R_val", PR_val); - - for(int i = 0; i < Penvpoints; i++) { - if(xml->enterbranch("POINT", i) == 0) - continue; - if(i != 0) - Penvdt[i] = xml->getpar127("dt", Penvdt[i]); - Penvval[i] = xml->getpar127("val", Penvval[i]); - xml->exitbranch(); - } - - if(!Pfreemode) - converttofree(); -} - - -void EnvelopeParams::defaults() -{ - Penvstretch = Denvstretch; - Pforcedrelease = Dforcedrelease; - Plinearenvelope = Dlinearenvelope; - PA_dt = DA_dt; - PD_dt = DD_dt; - PR_dt = DR_dt; - PA_val = DA_val; - PD_val = DD_val; - PS_val = DS_val; - PR_val = DR_val; - Pfreemode = 0; - converttofree(); -} - -void EnvelopeParams::store2defaults() -{ - Denvstretch = Penvstretch; - Dforcedrelease = Pforcedrelease; - Dlinearenvelope = Plinearenvelope; - DA_dt = PA_dt; - DD_dt = PD_dt; - DR_dt = PR_dt; - DA_val = PA_val; - DD_val = PD_val; - DS_val = PS_val; - DR_val = PR_val; -} - diff --git a/plugins/zynaddsubfx/src/Params/EnvelopeParams.h b/plugins/zynaddsubfx/src/Params/EnvelopeParams.h deleted file mode 100644 index 3a1c06aa0..000000000 --- a/plugins/zynaddsubfx/src/Params/EnvelopeParams.h +++ /dev/null @@ -1,90 +0,0 @@ -/* - ZynAddSubFX - a software synthesizer - - EnvelopeParams.h - Parameters for Envelope - Copyright (C) 2002-2005 Nasca Octavian Paul - Author: Nasca Octavian Paul - - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License - as published by the Free Software Foundation. - - 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 (version 2 or later) for more details. - - You should have received a copy of the GNU General Public License (version 2) - along with this program; if not, write to the Free Software Foundation, - Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -*/ - -#ifndef ENVELOPE_PARAMS_H -#define ENVELOPE_PARAMS_H - -#include "../globals.h" -#include "../Misc/XMLwrapper.h" -#include "Presets.h" - -#define MAX_ENVELOPE_POINTS 40 -#define MIN_ENVELOPE_DB -400 - -class EnvelopeParams:public Presets -{ - public: - EnvelopeParams(unsigned char Penvstretch_, - unsigned char Pforcedrelease_); - ~EnvelopeParams(); - void ADSRinit(char A_dt, char D_dt, char S_val, char R_dt); - void ADSRinit_dB(char A_dt, char D_dt, char S_val, char R_dt); - void ASRinit(char A_val, char A_dt, char R_val, char R_dt); - void ADSRinit_filter(char A_val, - char A_dt, - char D_val, - char D_dt, - char R_dt, - char R_val); - void ASRinit_bw(char A_val, char A_dt, char R_val, char R_dt); - void converttofree(); - - void add2XML(XMLwrapper *xml); - void defaults(); - void getfromXML(XMLwrapper *xml); - - REALTYPE getdt(char i); - - /* MIDI Parameters */ - unsigned char Pfreemode; //1 daca este in modul free sau 0 daca este in mod ADSR,ASR,... - unsigned char Penvpoints; - unsigned char Penvsustain; //127 pentru dezactivat - unsigned char Penvdt[MAX_ENVELOPE_POINTS]; - unsigned char Penvval[MAX_ENVELOPE_POINTS]; - unsigned char Penvstretch; //64=normal stretch (piano-like), 0=no stretch - unsigned char Pforcedrelease; //0 - OFF, 1 - ON - unsigned char Plinearenvelope; //if the amplitude envelope is linear - - unsigned char PA_dt, PD_dt, PR_dt, - PA_val, PD_val, PS_val, PR_val; - - - - int Envmode; // 1 for ADSR parameters (linear amplitude) - // 2 for ADSR_dB parameters (dB amplitude) - // 3 for ASR parameters (frequency LFO) - // 4 for ADSR_filter parameters (filter parameters) - // 5 for ASR_bw parameters (bandwidth parameters) - - private: - void store2defaults(); - - /* Default parameters */ - unsigned char Denvstretch; - unsigned char Dforcedrelease; - unsigned char Dlinearenvelope; - unsigned char DA_dt, DD_dt, DR_dt, - DA_val, DD_val, DS_val, DR_val; -}; - -#endif - diff --git a/plugins/zynaddsubfx/src/Params/FilterParams.cpp b/plugins/zynaddsubfx/src/Params/FilterParams.cpp deleted file mode 100644 index 6f87bc1a3..000000000 --- a/plugins/zynaddsubfx/src/Params/FilterParams.cpp +++ /dev/null @@ -1,392 +0,0 @@ -/* - ZynAddSubFX - a software synthesizer - - FilterParams.cpp - Parameters for filter - Copyright (C) 2002-2005 Nasca Octavian Paul - Author: Nasca Octavian Paul - - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License - as published by the Free Software Foundation. - - 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 (version 2 or later) for more details. - - You should have received a copy of the GNU General Public License (version 2) - along with this program; if not, write to the Free Software Foundation, - Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -*/ - -#include -#include -#include -#include "FilterParams.h" - -FilterParams::FilterParams(unsigned char Ptype_, - unsigned char Pfreq_, - unsigned char Pq_) - : PresetsArray() -{ - setpresettype("Pfilter"); - Dtype = Ptype_; - Dfreq = Pfreq_; - Dq = Pq_; - - changed = false; - defaults(); -} - -FilterParams::~FilterParams() -{} - - -void FilterParams::defaults() -{ - Ptype = Dtype; - Pfreq = Dfreq; - Pq = Dq; - - Pstages = 0; - Pfreqtrack = 64; - Pgain = 64; - Pcategory = 0; - - Pnumformants = 3; - Pformantslowness = 64; - for(int j = 0; j < FF_MAX_VOWELS; j++) - defaults(j); - ; - - Psequencesize = 3; - for(int i = 0; i < FF_MAX_SEQUENCE; i++) - Psequence[i].nvowel = i % FF_MAX_VOWELS; - - Psequencestretch = 40; - Psequencereversed = 0; - Pcenterfreq = 64; //1 kHz - Poctavesfreq = 64; - Pvowelclearness = 64; -} - -void FilterParams::defaults(int n) -{ - int j = n; - for(int i = 0; i < FF_MAX_FORMANTS; i++) { - Pvowels[j].formants[i].freq = (int)(RND * 127.0); //some random freqs - Pvowels[j].formants[i].q = 64; - Pvowels[j].formants[i].amp = 127; - } -} - - -/* - * Get the parameters from other FilterParams - */ - -void FilterParams::getfromFilterParams(FilterParams *pars) -{ - defaults(); - - if(pars == NULL) - return; - - Ptype = pars->Ptype; - Pfreq = pars->Pfreq; - Pq = pars->Pq; - - Pstages = pars->Pstages; - Pfreqtrack = pars->Pfreqtrack; - Pgain = pars->Pgain; - Pcategory = pars->Pcategory; - - Pnumformants = pars->Pnumformants; - Pformantslowness = pars->Pformantslowness; - for(int j = 0; j < FF_MAX_VOWELS; j++) { - for(int i = 0; i < FF_MAX_FORMANTS; i++) { - Pvowels[j].formants[i].freq = pars->Pvowels[j].formants[i].freq; - Pvowels[j].formants[i].q = pars->Pvowels[j].formants[i].q; - Pvowels[j].formants[i].amp = pars->Pvowels[j].formants[i].amp; - } - } - - Psequencesize = pars->Psequencesize; - for(int i = 0; i < FF_MAX_SEQUENCE; i++) - Psequence[i].nvowel = pars->Psequence[i].nvowel; - - Psequencestretch = pars->Psequencestretch; - Psequencereversed = pars->Psequencereversed; - Pcenterfreq = pars->Pcenterfreq; - Poctavesfreq = pars->Poctavesfreq; - Pvowelclearness = pars->Pvowelclearness; -} - - -/* - * Parameter control - */ -REALTYPE FilterParams::getfreq() -{ - return (Pfreq / 64.0 - 1.0) * 5.0; -} - -REALTYPE FilterParams::getq() -{ - return exp(pow((REALTYPE) Pq / 127.0, 2) * log(1000.0)) - 0.9; -} -REALTYPE FilterParams::getfreqtracking(REALTYPE notefreq) -{ - return log(notefreq / 440.0) * (Pfreqtrack - 64.0) / (64.0 * LOG_2); -} - -REALTYPE FilterParams::getgain() -{ - return (Pgain / 64.0 - 1.0) * 30.0; //-30..30dB -} - -/* - * Get the center frequency of the formant's graph - */ -REALTYPE FilterParams::getcenterfreq() -{ - return 10000.0 * pow(10, -(1.0 - Pcenterfreq / 127.0) * 2.0); -} - -/* - * Get the number of octave that the formant functions applies to - */ -REALTYPE FilterParams::getoctavesfreq() -{ - return 0.25 + 10.0 * Poctavesfreq / 127.0; -} - -/* - * Get the frequency from x, where x is [0..1] - */ -REALTYPE FilterParams::getfreqx(REALTYPE x) -{ - if(x > 1.0) - x = 1.0; - REALTYPE octf = pow(2.0, getoctavesfreq()); - return getcenterfreq() / sqrt(octf) * pow(octf, x); -} - -/* - * Get the x coordinate from frequency (used by the UI) - */ -REALTYPE FilterParams::getfreqpos(REALTYPE freq) -{ - return (log(freq) - log(getfreqx(0.0))) / log(2.0) / getoctavesfreq(); -} - - -/* - * Get the freq. response of the formant filter - */ -void FilterParams::formantfilterH(int nvowel, int nfreqs, REALTYPE *freqs) -{ - REALTYPE c[3], d[3]; - REALTYPE filter_freq, filter_q, filter_amp; - REALTYPE omega, sn, cs, alpha; - - for(int i = 0; i < nfreqs; i++) - freqs[i] = 0.0; - - //for each formant... - for(int nformant = 0; nformant < Pnumformants; nformant++) { - //compute formant parameters(frequency,amplitude,etc.) - filter_freq = getformantfreq(Pvowels[nvowel].formants[nformant].freq); - filter_q = getformantq(Pvowels[nvowel].formants[nformant].q) * getq(); - if(Pstages > 0) - filter_q = - (filter_q > 1.0 ? pow(filter_q, 1.0 / (Pstages + 1)) : filter_q); - - filter_amp = getformantamp(Pvowels[nvowel].formants[nformant].amp); - - - if(filter_freq <= (SAMPLE_RATE / 2 - 100.0)) { - omega = 2 * PI * filter_freq / SAMPLE_RATE; - sn = sin(omega); - cs = cos(omega); - alpha = sn / (2 * filter_q); - REALTYPE tmp = 1 + alpha; - c[0] = alpha / tmp *sqrt(filter_q + 1); - c[1] = 0; - c[2] = -alpha / tmp *sqrt(filter_q + 1); - d[1] = -2 * cs / tmp * (-1); - d[2] = (1 - alpha) / tmp * (-1); - } - else - continue; - - - for(int i = 0; i < nfreqs; i++) { - REALTYPE freq = getfreqx(i / (REALTYPE) nfreqs); - if(freq > SAMPLE_RATE / 2) { - for(int tmp = i; tmp < nfreqs; tmp++) - freqs[tmp] = 0.0; - break; - } - REALTYPE fr = freq / SAMPLE_RATE * PI * 2.0; - REALTYPE x = c[0], y = 0.0; - for(int n = 1; n < 3; n++) { - x += cos(n * fr) * c[n]; - y -= sin(n * fr) * c[n]; - } - REALTYPE h = x * x + y * y; - x = 1.0; - y = 0.0; - for(int n = 1; n < 3; n++) { - x -= cos(n * fr) * d[n]; - y += sin(n * fr) * d[n]; - } - h = h / (x * x + y * y); - - freqs[i] += pow(h, (Pstages + 1.0) / 2.0) * filter_amp; - } - } - for(int i = 0; i < nfreqs; i++) { - if(freqs[i] > 0.000000001) - freqs[i] = rap2dB(freqs[i]) + getgain(); - else - freqs[i] = -90.0; - } -} - -/* - * Transforms a parameter to the real value - */ -REALTYPE FilterParams::getformantfreq(unsigned char freq) -{ - REALTYPE result = getfreqx(freq / 127.0); - return result; -} - -REALTYPE FilterParams::getformantamp(unsigned char amp) -{ - REALTYPE result = pow(0.1, (1.0 - amp / 127.0) * 4.0); - return result; -} - -REALTYPE FilterParams::getformantq(unsigned char q) -{ - //temp - REALTYPE result = pow(25.0, (q - 32.0) / 64.0); - return result; -} - - - -void FilterParams::add2XMLsection(XMLwrapper *xml, int n) -{ - int nvowel = n; - for(int nformant = 0; nformant < FF_MAX_FORMANTS; nformant++) { - xml->beginbranch("FORMANT", nformant); - xml->addpar("freq", Pvowels[nvowel].formants[nformant].freq); - xml->addpar("amp", Pvowels[nvowel].formants[nformant].amp); - xml->addpar("q", Pvowels[nvowel].formants[nformant].q); - xml->endbranch(); - } -} - -void FilterParams::add2XML(XMLwrapper *xml) -{ - //filter parameters - xml->addpar("category", Pcategory); - xml->addpar("type", Ptype); - xml->addpar("freq", Pfreq); - xml->addpar("q", Pq); - xml->addpar("stages", Pstages); - xml->addpar("freq_track", Pfreqtrack); - xml->addpar("gain", Pgain); - - //formant filter parameters - if((Pcategory == 1) || (!xml->minimal)) { - xml->beginbranch("FORMANT_FILTER"); - xml->addpar("num_formants", Pnumformants); - xml->addpar("formant_slowness", Pformantslowness); - xml->addpar("vowel_clearness", Pvowelclearness); - xml->addpar("center_freq", Pcenterfreq); - xml->addpar("octaves_freq", Poctavesfreq); - for(int nvowel = 0; nvowel < FF_MAX_VOWELS; nvowel++) { - xml->beginbranch("VOWEL", nvowel); - add2XMLsection(xml, nvowel); - xml->endbranch(); - } - xml->addpar("sequence_size", Psequencesize); - xml->addpar("sequence_stretch", Psequencestretch); - xml->addparbool("sequence_reversed", Psequencereversed); - for(int nseq = 0; nseq < FF_MAX_SEQUENCE; nseq++) { - xml->beginbranch("SEQUENCE_POS", nseq); - xml->addpar("vowel_id", Psequence[nseq].nvowel); - xml->endbranch(); - } - xml->endbranch(); - } -} - - -void FilterParams::getfromXMLsection(XMLwrapper *xml, int n) -{ - int nvowel = n; - for(int nformant = 0; nformant < FF_MAX_FORMANTS; nformant++) { - if(xml->enterbranch("FORMANT", nformant) == 0) - continue; - Pvowels[nvowel].formants[nformant].freq = xml->getpar127( - "freq", - Pvowels[nvowel - ].formants[nformant].freq); - Pvowels[nvowel].formants[nformant].amp = xml->getpar127( - "amp", - Pvowels[nvowel - ].formants[nformant].amp); - Pvowels[nvowel].formants[nformant].q = - xml->getpar127("q", Pvowels[nvowel].formants[nformant].q); - xml->exitbranch(); - } -} - -void FilterParams::getfromXML(XMLwrapper *xml) -{ - //filter parameters - Pcategory = xml->getpar127("category", Pcategory); - Ptype = xml->getpar127("type", Ptype); - Pfreq = xml->getpar127("freq", Pfreq); - Pq = xml->getpar127("q", Pq); - Pstages = xml->getpar127("stages", Pstages); - Pfreqtrack = xml->getpar127("freq_track", Pfreqtrack); - Pgain = xml->getpar127("gain", Pgain); - - //formant filter parameters - if(xml->enterbranch("FORMANT_FILTER")) { - Pnumformants = xml->getpar127("num_formants", Pnumformants); - Pformantslowness = xml->getpar127("formant_slowness", Pformantslowness); - Pvowelclearness = xml->getpar127("vowel_clearness", Pvowelclearness); - Pcenterfreq = xml->getpar127("center_freq", Pcenterfreq); - Poctavesfreq = xml->getpar127("octaves_freq", Poctavesfreq); - - for(int nvowel = 0; nvowel < FF_MAX_VOWELS; nvowel++) { - if(xml->enterbranch("VOWEL", nvowel) == 0) - continue; - getfromXMLsection(xml, nvowel); - xml->exitbranch(); - } - Psequencesize = xml->getpar127("sequence_size", Psequencesize); - Psequencestretch = xml->getpar127("sequence_stretch", Psequencestretch); - Psequencereversed = xml->getparbool("sequence_reversed", - Psequencereversed); - for(int nseq = 0; nseq < FF_MAX_SEQUENCE; nseq++) { - if(xml->enterbranch("SEQUENCE_POS", nseq) == 0) - continue; - Psequence[nseq].nvowel = xml->getpar("vowel_id", - Psequence[nseq].nvowel, - 0, - FF_MAX_VOWELS - 1); - xml->exitbranch(); - } - xml->exitbranch(); - } -} - diff --git a/plugins/zynaddsubfx/src/Params/FilterParams.h b/plugins/zynaddsubfx/src/Params/FilterParams.h deleted file mode 100644 index 8facbe58c..000000000 --- a/plugins/zynaddsubfx/src/Params/FilterParams.h +++ /dev/null @@ -1,103 +0,0 @@ -/* - ZynAddSubFX - a software synthesizer - - FilterParams.h - Parameters for filter - Copyright (C) 2002-2005 Nasca Octavian Paul - Author: Nasca Octavian Paul - - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License - as published by the Free Software Foundation. - - 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 (version 2 or later) for more details. - - You should have received a copy of the GNU General Public License (version 2) - along with this program; if not, write to the Free Software Foundation, - Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -*/ - -#ifndef FILTER_PARAMS_H -#define FILTER_PARAMS_H - -#include "../globals.h" -#include "../Misc/XMLwrapper.h" -#include "PresetsArray.h" - -class FilterParams : public PresetsArray -{ - public: - FilterParams(unsigned char Ptype_, - unsigned char Pfreq, - unsigned char Pq_); - ~FilterParams(); - - void add2XML(XMLwrapper *xml); - void add2XMLsection(XMLwrapper *xml, int n); - void defaults(); - void getfromXML(XMLwrapper *xml); - void getfromXMLsection(XMLwrapper *xml, int n); - - - void getfromFilterParams(FilterParams *pars); - - REALTYPE getfreq(); - REALTYPE getq(); - REALTYPE getfreqtracking(REALTYPE notefreq); - REALTYPE getgain(); - - unsigned char Pcategory; //Filter category (Analog/Formant/StVar) - unsigned char Ptype; // Filter type (for analog lpf,hpf,bpf..) - unsigned char Pfreq; // Frequency (64-central frequency) - unsigned char Pq; // Q parameters (resonance or bandwidth) - unsigned char Pstages; //filter stages+1 - unsigned char Pfreqtrack; //how the filter frequency is changing according the note frequency - unsigned char Pgain; //filter's output gain - - //Formant filter parameters - unsigned char Pnumformants; //how many formants are used - unsigned char Pformantslowness; //how slow varies the formants - unsigned char Pvowelclearness; //how vowels are kept clean (how much try to avoid "mixed" vowels) - unsigned char Pcenterfreq, Poctavesfreq; //the center frequency of the res. func., and the number of octaves - - struct { - struct { - unsigned char freq, amp, q; //frequency,amplitude,Q - } formants[FF_MAX_FORMANTS]; - } Pvowels[FF_MAX_VOWELS]; - - - unsigned char Psequencesize; //how many vowels are in the sequence - unsigned char Psequencestretch; //how the sequence is stretched (how the input from filter envelopes/LFOs/etc. is "stretched") - unsigned char Psequencereversed; //if the input from filter envelopes/LFOs/etc. is reversed(negated) - struct { - unsigned char nvowel; //the vowel from the position - } Psequence[FF_MAX_SEQUENCE]; - - REALTYPE getcenterfreq(); - REALTYPE getoctavesfreq(); - REALTYPE getfreqpos(REALTYPE freq); - REALTYPE getfreqx(REALTYPE x); - - void formantfilterH(int nvowel, int nfreqs, REALTYPE *freqs); //used by UI - - REALTYPE getformantfreq(unsigned char freq); - REALTYPE getformantamp(unsigned char amp); - REALTYPE getformantq(unsigned char q); - - bool changed; - - private: - void defaults(int n); - - //stored default parameters - unsigned char Dtype; - unsigned char Dfreq; - unsigned char Dq; -}; - -#endif - diff --git a/plugins/zynaddsubfx/src/Params/LFOParams.cpp b/plugins/zynaddsubfx/src/Params/LFOParams.cpp deleted file mode 100644 index 33028defc..000000000 --- a/plugins/zynaddsubfx/src/Params/LFOParams.cpp +++ /dev/null @@ -1,105 +0,0 @@ -/* - ZynAddSubFX - a software synthesizer - - LFOParams.cpp - Parameters for LFO - Copyright (C) 2002-2005 Nasca Octavian Paul - Author: Nasca Octavian Paul - - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License - as published by the Free Software Foundation. - - 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 (version 2 or later) for more details. - - You should have received a copy of the GNU General Public License (version 2) - along with this program; if not, write to the Free Software Foundation, - Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -*/ - -#include -#include -#include "../globals.h" -#include "LFOParams.h" - -int LFOParams::time; - -LFOParams::LFOParams(char Pfreq_, - char Pintensity_, - char Pstartphase_, - char PLFOtype_, - char Prandomness_, - char Pdelay_, - char Pcontinous_, - char fel_):Presets() -{ - switch(fel_) { - case 0: - setpresettype("Plfofrequency"); - break; - case 1: - setpresettype("Plfoamplitude"); - break; - case 2: - setpresettype("Plfofilter"); - break; - } - Dfreq = Pfreq_; - Dintensity = Pintensity_; - Dstartphase = Pstartphase_; - DLFOtype = PLFOtype_; - Drandomness = Prandomness_; - Ddelay = Pdelay_; - Dcontinous = Pcontinous_; - fel = fel_; - time = 0; - - defaults(); -} - -LFOParams::~LFOParams() -{} - -void LFOParams::defaults() -{ - Pfreq = Dfreq / 127.0; - Pintensity = Dintensity; - Pstartphase = Dstartphase; - PLFOtype = DLFOtype; - Prandomness = Drandomness; - Pdelay = Ddelay; - Pcontinous = Dcontinous; - Pfreqrand = 0; - Pstretch = 64; -} - - -void LFOParams::add2XML(XMLwrapper *xml) -{ - xml->addparreal("freq", Pfreq); - xml->addpar("intensity", Pintensity); - xml->addpar("start_phase", Pstartphase); - xml->addpar("lfo_type", PLFOtype); - xml->addpar("randomness_amplitude", Prandomness); - xml->addpar("randomness_frequency", Pfreqrand); - xml->addpar("delay", Pdelay); - xml->addpar("stretch", Pstretch); - xml->addparbool("continous", Pcontinous); -} - -void LFOParams::getfromXML(XMLwrapper *xml) -{ - Pfreq = xml->getparreal("freq", Pfreq, 0.0, 1.0); - Pintensity = xml->getpar127("intensity", Pintensity); - Pstartphase = xml->getpar127("start_phase", Pstartphase); - PLFOtype = xml->getpar127("lfo_type", PLFOtype); - Prandomness = xml->getpar127("randomness_amplitude", Prandomness); - Pfreqrand = xml->getpar127("randomness_frequency", Pfreqrand); - Pdelay = xml->getpar127("delay", Pdelay); - Pstretch = xml->getpar127("stretch", Pstretch); - Pcontinous = xml->getparbool("continous", Pcontinous); -} - diff --git a/plugins/zynaddsubfx/src/Params/LFOParams.h b/plugins/zynaddsubfx/src/Params/LFOParams.h deleted file mode 100644 index 6a7dcd915..000000000 --- a/plugins/zynaddsubfx/src/Params/LFOParams.h +++ /dev/null @@ -1,72 +0,0 @@ -/* - ZynAddSubFX - a software synthesizer - - LFOParams.h - Parameters for LFO - Copyright (C) 2002-2005 Nasca Octavian Paul - Author: Nasca Octavian Paul - - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License - as published by the Free Software Foundation. - - 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 (version 2 or later) for more details. - - You should have received a copy of the GNU General Public License (version 2) - along with this program; if not, write to the Free Software Foundation, - Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -*/ - -#ifndef LFO_PARAMS_H -#define LFO_PARAMS_H - -#include "../Misc/XMLwrapper.h" -#include "Presets.h" - -class LFOParams:public Presets -{ - public: - LFOParams(char Pfreq_, - char Pintensity_, - char Pstartphase_, - char PLFOtype_, - char Prandomness_, - char Pdelay_, - char Pcontinous, - char fel_); - ~LFOParams(); - - void add2XML(XMLwrapper *xml); - void defaults(); - /**Loads the LFO from the xml*/ - void getfromXML(XMLwrapper *xml); - - /* MIDI Parameters*/ - REALTYPE Pfreq; /** -#include "PADnoteParameters.h" -#include "../Output/WAVaudiooutput.h" -using namespace std; - -PADnoteParameters::PADnoteParameters(FFTwrapper *fft_, - pthread_mutex_t *mutex_):Presets() -{ - setpresettype("Ppadsyth"); - - fft = fft_; - mutex = mutex_; - - resonance = new Resonance(); - oscilgen = new OscilGen(fft_, resonance); - oscilgen->ADvsPAD = true; - - FreqEnvelope = new EnvelopeParams(0, 0); - FreqEnvelope->ASRinit(64, 50, 64, 60); - FreqLfo = new LFOParams(70, 0, 64, 0, 0, 0, 0, 0); - - AmpEnvelope = new EnvelopeParams(64, 1); - AmpEnvelope->ADSRinit_dB(0, 40, 127, 25); - AmpLfo = new LFOParams(80, 0, 64, 0, 0, 0, 0, 1); - - GlobalFilter = new FilterParams(2, 94, 40); - FilterEnvelope = new EnvelopeParams(0, 1); - FilterEnvelope->ADSRinit_filter(64, 40, 64, 70, 60, 64); - FilterLfo = new LFOParams(80, 0, 64, 0, 0, 0, 0, 2); - - for(int i = 0; i < PAD_MAX_SAMPLES; i++) - sample[i].smp = NULL; - newsample.smp = NULL; - - defaults(); -} - -PADnoteParameters::~PADnoteParameters() -{ - deletesamples(); - delete (oscilgen); - delete (resonance); - - delete (FreqEnvelope); - delete (FreqLfo); - delete (AmpEnvelope); - delete (AmpLfo); - delete (GlobalFilter); - delete (FilterEnvelope); - delete (FilterLfo); -} - -void PADnoteParameters::defaults() -{ - Pmode = 0; - Php.base.type = 0; - Php.base.par1 = 80; - Php.freqmult = 0; - Php.modulator.par1 = 0; - Php.modulator.freq = 30; - Php.width = 127; - Php.amp.type = 0; - Php.amp.mode = 0; - Php.amp.par1 = 80; - Php.amp.par2 = 64; - Php.autoscale = true; - Php.onehalf = 0; - - setPbandwidth(500); - Pbwscale = 0; - - resonance->defaults(); - oscilgen->defaults(); - - Phrpos.type = 0; - Phrpos.par1 = 64; - Phrpos.par2 = 64; - Phrpos.par3 = 0; - - Pquality.samplesize = 3; - Pquality.basenote = 4; - Pquality.oct = 3; - Pquality.smpoct = 2; - - PStereo = 1; //stereo - /* Frequency Global Parameters */ - Pfixedfreq = 0; - PfixedfreqET = 0; - PDetune = 8192; //zero - PCoarseDetune = 0; - PDetuneType = 1; - FreqEnvelope->defaults(); - FreqLfo->defaults(); - - /* Amplitude Global Parameters */ - PVolume = 90; - PPanning = 64; //center - PAmpVelocityScaleFunction = 64; - AmpEnvelope->defaults(); - AmpLfo->defaults(); - PPunchStrength = 0; - PPunchTime = 60; - PPunchStretch = 64; - PPunchVelocitySensing = 72; - - /* Filter Global Parameters*/ - PFilterVelocityScale = 64; - PFilterVelocityScaleFunction = 64; - GlobalFilter->defaults(); - FilterEnvelope->defaults(); - FilterLfo->defaults(); - - deletesamples(); -} - -void PADnoteParameters::deletesample(int n) -{ - if((n < 0) || (n >= PAD_MAX_SAMPLES)) - return; - if(sample[n].smp != NULL) { - delete[] sample[n].smp; - sample[n].smp = NULL; - } - sample[n].size = 0; - sample[n].basefreq = 440.0; -} - -void PADnoteParameters::deletesamples() -{ - for(int i = 0; i < PAD_MAX_SAMPLES; i++) - deletesample(i); -} - -/* - * Get the harmonic profile (i.e. the frequency distributio of a single harmonic) - */ -REALTYPE PADnoteParameters::getprofile(REALTYPE *smp, int size) -{ - for(int i = 0; i < size; i++) - smp[i] = 0.0; - const int supersample = 16; - REALTYPE basepar = pow(2.0, (1.0 - Php.base.par1 / 127.0) * 12.0); - REALTYPE freqmult = floor(pow(2.0, - Php.freqmult / 127.0 * 5.0) + 0.000001); - - REALTYPE modfreq = floor(pow(2.0, - Php.modulator.freq / 127.0 - * 5.0) + 0.000001); - REALTYPE modpar1 = pow(Php.modulator.par1 / 127.0, 4.0) * 5.0 / sqrt( - modfreq); - REALTYPE amppar1 = - pow(2.0, pow(Php.amp.par1 / 127.0, 2.0) * 10.0) - 0.999; - REALTYPE amppar2 = (1.0 - Php.amp.par2 / 127.0) * 0.998 + 0.001; - REALTYPE width = pow(150.0 / (Php.width + 22.0), 2.0); - - for(int i = 0; i < size * supersample; i++) { - bool makezero = false; - REALTYPE x = i * 1.0 / (size * (REALTYPE) supersample); - - REALTYPE origx = x; - - //do the sizing (width) - x = (x - 0.5) * width + 0.5; - if(x < 0.0) { - x = 0.0; - makezero = true; - } - else { - if(x > 1.0) { - x = 1.0; - makezero = true; - } - } - - //compute the full profile or one half - switch(Php.onehalf) { - case 1: - x = x * 0.5 + 0.5; - break; - case 2: - x = x * 0.5; - break; - } - - REALTYPE x_before_freq_mult = x; - - //do the frequency multiplier - x *= freqmult; - - //do the modulation of the profile - x += sin(x_before_freq_mult * 3.1415926 * modfreq) * modpar1; - x = fmod(x + 1000.0, 1.0) * 2.0 - 1.0; - - - //this is the base function of the profile - REALTYPE f; - switch(Php.base.type) { - case 1: - f = exp(-(x * x) * basepar); - if(f < 0.4) - f = 0.0; - else - f = 1.0; - break; - case 2: - f = exp(-(fabs(x)) * sqrt(basepar)); - break; - default: - f = exp(-(x * x) * basepar); - break; - } - if(makezero) - f = 0.0; - - REALTYPE amp = 1.0; - origx = origx * 2.0 - 1.0; - - //compute the amplitude multiplier - switch(Php.amp.type) { - case 1: - amp = exp(-(origx * origx) * 10.0 * amppar1); - break; - case 2: - amp = 0.5 * (1.0 + cos(3.1415926 * origx * sqrt(amppar1 * 4.0 + 1.0))); - break; - case 3: - amp = 1.0 / (pow(origx * (amppar1 * 2.0 + 0.8), 14.0) + 1.0); - break; - } - - //apply the amplitude multiplier - REALTYPE finalsmp = f; - if(Php.amp.type != 0) - switch(Php.amp.mode) { - case 0: - finalsmp = amp * (1.0 - amppar2) + finalsmp * amppar2; - break; - case 1: - finalsmp *= amp * (1.0 - amppar2) + amppar2; - break; - case 2: - finalsmp = finalsmp / (amp + pow(amppar2, 4.0) * 20.0 + 0.0001); - break; - case 3: - finalsmp = amp / (finalsmp + pow(amppar2, 4.0) * 20.0 + 0.0001); - break; - } - ; - - smp[i / supersample] += finalsmp / supersample; - } - - //normalize the profile (make the max. to be equal to 1.0) - REALTYPE max = 0.0; - for(int i = 0; i < size; i++) { - if(smp[i] < 0.0) - smp[i] = 0.0; - if(smp[i] > max) - max = smp[i]; - } - if(max < 0.00001) - max = 1.0; - for(int i = 0; i < size; i++) - smp[i] /= max; - - if(!Php.autoscale) - return 0.5; - - //compute the estimated perceived bandwidth - REALTYPE sum = 0.0; - int i; - for(i = 0; i < size / 2 - 2; i++) { - sum += smp[i] * smp[i] + smp[size - i - 1] * smp[size - i - 1]; - if(sum >= 4.0) - break; - } - - REALTYPE result = 1.0 - 2.0 * i / (REALTYPE) size; - return result; -} - -/* - * Compute the real bandwidth in cents and returns it - * Also, sets the bandwidth parameter - */ -REALTYPE PADnoteParameters::setPbandwidth(int Pbandwidth) -{ - this->Pbandwidth = Pbandwidth; - REALTYPE result = pow(Pbandwidth / 1000.0, 1.1); - result = pow(10.0, result * 4.0) * 0.25; - return result; -} - -/* - * Get the harmonic(overtone) position - */ -REALTYPE PADnoteParameters::getNhr(int n) -{ - REALTYPE result = 1.0; - REALTYPE par1 = pow(10.0, -(1.0 - Phrpos.par1 / 255.0) * 3.0); - REALTYPE par2 = Phrpos.par2 / 255.0; - - REALTYPE n0 = n - 1.0; - REALTYPE tmp = 0.0; - int thresh = 0; - switch(Phrpos.type) { - case 1: - thresh = (int)(par2 * par2 * 100.0) + 1; - if(n < thresh) - result = n; - else - result = 1.0 + n0 + (n0 - thresh + 1.0) * par1 * 8.0; - break; - case 2: - thresh = (int)(par2 * par2 * 100.0) + 1; - if(n < thresh) - result = n; - else - result = 1.0 + n0 - (n0 - thresh + 1.0) * par1 * 0.90; - break; - case 3: - tmp = par1 * 100.0 + 1.0; - result = pow(n0 / tmp, 1.0 - par2 * 0.8) * tmp + 1.0; - break; - case 4: - result = n0 - * (1.0 - - par1) - + pow(n0 * 0.1, par2 * 3.0 + 1.0) * par1 * 10.0 + 1.0; - break; - case 5: - result = n0 - + sin(n0 * par2 * par2 * PI * 0.999) * sqrt(par1) * 2.0 + 1.0; - break; - case 6: - tmp = pow(par2 * 2.0, 2.0) + 0.1; - result = n0 * pow(1.0 + par1 * pow(n0 * 0.8, tmp), tmp) + 1.0; - break; - default: - result = n; - break; - } - - REALTYPE par3 = Phrpos.par3 / 255.0; - - REALTYPE iresult = floor(result + 0.5); - REALTYPE dresult = result - iresult; - - result = iresult + (1.0 - par3) * dresult; - - return result; -} - -/* - * Generates the long spectrum for Bandwidth mode (only amplitudes are generated; phases will be random) - */ -void PADnoteParameters::generatespectrum_bandwidthMode(REALTYPE *spectrum, - int size, - REALTYPE basefreq, - REALTYPE *profile, - int profilesize, - REALTYPE bwadjust) -{ - for(int i = 0; i < size; i++) - spectrum[i] = 0.0; - - REALTYPE harmonics[OSCIL_SIZE / 2]; - for(int i = 0; i < OSCIL_SIZE / 2; i++) - harmonics[i] = 0.0; - //get the harmonic structure from the oscillator (I am using the frequency amplitudes, only) - oscilgen->get(harmonics, basefreq, false); - - //normalize - REALTYPE max = 0.0; - for(int i = 0; i < OSCIL_SIZE / 2; i++) - if(harmonics[i] > max) - max = harmonics[i]; - if(max < 0.000001) - max = 1; - for(int i = 0; i < OSCIL_SIZE / 2; i++) - harmonics[i] /= max; - - for(int nh = 1; nh < OSCIL_SIZE / 2; nh++) { //for each harmonic - REALTYPE realfreq = getNhr(nh) * basefreq; - if(realfreq > SAMPLE_RATE * 0.49999) - break; - if(realfreq < 20.0) - break; - if(harmonics[nh - 1] < 1e-4) - continue; - - //compute the bandwidth of each harmonic - REALTYPE bandwidthcents = setPbandwidth(Pbandwidth); - REALTYPE bw = - (pow(2.0, bandwidthcents / 1200.0) - 1.0) * basefreq / bwadjust; - REALTYPE power = 1.0; - switch(Pbwscale) { - case 0: - power = 1.0; - break; - case 1: - power = 0.0; - break; - case 2: - power = 0.25; - break; - case 3: - power = 0.5; - break; - case 4: - power = 0.75; - break; - case 5: - power = 1.5; - break; - case 6: - power = 2.0; - break; - case 7: - power = -0.5; - break; - } - bw = bw * pow(realfreq / basefreq, power); - int ibw = (int)((bw / (SAMPLE_RATE * 0.5) * size)) + 1; - - REALTYPE amp = harmonics[nh - 1]; - if(resonance->Penabled) - amp *= resonance->getfreqresponse(realfreq); - - if(ibw > profilesize) { //if the bandwidth is larger than the profilesize - REALTYPE rap = sqrt((REALTYPE)profilesize / (REALTYPE)ibw); - int cfreq = - (int) (realfreq / (SAMPLE_RATE * 0.5) * size) - ibw / 2; - for(int i = 0; i < ibw; i++) { - int src = (int)(i * rap * rap); - int spfreq = i + cfreq; - if(spfreq < 0) - continue; - if(spfreq >= size) - break; - spectrum[spfreq] += amp * profile[src] * rap; - } - } - else { //if the bandwidth is smaller than the profilesize - REALTYPE rap = sqrt((REALTYPE)ibw / (REALTYPE)profilesize); - REALTYPE ibasefreq = realfreq / (SAMPLE_RATE * 0.5) * size; - for(int i = 0; i < profilesize; i++) { - REALTYPE idfreq = i / (REALTYPE)profilesize - 0.5; - idfreq *= ibw; - int spfreq = (int) (idfreq + ibasefreq); - REALTYPE fspfreq = fmod(idfreq + ibasefreq, 1.0); - if(spfreq <= 0) - continue; - if(spfreq >= size - 1) - break; - spectrum[spfreq] += amp * profile[i] * rap * (1.0 - fspfreq); - spectrum[spfreq + 1] += amp * profile[i] * rap * fspfreq; - } - } - } -} - -/* - * Generates the long spectrum for non-Bandwidth modes (only amplitudes are generated; phases will be random) - */ -void PADnoteParameters::generatespectrum_otherModes(REALTYPE *spectrum, - int size, - REALTYPE basefreq, - REALTYPE *profile, - int profilesize, - REALTYPE bwadjust) -{ - for(int i = 0; i < size; i++) - spectrum[i] = 0.0; - - REALTYPE harmonics[OSCIL_SIZE / 2]; - for(int i = 0; i < OSCIL_SIZE / 2; i++) - harmonics[i] = 0.0; - //get the harmonic structure from the oscillator (I am using the frequency amplitudes, only) - oscilgen->get(harmonics, basefreq, false); - - //normalize - REALTYPE max = 0.0; - for(int i = 0; i < OSCIL_SIZE / 2; i++) - if(harmonics[i] > max) - max = harmonics[i]; - if(max < 0.000001) - max = 1; - for(int i = 0; i < OSCIL_SIZE / 2; i++) - harmonics[i] /= max; - - for(int nh = 1; nh < OSCIL_SIZE / 2; nh++) { //for each harmonic - REALTYPE realfreq = getNhr(nh) * basefreq; - - ///sa fac aici interpolarea si sa am grija daca frecv descresc - - if(realfreq > SAMPLE_RATE * 0.49999) - break; - if(realfreq < 20.0) - break; -// if (harmonics[nh-1]<1e-4) continue; - - - REALTYPE amp = harmonics[nh - 1]; - if(resonance->Penabled) - amp *= resonance->getfreqresponse(realfreq); - int cfreq = (int) (realfreq / (SAMPLE_RATE * 0.5) * size); - - spectrum[cfreq] = amp + 1e-9; - } - - if(Pmode != 1) { - int old = 0; - for(int k = 1; k < size; k++) { - if((spectrum[k] > 1e-10) || (k == (size - 1))) { - int delta = k - old; - REALTYPE val1 = spectrum[old]; - REALTYPE val2 = spectrum[k]; - REALTYPE idelta = 1.0 / delta; - for(int i = 0; i < delta; i++) { - REALTYPE x = idelta * i; - spectrum[old + i] = val1 * (1.0 - x) + val2 * x; - } - old = k; - } - } - } -} - -/* - * Applies the parameters (i.e. computes all the samples, based on parameters); - */ -void PADnoteParameters::applyparameters(bool lockmutex) -{ - const int samplesize = (((int) 1) << (Pquality.samplesize + 14)); - int spectrumsize = samplesize / 2; - REALTYPE spectrum[spectrumsize]; - int profilesize = 512; - REALTYPE profile[profilesize]; - - - REALTYPE bwadjust = getprofile(profile, profilesize); -// for (int i=0;ifreqs2smps(fftfreqs, newsample.smp); //that's all; here is the only ifft for the whole sample; no windows are used ;-) - - - //normalize(rms) - REALTYPE rms = 0.0; - for(int i = 0; i < samplesize; i++) - rms += newsample.smp[i] * newsample.smp[i]; - rms = sqrt(rms); - if(rms < 0.000001) - rms = 1.0; - rms *= sqrt(262144.0 / samplesize); - for(int i = 0; i < samplesize; i++) - newsample.smp[i] *= 1.0 / rms * 50.0; - - //prepare extra samples used by the linear or cubic interpolation - for(int i = 0; i < extra_samples; i++) - newsample.smp[i + samplesize] = newsample.smp[i]; - - //replace the current sample with the new computed sample - if(lockmutex) { - pthread_mutex_lock(mutex); - deletesample(nsample); - sample[nsample].smp = newsample.smp; - sample[nsample].size = samplesize; - sample[nsample].basefreq = basefreq * basefreqadjust; - pthread_mutex_unlock(mutex); - } - else { - deletesample(nsample); - sample[nsample].smp = newsample.smp; - sample[nsample].size = samplesize; - sample[nsample].basefreq = basefreq * basefreqadjust; - } - newsample.smp = NULL; - } - delete (fft); - deleteFFTFREQS(&fftfreqs); - - //delete the additional samples that might exists and are not useful - if(lockmutex) { - pthread_mutex_lock(mutex); - for(int i = samplemax; i < PAD_MAX_SAMPLES; i++) - deletesample(i); - pthread_mutex_unlock(mutex); - } - else - for(int i = samplemax; i < PAD_MAX_SAMPLES; i++) - deletesample(i); - ; -} - -void PADnoteParameters::export2wav(string basefilename) -{ - applyparameters(true); - basefilename += "_PADsynth_"; - for(int k = 0; k < PAD_MAX_SAMPLES; k++) { - if(sample[k].smp == NULL) - continue; - char tmpstr[20]; - snprintf(tmpstr, 20, "_%02d", k + 1); - string filename = basefilename + string(tmpstr) + ".wav"; - WAVaudiooutput wav; - if(wav.newfile(filename, SAMPLE_RATE, 1)) { - int nsmps = sample[k].size; - short int *smps = new short int[nsmps]; - for(int i = 0; i < nsmps; i++) - smps[i] = (short int)(sample[k].smp[i] * 32767.0); - wav.write_mono_samples(nsmps, smps); - wav.close(); - } - } -} - - - -void PADnoteParameters::add2XML(XMLwrapper *xml) -{ - xml->setPadSynth(true); - - xml->addparbool("stereo", PStereo); - xml->addpar("mode", Pmode); - xml->addpar("bandwidth", Pbandwidth); - xml->addpar("bandwidth_scale", Pbwscale); - - xml->beginbranch("HARMONIC_PROFILE"); - xml->addpar("base_type", Php.base.type); - xml->addpar("base_par1", Php.base.par1); - xml->addpar("frequency_multiplier", Php.freqmult); - xml->addpar("modulator_par1", Php.modulator.par1); - xml->addpar("modulator_frequency", Php.modulator.freq); - xml->addpar("width", Php.width); - xml->addpar("amplitude_multiplier_type", Php.amp.type); - xml->addpar("amplitude_multiplier_mode", Php.amp.mode); - xml->addpar("amplitude_multiplier_par1", Php.amp.par1); - xml->addpar("amplitude_multiplier_par2", Php.amp.par2); - xml->addparbool("autoscale", Php.autoscale); - xml->addpar("one_half", Php.onehalf); - xml->endbranch(); - - xml->beginbranch("OSCIL"); - oscilgen->add2XML(xml); - xml->endbranch(); - - xml->beginbranch("RESONANCE"); - resonance->add2XML(xml); - xml->endbranch(); - - xml->beginbranch("HARMONIC_POSITION"); - xml->addpar("type", Phrpos.type); - xml->addpar("parameter1", Phrpos.par1); - xml->addpar("parameter2", Phrpos.par2); - xml->addpar("parameter3", Phrpos.par3); - xml->endbranch(); - - xml->beginbranch("SAMPLE_QUALITY"); - xml->addpar("samplesize", Pquality.samplesize); - xml->addpar("basenote", Pquality.basenote); - xml->addpar("octaves", Pquality.oct); - xml->addpar("samples_per_octave", Pquality.smpoct); - xml->endbranch(); - - xml->beginbranch("AMPLITUDE_PARAMETERS"); - xml->addpar("volume", PVolume); - xml->addpar("panning", PPanning); - xml->addpar("velocity_sensing", PAmpVelocityScaleFunction); - xml->addpar("punch_strength", PPunchStrength); - xml->addpar("punch_time", PPunchTime); - xml->addpar("punch_stretch", PPunchStretch); - xml->addpar("punch_velocity_sensing", PPunchVelocitySensing); - - xml->beginbranch("AMPLITUDE_ENVELOPE"); - AmpEnvelope->add2XML(xml); - xml->endbranch(); - - xml->beginbranch("AMPLITUDE_LFO"); - AmpLfo->add2XML(xml); - xml->endbranch(); - - xml->endbranch(); - - xml->beginbranch("FREQUENCY_PARAMETERS"); - xml->addpar("fixed_freq", Pfixedfreq); - xml->addpar("fixed_freq_et", PfixedfreqET); - xml->addpar("detune", PDetune); - xml->addpar("coarse_detune", PCoarseDetune); - xml->addpar("detune_type", PDetuneType); - - xml->beginbranch("FREQUENCY_ENVELOPE"); - FreqEnvelope->add2XML(xml); - xml->endbranch(); - - xml->beginbranch("FREQUENCY_LFO"); - FreqLfo->add2XML(xml); - xml->endbranch(); - xml->endbranch(); - - xml->beginbranch("FILTER_PARAMETERS"); - xml->addpar("velocity_sensing_amplitude", PFilterVelocityScale); - xml->addpar("velocity_sensing", PFilterVelocityScaleFunction); - - xml->beginbranch("FILTER"); - GlobalFilter->add2XML(xml); - xml->endbranch(); - - xml->beginbranch("FILTER_ENVELOPE"); - FilterEnvelope->add2XML(xml); - xml->endbranch(); - - xml->beginbranch("FILTER_LFO"); - FilterLfo->add2XML(xml); - xml->endbranch(); - xml->endbranch(); -} - -void PADnoteParameters::getfromXML(XMLwrapper *xml) -{ - PStereo = xml->getparbool("stereo", PStereo); - Pmode = xml->getpar127("mode", 0); - Pbandwidth = xml->getpar("bandwidth", Pbandwidth, 0, 1000); - Pbwscale = xml->getpar127("bandwidth_scale", Pbwscale); - - if(xml->enterbranch("HARMONIC_PROFILE")) { - Php.base.type = xml->getpar127("base_type", Php.base.type); - Php.base.par1 = xml->getpar127("base_par1", Php.base.par1); - Php.freqmult = xml->getpar127("frequency_multiplier", - Php.freqmult); - Php.modulator.par1 = xml->getpar127("modulator_par1", - Php.modulator.par1); - Php.modulator.freq = xml->getpar127("modulator_frequency", - Php.modulator.freq); - Php.width = xml->getpar127("width", Php.width); - Php.amp.type = xml->getpar127("amplitude_multiplier_type", - Php.amp.type); - Php.amp.mode = xml->getpar127("amplitude_multiplier_mode", - Php.amp.mode); - Php.amp.par1 = xml->getpar127("amplitude_multiplier_par1", - Php.amp.par1); - Php.amp.par2 = xml->getpar127("amplitude_multiplier_par2", - Php.amp.par2); - Php.autoscale = xml->getparbool("autoscale", Php.autoscale); - Php.onehalf = xml->getpar127("one_half", Php.onehalf); - xml->exitbranch(); - } - - if(xml->enterbranch("OSCIL")) { - oscilgen->getfromXML(xml); - xml->exitbranch(); - } - - if(xml->enterbranch("RESONANCE")) { - resonance->getfromXML(xml); - xml->exitbranch(); - } - - if(xml->enterbranch("HARMONIC_POSITION")) { - Phrpos.type = xml->getpar127("type", Phrpos.type); - Phrpos.par1 = xml->getpar("parameter1", Phrpos.par1, 0, 255); - Phrpos.par2 = xml->getpar("parameter2", Phrpos.par2, 0, 255); - Phrpos.par3 = xml->getpar("parameter3", Phrpos.par3, 0, 255); - xml->exitbranch(); - } - - if(xml->enterbranch("SAMPLE_QUALITY")) { - Pquality.samplesize = xml->getpar127("samplesize", Pquality.samplesize); - Pquality.basenote = xml->getpar127("basenote", Pquality.basenote); - Pquality.oct = xml->getpar127("octaves", Pquality.oct); - Pquality.smpoct = xml->getpar127("samples_per_octave", - Pquality.smpoct); - xml->exitbranch(); - } - - if(xml->enterbranch("AMPLITUDE_PARAMETERS")) { - PVolume = xml->getpar127("volume", PVolume); - PPanning = xml->getpar127("panning", PPanning); - PAmpVelocityScaleFunction = xml->getpar127("velocity_sensing", - PAmpVelocityScaleFunction); - PPunchStrength = xml->getpar127("punch_strength", PPunchStrength); - PPunchTime = xml->getpar127("punch_time", PPunchTime); - PPunchStretch = xml->getpar127("punch_stretch", PPunchStretch); - PPunchVelocitySensing = xml->getpar127("punch_velocity_sensing", - PPunchVelocitySensing); - - xml->enterbranch("AMPLITUDE_ENVELOPE"); - AmpEnvelope->getfromXML(xml); - xml->exitbranch(); - - xml->enterbranch("AMPLITUDE_LFO"); - AmpLfo->getfromXML(xml); - xml->exitbranch(); - - xml->exitbranch(); - } - - if(xml->enterbranch("FREQUENCY_PARAMETERS")) { - Pfixedfreq = xml->getpar127("fixed_freq", Pfixedfreq); - PfixedfreqET = xml->getpar127("fixed_freq_et", PfixedfreqET); - PDetune = xml->getpar("detune", PDetune, 0, 16383); - PCoarseDetune = xml->getpar("coarse_detune", PCoarseDetune, 0, 16383); - PDetuneType = xml->getpar127("detune_type", PDetuneType); - - xml->enterbranch("FREQUENCY_ENVELOPE"); - FreqEnvelope->getfromXML(xml); - xml->exitbranch(); - - xml->enterbranch("FREQUENCY_LFO"); - FreqLfo->getfromXML(xml); - xml->exitbranch(); - xml->exitbranch(); - } - - if(xml->enterbranch("FILTER_PARAMETERS")) { - PFilterVelocityScale = xml->getpar127("velocity_sensing_amplitude", - PFilterVelocityScale); - PFilterVelocityScaleFunction = xml->getpar127( - "velocity_sensing", - PFilterVelocityScaleFunction); - - xml->enterbranch("FILTER"); - GlobalFilter->getfromXML(xml); - xml->exitbranch(); - - xml->enterbranch("FILTER_ENVELOPE"); - FilterEnvelope->getfromXML(xml); - xml->exitbranch(); - - xml->enterbranch("FILTER_LFO"); - FilterLfo->getfromXML(xml); - xml->exitbranch(); - xml->exitbranch(); - } -} - diff --git a/plugins/zynaddsubfx/src/Params/PADnoteParameters.h b/plugins/zynaddsubfx/src/Params/PADnoteParameters.h deleted file mode 100644 index 37d598529..000000000 --- a/plugins/zynaddsubfx/src/Params/PADnoteParameters.h +++ /dev/null @@ -1,183 +0,0 @@ -/* - ZynAddSubFX - a software synthesizer - - PADnoteParameters.h - Parameters for PADnote (PADsynth) - Copyright (C) 2002-2005 Nasca Octavian Paul - Author: Nasca Octavian Paul - - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License - as published by the Free Software Foundation. - - 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 (version 2 or later) for more details. - - You should have received a copy of the GNU General Public License (version 2) - along with this program; if not, write to the Free Software Foundation, - Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -*/ - -#ifndef PAD_NOTE_PARAMETERS_H -#define PAD_NOTE_PARAMETERS_H - -#include "../Misc/XMLwrapper.h" -#include "../DSP/FFTwrapper.h" -#include "../globals.h" -#include "../Synth/OscilGen.h" -#include "../Synth/Resonance.h" -#include "../Misc/Util.h" - -#include "EnvelopeParams.h" -#include "LFOParams.h" -#include "FilterParams.h" -#include "Presets.h" -#include -#include - -class PADnoteParameters:public Presets -{ - public: - PADnoteParameters(FFTwrapper *fft_, pthread_mutex_t *mutex_); - ~PADnoteParameters(); - - void defaults(); - void add2XML(XMLwrapper *xml); - void getfromXML(XMLwrapper *xml); - - //returns a value between 0.0-1.0 that represents the estimation perceived bandwidth - REALTYPE getprofile(REALTYPE *smp, int size); - - //parameters - - //the mode: 0 - bandwidth, 1 - discrete (bandwidth=0), 2 - continous - //the harmonic profile is used only on mode 0 - unsigned char Pmode; - - //Harmonic profile (the frequency distribution of a single harmonic) - struct { - struct { //base function - unsigned char type; - unsigned char par1; - } base; - unsigned char freqmult; //frequency multiplier of the distribution - struct { //the modulator of the distribution - unsigned char par1; - unsigned char freq; - } modulator; - - unsigned char width; //the width of the resulting function after the modulation - struct { //the amplitude multiplier of the harmonic profile - unsigned char mode; - unsigned char type; - unsigned char par1; - unsigned char par2; - } amp; - bool autoscale; //if the scale of the harmonic profile is computed automaticaly - unsigned char onehalf; //what part of the base function is used to make the distribution - } Php; - - - unsigned int Pbandwidth; //the values are from 0 to 1000 - unsigned char Pbwscale; //how the bandwidth is increased according to the harmonic's frequency - - struct { //where are positioned the harmonics (on integer multimplier or different places) - unsigned char type; - unsigned char par1, par2, par3; //0..255 - } Phrpos; - - struct { //quality of the samples (how many samples, the length of them,etc.) - unsigned char samplesize; - unsigned char basenote, oct, smpoct; - } Pquality; - - //frequency parameters - //If the base frequency is fixed to 440 Hz - unsigned char Pfixedfreq; - - /* Equal temperate (this is used only if the Pfixedfreq is enabled) - If this parameter is 0, the frequency is fixed (to 440 Hz); - if this parameter is 64, 1 MIDI halftone -> 1 frequency halftone */ - unsigned char PfixedfreqET; - unsigned short int PDetune; //fine detune - unsigned short int PCoarseDetune; //coarse detune+octave - unsigned char PDetuneType; //detune type - - EnvelopeParams *FreqEnvelope; //Frequency Envelope - LFOParams *FreqLfo; //Frequency LFO - - //Amplitude parameters - unsigned char PStereo; - /* Panning - 0 - random - 1 - left - 64 - center - 127 - right */ - unsigned char PPanning; - - unsigned char PVolume; - - unsigned char PAmpVelocityScaleFunction; - - EnvelopeParams *AmpEnvelope; - - LFOParams *AmpLfo; - - unsigned char PPunchStrength, PPunchTime, PPunchStretch, - PPunchVelocitySensing; - - //Filter Parameters - FilterParams *GlobalFilter; - - // filter velocity sensing - unsigned char PFilterVelocityScale; - - // filter velocity sensing - unsigned char PFilterVelocityScaleFunction; - - EnvelopeParams *FilterEnvelope; - LFOParams *FilterLfo; - - - - - REALTYPE setPbandwidth(int Pbandwidth); //returns the BandWidth in cents - REALTYPE getNhr(int n); //gets the n-th overtone position relatively to N harmonic - - void applyparameters(bool lockmutex); - void export2wav(std::string basefilename); - - OscilGen *oscilgen; - Resonance *resonance; - - struct { - int size; - REALTYPE basefreq; - REALTYPE *smp; - } sample[PAD_MAX_SAMPLES], newsample; - - private: - void generatespectrum_bandwidthMode(REALTYPE *spectrum, - int size, - REALTYPE basefreq, - REALTYPE *profile, - int profilesize, - REALTYPE bwadjust); - void generatespectrum_otherModes(REALTYPE *spectrum, - int size, - REALTYPE basefreq, - REALTYPE *profile, - int profilesize, - REALTYPE bwadjust); - void deletesamples(); - void deletesample(int n); - - FFTwrapper *fft; - pthread_mutex_t *mutex; -}; - - - -#endif - diff --git a/plugins/zynaddsubfx/src/Params/Presets.cpp b/plugins/zynaddsubfx/src/Params/Presets.cpp deleted file mode 100644 index 228964aac..000000000 --- a/plugins/zynaddsubfx/src/Params/Presets.cpp +++ /dev/null @@ -1,122 +0,0 @@ -/* - ZynAddSubFX - a software synthesizer - - Presets.cpp - Presets and Clipboard management - Copyright (C) 2002-2005 Nasca Octavian Paul - Author: Nasca Octavian Paul - - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License - as published by the Free Software Foundation. - - 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 (version 2 or later) for more details. - - You should have received a copy of the GNU General Public License (version 2) - along with this program; if not, write to the Free Software Foundation, - Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -*/ - -#include "Presets.h" -#include - - -Presets::Presets() -{ - type[0] = 0; -} - -Presets::~Presets() -{} - -void Presets::setpresettype(const char *type) -{ - strcpy(this->type, type); -} - -void Presets::copy(const char *name) -{ - XMLwrapper *xml = new XMLwrapper(); - - //used only for the clipboard - if(name == NULL) - xml->minimal = false; - - char type[MAX_PRESETTYPE_SIZE]; - strcpy(type, this->type); - //strcat(type, "n"); - if(name == NULL) - if(strstr(type, "Plfo") != NULL) - strcpy(type, "Plfo"); - - xml->beginbranch(type); - add2XML(xml); - xml->endbranch(); - - if(name == NULL) - presetsstore.copyclipboard(xml, type); - else - presetsstore.copypreset(xml, type, name); - - delete (xml); -} - -void Presets::paste(int npreset) -{ - char type[MAX_PRESETTYPE_SIZE]; - strcpy(type, this->type); - //strcat(type, "n"); - - if(npreset == 0) - if(strstr(type, "Plfo") != NULL) - strcpy(type, "Plfo"); - - XMLwrapper *xml = new XMLwrapper(); - if(npreset == 0) { - if(!checkclipboardtype()) { - delete (xml); - return; - } - if(!presetsstore.pasteclipboard(xml)) { - delete (xml); - return; - } - } - else { - if(!presetsstore.pastepreset(xml, npreset)) { - delete (xml); - return; - } - } - - if(xml->enterbranch(type) == 0) { - return; - } - - defaults(); - getfromXML(xml); - - xml->exitbranch(); - - delete (xml); -} - -bool Presets::checkclipboardtype() -{ - return presetsstore.checkclipboardtype(type); -} - -void Presets::rescanforpresets() -{ - presetsstore.rescanforpresets(type); -} - - -void Presets::deletepreset(int npreset) -{ - presetsstore.deletepreset(npreset); -} - diff --git a/plugins/zynaddsubfx/src/Params/Presets.h b/plugins/zynaddsubfx/src/Params/Presets.h deleted file mode 100644 index d8000fe3b..000000000 --- a/plugins/zynaddsubfx/src/Params/Presets.h +++ /dev/null @@ -1,57 +0,0 @@ -/* - ZynAddSubFX - a software synthesizer - - Presets.h - Presets and Clipboard management - Copyright (C) 2002-2005 Nasca Octavian Paul - Author: Nasca Octavian Paul - - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License - as published by the Free Software Foundation. - - 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 (version 2 or later) for more details. - - You should have received a copy of the GNU General Public License (version 2) - along with this program; if not, write to the Free Software Foundation, - Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -*/ - -#ifndef PRESETS_H -#define PRESETS_H - -#include "../Misc/XMLwrapper.h" - -#include "PresetsStore.h" - -/**Presets and Clipboard management*/ -class Presets -{ - friend class PresetsArray; - public: - Presets(); - virtual ~Presets(); - - virtual void copy(const char *name); /** - - -PresetsArray::PresetsArray() -{ - type[0] = 0; - nelement = -1; -} - -PresetsArray::~PresetsArray() -{} - -void PresetsArray::setpresettype(const char *type) -{ - strcpy(this->type, type); -} - -void PresetsArray::copy(const char *name) -{ - XMLwrapper *xml = new XMLwrapper(); - - //used only for the clipboard - if(name == NULL) - xml->minimal = false; - - char type[MAX_PRESETTYPE_SIZE]; - strcpy(type, this->type); - if(nelement != -1) - strcat(type, "n"); - if(name == NULL) - if(strstr(type, "Plfo") != NULL) - strcpy(type, "Plfo"); - ; - - xml->beginbranch(type); - if(nelement == -1) - add2XML(xml); - else - add2XMLsection(xml, nelement); - xml->endbranch(); - - if(name == NULL) - presetsstore.copyclipboard(xml, type); - else - presetsstore.copypreset(xml, type, name); - - delete (xml); - nelement = -1; -} - -void PresetsArray::paste(int npreset) -{ - char type[MAX_PRESETTYPE_SIZE]; - strcpy(type, this->type); - if(nelement != -1) - strcat(type, "n"); - if(npreset == 0) - if(strstr(type, "Plfo") != NULL) - strcpy(type, "Plfo"); - ; - - XMLwrapper *xml = new XMLwrapper(); - if(npreset == 0) { - if(!checkclipboardtype()) { - nelement = -1; - delete (xml); - return; - } - if(!presetsstore.pasteclipboard(xml)) { - delete (xml); - nelement = -1; - return; - } - } - else { - if(!presetsstore.pastepreset(xml, npreset)) { - delete (xml); - nelement = -1; - return; - } - } - - if(xml->enterbranch(type) == 0) { - nelement = -1; - return; - } - if(nelement == -1) { - defaults(); - getfromXML(xml); - } - else { - defaults(nelement); - getfromXMLsection(xml, nelement); - } - xml->exitbranch(); - - delete (xml); - nelement = -1; -} - -bool PresetsArray::checkclipboardtype() -{ - char type[MAX_PRESETTYPE_SIZE]; - strcpy(type, this->type); - if(nelement != -1) - strcat(type, "n"); - - return presetsstore.checkclipboardtype(type); -} - -void PresetsArray::setelement(int n) -{ - nelement = n; -} - diff --git a/plugins/zynaddsubfx/src/Params/PresetsArray.h b/plugins/zynaddsubfx/src/Params/PresetsArray.h deleted file mode 100644 index aea7ed362..000000000 --- a/plugins/zynaddsubfx/src/Params/PresetsArray.h +++ /dev/null @@ -1,60 +0,0 @@ -/* - ZynAddSubFX - a software synthesizer - - PresetsArray.h - PresetsArray and Clipboard management - Copyright (C) 2002-2005 Nasca Octavian Paul - Author: Nasca Octavian Paul - - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License - as published by the Free Software Foundation. - - 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 (version 2 or later) for more details. - - You should have received a copy of the GNU General Public License (version 2) - along with this program; if not, write to the Free Software Foundation, - Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -*/ - -#ifndef PRESETSARRAY_H -#define PRESETSARRAY_H - -#include "../Misc/XMLwrapper.h" - -#include "Presets.h" - -/**PresetsArray and Clipboard management*/ -class PresetsArray : public Presets -{ - public: - PresetsArray(); - virtual ~PresetsArray(); - - void copy(const char *name); /** -#include -#include -#include -#include -#include -#include - -#include "PresetsStore.h" -#include "../Misc/Util.h" - -using namespace std; - -PresetsStore presetsstore; - -PresetsStore::PresetsStore() -{ - clipboard.data = NULL; - clipboard.type[0] = 0; -} - -PresetsStore::~PresetsStore() -{ - if(clipboard.data != NULL) - free(clipboard.data); - clearpresets(); -} - -//Clipboard management - -void PresetsStore::copyclipboard(XMLwrapper *xml, char *type) -{ - strcpy(clipboard.type, type); - if(clipboard.data != NULL) - free(clipboard.data); - clipboard.data = xml->getXMLdata(); -} - -bool PresetsStore::pasteclipboard(XMLwrapper *xml) -{ - if(clipboard.data != NULL) - xml->putXMLdata(clipboard.data); - else - return false; - return true; -} - -bool PresetsStore::checkclipboardtype(const char *type) -{ - //makes LFO's compatible - if((strstr(type, - "Plfo") != NULL) && (strstr(clipboard.type, "Plfo") != NULL)) - return true; - return strcmp(type, clipboard.type) == 0; -} - -//Presets management -void PresetsStore::clearpresets() -{ - presets.clear(); -} - -//a helper function that compares 2 presets[] -bool PresetsStore::presetstruct::operator<(const presetstruct &b) const -{ - return name < b.name; -} - - -void PresetsStore::rescanforpresets(const string &type) -{ - //std::cout << "Scanning For Presets" << std::endl; - //std::cout << "Of Type: " << type << std::endl; - - clearpresets(); - string ftype = "." + type + ".xpz"; - - for(int i = 0; i < MAX_BANK_ROOT_DIRS; i++) { - if(config.cfg.presetsDirList[i] == NULL) - continue; - - //open directory - string dirname = config.cfg.presetsDirList[i]; - DIR *dir = opendir(dirname.c_str()); - if(dir == NULL) - continue; - struct dirent *fn; - - //check all files in directory - while((fn = readdir(dir))) { - string filename = fn->d_name; - if(filename.find(ftype) == string::npos) - continue; - - //ensure proper path is formed - char tmpc = dirname[dirname.size() - 1]; - const char *tmps; - if((tmpc == '/') || (tmpc == '\\')) - tmps = ""; - else - tmps = "/"; - - string location = "" + dirname + tmps + filename; - - //trim file type off of name - string name = filename.substr(0, filename.find(ftype)); - - //put on list - presets.push_back(presetstruct(location, name)); - } - - closedir(dir); - } - - //sort the presets - sort(presets.begin(), presets.end()); -} - - -void PresetsStore::copypreset(XMLwrapper *xml, char *type, string name) -{ - if(config.cfg.presetsDirList[0] == NULL) - return; - - //make the filenames legal - for(int i = 0; i < (int) name.size(); i++) { - char c = name[i]; - if(!(isdigit(c) || isalpha(c) || (c == '-') || (c == ' '))) - name[i] = '_'; - } - - //make path legal - const string dirname = config.cfg.presetsDirList[0]; - char tmpc = dirname[dirname.size() - 1]; - const char *tmps; - if((tmpc == '/') || (tmpc == '\\')) - tmps = ""; - else - tmps = "/"; - - string filename("" + dirname + tmps + name + type); - - xml->saveXMLfile(filename); -} - -bool PresetsStore::pastepreset(XMLwrapper *xml, int npreset) -{ - npreset--; - if(npreset < 0) - return false; - unsigned int unsigned_npreset = npreset; - if(unsigned_npreset >= presets.size()) - return false; - string filename = presets[unsigned_npreset].file; - if(filename.empty()) - return false; - bool result = (xml->loadXMLfile(filename) >= 0); - return result; -} - -void PresetsStore::deletepreset(int npreset) -{ - npreset--; - if(npreset < 0) - return; - unsigned int unsigned_npreset = npreset; - if(unsigned_npreset >= presets.size()) - return; - string filename = presets[unsigned_npreset].file; - if(filename.empty()) - return; - remove(filename.c_str()); -} - diff --git a/plugins/zynaddsubfx/src/Params/PresetsStore.h b/plugins/zynaddsubfx/src/Params/PresetsStore.h deleted file mode 100644 index 08437956e..000000000 --- a/plugins/zynaddsubfx/src/Params/PresetsStore.h +++ /dev/null @@ -1,67 +0,0 @@ -/* - ZynAddSubFX - a software synthesizer - - PresetsStore.cpp - Presets and Clipboard store - Copyright (C) 2002-2005 Nasca Octavian Paul - Author: Nasca Octavian Paul - - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License - as published by the Free Software Foundation. - - 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 (version 2 or later) for more details. - - You should have received a copy of the GNU General Public License (version 2) - along with this program; if not, write to the Free Software Foundation, - Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -*/ - -#include -#include -#include "../Misc/XMLwrapper.h" -#include "../Misc/Config.h" - -#define MAX_PRESETTYPE_SIZE 30 - -class PresetsStore -{ - public: - PresetsStore(); - ~PresetsStore(); - - //Clipboard stuff - void copyclipboard(XMLwrapper *xml, char *type); - bool pasteclipboard(XMLwrapper *xml); - bool checkclipboardtype(const char *type); - - //presets stuff - void copypreset(XMLwrapper *xml, char *type, std::string name); - bool pastepreset(XMLwrapper *xml, int npreset); - void deletepreset(int npreset); - - struct presetstruct { - presetstruct(std::string _file, std::string _name) - :file(_file),name(_name){}; - bool operator<(const presetstruct &b) const; - std::string file; - std::string name; - }; - std::vector presets; - - void rescanforpresets(const std::string &type); - - private: - struct { - char *data; - char type[MAX_PRESETTYPE_SIZE]; - } clipboard; - - void clearpresets(); -}; - -extern PresetsStore presetsstore; - diff --git a/plugins/zynaddsubfx/src/Params/SUBnoteParameters.cpp b/plugins/zynaddsubfx/src/Params/SUBnoteParameters.cpp deleted file mode 100644 index 425ddad75..000000000 --- a/plugins/zynaddsubfx/src/Params/SUBnoteParameters.cpp +++ /dev/null @@ -1,251 +0,0 @@ -/* - ZynAddSubFX - a software synthesizer - - SUBnoteParameters.cpp - Parameters for SUBnote (SUBsynth) - Copyright (C) 2002-2005 Nasca Octavian Paul - Author: Nasca Octavian Paul - - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License - as published by the Free Software Foundation. - - 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 (version 2 or later) for more details. - - You should have received a copy of the GNU General Public License (version 2) - along with this program; if not, write to the Free Software Foundation, - Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -*/ - -#include "../globals.h" -#include "SUBnoteParameters.h" -#include - -SUBnoteParameters::SUBnoteParameters():Presets() -{ - setpresettype("Psubsyth"); - AmpEnvelope = new EnvelopeParams(64, 1); - AmpEnvelope->ADSRinit_dB(0, 40, 127, 25); - FreqEnvelope = new EnvelopeParams(64, 0); - FreqEnvelope->ASRinit(30, 50, 64, 60); - BandWidthEnvelope = new EnvelopeParams(64, 0); - BandWidthEnvelope->ASRinit_bw(100, 70, 64, 60); - - GlobalFilter = new FilterParams(2, 80, 40); - GlobalFilterEnvelope = new EnvelopeParams(0, 1); - GlobalFilterEnvelope->ADSRinit_filter(64, 40, 64, 70, 60, 64); - - defaults(); -} - - -void SUBnoteParameters::defaults() -{ - PVolume = 96; - PPanning = 64; - PAmpVelocityScaleFunction = 90; - - Pfixedfreq = 0; - PfixedfreqET = 0; - Pnumstages = 2; - Pbandwidth = 40; - Phmagtype = 0; - Pbwscale = 64; - Pstereo = 1; - Pstart = 1; - - PDetune = 8192; - PCoarseDetune = 0; - PDetuneType = 1; - PFreqEnvelopeEnabled = 0; - PBandWidthEnvelopeEnabled = 0; - - for(int n = 0; n < MAX_SUB_HARMONICS; n++) { - Phmag[n] = 0; - Phrelbw[n] = 64; - } - Phmag[0] = 127; - - PGlobalFilterEnabled = 0; - PGlobalFilterVelocityScale = 64; - PGlobalFilterVelocityScaleFunction = 64; - - AmpEnvelope->defaults(); - FreqEnvelope->defaults(); - BandWidthEnvelope->defaults(); - GlobalFilter->defaults(); - GlobalFilterEnvelope->defaults(); -} - - - -SUBnoteParameters::~SUBnoteParameters() -{ - delete (AmpEnvelope); - delete (FreqEnvelope); - delete (BandWidthEnvelope); - delete (GlobalFilter); - delete (GlobalFilterEnvelope); -} - - - - -void SUBnoteParameters::add2XML(XMLwrapper *xml) -{ - xml->addpar("num_stages", Pnumstages); - xml->addpar("harmonic_mag_type", Phmagtype); - xml->addpar("start", Pstart); - - xml->beginbranch("HARMONICS"); - for(int i = 0; i < MAX_SUB_HARMONICS; i++) { - if((Phmag[i] == 0) && (xml->minimal)) - continue; - xml->beginbranch("HARMONIC", i); - xml->addpar("mag", Phmag[i]); - xml->addpar("relbw", Phrelbw[i]); - xml->endbranch(); - } - xml->endbranch(); - - xml->beginbranch("AMPLITUDE_PARAMETERS"); - xml->addparbool("stereo", Pstereo); - xml->addpar("volume", PVolume); - xml->addpar("panning", PPanning); - xml->addpar("velocity_sensing", PAmpVelocityScaleFunction); - xml->beginbranch("AMPLITUDE_ENVELOPE"); - AmpEnvelope->add2XML(xml); - xml->endbranch(); - xml->endbranch(); - - xml->beginbranch("FREQUENCY_PARAMETERS"); - xml->addparbool("fixed_freq", Pfixedfreq); - xml->addpar("fixed_freq_et", PfixedfreqET); - - xml->addpar("detune", PDetune); - xml->addpar("coarse_detune", PCoarseDetune); - xml->addpar("detune_type", PDetuneType); - - xml->addpar("bandwidth", Pbandwidth); - xml->addpar("bandwidth_scale", Pbwscale); - - xml->addparbool("freq_envelope_enabled", PFreqEnvelopeEnabled); - if((PFreqEnvelopeEnabled != 0) || (!xml->minimal)) { - xml->beginbranch("FREQUENCY_ENVELOPE"); - FreqEnvelope->add2XML(xml); - xml->endbranch(); - } - - xml->addparbool("band_width_envelope_enabled", PBandWidthEnvelopeEnabled); - if((PBandWidthEnvelopeEnabled != 0) || (!xml->minimal)) { - xml->beginbranch("BANDWIDTH_ENVELOPE"); - BandWidthEnvelope->add2XML(xml); - xml->endbranch(); - } - xml->endbranch(); - - xml->beginbranch("FILTER_PARAMETERS"); - xml->addparbool("enabled", PGlobalFilterEnabled); - if((PGlobalFilterEnabled != 0) || (!xml->minimal)) { - xml->beginbranch("FILTER"); - GlobalFilter->add2XML(xml); - xml->endbranch(); - - xml->addpar("filter_velocity_sensing", - PGlobalFilterVelocityScaleFunction); - xml->addpar("filter_velocity_sensing_amplitude", - PGlobalFilterVelocityScale); - - xml->beginbranch("FILTER_ENVELOPE"); - GlobalFilterEnvelope->add2XML(xml); - xml->endbranch(); - } - xml->endbranch(); -} - -void SUBnoteParameters::getfromXML(XMLwrapper *xml) -{ - Pnumstages = xml->getpar127("num_stages", Pnumstages); - Phmagtype = xml->getpar127("harmonic_mag_type", Phmagtype); - Pstart = xml->getpar127("start", Pstart); - - if(xml->enterbranch("HARMONICS")) { - Phmag[0] = 0; - for(int i = 0; i < MAX_SUB_HARMONICS; i++) { - if(xml->enterbranch("HARMONIC", i) == 0) - continue; - Phmag[i] = xml->getpar127("mag", Phmag[i]); - Phrelbw[i] = xml->getpar127("relbw", Phrelbw[i]); - xml->exitbranch(); - } - xml->exitbranch(); - } - - if(xml->enterbranch("AMPLITUDE_PARAMETERS")) { - Pstereo = xml->getparbool("stereo", Pstereo); - PVolume = xml->getpar127("volume", PVolume); - PPanning = xml->getpar127("panning", PPanning); - PAmpVelocityScaleFunction = xml->getpar127("velocity_sensing", - PAmpVelocityScaleFunction); - if(xml->enterbranch("AMPLITUDE_ENVELOPE")) { - AmpEnvelope->getfromXML(xml); - xml->exitbranch(); - } - xml->exitbranch(); - } - - if(xml->enterbranch("FREQUENCY_PARAMETERS")) { - Pfixedfreq = xml->getparbool("fixed_freq", Pfixedfreq); - PfixedfreqET = xml->getpar127("fixed_freq_et", PfixedfreqET); - - PDetune = xml->getpar("detune", PDetune, 0, 16383); - PCoarseDetune = xml->getpar("coarse_detune", PCoarseDetune, 0, 16383); - PDetuneType = xml->getpar127("detune_type", PDetuneType); - - Pbandwidth = xml->getpar127("bandwidth", Pbandwidth); - Pbwscale = xml->getpar127("bandwidth_scale", Pbwscale); - - PFreqEnvelopeEnabled = xml->getparbool("freq_envelope_enabled", - PFreqEnvelopeEnabled); - if(xml->enterbranch("FREQUENCY_ENVELOPE")) { - FreqEnvelope->getfromXML(xml); - xml->exitbranch(); - } - - PBandWidthEnvelopeEnabled = xml->getparbool( - "band_width_envelope_enabled", - PBandWidthEnvelopeEnabled); - if(xml->enterbranch("BANDWIDTH_ENVELOPE")) { - BandWidthEnvelope->getfromXML(xml); - xml->exitbranch(); - } - - xml->exitbranch(); - } - - if(xml->enterbranch("FILTER_PARAMETERS")) { - PGlobalFilterEnabled = xml->getparbool("enabled", PGlobalFilterEnabled); - if(xml->enterbranch("FILTER")) { - GlobalFilter->getfromXML(xml); - xml->exitbranch(); - } - - PGlobalFilterVelocityScaleFunction = xml->getpar127( - "filter_velocity_sensing", - PGlobalFilterVelocityScaleFunction); - PGlobalFilterVelocityScale = xml->getpar127( - "filter_velocity_sensing_amplitude", - PGlobalFilterVelocityScale); - - if(xml->enterbranch("FILTER_ENVELOPE")) { - GlobalFilterEnvelope->getfromXML(xml); - xml->exitbranch(); - } - - xml->exitbranch(); - } -} - diff --git a/plugins/zynaddsubfx/src/Params/SUBnoteParameters.h b/plugins/zynaddsubfx/src/Params/SUBnoteParameters.h deleted file mode 100644 index 57bc08004..000000000 --- a/plugins/zynaddsubfx/src/Params/SUBnoteParameters.h +++ /dev/null @@ -1,104 +0,0 @@ -/* - ZynAddSubFX - a software synthesizer - - SUBnoteParameters.h - Parameters for SUBnote (SUBsynth) - Copyright (C) 2002-2005 Nasca Octavian Paul - Author: Nasca Octavian Paul - - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License - as published by the Free Software Foundation. - - 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 (version 2 or later) for more details. - - You should have received a copy of the GNU General Public License (version 2) - along with this program; if not, write to the Free Software Foundation, - Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -*/ - -#ifndef SUB_NOTE_PARAMETERS_H -#define SUB_NOTE_PARAMETERS_H - -#include "../globals.h" -#include "../Misc/XMLwrapper.h" -#include "EnvelopeParams.h" -#include "FilterParams.h" -#include "Presets.h" - -class SUBnoteParameters:public Presets -{ - public: - SUBnoteParameters(); - ~SUBnoteParameters(); - - void add2XML(XMLwrapper *xml); - void defaults(); - void getfromXML(XMLwrapper *xml); - - //Parameters - //AMPLITUDE PARAMETRERS - unsigned char Pstereo; //0 for mono,1 for stereo - unsigned char PVolume; - unsigned char PPanning; - unsigned char PAmpVelocityScaleFunction; - EnvelopeParams *AmpEnvelope; - - //Frequency Parameters - unsigned short int PDetune; - unsigned short int PCoarseDetune; - unsigned char PDetuneType; - unsigned char PFreqEnvelopeEnabled; - EnvelopeParams *FreqEnvelope; - unsigned char PBandWidthEnvelopeEnabled; - EnvelopeParams *BandWidthEnvelope; - - //Filter Parameters (Global) - unsigned char PGlobalFilterEnabled; - FilterParams *GlobalFilter; - unsigned char PGlobalFilterVelocityScale; - unsigned char PGlobalFilterVelocityScaleFunction; - EnvelopeParams *GlobalFilterEnvelope; - - - //Other Parameters - - //If the base frequency is fixed to 440 Hz - unsigned char Pfixedfreq; - - /* Equal temperate (this is used only if the Pfixedfreq is enabled) - If this parameter is 0, the frequency is fixed (to 440 Hz); - if this parameter is 64, 1 MIDI halftone -> 1 frequency halftone */ - unsigned char PfixedfreqET; - - - //how many times the filters are applied - unsigned char Pnumstages; - - //bandwidth - unsigned char Pbandwidth; - - //How the magnitudes are computed (0=linear,1=-60dB,2=-60dB) - unsigned char Phmagtype; - - //Magnitudes - unsigned char Phmag[MAX_SUB_HARMONICS]; - - //Relative BandWidth ("64"=1.0) - unsigned char Phrelbw[MAX_SUB_HARMONICS]; - - //how much the bandwidth is increased according to lower/higher frequency; 64-default - unsigned char Pbwscale; - - //how the harmonics start("0"=0,"1"=random,"2"=1) - unsigned char Pstart; - - - private: -}; - -#endif - diff --git a/plugins/zynaddsubfx/src/Samples/CMakeLists.txt b/plugins/zynaddsubfx/src/Samples/CMakeLists.txt deleted file mode 100644 index a6ef7b2a0..000000000 --- a/plugins/zynaddsubfx/src/Samples/CMakeLists.txt +++ /dev/null @@ -1,11 +0,0 @@ -set(zynaddsubfx_samples_SRCS - Sample.cpp -) - -add_library(zynaddsubfx_samples STATIC - ${zynaddsubfx_samples_SRCS} - ) - -target_link_libraries(zynaddsubfx_samples - zynaddsubfx_samples - ) diff --git a/plugins/zynaddsubfx/src/Samples/Sample.cpp b/plugins/zynaddsubfx/src/Samples/Sample.cpp deleted file mode 100644 index 33c9b3a20..000000000 --- a/plugins/zynaddsubfx/src/Samples/Sample.cpp +++ /dev/null @@ -1,193 +0,0 @@ -/* - ZynAddSubFX - a software synthesizer - - Sample.cpp - Object for storing information on samples - Copyright (C) 2009-2009 Mark McCurry - Author: Mark McCurry - - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License - as published by the Free Software Foundation. - - 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 (version 2 or later) for more details. - - You should have received a copy of the GNU General Public License (version 2) - along with this program; if not, write to the Free Software Foundation, - Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ -#include -#include //for memcpy/memset -#include -#include "Sample.h" - -using namespace std; - -/**\TODO start using pointer math here as these will be Frequency called - * functions throughout the code*/ -Sample::Sample(const Sample &smp) - :bufferSize(smp.bufferSize) -{ - buffer = new REALTYPE[bufferSize]; - for(int i = 0; i < bufferSize; ++i) - *(i + buffer) = *(i + smp.buffer); -} - -Sample::Sample(int length, REALTYPE fill) - :bufferSize(length) -{ - if(length < 1) - bufferSize = 1; - buffer = new REALTYPE[bufferSize]; - for(int i = 0; i < bufferSize; ++i) - buffer[i] = fill; -} - -Sample::Sample(int length, const REALTYPE *input) - :bufferSize(length) -{ - if(length > 0) { - buffer = new REALTYPE[length]; - for(int i = 0; i < length; ++i) - *(buffer + i) = *(input + i); - } - else { - buffer = new REALTYPE[1]; - bufferSize = 1; - *buffer = 0; - } -} - -Sample::~Sample() -{ - delete[] buffer; -} - -void Sample::clear() -{ - for(int i = 0; i < bufferSize; ++i) - *(i + buffer) = 0; -} - -void Sample::operator=(const Sample &smp) -{ - /**\todo rewrite to be less repetitive*/ - if(bufferSize == smp.bufferSize) - for(int i = 0; i < bufferSize; ++i) - *(i + buffer) = *(i + smp.buffer); - else { - delete[] buffer; - buffer = new REALTYPE[smp.bufferSize]; - bufferSize = smp.bufferSize; - for(int i = 0; i < bufferSize; ++i) - *(i + buffer) = *(i + smp.buffer); - } -} - -bool Sample::operator==(const Sample &smp) const -{ - if(this->bufferSize != smp.bufferSize) - return false; - for(int i = 0; i < bufferSize; ++i) - if(this->buffer[i] != smp.buffer[i]) - return false; - return true; -} - -/** - * Linear point estimation - * @param ya Y of point a - * @param yb Y of point b - * @param xt X of test point - * @param xa X of point a - * @param xb X of point b - * @return estimated Y of test point - */ -inline float linearEstimate(float ya, float yb, float xt, int xa = 0, int xb = 1) -{ - if(xa == xb) - return ya; - - return (yb-ya) * (xt-xa)/(xb-xa) + ya; -} - -void Sample::resize(int nsize) -{ - if(bufferSize == nsize) - return; - else {//resampling occurs here - float ratio = (nsize * 1.0) / (bufferSize * 1.0); - - int nBufferSize = nsize; - float *nBuffer = new float[nBufferSize]; - - //take care of edge cases - *nBuffer = *buffer; - *(nBuffer+nBufferSize-1) = *(buffer+bufferSize-1); - - //addition is done to avoid 0 edge case - for(int i = 1; i < nBufferSize - 1; ++i) - { - float left = floor(i/ratio); - float right = ceil((i+1)/ratio); - float test = i/ratio; - if(left > bufferSize - 1) - left = bufferSize - 1; - if(right > bufferSize - 1) - right = bufferSize - 1; - if(left > test) - test = left; - nBuffer[i] = linearEstimate(buffer[(int)left], - buffer[(int)right], - test, (int)left, (int)right); - } - - //put the new data in - delete[] buffer; - buffer = nBuffer; - bufferSize = nBufferSize; - } -} - -void Sample::append(const Sample &smp) -{ - int nbufferSize = bufferSize + smp.bufferSize; - float *nbuffer = new float[nbufferSize]; - - memcpy(nbuffer, buffer, bufferSize * sizeof(float)); - memcpy(nbuffer + bufferSize, smp.buffer, smp.bufferSize * sizeof(float)); - delete buffer; - - buffer = nbuffer; - bufferSize = nbufferSize; -} - -REALTYPE Sample::max() const -{ - REALTYPE max = -1500; //a good low considering that samples should store values -1.0 to 1.0 - for(int i = 0; i < bufferSize; ++i) - if(buffer[i] > max) - max = buffer[i]; - return max; -} - -REALTYPE Sample::min() const -{ - REALTYPE min = 1500; //a good high considering that samples should store values -1.0 to 1.0 - for(int i = 0; i < bufferSize; ++i) - if(buffer[i] < min) - min = buffer[i]; - return min; -} - -REALTYPE Sample::absMax() const -{ - REALTYPE max = 0; - for(int i = 0; i < bufferSize; ++i) - if(fabs(buffer[i]) > max) - max = fabs(buffer[i]); - return max; -} - diff --git a/plugins/zynaddsubfx/src/Samples/Sample.h b/plugins/zynaddsubfx/src/Samples/Sample.h deleted file mode 100644 index de6b6dfb0..000000000 --- a/plugins/zynaddsubfx/src/Samples/Sample.h +++ /dev/null @@ -1,74 +0,0 @@ -/* - ZynAddSubFX - a software synthesizer - - Sample.h - Object for storing information on samples - Copyright (C) 2009-2009 Mark McCurry - Author: Mark McCurry - - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License - as published by the Free Software Foundation. - - 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 (version 2 or later) for more details. - - You should have received a copy of the GNU General Public License (version 2) - along with this program; if not, write to the Free Software Foundation, - Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ -#ifndef SAMPLE_H -#define SAMPLE_H -#include "../globals.h" -/** - * Base Class for Samples - */ -class Sample -{ - public: - Sample(const Sample &smp); - Sample(int length, REALTYPE fill = 0); - Sample(int length, const REALTYPE *fill); - ~Sample(); - /**Fills the buffer with zeros*/ - void clear(); - /**States the size of the buffer - * @return the size of the buffer*/ - int size() const { - return bufferSize; - } - /**Provides the indexing operator for non const Samples*/ - REALTYPE &operator[](int index) { - return *(buffer + index % bufferSize); - } - /**Provides the indexing operator for const Samples*/ - const REALTYPE &operator[](int index) const { - return *(buffer + index % bufferSize); - } - /**Provides the assignment operator*/ - void operator=(const Sample &smp); - /**Provides the == operator*/ - bool operator==(const Sample &smp) const; - - /**Provides direct access to the buffer to allow for transition - * - * This method is like c_str() from the string class and should be used - * sparingly*/ - const REALTYPE *c_buf() const {return buffer;} - - /**Change the size of the sample*/ - void resize(int nsize); - - /**Appends another Sample to this Sample*/ - void append(const Sample &smp); - - REALTYPE max() const; - REALTYPE min() const; - REALTYPE absMax() const; - private: - int bufferSize; - float *buffer; -}; -#endif - diff --git a/plugins/zynaddsubfx/src/Seq/CMakeLists.txt b/plugins/zynaddsubfx/src/Seq/CMakeLists.txt deleted file mode 100644 index 008c821e4..000000000 --- a/plugins/zynaddsubfx/src/Seq/CMakeLists.txt +++ /dev/null @@ -1,11 +0,0 @@ -set(zynaddsubfx_seq_SRCS - MIDIEvents.cpp - MIDIFile.cpp - Sequencer.cpp -) - -add_library(zynaddsubfx_seq STATIC - ${zynaddsubfx_seq_SRCS} - ) - -target_link_libraries(zynaddsubfx_seq) diff --git a/plugins/zynaddsubfx/src/Seq/MIDIEvents.cpp b/plugins/zynaddsubfx/src/Seq/MIDIEvents.cpp deleted file mode 100644 index 22d9a0565..000000000 --- a/plugins/zynaddsubfx/src/Seq/MIDIEvents.cpp +++ /dev/null @@ -1,93 +0,0 @@ -/* - ZynAddSubFX - a software synthesizer - - MIDIEvents.cpp - It stores the midi events from midi file or sequencer - Copyright (C) 2003-2005 Nasca Octavian Paul - Author: Nasca Octavian Paul - - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License - as published by the Free Software Foundation. - - 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 (version 2 or later) for more details. - - You should have received a copy of the GNU General Public License (version 2) - along with this program; if not, write to the Free Software Foundation, - Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -*/ - -#include "MIDIEvents.h" -#include -#include - -MIDIEvents::MIDIEvents() -{} - -MIDIEvents::~MIDIEvents() -{} - - -/************** Track stuff ***************/ -void MIDIEvents::writeevent(list *l, event *ev) -{ - listpos *tmp = new listpos; - tmp->next = NULL; - tmp->ev = *ev; - if(l->current != NULL) - l->current->next = tmp; - else - l->first = tmp; - l->current = tmp; -// printf("Wx%x ",(int) l->current); -// printf("-> %d \n",l->current->ev.deltatime); - l->size++; -} - -void MIDIEvents::readevent(list *l, event *ev) -{ - if(l->current == NULL) { - ev->type = -1; - return; - } - *ev = l->current->ev; - l->current = l->current->next; - - //test - if(l->current != NULL) { -// ev->deltatime=10000; -// printf("Rx%d\n",l->current->ev.deltatime); -// printf("Rx%x ",(int) l->current); -// printf("-> %d (next=%x) \n",(int)l->current->ev.deltatime,(int)l->current->next); - } -} - - -void MIDIEvents::rewindlist(list *l) -{ - l->current = l->first; -} - -void MIDIEvents::deletelist(list *l) -{ - l->current = l->first; - if(l->current == NULL) - return; - while(l->current->next != NULL) { - listpos *tmp = l->current; - l->current = l->current->next; - delete (tmp); - } - deletelistreference(l); -} - -void MIDIEvents::deletelistreference(list *l) -{ - l->current = l->first = NULL; - l->size = 0; - l->length = 0.0; -} - diff --git a/plugins/zynaddsubfx/src/Seq/MIDIEvents.h b/plugins/zynaddsubfx/src/Seq/MIDIEvents.h deleted file mode 100644 index 222404876..000000000 --- a/plugins/zynaddsubfx/src/Seq/MIDIEvents.h +++ /dev/null @@ -1,69 +0,0 @@ -/* - ZynAddSubFX - a software synthesizer - - MIDIEvents.h - It stores the midi events from midi file or sequencer - Copyright (C) 2003-2005 Nasca Octavian Paul - Author: Nasca Octavian Paul - - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License - as published by the Free Software Foundation. - - 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 (version 2 or later) for more details. - - You should have received a copy of the GNU General Public License (version 2) - along with this program; if not, write to the Free Software Foundation, - Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -*/ -#ifndef MIDI_EVENTS_H -#define MIDI_EVENTS_H - -#include "../globals.h" -#define NUM_MIDI_TRACKS NUM_MIDI_CHANNELS - -/**storage the midi events from midi file or sequencer - * \todo this looks quite like a remake of a linked list - * if it is, then it should be rewritten to use */ -class MIDIEvents -{ - friend class MIDIFile; - public: - MIDIEvents(); - ~MIDIEvents(); - - protected: - - /* Events */ - struct event { - int deltatime; - int channel; //on what midi channel is - int type, par1, par2; //type=1 for note, type=2 for controller, type=255 for time messages - } tmpevent; - struct listpos { - event ev; - struct listpos *next; - }; - struct list { - listpos *first, *current; - int size; //how many events are - double length; //in seconds - }; - struct { - list track; //the stored track - list record; //the track being "recorded" from midi - } miditrack[NUM_MIDI_TRACKS]; - - void writeevent(list *l, event *ev); - void readevent(list *l, event *ev); - - void rewindlist(list *l); - void deletelist(list *l); - void deletelistreference(list *l); -}; - -#endif - diff --git a/plugins/zynaddsubfx/src/Seq/MIDIFile.cpp b/plugins/zynaddsubfx/src/Seq/MIDIFile.cpp deleted file mode 100644 index d6c70ecb4..000000000 --- a/plugins/zynaddsubfx/src/Seq/MIDIFile.cpp +++ /dev/null @@ -1,424 +0,0 @@ -/* - ZynAddSubFX - a software synthesizer - - MIDIFile.cpp - MIDI file loader - Copyright (C) 2003-2005 Nasca Octavian Paul - Author: Nasca Octavian Paul - - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License - as published by the Free Software Foundation. - - 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 (version 2 or later) for more details. - - You should have received a copy of the GNU General Public License (version 2) - along with this program; if not, write to the Free Software Foundation, - Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -*/ - -#include -#include -#include -#include "MIDIFile.h" - - -MIDIFile::MIDIFile() -{ - midifile = NULL; - midifilesize = 0; - midifilek = 0; - midieof = false; - me = NULL; -} - -MIDIFile::~MIDIFile() -{ - clearmidifile(); -} - -int MIDIFile::loadfile(const char *filename) -{ - clearmidifile(); - - FILE *file = fopen(filename, "r"); - if(file == NULL) - return -1; - - char header[4]; - ZERO(header, 4); - if (fread(header, 4, 1, file) != 1) { - return -1; - } - - //test to see if this a midi file - if((header[0] != 'M') || (header[1] != 'T') || (header[2] != 'h') - || (header[3] != 'd')) { - fclose(file); - return -1; - } - - //get the filesize - fseek(file, 0, SEEK_END); - midifilesize = ftell(file); - rewind(file); - - midifile = new unsigned char[midifilesize]; - ZERO(midifile, midifilesize); - if (fread(midifile, midifilesize, 1, file) != 1) { - clearmidifile(); - return -1; - } - fclose(file); - -// for (int i=0;ime = me_; - - //read the header - int chunk = getint32(); //MThd - if(chunk != 0x4d546864) - return -1; - int size = getint32(); - if(size != 6) - return -1; //header is always 6 bytes long - - - int format = getint16(); - printf("format %d\n", format); - - int ntracks = getint16(); //this is always 1 if the format is "0" - printf("ntracks %d\n", ntracks); - - int division = getint16(); - printf("division %d\n", division); - if(division >= 0) { //delta time units in each a quater note -// tick=???; - } - else //SMPTE (frames/second and ticks/frame) - printf( - "ERROR:in MIDIFile.cpp::parsemidifile() - SMPTE not implemented yet."); - ; - - if(ntracks >= NUM_MIDI_TRACKS) - ntracks = NUM_MIDI_TRACKS - 1; - - for(int n = 0; n < ntracks; n++) { - if(parsetrack(n) < 0) { - clearmidifile(); - return -1; - } - } - - printf("\n\nCURRENT File position is = 0x%x\n", midifilek); - printf("\nMIDI file succesfully parsed.\n"); -// printf("\n0x%x\n",getbyte()); - - this->me = NULL; - return 0; -} - -//private members - - -int MIDIFile::parsetrack(int ntrack) -{ - printf("\n--==*Reading track %d **==--\n", ntrack); - - int chunk = getint32(); //MTrk - if(chunk != 0x4d54726b) - return -1; - - int size = getint32(); - printf("size = %d\n", size); - - int oldmidifilek = midifilek; - - unsigned char lastmsg = 0; - unsigned int dt = 0; - - while(!midieof) { - unsigned int msgdeltatime = getvarint32(); - -/// printf("MSGDELTATIME = %d\n",msgdeltatime); - -// dt+=msgdeltatime; - - int msg = peekbyte(); -/// printf("raw msg=0x%x ",msg); - if(msg < 0x80) - msg = lastmsg; - else { - lastmsg = msg; - getbyte(); - } -/// printf("msg=0x%x\n",msg); - -// dt+=msgdeltatime; - add_dt(ntrack, msgdeltatime); - - unsigned int mtype, mlength; - - switch(msg) { - case 0x80 ... 0x8f: //note on off - parsenoteoff(ntrack, msg & 0x0f, dt); - dt = 0; - break; - case 0x90 ... 0x9f: //note on (or note off) - parsenoteon(ntrack, msg & 0x0f, dt); - dt = 0; - break; - case 0xa0 ... 0xaf: //aftertouch - ignored - skipnbytes(2); - break; - case 0xb0 ... 0xbf: //control change - parsecontrolchange(ntrack, msg & 0x0f, dt); - dt = 0; - break; - case 0xc0 ... 0xcf: //program change - ignored - skipnbytes(1); - break; - case 0xd0 ... 0xdf: //channel pressure - ignored - skipnbytes(1); - break; - case 0xe0 ... 0xef: //channel mode messages - skipnbytes(2); - break; - case 0xf0: //sysex - ignored - while(getbyte() != 0xf7) { - if(midieof) - break; - } - break; - case 0xf7: //sysex (another type) - ignored - skipnbytes(getvarint32()); - break; - - case 0xff: //meta-event - mtype = getbyte(); - mlength = getbyte(); - parsemetaevent(mtype, mlength); - break; - - default: - getbyte(); - printf("UNKNOWN message! 0x%x\n", msg); - return -1; - break; - } - - - - if(midieof) - return -1; - - if((midifilek - oldmidifilek) == size) - break; - else - if((midifilek - oldmidifilek) > size) - return -1; -// if (size!=6) return(-1);//header is always 6 bytes long - } - - printf("End Track\n\n"); - - return 0; -} - - -void MIDIFile::parsenoteoff(char ntrack, char chan, unsigned int dt) -{ - unsigned char note; - note = getbyte(); - - (void) getbyte(); //Read in unused noteoff_velocity - if(chan >= NUM_MIDI_CHANNELS) - return; - - me->tmpevent.deltatime = convertdt(dt); - me->tmpevent.type = 1; - me->tmpevent.par1 = note; - me->tmpevent.par2 = 0; - me->tmpevent.channel = chan; - - printf("Note off:%d \n", note); - - ///test -// ntrack=0; - - me->writeevent(&me->miditrack[(int)ntrack].record, &me->tmpevent); -} - - -void MIDIFile::parsenoteon(char ntrack, char chan, unsigned int dt) -{ - unsigned char note, vel; - note = getbyte(); - vel = getbyte(); - -// printf("ntrack=%d\n",ntrack); - printf("[dt %d ] Note on:%d %d\n", dt, note, vel); - - if(chan >= NUM_MIDI_CHANNELS) - return; - - me->tmpevent.deltatime = convertdt(dt); - me->tmpevent.type = 1; - me->tmpevent.par1 = note; - me->tmpevent.par2 = vel; - me->tmpevent.channel = chan; - me->writeevent(&me->miditrack[(int)ntrack].record, &me->tmpevent); -} - -void MIDIFile::parsecontrolchange(char ntrack, char chan, unsigned int dt) -{ - unsigned char control, value; - control = getbyte(); - value = getbyte(); - - if(chan >= NUM_MIDI_CHANNELS) - return; - - printf("[dt %d] Control change:%d %d\n", dt, control, value); - - me->tmpevent.deltatime = convertdt(dt); - me->tmpevent.type = 2; - me->tmpevent.par1 = control; //???????????? ma uit la Sequencer::recordnote() din varianele vechi de zyn - me->tmpevent.par2 = value; - me->tmpevent.channel = chan; - me->writeevent(&me->miditrack[(int)ntrack].record, &me->tmpevent); -} - -void MIDIFile::parsepitchwheel(char ntrack, char chan, unsigned int dt) -{ - unsigned char valhi, vallo; - vallo = getbyte(); - valhi = getbyte(); - - if(chan >= NUM_MIDI_CHANNELS) - return; - - int value = (int)valhi * 128 + vallo; - - printf("[dt %d] Pitch wheel:%d\n", dt, value); -} - -void MIDIFile::parsemetaevent(unsigned char mtype, unsigned char mlength) -{ - int oldmidifilek = midifilek; - printf("meta-event type=0x%x length=%d\n", mtype, mlength); - - - - midifilek = oldmidifilek + mlength; -} - -void MIDIFile::add_dt(char ntrack, unsigned int dt) -{ - me->tmpevent.deltatime = convertdt(dt); - me->tmpevent.type = 255; - me->tmpevent.par1 = 0; - me->tmpevent.par2 = 0; - me->tmpevent.channel = 0; - me->writeevent(&me->miditrack[(int)ntrack].record, &me->tmpevent); -} - - -unsigned int MIDIFile::convertdt(unsigned int dt) -{ - double result = dt; - printf("DT=%d\n", dt); - - return (int) (result * 15.0); -} - - -void MIDIFile::clearmidifile() -{ - if(midifile != NULL) - delete (midifile); - midifile = NULL; - midifilesize = 0; - midifilek = 0; - midieof = false; -} - -unsigned char MIDIFile::getbyte() -{ - if(midifilek >= midifilesize) { - midieof = true; - return 0; - } - -/// printf("(%d) ",midifile[midifilek]); - return midifile[midifilek++]; -} - -unsigned char MIDIFile::peekbyte() -{ - if(midifilek >= midifilesize) { - midieof = true; - return 0; - } - return midifile[midifilek]; -} - -unsigned int MIDIFile::getint32() -{ - unsigned int result = 0; - for(int i = 0; i < 4; i++) - result = result * 256 + getbyte(); - ; - if(midieof) - result = 0; - return result; -} - -unsigned short int MIDIFile::getint16() -{ - unsigned short int result = 0; - for(int i = 0; i < 2; i++) - result = result * 256 + getbyte(); - ; - if(midieof) - result = 0; - return result; -} - -unsigned int MIDIFile::getvarint32() -{ - unsigned long result = 0; -/// printf("\n[start]"); - - if((result = getbyte()) & 0x80) { - result &= 0x7f; - uint8_t b; - do { - b = getbyte(); - result = (result << 7) + (b & 0x7f); - } while(b & 0x80); - } -/// printf("[end - result= %d]\n",result); - return result; -} - - -void MIDIFile::skipnbytes(int n) -{ - midifilek += n; - if(midifilek >= midifilesize) { - midifilek = midifilesize - 1; - midieof = true; - } -} - diff --git a/plugins/zynaddsubfx/src/Seq/MIDIFile.h b/plugins/zynaddsubfx/src/Seq/MIDIFile.h deleted file mode 100644 index ed1153bd2..000000000 --- a/plugins/zynaddsubfx/src/Seq/MIDIFile.h +++ /dev/null @@ -1,89 +0,0 @@ -/* - ZynAddSubFX - a software synthesizer - - MIDIFile.h - MIDI file loader - Copyright (C) 2003-2005 Nasca Octavian Paul - Author: Nasca Octavian Paul - - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License - as published by the Free Software Foundation. - - 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 (version 2 or later) for more details. - - You should have received a copy of the GNU General Public License (version 2) - along with this program; if not, write to the Free Software Foundation, - Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -*/ - -#ifndef MIDIFILE_H -#define MIDIFILE_H - -#include "../globals.h" -#include "MIDIEvents.h" - -/**MIDI file loader*/ -class MIDIFile -{ - public: - MIDIFile(); - ~MIDIFile(); - - /**Loads the given file - * @param filename The name of the file to load - * @return -1 if there is an error, otherwise 0*/ - int loadfile(const char *filename); - - //returns -1 if there is an error, otherwise 0 - int parsemidifile(MIDIEvents *me_); - - private: - MIDIEvents *me; - - unsigned char *midifile; - int midifilesize, midifilek; - bool midieof; - - //returns -1 if there is an error, otherwise 0 - int parsetrack(int ntrack); - - void parsenoteoff(char ntrack, char chan, unsigned int dt); - void parsenoteon(char ntrack, char chan, unsigned int dt); - void parsecontrolchange(char ntrack, char chan, unsigned int dt); - void parsepitchwheel(char ntrack, char chan, unsigned int dt); - void parsemetaevent(unsigned char mtype, unsigned char mlength); - - void add_dt(char ntrack, unsigned int dt); - - void clearmidifile(); - - //convert the delta-time to internal format - unsigned int convertdt(unsigned int dt); - - /* Low Level MIDIfile functions */ - - //get a byte from the midifile - unsigned char getbyte(); - - //peek the current byte from the midifile - unsigned char peekbyte(); - - //get a set of 4 bytes from the midifile - unsigned int getint32(); - - //get a word of 2 bytes from the midifile - unsigned short int getint16(); - - //read a variable length quantity - unsigned int getvarint32(); - - //skip some bytes - void skipnbytes(int n); -}; - -#endif - diff --git a/plugins/zynaddsubfx/src/Seq/Sequencer.cpp b/plugins/zynaddsubfx/src/Seq/Sequencer.cpp deleted file mode 100644 index c11e68a7c..000000000 --- a/plugins/zynaddsubfx/src/Seq/Sequencer.cpp +++ /dev/null @@ -1,189 +0,0 @@ -/* - ZynAddSubFX - a software synthesizer - - Sequencer.cpp - The Sequencer - Copyright (C) 2003-2005 Nasca Octavian Paul - Author: Nasca Octavian Paul - - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License - as published by the Free Software Foundation. - - 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 (version 2 or later) for more details. - - You should have received a copy of the GNU General Public License (version 2) - along with this program; if not, write to the Free Software Foundation, - Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -*/ - -#include -#include -#include - -#include -#include - -#include "Sequencer.h" - - - -Sequencer::Sequencer() -{ - play = 0; - for(int i = 0; i < NUM_MIDI_TRACKS; i++) { - miditrack[i].track.first = NULL; - miditrack[i].track.current = NULL; - miditrack[i].track.size = 0; - miditrack[i].track.length = 0.0; - miditrack[i].record.first = NULL; - miditrack[i].record.current = NULL; - miditrack[i].record.size = 0; - miditrack[i].record.length = 0.0; - - nextevent[i].time = 0.0; - resettime(&playtime[i]); - } - - setplayspeed(0); -} - -Sequencer::~Sequencer() -{ - for(int i = 0; i < NUM_MIDI_TRACKS; i++) { - deletelist(&miditrack[i].track); - deletelist(&miditrack[i].record); - } -} - - -int Sequencer::importmidifile(const char *filename) -{ - if(midifile.loadfile(filename) < 0) - return -1; - - for(int i = 0; i < NUM_MIDI_TRACKS; i++) - deletelist(&miditrack[i].record); - ; - if(midifile.parsemidifile(this) < 0) - return -1; - - //copy the "record" track to the main track - for(int i = 0; i < NUM_MIDI_TRACKS; i++) { - deletelist(&miditrack[i].track); - miditrack[i].track = miditrack[i].record; - deletelistreference(&miditrack[i].record); - } - return 0; -} - - - -void Sequencer::startplay() -{ - if(play != 0) - return; - for(int i = 0; i < NUM_MIDI_TRACKS; i++) - resettime(&playtime[i]); - - for(int i = 0; i < NUM_MIDI_TRACKS; i++) - rewindlist(&miditrack[i].track); - ; - play = 1; -} -void Sequencer::stopplay() -{ - if(play == 0) - return; - play = 0; -} - -// ************ Player stuff *************** - -int Sequencer::getevent(char ntrack, - int *midich, - int *type, - int *par1, - int *par2) -{ - *type = 0; - if(play == 0) - return -1; - - //test -// if (ntrack!=0) return(-1); - - updatecounter(&playtime[(int)ntrack]); - -// printf("%g %g\n",nextevent[ntrack].time,playtime[ntrack].abs); - - if(nextevent[(int)ntrack].time < playtime[(int)ntrack].abs) - readevent(&miditrack[(int)ntrack].track, &nextevent[(int)ntrack].ev); - else - return -1; - if(nextevent[(int)ntrack].ev.type == -1) - return -1; -// printf("********************************\n"); - - //sa pun aici o protectie. a.i. daca distanta dintre timpul curent si eveliment e prea mare (>1sec) sa elimin nota - - if(ntrack == 1) - printf("_ %f %.2f (%d)\n", nextevent[(int)ntrack].time, - playtime[(int)ntrack].abs, nextevent[(int)ntrack].ev.par2); - - *type = nextevent[(int)ntrack].ev.type; - *par1 = nextevent[(int)ntrack].ev.par1; - *par2 = nextevent[(int)ntrack].ev.par2; - *midich = nextevent[(int)ntrack].ev.channel; - - - double dt = nextevent[(int)ntrack].ev.deltatime * 0.0001 * realplayspeed; - printf("zzzzzzzzzzzzzz[%d] %d\n", - ntrack, - nextevent[(int)ntrack].ev.deltatime); - nextevent[(int)ntrack].time += dt; - -// printf("%f - %d %d \n",nextevent[ntrack].time,par1,par2); - return 0; //?? sau 1 -} - -/************** Timer stuff ***************/ - -void Sequencer::resettime(timestruct *t) -{ - t->abs = 0.0; - t->rel = 0.0; - - t->last = 0.0; -#ifndef OS_WINDOWS - timeval tval; - if(gettimeofday(&tval, NULL) == 0) - t->last = tval.tv_sec + tval.tv_usec * 0.000001; -#endif -} - -void Sequencer::updatecounter(timestruct *t) -{ - double current = 0.0; -#ifndef OS_WINDOWS - timeval tval; - if(gettimeofday(&tval, NULL) == 0) - current = tval.tv_sec + tval.tv_usec * 0.000001; -#endif - - t->rel = current - t->last; - t->abs += t->rel; - t->last = current; - -// printf("%f %f %f\n",t->last,t->abs,t->rel); -} - -void Sequencer::setplayspeed(int speed) -{ - playspeed = speed; - realplayspeed = pow(10.0, speed / 128.0); -} - diff --git a/plugins/zynaddsubfx/src/Seq/Sequencer.h b/plugins/zynaddsubfx/src/Seq/Sequencer.h deleted file mode 100644 index dd2d75613..000000000 --- a/plugins/zynaddsubfx/src/Seq/Sequencer.h +++ /dev/null @@ -1,90 +0,0 @@ -/* - ZynAddSubFX - a software synthesizer - - Sequencer.h - The Sequencer - Copyright (C) 2003-2005 Nasca Octavian Paul - Author: Nasca Octavian Paul - - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License - as published by the Free Software Foundation. - - 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 (version 2 or later) for more details. - - You should have received a copy of the GNU General Public License (version 2) - along with this program; if not, write to the Free Software Foundation, - Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#ifndef SEQUENCER_H -#define SEQUENCER_H - -#include "../globals.h" -#include "MIDIEvents.h" -#include "MIDIFile.h" - -/**The Sequencer - * \todo restructure some of this code*/ -class Sequencer:public MIDIEvents -{ - public: - /**Constructor*/ - Sequencer(); - /**Destructor*/ - ~Sequencer(); - - //these functions are called by the master and are ignored if the recorder/player are stopped - void recordnote(char chan, char note, char vel); - void recordcontroller(char chan, unsigned int type, int par); - - /**Gets an event \todo better description - * - * this is only for player - * @return 1 if this must be called at least once more - * 0 if there are no more notes for the current time - * -1 if there are no notes*/ - int getevent(char ntrack, int *midich, int *type, int *par1, int *par2); - - /**Imports a given midifile - * @return 0 if ok or -1 if there is a error loading file*/ - int importmidifile(const char *filename); - - void startplay(); - void stopplay(); - - - int play; - int playspeed; //viteza de rulare (0.1x-10x), 0=1.0x, 128=10x - void setplayspeed(int speed); - - private: - - MIDIFile midifile; - - /* Timer */ - struct timestruct { - double abs; //the time from the begining of the track - double rel; //the time difference between the last and the current event - double last; //the time of the last event (absolute, since 1 Jan 1970) - //these must be double, because the float's precision is too low - //and all these represent the time in seconds - } playtime[NUM_MIDI_TRACKS]; - - void resettime(timestruct *t); - void updatecounter(timestruct *t); //this updates the timer values - - /* Player only*/ - - struct { - event ev; - double time; - } nextevent[NUM_MIDI_TRACKS]; - - double realplayspeed; -}; - -#endif - diff --git a/plugins/zynaddsubfx/src/Synth/ADnote.cpp b/plugins/zynaddsubfx/src/Synth/ADnote.cpp deleted file mode 100644 index aa149cef5..000000000 --- a/plugins/zynaddsubfx/src/Synth/ADnote.cpp +++ /dev/null @@ -1,1987 +0,0 @@ -/* - ZynAddSubFX - a software synthesizer - - ADnote.cpp - The "additive" synthesizer - Copyright (C) 2002-2005 Nasca Octavian Paul - Author: Nasca Octavian Paul - - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License - as published by the Free Software Foundation. - - 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 (version 2 or later) for more details. - - You should have received a copy of the GNU General Public License (version 2) - along with this program; if not, write to the Free Software Foundation, - Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#include -#include -#include -#include - -#include "../globals.h" -#include "../Misc/Util.h" -#include "ADnote.h" - - -ADnote::ADnote(ADnoteParameters *pars, - Controller *ctl_, - REALTYPE freq, - REALTYPE velocity, - int portamento_, - int midinote_, - bool besilent) -{ - ready = 0; - - tmpwavel = new REALTYPE [SOUND_BUFFER_SIZE]; - tmpwaver = new REALTYPE [SOUND_BUFFER_SIZE]; - bypassl = new REALTYPE [SOUND_BUFFER_SIZE]; - bypassr = new REALTYPE [SOUND_BUFFER_SIZE]; - - // Initialise some legato-specific vars - Legato.msg = LM_Norm; - Legato.fade.length = (int)(SAMPLE_RATE * 0.005); // 0.005 seems ok. - if(Legato.fade.length < 1) - Legato.fade.length = 1; // (if something's fishy) - Legato.fade.step = (1.0 / Legato.fade.length); - Legato.decounter = -10; - Legato.param.freq = freq; - Legato.param.vel = velocity; - Legato.param.portamento = portamento_; - Legato.param.midinote = midinote_; - Legato.silent = besilent; - - partparams = pars; - ctl = ctl_; - portamento = portamento_; - midinote = midinote_; - NoteEnabled = ON; - basefreq = freq; - if(velocity > 1.0) - velocity = 1.0; - this->velocity = velocity; - time = 0.0; - stereo = pars->GlobalPar.PStereo; - - NoteGlobalPar.Detune = getdetune(pars->GlobalPar.PDetuneType, - pars->GlobalPar.PCoarseDetune, - pars->GlobalPar.PDetune); - bandwidthDetuneMultiplier = pars->getBandwidthDetuneMultiplier(); - - if(pars->GlobalPar.PPanning == 0) - NoteGlobalPar.Panning = RND; - else - NoteGlobalPar.Panning = pars->GlobalPar.PPanning / 128.0; - - - NoteGlobalPar.FilterCenterPitch = pars->GlobalPar.GlobalFilter->getfreq() //center freq - + pars->GlobalPar.PFilterVelocityScale - / 127.0 * 6.0 //velocity sensing - * (VelF(velocity, - pars->GlobalPar. - PFilterVelocityScaleFunction) - 1); - - if(pars->GlobalPar.PPunchStrength != 0) { - NoteGlobalPar.Punch.Enabled = 1; - NoteGlobalPar.Punch.t = 1.0; //start from 1.0 and to 0.0 - NoteGlobalPar.Punch.initialvalue = - ((pow(10, 1.5 * pars->GlobalPar.PPunchStrength / 127.0) - 1.0) - * VelF(velocity, - pars->GlobalPar.PPunchVelocitySensing)); - REALTYPE time = - pow(10, 3.0 * pars->GlobalPar.PPunchTime / 127.0) / 10000.0; //0.1 .. 100 ms - REALTYPE stretch = pow(440.0 / freq, - pars->GlobalPar.PPunchStretch / 64.0); - NoteGlobalPar.Punch.dt = 1.0 / (time * SAMPLE_RATE * stretch); - } - else - NoteGlobalPar.Punch.Enabled = 0; - - for(int nvoice = 0; nvoice < NUM_VOICES; nvoice++) { - pars->VoicePar[nvoice].OscilSmp->newrandseed(rand()); - NoteVoicePar[nvoice].OscilSmp = NULL; - NoteVoicePar[nvoice].FMSmp = NULL; - NoteVoicePar[nvoice].VoiceOut = NULL; - - NoteVoicePar[nvoice].FMVoice = -1; - unison_size[nvoice] = 1; - - if(pars->VoicePar[nvoice].Enabled == 0) { - NoteVoicePar[nvoice].Enabled = OFF; - continue; //the voice is disabled - } - - unison_stereo_spread[nvoice] = - pars->VoicePar[nvoice].Unison_stereo_spread / 127.0; - int unison = pars->VoicePar[nvoice].Unison_size; - if(unison < 1) - unison = 1; - - //compute unison - unison_size[nvoice] = unison; - - unison_base_freq_rap[nvoice] = new REALTYPE[unison]; - unison_freq_rap[nvoice] = new REALTYPE[unison]; - unison_invert_phase[nvoice] = new bool[unison]; - REALTYPE unison_spread = pars->getUnisonFrequencySpreadCents( - nvoice); - REALTYPE unison_real_spread = pow(2.0, (unison_spread * 0.5) / 1200.0); - REALTYPE unison_vibratto_a = pars->VoicePar[nvoice].Unison_vibratto - / 127.0; //0.0 .. 1.0 - - - switch(unison) { - case 1: - unison_base_freq_rap[nvoice][0] = 1.0; //if the unison is not used, always make the only subvoice to have the default note - break; - case 2: { //unison for 2 subvoices - unison_base_freq_rap[nvoice][0] = 1.0 / unison_real_spread; - unison_base_freq_rap[nvoice][1] = unison_real_spread; - }; - break; - default: { //unison for more than 2 subvoices - REALTYPE unison_values[unison]; - REALTYPE min = -1e-6, max = 1e-6; - for(int k = 0; k < unison; k++) { - REALTYPE step = (k / (REALTYPE) (unison - 1)) * 2.0 - 1.0; //this makes the unison spread more uniform - REALTYPE val = step + (RND * 2.0 - 1.0) / (unison - 1); - unison_values[k] = val; - if(val > max) - max = val; - if(val < min) - min = val; - } - REALTYPE diff = max - min; - for(int k = 0; k < unison; k++) { - unison_values[k] = - (unison_values[k] - (max + min) * 0.5) / diff; //the lowest value will be -1 and the highest will be 1 - unison_base_freq_rap[nvoice][k] = - pow(2.0, (unison_spread * unison_values[k]) / 1200); - } - }; - } - - //unison vibrattos - if(unison > 1) { - for(int k = 0; k < unison; k++) //reduce the frequency difference for larger vibrattos - unison_base_freq_rap[nvoice][k] = 1.0 - + (unison_base_freq_rap[ - nvoice][k] - - 1.0) - * (1.0 - unison_vibratto_a); - ; - } - unison_vibratto[nvoice].step = new REALTYPE[unison]; - unison_vibratto[nvoice].position = new REALTYPE[unison]; - unison_vibratto[nvoice].amplitude = - (unison_real_spread - 1.0) * unison_vibratto_a; - - REALTYPE increments_per_second = SAMPLE_RATE - / (REALTYPE)SOUND_BUFFER_SIZE; - REALTYPE vibratto_base_period = 0.25 - * pow(2.0, - (1.0 - - pars->VoicePar[nvoice]. - Unison_vibratto_speed / 127.0) * 4.0); - for(int k = 0; k < unison; k++) { - unison_vibratto[nvoice].position[k] = RND * 1.8 - 0.9; - REALTYPE vibratto_period = vibratto_base_period * pow( - 2.0, - RND * 2.0 - - 1.0); //make period to vary randomly from 50% to 200% vibratto base period - - REALTYPE m = 4.0 / (vibratto_period * increments_per_second); - if(RND < 0.5) - m = -m; - unison_vibratto[nvoice].step[k] = m; - } - - if(unison == 1) { //no vibratto for a single voice - unison_vibratto[nvoice].step[0] = 0.0; - unison_vibratto[nvoice].position[0] = 0.0; - unison_vibratto[nvoice].amplitude = 0.0; - } - - //phase invert for unison - unison_invert_phase[nvoice][0] = false; - if(unison != 1) { - int inv = pars->VoicePar[nvoice].Unison_invert_phase; - switch(inv) { - case 0: for(int k = 0; k < unison; k++) - unison_invert_phase[nvoice][k] = false; - break; - case 1: for(int k = 0; k < unison; k++) - unison_invert_phase[nvoice][k] = (RND > 0.5); - break; - default: for(int k = 0; k < unison; k++) - unison_invert_phase[nvoice][k] = - (k % inv == 0) ? true : false; - break; - } - } - - - oscfreqhi[nvoice] = new int[unison]; - oscfreqlo[nvoice] = new REALTYPE[unison]; - oscfreqhiFM[nvoice] = new unsigned int[unison]; - oscfreqloFM[nvoice] = new REALTYPE[unison]; - oscposhi[nvoice] = new int[unison]; - oscposlo[nvoice] = new REALTYPE[unison]; - oscposhiFM[nvoice] = new unsigned int[unison]; - oscposloFM[nvoice] = new REALTYPE[unison]; - - NoteVoicePar[nvoice].Enabled = ON; - NoteVoicePar[nvoice].fixedfreq = pars->VoicePar[nvoice].Pfixedfreq; - NoteVoicePar[nvoice].fixedfreqET = pars->VoicePar[nvoice].PfixedfreqET; - - //use the Globalpars.detunetype if the detunetype is 0 - if(pars->VoicePar[nvoice].PDetuneType != 0) { - NoteVoicePar[nvoice].Detune = getdetune( - pars->VoicePar[nvoice].PDetuneType, - pars->VoicePar[nvoice]. - PCoarseDetune, - 8192); //coarse detune - NoteVoicePar[nvoice].FineDetune = getdetune( - pars->VoicePar[nvoice].PDetuneType, - 0, - pars->VoicePar[nvoice].PDetune); //fine detune - } - else { - NoteVoicePar[nvoice].Detune = getdetune( - pars->GlobalPar.PDetuneType, - pars->VoicePar[nvoice]. - PCoarseDetune, - 8192); //coarse detune - NoteVoicePar[nvoice].FineDetune = getdetune( - pars->GlobalPar.PDetuneType, - 0, - pars->VoicePar[nvoice].PDetune); //fine detune - } - if(pars->VoicePar[nvoice].PFMDetuneType != 0) - NoteVoicePar[nvoice].FMDetune = getdetune( - pars->VoicePar[nvoice].PFMDetuneType, - pars->VoicePar[nvoice]. - PFMCoarseDetune, - pars->VoicePar[nvoice].PFMDetune); - else - NoteVoicePar[nvoice].FMDetune = getdetune( - pars->GlobalPar.PDetuneType, - pars->VoicePar[nvoice]. - PFMCoarseDetune, - pars->VoicePar[nvoice].PFMDetune); - ; - - - for(int k = 0; k < unison; k++) { - oscposhi[nvoice][k] = 0; - oscposlo[nvoice][k] = 0.0; - oscposhiFM[nvoice][k] = 0; - oscposloFM[nvoice][k] = 0.0; - } - - NoteVoicePar[nvoice].OscilSmp = - new REALTYPE[OSCIL_SIZE + OSCIL_SMP_EXTRA_SAMPLES]; //the extra points contains the first point - - //Get the voice's oscil or external's voice oscil - int vc = nvoice; - if(pars->VoicePar[nvoice].Pextoscil != -1) - vc = pars->VoicePar[nvoice].Pextoscil; - if(!pars->GlobalPar.Hrandgrouping) - pars->VoicePar[vc].OscilSmp->newrandseed(rand()); - int oscposhi_start = - pars->VoicePar[vc].OscilSmp->get(NoteVoicePar[nvoice].OscilSmp, - getvoicebasefreq(nvoice), - pars->VoicePar[nvoice].Presonance); - - //I store the first elments to the last position for speedups - for(int i = 0; i < OSCIL_SMP_EXTRA_SAMPLES; i++) - NoteVoicePar[nvoice].OscilSmp[OSCIL_SIZE - + i] = - NoteVoicePar[nvoice].OscilSmp[i]; - - oscposhi_start += - (int)((pars->VoicePar[nvoice].Poscilphase - - 64.0) / 128.0 * OSCIL_SIZE + OSCIL_SIZE * 4); - oscposhi_start %= OSCIL_SIZE; - - for(int k = 0; k < unison; k++) { - oscposhi[nvoice][k] = oscposhi_start; - oscposhi_start = (int)(RND * (OSCIL_SIZE - 1)); //put random starting point for other subvoices - } - - NoteVoicePar[nvoice].FreqLfo = NULL; - NoteVoicePar[nvoice].FreqEnvelope = NULL; - - NoteVoicePar[nvoice].AmpLfo = NULL; - NoteVoicePar[nvoice].AmpEnvelope = NULL; - - NoteVoicePar[nvoice].VoiceFilterL = NULL; - NoteVoicePar[nvoice].VoiceFilterR = NULL; - NoteVoicePar[nvoice].FilterEnvelope = NULL; - NoteVoicePar[nvoice].FilterLfo = NULL; - - NoteVoicePar[nvoice].FilterCenterPitch = - pars->VoicePar[nvoice].VoiceFilter->getfreq(); - NoteVoicePar[nvoice].filterbypass = - pars->VoicePar[nvoice].Pfilterbypass; - - switch(pars->VoicePar[nvoice].PFMEnabled) { - case 1: - NoteVoicePar[nvoice].FMEnabled = MORPH; - break; - case 2: - NoteVoicePar[nvoice].FMEnabled = RING_MOD; - break; - case 3: - NoteVoicePar[nvoice].FMEnabled = PHASE_MOD; - break; - case 4: - NoteVoicePar[nvoice].FMEnabled = FREQ_MOD; - break; - case 5: - NoteVoicePar[nvoice].FMEnabled = PITCH_MOD; - break; - default: - NoteVoicePar[nvoice].FMEnabled = NONE; - } - - NoteVoicePar[nvoice].FMVoice = pars->VoicePar[nvoice].PFMVoice; - NoteVoicePar[nvoice].FMFreqEnvelope = NULL; - NoteVoicePar[nvoice].FMAmpEnvelope = NULL; - - //Compute the Voice's modulator volume (incl. damping) - REALTYPE fmvoldamp = pow(440.0 / getvoicebasefreq( - nvoice), - pars->VoicePar[nvoice].PFMVolumeDamp / 64.0 - - 1.0); - switch(NoteVoicePar[nvoice].FMEnabled) { - case PHASE_MOD: - fmvoldamp = - pow(440.0 / getvoicebasefreq( - nvoice), pars->VoicePar[nvoice].PFMVolumeDamp / 64.0); - NoteVoicePar[nvoice].FMVolume = - (exp(pars->VoicePar[nvoice].PFMVolume / 127.0 - * FM_AMP_MULTIPLIER) - 1.0) * fmvoldamp * 4.0; - break; - case FREQ_MOD: - NoteVoicePar[nvoice].FMVolume = - (exp(pars->VoicePar[nvoice].PFMVolume / 127.0 - * FM_AMP_MULTIPLIER) - 1.0) * fmvoldamp * 4.0; - break; - // case PITCH_MOD:NoteVoicePar[nvoice].FMVolume=(pars->VoicePar[nvoice].PFMVolume/127.0*8.0)*fmvoldamp;//??????????? - // break; - default: - if(fmvoldamp > 1.0) - fmvoldamp = 1.0; - NoteVoicePar[nvoice].FMVolume = pars->VoicePar[nvoice].PFMVolume - / 127.0 * fmvoldamp; - } - - //Voice's modulator velocity sensing - NoteVoicePar[nvoice].FMVolume *= - VelF(velocity, - partparams->VoicePar[nvoice].PFMVelocityScaleFunction); - - FMoldsmp[nvoice] = new REALTYPE [unison]; - for(int k = 0; k < unison; k++) - FMoldsmp[nvoice][k] = 0.0; //this is for FM (integration) - - firsttick[nvoice] = 1; - NoteVoicePar[nvoice].DelayTicks = - (int)((exp(pars->VoicePar[nvoice].PDelay / 127.0 - * log(50.0)) - - 1.0) / SOUND_BUFFER_SIZE / 10.0 * SAMPLE_RATE); - } - - max_unison = 1; - for(int nvoice = 0; nvoice < NUM_VOICES; nvoice++) - if(unison_size[nvoice] > max_unison) - max_unison = unison_size[nvoice]; - ; - - tmpwave_unison = new REALTYPE *[max_unison]; - for(int k = 0; k < max_unison; k++) { - tmpwave_unison[k] = new REALTYPE[SOUND_BUFFER_SIZE]; - memset(tmpwave_unison[k], 0, SOUND_BUFFER_SIZE * sizeof(REALTYPE)); - } - - initparameters(); - ready = 1; -} - -// ADlegatonote: This function is (mostly) a copy of ADnote(...) and -// initparameters() stuck together with some lines removed so that it -// only alter the already playing note (to perform legato). It is -// possible I left stuff that is not required for this. -void ADnote::ADlegatonote(REALTYPE freq, - REALTYPE velocity, - int portamento_, - int midinote_, - bool externcall) -{ - ADnoteParameters *pars = partparams; - //Controller *ctl_=ctl; - - // Manage legato stuff - if(externcall) - Legato.msg = LM_Norm; - if(Legato.msg != LM_CatchUp) { - Legato.lastfreq = Legato.param.freq; - Legato.param.freq = freq; - Legato.param.vel = velocity; - Legato.param.portamento = portamento_; - Legato.param.midinote = midinote_; - if(Legato.msg == LM_Norm) { - if(Legato.silent) { - Legato.fade.m = 0.0; - Legato.msg = LM_FadeIn; - } - else { - Legato.fade.m = 1.0; - Legato.msg = LM_FadeOut; - return; - } - } - if(Legato.msg == LM_ToNorm) - Legato.msg = LM_Norm; - } - - portamento = portamento_; - midinote = midinote_; - basefreq = freq; - - if(velocity > 1.0) - velocity = 1.0; - this->velocity = velocity; - - NoteGlobalPar.Detune = getdetune(pars->GlobalPar.PDetuneType, - pars->GlobalPar.PCoarseDetune, - pars->GlobalPar.PDetune); - bandwidthDetuneMultiplier = pars->getBandwidthDetuneMultiplier(); - - if(pars->GlobalPar.PPanning == 0) - NoteGlobalPar.Panning = RND; - else - NoteGlobalPar.Panning = pars->GlobalPar.PPanning / 128.0; - - - NoteGlobalPar.FilterCenterPitch = pars->GlobalPar.GlobalFilter->getfreq() //center freq - + pars->GlobalPar.PFilterVelocityScale - / 127.0 * 6.0 //velocity sensing - * (VelF(velocity, - pars->GlobalPar. - PFilterVelocityScaleFunction) - 1); - - - for(int nvoice = 0; nvoice < NUM_VOICES; nvoice++) { - if(NoteVoicePar[nvoice].Enabled == OFF) - continue; //(gf) Stay the same as first note in legato. - - NoteVoicePar[nvoice].fixedfreq = pars->VoicePar[nvoice].Pfixedfreq; - NoteVoicePar[nvoice].fixedfreqET = pars->VoicePar[nvoice].PfixedfreqET; - - //use the Globalpars.detunetype if the detunetype is 0 - if(pars->VoicePar[nvoice].PDetuneType != 0) { - NoteVoicePar[nvoice].Detune = getdetune( - pars->VoicePar[nvoice].PDetuneType, - pars->VoicePar[nvoice]. - PCoarseDetune, - 8192); //coarse detune - NoteVoicePar[nvoice].FineDetune = getdetune( - pars->VoicePar[nvoice].PDetuneType, - 0, - pars->VoicePar[nvoice].PDetune); //fine detune - } - else { - NoteVoicePar[nvoice].Detune = getdetune( - pars->GlobalPar.PDetuneType, - pars->VoicePar[nvoice]. - PCoarseDetune, - 8192); //coarse detune - NoteVoicePar[nvoice].FineDetune = getdetune( - pars->GlobalPar.PDetuneType, - 0, - pars->VoicePar[nvoice].PDetune); //fine detune - } - if(pars->VoicePar[nvoice].PFMDetuneType != 0) - NoteVoicePar[nvoice].FMDetune = getdetune( - pars->VoicePar[nvoice].PFMDetuneType, - pars->VoicePar[nvoice]. - PFMCoarseDetune, - pars->VoicePar[nvoice].PFMDetune); - else - NoteVoicePar[nvoice].FMDetune = getdetune( - pars->GlobalPar.PDetuneType, - pars->VoicePar[nvoice]. - PFMCoarseDetune, - pars->VoicePar[nvoice].PFMDetune); - ; - - //Get the voice's oscil or external's voice oscil - int vc = nvoice; - if(pars->VoicePar[nvoice].Pextoscil != -1) - vc = pars->VoicePar[nvoice].Pextoscil; - if(!pars->GlobalPar.Hrandgrouping) - pars->VoicePar[vc].OscilSmp->newrandseed(rand()); - - pars->VoicePar[vc].OscilSmp->get(NoteVoicePar[nvoice].OscilSmp, - getvoicebasefreq(nvoice), - pars->VoicePar[nvoice].Presonance); //(gf)Modif of the above line. - - //I store the first elments to the last position for speedups - for(int i = 0; i < OSCIL_SMP_EXTRA_SAMPLES; i++) - NoteVoicePar[nvoice].OscilSmp[OSCIL_SIZE - + i] = - NoteVoicePar[nvoice].OscilSmp[i]; - - - NoteVoicePar[nvoice].FilterCenterPitch = - pars->VoicePar[nvoice].VoiceFilter->getfreq(); - NoteVoicePar[nvoice].filterbypass = - pars->VoicePar[nvoice].Pfilterbypass; - - - NoteVoicePar[nvoice].FMVoice = pars->VoicePar[nvoice].PFMVoice; - - //Compute the Voice's modulator volume (incl. damping) - REALTYPE fmvoldamp = pow(440.0 / getvoicebasefreq( - nvoice), - pars->VoicePar[nvoice].PFMVolumeDamp / 64.0 - - 1.0); - - switch(NoteVoicePar[nvoice].FMEnabled) { - case PHASE_MOD: - fmvoldamp = - pow(440.0 / getvoicebasefreq( - nvoice), pars->VoicePar[nvoice].PFMVolumeDamp / 64.0); - NoteVoicePar[nvoice].FMVolume = - (exp(pars->VoicePar[nvoice].PFMVolume / 127.0 - * FM_AMP_MULTIPLIER) - 1.0) * fmvoldamp * 4.0; - break; - case FREQ_MOD: - NoteVoicePar[nvoice].FMVolume = - (exp(pars->VoicePar[nvoice].PFMVolume / 127.0 - * FM_AMP_MULTIPLIER) - 1.0) * fmvoldamp * 4.0; - break; - // case PITCH_MOD:NoteVoicePar[nvoice].FMVolume=(pars->VoicePar[nvoice].PFMVolume/127.0*8.0)*fmvoldamp;//??????????? - // break; - default: - if(fmvoldamp > 1.0) - fmvoldamp = 1.0; - NoteVoicePar[nvoice].FMVolume = pars->VoicePar[nvoice].PFMVolume - / 127.0 * fmvoldamp; - } - - //Voice's modulator velocity sensing - NoteVoicePar[nvoice].FMVolume *= - VelF(velocity, - partparams->VoicePar[nvoice].PFMVelocityScaleFunction); - - NoteVoicePar[nvoice].DelayTicks = - (int)((exp(pars->VoicePar[nvoice].PDelay / 127.0 - * log(50.0)) - - 1.0) / SOUND_BUFFER_SIZE / 10.0 * SAMPLE_RATE); - } - - /// initparameters(); - - /////////////// - // Altered content of initparameters(): - - int nvoice, i, tmp[NUM_VOICES]; - - NoteGlobalPar.Volume = 4.0 - * pow(0.1, 3.0 - * (1.0 - partparams->GlobalPar.PVolume / 96.0)) //-60 dB .. 0 dB - * VelF( - velocity, - partparams->GlobalPar. - PAmpVelocityScaleFunction); //velocity sensing - - globalnewamplitude = NoteGlobalPar.Volume - * NoteGlobalPar.AmpEnvelope->envout_dB() - * NoteGlobalPar.AmpLfo->amplfoout(); - - NoteGlobalPar.FilterQ = partparams->GlobalPar.GlobalFilter->getq(); - NoteGlobalPar.FilterFreqTracking = - partparams->GlobalPar.GlobalFilter->getfreqtracking(basefreq); - - // Forbids the Modulation Voice to be greater or equal than voice - for(i = 0; i < NUM_VOICES; i++) - if(NoteVoicePar[i].FMVoice >= i) - NoteVoicePar[i].FMVoice = -1; - - // Voice Parameter init - for(nvoice = 0; nvoice < NUM_VOICES; nvoice++) { - if(NoteVoicePar[nvoice].Enabled == 0) - continue; - - NoteVoicePar[nvoice].noisetype = partparams->VoicePar[nvoice].Type; - /* Voice Amplitude Parameters Init */ - NoteVoicePar[nvoice].Volume = - pow(0.1, 3.0 * (1.0 - partparams->VoicePar[nvoice].PVolume / 127.0)) // -60 dB .. 0 dB - * VelF(velocity, - partparams->VoicePar[nvoice].PAmpVelocityScaleFunction); //velocity - - if(partparams->VoicePar[nvoice].PVolumeminus != 0) - NoteVoicePar[nvoice].Volume = -NoteVoicePar[nvoice].Volume; - - if(partparams->VoicePar[nvoice].PPanning == 0) - NoteVoicePar[nvoice].Panning = RND; // random panning - else - NoteVoicePar[nvoice].Panning = - partparams->VoicePar[nvoice].PPanning / 128.0; - - newamplitude[nvoice] = 1.0; - if((partparams->VoicePar[nvoice].PAmpEnvelopeEnabled != 0) - && (NoteVoicePar[nvoice].AmpEnvelope != NULL)) - newamplitude[nvoice] *= NoteVoicePar[nvoice].AmpEnvelope->envout_dB(); - ; - - if((partparams->VoicePar[nvoice].PAmpLfoEnabled != 0) - && (NoteVoicePar[nvoice].AmpLfo != NULL)) - newamplitude[nvoice] *= NoteVoicePar[nvoice].AmpLfo->amplfoout(); - ; - - - NoteVoicePar[nvoice].FilterFreqTracking = - partparams->VoicePar[nvoice].VoiceFilter->getfreqtracking(basefreq); - - /* Voice Modulation Parameters Init */ - if((NoteVoicePar[nvoice].FMEnabled != NONE) - && (NoteVoicePar[nvoice].FMVoice < 0)) { - partparams->VoicePar[nvoice].FMSmp->newrandseed(rand()); - - //Perform Anti-aliasing only on MORPH or RING MODULATION - - int vc = nvoice; - if(partparams->VoicePar[nvoice].PextFMoscil != -1) - vc = partparams->VoicePar[nvoice].PextFMoscil; - - if(!partparams->GlobalPar.Hrandgrouping) - partparams->VoicePar[vc].FMSmp->newrandseed(rand()); - - ///oscposhiFM[nvoice]=(oscposhi[nvoice]+partparams->VoicePar[vc].FMSmp->get(NoteVoicePar[nvoice].FMSmp,tmp)) % OSCIL_SIZE; - // / oscposhi[nvoice]+partparams->VoicePar[vc].FMSmp->get(NoteVoicePar[nvoice].FMSmp,tmp); //(gf) Modif of the above line. - for(int i = 0; i < OSCIL_SMP_EXTRA_SAMPLES; i++) - NoteVoicePar[nvoice].FMSmp[OSCIL_SIZE - + i] = NoteVoicePar[nvoice].FMSmp[i]; - ///oscposhiFM[nvoice]+=(int)((partparams->VoicePar[nvoice].PFMoscilphase-64.0)/128.0*OSCIL_SIZE+OSCIL_SIZE*4); - ///oscposhiFM[nvoice]%=OSCIL_SIZE; - } - - FMnewamplitude[nvoice] = NoteVoicePar[nvoice].FMVolume - * ctl->fmamp.relamp; - - if((partparams->VoicePar[nvoice].PFMAmpEnvelopeEnabled != 0) - && (NoteVoicePar[nvoice].FMAmpEnvelope != NULL)) - FMnewamplitude[nvoice] *= - NoteVoicePar[nvoice].FMAmpEnvelope->envout_dB(); - ; - } - - for(nvoice = 0; nvoice < NUM_VOICES; nvoice++) { - for(i = nvoice + 1; i < NUM_VOICES; i++) - tmp[i] = 0; - for(i = nvoice + 1; i < NUM_VOICES; i++) - if((NoteVoicePar[i].FMVoice == nvoice) && (tmp[i] == 0)) - tmp[i] = 1; - ; - } - /////////////// - - // End of the ADlegatonote function. -} - - -/* - * Kill a voice of ADnote - */ -void ADnote::KillVoice(int nvoice) -{ - delete [] oscfreqhi[nvoice]; - delete [] oscfreqlo[nvoice]; - delete [] oscfreqhiFM[nvoice]; - delete [] oscfreqloFM[nvoice]; - delete [] oscposhi[nvoice]; - delete [] oscposlo[nvoice]; - delete [] oscposhiFM[nvoice]; - delete [] oscposloFM[nvoice]; - - delete [] NoteVoicePar[nvoice].OscilSmp; - delete [] unison_base_freq_rap[nvoice]; - delete [] unison_freq_rap[nvoice]; - delete [] unison_invert_phase[nvoice]; - delete [] FMoldsmp[nvoice]; - delete [] unison_vibratto[nvoice].step; - delete [] unison_vibratto[nvoice].position; - - if(NoteVoicePar[nvoice].FreqEnvelope != NULL) - delete (NoteVoicePar[nvoice].FreqEnvelope); - NoteVoicePar[nvoice].FreqEnvelope = NULL; - - if(NoteVoicePar[nvoice].FreqLfo != NULL) - delete (NoteVoicePar[nvoice].FreqLfo); - NoteVoicePar[nvoice].FreqLfo = NULL; - - if(NoteVoicePar[nvoice].AmpEnvelope != NULL) - delete (NoteVoicePar[nvoice].AmpEnvelope); - NoteVoicePar[nvoice].AmpEnvelope = NULL; - - if(NoteVoicePar[nvoice].AmpLfo != NULL) - delete (NoteVoicePar[nvoice].AmpLfo); - NoteVoicePar[nvoice].AmpLfo = NULL; - - if(NoteVoicePar[nvoice].VoiceFilterL != NULL) - delete (NoteVoicePar[nvoice].VoiceFilterL); - NoteVoicePar[nvoice].VoiceFilterL = NULL; - - if(NoteVoicePar[nvoice].VoiceFilterR != NULL) - delete (NoteVoicePar[nvoice].VoiceFilterR); - NoteVoicePar[nvoice].VoiceFilterR = NULL; - - if(NoteVoicePar[nvoice].FilterEnvelope != NULL) - delete (NoteVoicePar[nvoice].FilterEnvelope); - NoteVoicePar[nvoice].FilterEnvelope = NULL; - - if(NoteVoicePar[nvoice].FilterLfo != NULL) - delete (NoteVoicePar[nvoice].FilterLfo); - NoteVoicePar[nvoice].FilterLfo = NULL; - - if(NoteVoicePar[nvoice].FMFreqEnvelope != NULL) - delete (NoteVoicePar[nvoice].FMFreqEnvelope); - NoteVoicePar[nvoice].FMFreqEnvelope = NULL; - - if(NoteVoicePar[nvoice].FMAmpEnvelope != NULL) - delete (NoteVoicePar[nvoice].FMAmpEnvelope); - NoteVoicePar[nvoice].FMAmpEnvelope = NULL; - - if((NoteVoicePar[nvoice].FMEnabled != NONE) - && (NoteVoicePar[nvoice].FMVoice < 0)) - delete [] NoteVoicePar[nvoice].FMSmp; - - if(NoteVoicePar[nvoice].VoiceOut != NULL) - memset(NoteVoicePar[nvoice].VoiceOut, 0, SOUND_BUFFER_SIZE - * sizeof(REALTYPE));//do not delete, yet: perhaps is used by another voice - - NoteVoicePar[nvoice].Enabled = OFF; -} - -/* - * Kill the note - */ -void ADnote::KillNote() -{ - int nvoice; - for(nvoice = 0; nvoice < NUM_VOICES; nvoice++) { - if(NoteVoicePar[nvoice].Enabled == ON) - KillVoice(nvoice); - - //delete VoiceOut - if(NoteVoicePar[nvoice].VoiceOut != NULL) - delete (NoteVoicePar[nvoice].VoiceOut); - NoteVoicePar[nvoice].VoiceOut = NULL; - } - - delete (NoteGlobalPar.FreqEnvelope); - delete (NoteGlobalPar.FreqLfo); - delete (NoteGlobalPar.AmpEnvelope); - delete (NoteGlobalPar.AmpLfo); - delete (NoteGlobalPar.GlobalFilterL); - if(stereo != 0) - delete (NoteGlobalPar.GlobalFilterR); - delete (NoteGlobalPar.FilterEnvelope); - delete (NoteGlobalPar.FilterLfo); - - NoteEnabled = OFF; -} - -ADnote::~ADnote() -{ - if(NoteEnabled == ON) - KillNote(); - delete [] tmpwavel; - delete [] tmpwaver; - delete [] bypassl; - delete [] bypassr; - for(int k = 0; k < max_unison; k++) - delete[] tmpwave_unison[k]; - delete[] tmpwave_unison; -} - - -/* - * Init the parameters - */ -void ADnote::initparameters() -{ - int nvoice, i, tmp[NUM_VOICES]; - - // Global Parameters - NoteGlobalPar.FreqEnvelope = new Envelope( - partparams->GlobalPar.FreqEnvelope, - basefreq); - NoteGlobalPar.FreqLfo = new LFO(partparams->GlobalPar.FreqLfo, - basefreq); - - NoteGlobalPar.AmpEnvelope = new Envelope(partparams->GlobalPar.AmpEnvelope, - basefreq); - NoteGlobalPar.AmpLfo = new LFO(partparams->GlobalPar.AmpLfo, basefreq); - - NoteGlobalPar.Volume = 4.0 - * pow(0.1, 3.0 - * (1.0 - partparams->GlobalPar.PVolume / 96.0)) //-60 dB .. 0 dB - * VelF( - velocity, - partparams->GlobalPar. - PAmpVelocityScaleFunction); //velocity sensing - - NoteGlobalPar.AmpEnvelope->envout_dB(); //discard the first envelope output - globalnewamplitude = NoteGlobalPar.Volume - * NoteGlobalPar.AmpEnvelope->envout_dB() - * NoteGlobalPar.AmpLfo->amplfoout(); - - NoteGlobalPar.GlobalFilterL = new Filter(partparams->GlobalPar.GlobalFilter); - if(stereo != 0) - NoteGlobalPar.GlobalFilterR = new Filter( - partparams->GlobalPar.GlobalFilter); - - NoteGlobalPar.FilterEnvelope = new Envelope( - partparams->GlobalPar.FilterEnvelope, - basefreq); - NoteGlobalPar.FilterLfo = new LFO(partparams->GlobalPar.FilterLfo, - basefreq); - NoteGlobalPar.FilterQ = partparams->GlobalPar.GlobalFilter->getq(); - NoteGlobalPar.FilterFreqTracking = - partparams->GlobalPar.GlobalFilter->getfreqtracking(basefreq); - - // Forbids the Modulation Voice to be greater or equal than voice - for(i = 0; i < NUM_VOICES; i++) - if(NoteVoicePar[i].FMVoice >= i) - NoteVoicePar[i].FMVoice = -1; - - // Voice Parameter init - for(nvoice = 0; nvoice < NUM_VOICES; nvoice++) { - if(NoteVoicePar[nvoice].Enabled == 0) - continue; - - NoteVoicePar[nvoice].noisetype = partparams->VoicePar[nvoice].Type; - /* Voice Amplitude Parameters Init */ - NoteVoicePar[nvoice].Volume = - pow(0.1, 3.0 * (1.0 - partparams->VoicePar[nvoice].PVolume / 127.0)) // -60 dB .. 0 dB - * VelF(velocity, - partparams->VoicePar[nvoice].PAmpVelocityScaleFunction); //velocity - - if(partparams->VoicePar[nvoice].PVolumeminus != 0) - NoteVoicePar[nvoice].Volume = -NoteVoicePar[nvoice].Volume; - - if(partparams->VoicePar[nvoice].PPanning == 0) - NoteVoicePar[nvoice].Panning = RND; // random panning - else - NoteVoicePar[nvoice].Panning = - partparams->VoicePar[nvoice].PPanning / 128.0; - - newamplitude[nvoice] = 1.0; - if(partparams->VoicePar[nvoice].PAmpEnvelopeEnabled != 0) { - NoteVoicePar[nvoice].AmpEnvelope = new Envelope( - partparams->VoicePar[nvoice].AmpEnvelope, - basefreq); - NoteVoicePar[nvoice].AmpEnvelope->envout_dB(); //discard the first envelope sample - newamplitude[nvoice] *= NoteVoicePar[nvoice].AmpEnvelope->envout_dB(); - } - - if(partparams->VoicePar[nvoice].PAmpLfoEnabled != 0) { - NoteVoicePar[nvoice].AmpLfo = new LFO( - partparams->VoicePar[nvoice].AmpLfo, - basefreq); - newamplitude[nvoice] *= NoteVoicePar[nvoice].AmpLfo->amplfoout(); - } - - /* Voice Frequency Parameters Init */ - if(partparams->VoicePar[nvoice].PFreqEnvelopeEnabled != 0) - NoteVoicePar[nvoice].FreqEnvelope = new Envelope( - partparams->VoicePar[nvoice].FreqEnvelope, - basefreq); - - if(partparams->VoicePar[nvoice].PFreqLfoEnabled != 0) - NoteVoicePar[nvoice].FreqLfo = new LFO( - partparams->VoicePar[nvoice].FreqLfo, - basefreq); - - /* Voice Filter Parameters Init */ - if(partparams->VoicePar[nvoice].PFilterEnabled != 0) { - NoteVoicePar[nvoice].VoiceFilterL = new Filter( - partparams->VoicePar[nvoice].VoiceFilter); - NoteVoicePar[nvoice].VoiceFilterR = new Filter( - partparams->VoicePar[nvoice].VoiceFilter); - } - - if(partparams->VoicePar[nvoice].PFilterEnvelopeEnabled != 0) - NoteVoicePar[nvoice].FilterEnvelope = new Envelope( - partparams->VoicePar[nvoice].FilterEnvelope, - basefreq); - - if(partparams->VoicePar[nvoice].PFilterLfoEnabled != 0) - NoteVoicePar[nvoice].FilterLfo = - new LFO(partparams->VoicePar[nvoice].FilterLfo, basefreq); - - NoteVoicePar[nvoice].FilterFreqTracking = - partparams->VoicePar[nvoice].VoiceFilter->getfreqtracking(basefreq); - - /* Voice Modulation Parameters Init */ - if((NoteVoicePar[nvoice].FMEnabled != NONE) - && (NoteVoicePar[nvoice].FMVoice < 0)) { - partparams->VoicePar[nvoice].FMSmp->newrandseed(rand()); - NoteVoicePar[nvoice].FMSmp = - new REALTYPE[OSCIL_SIZE + OSCIL_SMP_EXTRA_SAMPLES]; - - //Perform Anti-aliasing only on MORPH or RING MODULATION - - int vc = nvoice; - if(partparams->VoicePar[nvoice].PextFMoscil != -1) - vc = partparams->VoicePar[nvoice].PextFMoscil; - - REALTYPE tmp = 1.0; - if((partparams->VoicePar[vc].FMSmp->Padaptiveharmonics != 0) - || (NoteVoicePar[nvoice].FMEnabled == MORPH) - || (NoteVoicePar[nvoice].FMEnabled == RING_MOD)) - tmp = getFMvoicebasefreq(nvoice); - ; - if(!partparams->GlobalPar.Hrandgrouping) - partparams->VoicePar[vc].FMSmp->newrandseed(rand()); - - for(int k = 0; k < unison_size[nvoice]; k++) - oscposhiFM[nvoice][k] = - (oscposhi[nvoice][k] - + partparams->VoicePar[vc].FMSmp->get(NoteVoicePar[nvoice] - . - FMSmp, - tmp)) % OSCIL_SIZE; - ; - for(int i = 0; i < OSCIL_SMP_EXTRA_SAMPLES; i++) - NoteVoicePar[nvoice].FMSmp[OSCIL_SIZE - + i] = NoteVoicePar[nvoice].FMSmp[i]; - int oscposhiFM_add = - (int)((partparams->VoicePar[nvoice].PFMoscilphase - - 64.0) / 128.0 * OSCIL_SIZE + OSCIL_SIZE * 4); - for(int k = 0; k < unison_size[nvoice]; k++) { - oscposhiFM[nvoice][k] += oscposhiFM_add; - oscposhiFM[nvoice][k] %= OSCIL_SIZE; - } - } - - if(partparams->VoicePar[nvoice].PFMFreqEnvelopeEnabled != 0) - NoteVoicePar[nvoice].FMFreqEnvelope = new Envelope( - partparams->VoicePar[nvoice].FMFreqEnvelope, - basefreq); - - FMnewamplitude[nvoice] = NoteVoicePar[nvoice].FMVolume - * ctl->fmamp.relamp; - - if(partparams->VoicePar[nvoice].PFMAmpEnvelopeEnabled != 0) { - NoteVoicePar[nvoice].FMAmpEnvelope = new Envelope( - partparams->VoicePar[nvoice].FMAmpEnvelope, - basefreq); - FMnewamplitude[nvoice] *= - NoteVoicePar[nvoice].FMAmpEnvelope->envout_dB(); - } - } - - for(nvoice = 0; nvoice < NUM_VOICES; nvoice++) { - for(i = nvoice + 1; i < NUM_VOICES; i++) - tmp[i] = 0; - for(i = nvoice + 1; i < NUM_VOICES; i++) - if((NoteVoicePar[i].FMVoice == nvoice) && (tmp[i] == 0)) { - NoteVoicePar[nvoice].VoiceOut = new REALTYPE[SOUND_BUFFER_SIZE]; - tmp[i] = 1; - } - ; - if(NoteVoicePar[nvoice].VoiceOut != NULL) - memset(NoteVoicePar[nvoice].VoiceOut, 0, SOUND_BUFFER_SIZE * sizeof(REALTYPE)); - } -} - - -/* - * Computes the relative frequency of each unison voice and it's vibratto - * This must be called before setfreq* functions - */ -void ADnote::compute_unison_freq_rap(int nvoice) { - if(unison_size[nvoice] == 1) { //no unison - unison_freq_rap[nvoice][0] = 1.0; - return; - } - REALTYPE relbw = ctl->bandwidth.relbw * bandwidthDetuneMultiplier; - for(int k = 0; k < unison_size[nvoice]; k++) { - REALTYPE pos = unison_vibratto[nvoice].position[k]; - REALTYPE step = unison_vibratto[nvoice].step[k]; - pos += step; - if(pos <= -1.0) { - pos = -1.0; - step = -step; - } - if(pos >= 1.0) { - pos = 1.0; - step = -step; - } - REALTYPE vibratto_val = (pos - 0.333333333 * pos * pos * pos) * 1.5; //make the vibratto lfo smoother - unison_freq_rap[nvoice][k] = 1.0 - + ((unison_base_freq_rap[nvoice][k] - - 1.0) + vibratto_val - * unison_vibratto[nvoice].amplitude) - * relbw; - - unison_vibratto[nvoice].position[k] = pos; - step = unison_vibratto[nvoice].step[k] = step; - } -} - - -/* - * Computes the frequency of an oscillator - */ -void ADnote::setfreq(int nvoice, REALTYPE in_freq) -{ - for(int k = 0; k < unison_size[nvoice]; k++) { - REALTYPE freq = fabs(in_freq) * unison_freq_rap[nvoice][k]; - REALTYPE speed = freq * REALTYPE(OSCIL_SIZE) / (REALTYPE) SAMPLE_RATE; - if(speed > OSCIL_SIZE) - speed = OSCIL_SIZE; - - F2I(speed, oscfreqhi[nvoice][k]); - oscfreqlo[nvoice][k] = speed - floor(speed); - } -} - -/* - * Computes the frequency of an modullator oscillator - */ -void ADnote::setfreqFM(int nvoice, REALTYPE in_freq) -{ - for(int k = 0; k < unison_size[nvoice]; k++) { - REALTYPE freq = fabs(in_freq) * unison_freq_rap[nvoice][k]; - REALTYPE speed = freq * REALTYPE(OSCIL_SIZE) / (REALTYPE) SAMPLE_RATE; - if(speed > OSCIL_SIZE) - speed = OSCIL_SIZE; - - F2I(speed, oscfreqhiFM[nvoice][k]); - oscfreqloFM[nvoice][k] = speed - floor(speed); - } -} - -/* - * Get Voice base frequency - */ -REALTYPE ADnote::getvoicebasefreq(int nvoice) const -{ - REALTYPE detune = NoteVoicePar[nvoice].Detune / 100.0 - + NoteVoicePar[nvoice].FineDetune / 100.0 - * ctl->bandwidth.relbw * bandwidthDetuneMultiplier - + NoteGlobalPar.Detune / 100.0; - - if(NoteVoicePar[nvoice].fixedfreq == 0) - return this->basefreq * pow(2, detune / 12.0); - else { //the fixed freq is enabled - REALTYPE fixedfreq = 440.0; - int fixedfreqET = NoteVoicePar[nvoice].fixedfreqET; - if(fixedfreqET != 0) { //if the frequency varies according the keyboard note - REALTYPE tmp = - (midinote - - 69.0) / 12.0 * (pow(2.0, (fixedfreqET - 1) / 63.0) - 1.0); - if(fixedfreqET <= 64) - fixedfreq *= pow(2.0, tmp); - else - fixedfreq *= pow(3.0, tmp); - } - return fixedfreq * pow(2.0, detune / 12.0); - } -} - -/* - * Get Voice's Modullator base frequency - */ -REALTYPE ADnote::getFMvoicebasefreq(int nvoice) const -{ - REALTYPE detune = NoteVoicePar[nvoice].FMDetune / 100.0; - return getvoicebasefreq(nvoice) * pow(2, detune / 12.0); -} - -/* - * Computes all the parameters for each tick - */ -void ADnote::computecurrentparameters() -{ - int nvoice; - REALTYPE voicefreq, voicepitch, filterpitch, filterfreq, FMfreq, - FMrelativepitch, globalpitch, globalfilterpitch; - globalpitch = 0.01 * (NoteGlobalPar.FreqEnvelope->envout() - + NoteGlobalPar.FreqLfo->lfoout() - * ctl->modwheel.relmod); - globaloldamplitude = globalnewamplitude; - globalnewamplitude = NoteGlobalPar.Volume - * NoteGlobalPar.AmpEnvelope->envout_dB() - * NoteGlobalPar.AmpLfo->amplfoout(); - - globalfilterpitch = NoteGlobalPar.FilterEnvelope->envout() - + NoteGlobalPar.FilterLfo->lfoout() - + NoteGlobalPar.FilterCenterPitch; - - REALTYPE tmpfilterfreq = globalfilterpitch + ctl->filtercutoff.relfreq - + NoteGlobalPar.FilterFreqTracking; - - tmpfilterfreq = NoteGlobalPar.GlobalFilterL->getrealfreq(tmpfilterfreq); - - REALTYPE globalfilterq = NoteGlobalPar.FilterQ * ctl->filterq.relq; - NoteGlobalPar.GlobalFilterL->setfreq_and_q(tmpfilterfreq, globalfilterq); - if(stereo != 0) - NoteGlobalPar.GlobalFilterR->setfreq_and_q(tmpfilterfreq, globalfilterq); - - //compute the portamento, if it is used by this note - REALTYPE portamentofreqrap = 1.0; - if(portamento != 0) { //this voice use portamento - portamentofreqrap = ctl->portamento.freqrap; - if(ctl->portamento.used == 0) //the portamento has finished - portamento = 0; //this note is no longer "portamented" - ; - } - - //compute parameters for all voices - for(nvoice = 0; nvoice < NUM_VOICES; nvoice++) { - if(NoteVoicePar[nvoice].Enabled != ON) - continue; - NoteVoicePar[nvoice].DelayTicks -= 1; - if(NoteVoicePar[nvoice].DelayTicks > 0) - continue; - - compute_unison_freq_rap(nvoice); - - /*******************/ - /* Voice Amplitude */ - /*******************/ - oldamplitude[nvoice] = newamplitude[nvoice]; - newamplitude[nvoice] = 1.0; - - if(NoteVoicePar[nvoice].AmpEnvelope != NULL) - newamplitude[nvoice] *= NoteVoicePar[nvoice].AmpEnvelope->envout_dB(); - - if(NoteVoicePar[nvoice].AmpLfo != NULL) - newamplitude[nvoice] *= NoteVoicePar[nvoice].AmpLfo->amplfoout(); - - /****************/ - /* Voice Filter */ - /****************/ - if(NoteVoicePar[nvoice].VoiceFilterL != NULL) { - filterpitch = NoteVoicePar[nvoice].FilterCenterPitch; - - if(NoteVoicePar[nvoice].FilterEnvelope != NULL) - filterpitch += NoteVoicePar[nvoice].FilterEnvelope->envout(); - - if(NoteVoicePar[nvoice].FilterLfo != NULL) - filterpitch += NoteVoicePar[nvoice].FilterLfo->lfoout(); - - filterfreq = filterpitch + NoteVoicePar[nvoice].FilterFreqTracking; - filterfreq = NoteVoicePar[nvoice].VoiceFilterL->getrealfreq( - filterfreq); - - NoteVoicePar[nvoice].VoiceFilterL->setfreq(filterfreq); - if(stereo && NoteVoicePar[nvoice].VoiceFilterR) - NoteVoicePar[nvoice].VoiceFilterR->setfreq(filterfreq); - } - - if(NoteVoicePar[nvoice].noisetype == 0) { //compute only if the voice isn't noise - /*******************/ - /* Voice Frequency */ - /*******************/ - voicepitch = 0.0; - if(NoteVoicePar[nvoice].FreqLfo != NULL) - voicepitch += NoteVoicePar[nvoice].FreqLfo->lfoout() / 100.0 - * ctl->bandwidth.relbw; - - if(NoteVoicePar[nvoice].FreqEnvelope != NULL) - voicepitch += NoteVoicePar[nvoice].FreqEnvelope->envout() - / 100.0; - voicefreq = getvoicebasefreq(nvoice) - * pow(2, (voicepitch + globalpitch) / 12.0); //Hz frequency - voicefreq *= ctl->pitchwheel.relfreq; //change the frequency by the controller - setfreq(nvoice, voicefreq * portamentofreqrap); - - /***************/ - /* Modulator */ - /***************/ - if(NoteVoicePar[nvoice].FMEnabled != NONE) { - FMrelativepitch = NoteVoicePar[nvoice].FMDetune / 100.0; - if(NoteVoicePar[nvoice].FMFreqEnvelope != NULL) - FMrelativepitch += - NoteVoicePar[nvoice].FMFreqEnvelope->envout() / 100; - FMfreq = - pow(2.0, FMrelativepitch - / 12.0) * voicefreq * portamentofreqrap; - setfreqFM(nvoice, FMfreq); - - FMoldamplitude[nvoice] = FMnewamplitude[nvoice]; - FMnewamplitude[nvoice] = NoteVoicePar[nvoice].FMVolume - * ctl->fmamp.relamp; - if(NoteVoicePar[nvoice].FMAmpEnvelope != NULL) - FMnewamplitude[nvoice] *= - NoteVoicePar[nvoice].FMAmpEnvelope->envout_dB(); - } - } - } - time += (REALTYPE)SOUND_BUFFER_SIZE / (REALTYPE)SAMPLE_RATE; -} - - -/* - * Fadein in a way that removes clicks but keep sound "punchy" - */ -inline void ADnote::fadein(REALTYPE *smps) const -{ - int zerocrossings = 0; - for(int i = 1; i < SOUND_BUFFER_SIZE; i++) - if((smps[i - 1] < 0.0) && (smps[i] > 0.0)) - zerocrossings++; //this is only the possitive crossings - - REALTYPE tmp = (SOUND_BUFFER_SIZE - 1.0) / (zerocrossings + 1) / 3.0; - if(tmp < 8.0) - tmp = 8.0; - - int n; - F2I(tmp, n); //how many samples is the fade-in - if(n > SOUND_BUFFER_SIZE) - n = SOUND_BUFFER_SIZE; - for(int i = 0; i < n; i++) { //fade-in - REALTYPE tmp = 0.5 - cos((REALTYPE)i / (REALTYPE) n * PI) * 0.5; - smps[i] *= tmp; - } -} - -/* - * Computes the Oscillator (Without Modulation) - LinearInterpolation - */ -inline void ADnote::ComputeVoiceOscillator_LinearInterpolation(int nvoice) -{ - int i, poshi; - REALTYPE poslo; - - for(int k = 0; k < unison_size[nvoice]; k++) { - poshi = oscposhi[nvoice][k]; - poslo = oscposlo[nvoice][k]; - int freqhi = oscfreqhi[nvoice][k]; - REALTYPE freqlo = oscfreqlo[nvoice][k]; - REALTYPE *smps = NoteVoicePar[nvoice].OscilSmp; - REALTYPE *tw = tmpwave_unison[k]; - for(i = 0; i < SOUND_BUFFER_SIZE; i++) { - tw[i] = smps[poshi] * (1.0 - poslo) + smps[poshi + 1] * poslo; - poslo += freqlo; - if(poslo >= 1.0) { - poslo -= 1.0; - poshi++; - } - poshi += freqhi; - poshi &= OSCIL_SIZE - 1; - } - oscposhi[nvoice][k] = poshi; - oscposlo[nvoice][k] = poslo; - } -} - - - -/* - * Computes the Oscillator (Without Modulation) - CubicInterpolation - * - The differences from the Linear are to little to deserve to be used. This is because I am using a large OSCIL_SIZE (>512) -inline void ADnote::ComputeVoiceOscillator_CubicInterpolation(int nvoice){ - int i,poshi; - REALTYPE poslo; - - poshi=oscposhi[nvoice]; - poslo=oscposlo[nvoice]; - REALTYPE *smps=NoteVoicePar[nvoice].OscilSmp; - REALTYPE xm1,x0,x1,x2,a,b,c; - for (i=0;i=1.0) { - poslo-=1.0; - poshi++; - }; - poshi+=oscfreqhi[nvoice]; - poshi&=OSCIL_SIZE-1; - }; - oscposhi[nvoice]=poshi; - oscposlo[nvoice]=poslo; -}; -*/ -/* - * Computes the Oscillator (Morphing) - */ -inline void ADnote::ComputeVoiceOscillatorMorph(int nvoice) -{ - int i; - REALTYPE amp; - ComputeVoiceOscillator_LinearInterpolation(nvoice); - if(FMnewamplitude[nvoice] > 1.0) - FMnewamplitude[nvoice] = 1.0; - if(FMoldamplitude[nvoice] > 1.0) - FMoldamplitude[nvoice] = 1.0; - - if(NoteVoicePar[nvoice].FMVoice >= 0) { - //if I use VoiceOut[] as modullator - int FMVoice = NoteVoicePar[nvoice].FMVoice; - for(int k = 0; k < unison_size[nvoice]; k++) { - REALTYPE *tw = tmpwave_unison[k]; - for(i = 0; i < SOUND_BUFFER_SIZE; i++) { - amp = INTERPOLATE_AMPLITUDE(FMoldamplitude[nvoice], - FMnewamplitude[nvoice], - i, - SOUND_BUFFER_SIZE); - tw[i] = tw[i] - * (1.0 - amp) + amp * NoteVoicePar[FMVoice].VoiceOut[i]; - } - } - } - else { - for(int k = 0; k < unison_size[nvoice]; k++) { - int poshiFM = oscposhiFM[nvoice][k]; - REALTYPE posloFM = oscposloFM[nvoice][k]; - int freqhiFM = oscfreqhiFM[nvoice][k]; - REALTYPE freqloFM = oscfreqloFM[nvoice][k]; - REALTYPE *tw = tmpwave_unison[k]; - - for(i = 0; i < SOUND_BUFFER_SIZE; i++) { - amp = INTERPOLATE_AMPLITUDE(FMoldamplitude[nvoice], - FMnewamplitude[nvoice], - i, - SOUND_BUFFER_SIZE); - tw[i] = tw[i] * (1.0 - amp) + amp - * (NoteVoicePar[nvoice].FMSmp[poshiFM] * (1 - posloFM) - + NoteVoicePar[nvoice].FMSmp[poshiFM + 1] * posloFM); - posloFM += freqloFM; - if(posloFM >= 1.0) { - posloFM -= 1.0; - poshiFM++; - } - poshiFM += freqhiFM; - poshiFM &= OSCIL_SIZE - 1; - } - oscposhiFM[nvoice][k] = poshiFM; - oscposloFM[nvoice][k] = posloFM; - } - } -} - -/* - * Computes the Oscillator (Ring Modulation) - */ -inline void ADnote::ComputeVoiceOscillatorRingModulation(int nvoice) -{ - int i; - REALTYPE amp; - ComputeVoiceOscillator_LinearInterpolation(nvoice); - if(FMnewamplitude[nvoice] > 1.0) - FMnewamplitude[nvoice] = 1.0; - if(FMoldamplitude[nvoice] > 1.0) - FMoldamplitude[nvoice] = 1.0; - if(NoteVoicePar[nvoice].FMVoice >= 0) { - // if I use VoiceOut[] as modullator - for(int k = 0; k < unison_size[nvoice]; k++) { - REALTYPE *tw = tmpwave_unison[k]; - for(i = 0; i < SOUND_BUFFER_SIZE; i++) { - amp = INTERPOLATE_AMPLITUDE(FMoldamplitude[nvoice], - FMnewamplitude[nvoice], - i, - SOUND_BUFFER_SIZE); - int FMVoice = NoteVoicePar[nvoice].FMVoice; - tw[i] *= (1.0 - amp) + amp * NoteVoicePar[FMVoice].VoiceOut[i]; - } - } - } - else { - for(int k = 0; k < unison_size[nvoice]; k++) { - int poshiFM = oscposhiFM[nvoice][k]; - REALTYPE posloFM = oscposloFM[nvoice][k]; - int freqhiFM = oscfreqhiFM[nvoice][k]; - REALTYPE freqloFM = oscfreqloFM[nvoice][k]; - REALTYPE *tw = tmpwave_unison[k]; - - for(i = 0; i < SOUND_BUFFER_SIZE; i++) { - amp = INTERPOLATE_AMPLITUDE(FMoldamplitude[nvoice], - FMnewamplitude[nvoice], - i, - SOUND_BUFFER_SIZE); - tw[i] *= (NoteVoicePar[nvoice].FMSmp[poshiFM] * (1.0 - posloFM) - + NoteVoicePar[nvoice].FMSmp[poshiFM - + 1] * posloFM) * amp - + (1.0 - amp); - posloFM += freqloFM; - if(posloFM >= 1.0) { - posloFM -= 1.0; - poshiFM++; - } - poshiFM += freqhiFM; - poshiFM &= OSCIL_SIZE - 1; - } - oscposhiFM[nvoice][k] = poshiFM; - oscposloFM[nvoice][k] = posloFM; - } - } -} - - - -/* - * Computes the Oscillator (Phase Modulation or Frequency Modulation) - */ -inline void ADnote::ComputeVoiceOscillatorFrequencyModulation(int nvoice, - int FMmode) -{ - int carposhi = 0; - int i, FMmodfreqhi = 0; - REALTYPE FMmodfreqlo = 0, carposlo = 0; - - if(NoteVoicePar[nvoice].FMVoice >= 0) { - //if I use VoiceOut[] as modulator - for(int k = 0; k < unison_size[nvoice]; k++) { - REALTYPE *tw = tmpwave_unison[k]; - memcpy(tw, NoteVoicePar[NoteVoicePar[nvoice].FMVoice].VoiceOut, - SOUND_BUFFER_SIZE * sizeof(REALTYPE)); - } - } - else { - //Compute the modulator and store it in tmpwave_unison[][] - for(int k = 0; k < unison_size[nvoice]; k++) { - int poshiFM = oscposhiFM[nvoice][k]; - REALTYPE posloFM = oscposloFM[nvoice][k]; - int freqhiFM = oscfreqhiFM[nvoice][k]; - REALTYPE freqloFM = oscfreqloFM[nvoice][k]; - REALTYPE *tw = tmpwave_unison[k]; - - for(i = 0; i < SOUND_BUFFER_SIZE; i++) { - tw[i] = - (NoteVoicePar[nvoice].FMSmp[poshiFM] * (1.0 - posloFM) - + NoteVoicePar[nvoice].FMSmp[poshiFM + 1] * posloFM); - posloFM += freqloFM; - if(posloFM >= 1.0) { - posloFM = fmod(posloFM, 1.0); - poshiFM++; - } - poshiFM += freqhiFM; - poshiFM &= OSCIL_SIZE - 1; - } - oscposhiFM[nvoice][k] = poshiFM; - oscposloFM[nvoice][k] = posloFM; - } - } - // Amplitude interpolation - if(ABOVE_AMPLITUDE_THRESHOLD(FMoldamplitude[nvoice], - FMnewamplitude[nvoice])) { - for(int k = 0; k < unison_size[nvoice]; k++) { - REALTYPE *tw = tmpwave_unison[k]; - for(i = 0; i < SOUND_BUFFER_SIZE; i++) - tw[i] *= INTERPOLATE_AMPLITUDE(FMoldamplitude[nvoice], - FMnewamplitude[nvoice], - i, - SOUND_BUFFER_SIZE); - ; - } - } - else { - for(int k = 0; k < unison_size[nvoice]; k++) { - REALTYPE *tw = tmpwave_unison[k]; - for(i = 0; i < SOUND_BUFFER_SIZE; i++) - tw[i] *= FMnewamplitude[nvoice]; - } - } - - - //normalize: makes all sample-rates, oscil_sizes to produce same sound - if(FMmode != 0) { //Frequency modulation - REALTYPE normalize = OSCIL_SIZE / 262144.0 * 44100.0 - / (REALTYPE)SAMPLE_RATE; - for(int k = 0; k < unison_size[nvoice]; k++) { - REALTYPE *tw = tmpwave_unison[k]; - REALTYPE fmold = FMoldsmp[nvoice][k]; - for(i = 0; i < SOUND_BUFFER_SIZE; i++) { - fmold = fmod(fmold + tw[i] * normalize, OSCIL_SIZE); - tw[i] = fmold; - } - FMoldsmp[nvoice][k] = fmold; - } - } - else { //Phase modulation - REALTYPE normalize = OSCIL_SIZE / 262144.0; - for(int k = 0; k < unison_size[nvoice]; k++) { - REALTYPE *tw = tmpwave_unison[k]; - for(i = 0; i < SOUND_BUFFER_SIZE; i++) - tw[i] *= normalize; - } - } - - //do the modulation - for(int k = 0; k < unison_size[nvoice]; k++) { - REALTYPE *tw = tmpwave_unison[k]; - int poshi = oscposhi[nvoice][k]; - REALTYPE poslo = oscposlo[nvoice][k]; - int freqhi = oscfreqhi[nvoice][k]; - REALTYPE freqlo = oscfreqlo[nvoice][k]; - - for(i = 0; i < SOUND_BUFFER_SIZE; i++) { - F2I(tw[i], FMmodfreqhi); - FMmodfreqlo = fmod(tw[i] + 0.0000000001, 1.0); - if(FMmodfreqhi < 0) - FMmodfreqlo++; - - //carrier - carposhi = poshi + FMmodfreqhi; - carposlo = poslo + FMmodfreqlo; - - if(carposlo >= 1.0) { - carposhi++; - carposlo = fmod(carposlo, 1.0); - } - carposhi &= (OSCIL_SIZE - 1); - - tw[i] = NoteVoicePar[nvoice].OscilSmp[carposhi] - * (1.0 - carposlo) - + NoteVoicePar[nvoice].OscilSmp[carposhi - + 1] * carposlo; - - poslo += freqlo; - if(poslo >= 1.0) { - poslo = fmod(poslo, 1.0); - poshi++; - } - - poshi += freqhi; - poshi &= OSCIL_SIZE - 1; - } - oscposhi[nvoice][k] = poshi; - oscposlo[nvoice][k] = poslo; - } -} - - -/*Calculeaza Oscilatorul cu PITCH MODULATION*/ -inline void ADnote::ComputeVoiceOscillatorPitchModulation(int nvoice) -{ -//TODO -} - -/* - * Computes the Noise - */ -inline void ADnote::ComputeVoiceNoise(int nvoice) -{ - for(int k = 0; k < unison_size[nvoice]; k++) { - REALTYPE *tw = tmpwave_unison[k]; - for(int i = 0; i < SOUND_BUFFER_SIZE; i++) - tw[i] = RND * 2.0 - 1.0; - } -} - - - -/* - * Compute the ADnote samples - * Returns 0 if the note is finished - */ -int ADnote::noteout(REALTYPE *outl, REALTYPE *outr) -{ - int i, nvoice; - - memcpy(outl, denormalkillbuf, SOUND_BUFFER_SIZE * sizeof(REALTYPE)); - memcpy(outr, denormalkillbuf, SOUND_BUFFER_SIZE * sizeof(REALTYPE)); - - if(NoteEnabled == OFF) - return 0; - - memset(bypassl, 0, SOUND_BUFFER_SIZE * sizeof(REALTYPE)); - memset(bypassr, 0, SOUND_BUFFER_SIZE * sizeof(REALTYPE)); - computecurrentparameters(); - - for(nvoice = 0; nvoice < NUM_VOICES; nvoice++) { - if((NoteVoicePar[nvoice].Enabled != ON) - || (NoteVoicePar[nvoice].DelayTicks > 0)) - continue; - if(NoteVoicePar[nvoice].noisetype == 0) //voice mode=sound - switch(NoteVoicePar[nvoice].FMEnabled) { - case MORPH: - ComputeVoiceOscillatorMorph(nvoice); - break; - case RING_MOD: - ComputeVoiceOscillatorRingModulation(nvoice); - break; - case PHASE_MOD: - ComputeVoiceOscillatorFrequencyModulation(nvoice, 0); - break; - case FREQ_MOD: - ComputeVoiceOscillatorFrequencyModulation(nvoice, 1); - break; - //case PITCH_MOD:ComputeVoiceOscillatorPitchModulation(nvoice);break; - default: - ComputeVoiceOscillator_LinearInterpolation(nvoice); - //if (config.cfg.Interpolation) ComputeVoiceOscillator_CubicInterpolation(nvoice); - } - else - ComputeVoiceNoise(nvoice); - // Voice Processing - - - //mix subvoices into voice - memset(tmpwavel, 0, SOUND_BUFFER_SIZE * sizeof(REALTYPE)); - if(stereo) - memset(tmpwaver, 0, SOUND_BUFFER_SIZE * sizeof(REALTYPE)); - for(int k = 0; k < unison_size[nvoice]; k++) { - REALTYPE *tw = tmpwave_unison[k]; - if(stereo) { - REALTYPE stereo_pos = 0; - if(unison_size[nvoice] > 1) - stereo_pos = k - / (REALTYPE)(unison_size[nvoice] - - 1) * 2.0 - 1.0; - REALTYPE stereo_spread = unison_stereo_spread[nvoice] * 2.0; //between 0 and 2.0 - if(stereo_spread > 1.0) { - REALTYPE stereo_pos_1 = (stereo_pos >= 0.0) ? 1.0 : -1.0; - stereo_pos = - (2.0 - - stereo_spread) * stereo_pos - + (stereo_spread - 1.0) * stereo_pos_1; - } - else - stereo_pos *= stereo_spread; - ; - if(unison_size[nvoice] == 1) - stereo_pos = 0.0; - REALTYPE panning = (stereo_pos + 1.0) * 0.5; - - - REALTYPE lvol = (1.0 - panning) * 2.0; - if(lvol > 1.0) - lvol = 1.0; - - REALTYPE rvol = panning * 2.0; - if(rvol > 1.0) - rvol = 1.0; - - if(unison_invert_phase[nvoice][k]) { - lvol = -lvol; - rvol = -rvol; - } - - for(i = 0; i < SOUND_BUFFER_SIZE; i++) - tmpwavel[i] += tw[i] * lvol; - for(i = 0; i < SOUND_BUFFER_SIZE; i++) - tmpwaver[i] += tw[i] * rvol; - } - else - for(i = 0; i < SOUND_BUFFER_SIZE; i++) - tmpwavel[i] += tw[i]; - ; - } - - - REALTYPE unison_amplitude = 1.0 / sqrt(unison_size[nvoice]); //reduce the amplitude for large unison sizes - // Amplitude - REALTYPE oldam = oldamplitude[nvoice] * unison_amplitude; - REALTYPE newam = newamplitude[nvoice] * unison_amplitude; - - if(ABOVE_AMPLITUDE_THRESHOLD(oldam, newam)) { - int rest = SOUND_BUFFER_SIZE; - //test if the amplitude if raising and the difference is high - if((newam > oldam) && ((newam - oldam) > 0.25)) { - rest = 10; - if(rest > SOUND_BUFFER_SIZE) - rest = SOUND_BUFFER_SIZE; - for(int i = 0; i < SOUND_BUFFER_SIZE - rest; i++) - tmpwavel[i] *= oldam; - if(stereo) - for(int i = 0; i < SOUND_BUFFER_SIZE - rest; i++) - tmpwaver[i] *= oldam; - } - // Amplitude interpolation - for(i = 0; i < rest; i++) { - REALTYPE amp = INTERPOLATE_AMPLITUDE(oldam, newam, i, rest); - tmpwavel[i + (SOUND_BUFFER_SIZE - rest)] *= amp; - if(stereo) - tmpwaver[i + (SOUND_BUFFER_SIZE - rest)] *= amp; - } - } - else { - for(i = 0; i < SOUND_BUFFER_SIZE; i++) - tmpwavel[i] *= newam; - if(stereo) - for(i = 0; i < SOUND_BUFFER_SIZE; i++) - tmpwaver[i] *= newam; - } - - // Fade in - if(firsttick[nvoice] != 0) { - fadein(&tmpwavel[0]); - if(stereo) - fadein(&tmpwaver[0]); - firsttick[nvoice] = 0; - } - - - // Filter - if(NoteVoicePar[nvoice].VoiceFilterL != NULL) - NoteVoicePar[nvoice].VoiceFilterL->filterout(&tmpwavel[0]); - if((stereo) && (NoteVoicePar[nvoice].VoiceFilterR != NULL)) - NoteVoicePar[nvoice].VoiceFilterR->filterout(&tmpwaver[0]); - - //check if the amplitude envelope is finished, if yes, the voice will be fadeout - if(NoteVoicePar[nvoice].AmpEnvelope != NULL) { - if(NoteVoicePar[nvoice].AmpEnvelope->finished() != 0) { - for(i = 0; i < SOUND_BUFFER_SIZE; i++) - tmpwavel[i] *= 1.0 - (REALTYPE)i - / (REALTYPE)SOUND_BUFFER_SIZE; - if(stereo) - for(i = 0; i < SOUND_BUFFER_SIZE; i++) - tmpwaver[i] *= 1.0 - (REALTYPE)i - / (REALTYPE)SOUND_BUFFER_SIZE; - } - //the voice is killed later - } - - - // Put the ADnote samples in VoiceOut (without appling Global volume, because I wish to use this voice as a modullator) - if(NoteVoicePar[nvoice].VoiceOut != NULL) { - if(stereo) - for(i = 0; i < SOUND_BUFFER_SIZE; i++) - NoteVoicePar[nvoice].VoiceOut[i] = tmpwavel[i] - + tmpwaver[i]; - else //mono - for(i = 0; i < SOUND_BUFFER_SIZE; i++) - NoteVoicePar[nvoice].VoiceOut[i] = tmpwavel[i]; - ; - } - - - // Add the voice that do not bypass the filter to out - if(NoteVoicePar[nvoice].filterbypass == 0) { //no bypass - if(stereo) { - for(i = 0; i < SOUND_BUFFER_SIZE; i++) { //stereo - outl[i] += tmpwavel[i] * NoteVoicePar[nvoice].Volume - * NoteVoicePar[nvoice].Panning * 2.0; - outr[i] += tmpwaver[i] * NoteVoicePar[nvoice].Volume - * (1.0 - NoteVoicePar[nvoice].Panning) * 2.0; - } - } - else - for(i = 0; i < SOUND_BUFFER_SIZE; i++) - outl[i] += tmpwavel[i] * NoteVoicePar[nvoice].Volume; //mono - ; - } - else { //bypass the filter - if(stereo) { - for(i = 0; i < SOUND_BUFFER_SIZE; i++) { //stereo - bypassl[i] += tmpwavel[i] * NoteVoicePar[nvoice].Volume - * NoteVoicePar[nvoice].Panning * 2.0; - bypassr[i] += tmpwaver[i] * NoteVoicePar[nvoice].Volume - * (1.0 - NoteVoicePar[nvoice].Panning) * 2.0; - } - } - else - for(i = 0; i < SOUND_BUFFER_SIZE; i++) - bypassl[i] += tmpwavel[i] * NoteVoicePar[nvoice].Volume; //mono - ; - } - // chech if there is necesary to proces the voice longer (if the Amplitude envelope isn't finished) - if(NoteVoicePar[nvoice].AmpEnvelope != NULL) - if(NoteVoicePar[nvoice].AmpEnvelope->finished() != 0) - KillVoice(nvoice); - ; - } - - - //Processing Global parameters - NoteGlobalPar.GlobalFilterL->filterout(&outl[0]); - - if(stereo == 0) { //set the right channel=left channel - memcpy(outr, outl, SOUND_BUFFER_SIZE * sizeof(REALTYPE)); - memcpy(bypassr, bypassl, SOUND_BUFFER_SIZE * sizeof(REALTYPE)); - } - else - NoteGlobalPar.GlobalFilterR->filterout(&outr[0]); - - for(i = 0; i < SOUND_BUFFER_SIZE; i++) { - outl[i] += bypassl[i]; - outr[i] += bypassr[i]; - } - - if(ABOVE_AMPLITUDE_THRESHOLD(globaloldamplitude, globalnewamplitude)) { - // Amplitude Interpolation - for(i = 0; i < SOUND_BUFFER_SIZE; i++) { - REALTYPE tmpvol = INTERPOLATE_AMPLITUDE(globaloldamplitude, - globalnewamplitude, - i, - SOUND_BUFFER_SIZE); - outl[i] *= tmpvol * NoteGlobalPar.Panning; - outr[i] *= tmpvol * (1.0 - NoteGlobalPar.Panning); - } - } - else { - for(i = 0; i < SOUND_BUFFER_SIZE; i++) { - outl[i] *= globalnewamplitude * NoteGlobalPar.Panning; - outr[i] *= globalnewamplitude * (1.0 - NoteGlobalPar.Panning); - } - } - -//Apply the punch - if(NoteGlobalPar.Punch.Enabled != 0) { - for(i = 0; i < SOUND_BUFFER_SIZE; i++) { - REALTYPE punchamp = NoteGlobalPar.Punch.initialvalue - * NoteGlobalPar.Punch.t + 1.0; - outl[i] *= punchamp; - outr[i] *= punchamp; - NoteGlobalPar.Punch.t -= NoteGlobalPar.Punch.dt; - if(NoteGlobalPar.Punch.t < 0.0) { - NoteGlobalPar.Punch.Enabled = 0; - break; - } - } - } - - - // Apply legato-specific sound signal modifications - if(Legato.silent) // Silencer - if(Legato.msg != LM_FadeIn) { - memset(outl, 0, SOUND_BUFFER_SIZE * sizeof(REALTYPE)); - memset(outr, 0, SOUND_BUFFER_SIZE * sizeof(REALTYPE)); - } - switch(Legato.msg) { - case LM_CatchUp: // Continue the catch-up... - if(Legato.decounter == -10) - Legato.decounter = Legato.fade.length; - for(i = 0; i < SOUND_BUFFER_SIZE; i++) { //Yea, could be done without the loop... - Legato.decounter--; - if(Legato.decounter < 1) { - // Catching-up done, we can finally set - // the note to the actual parameters. - Legato.decounter = -10; - Legato.msg = LM_ToNorm; - ADlegatonote(Legato.param.freq, - Legato.param.vel, - Legato.param.portamento, - Legato.param.midinote, - false); - break; - } - } - break; - case LM_FadeIn: // Fade-in - if(Legato.decounter == -10) - Legato.decounter = Legato.fade.length; - Legato.silent = false; - for(i = 0; i < SOUND_BUFFER_SIZE; i++) { - Legato.decounter--; - if(Legato.decounter < 1) { - Legato.decounter = -10; - Legato.msg = LM_Norm; - break; - } - Legato.fade.m += Legato.fade.step; - outl[i] *= Legato.fade.m; - outr[i] *= Legato.fade.m; - } - break; - case LM_FadeOut: // Fade-out, then set the catch-up - if(Legato.decounter == -10) - Legato.decounter = Legato.fade.length; - for(i = 0; i < SOUND_BUFFER_SIZE; i++) { - Legato.decounter--; - if(Legato.decounter < 1) { - for(int j = i; j < SOUND_BUFFER_SIZE; j++) { - outl[j] = 0.0; - outr[j] = 0.0; - } - Legato.decounter = -10; - Legato.silent = true; - // Fading-out done, now set the catch-up : - Legato.decounter = Legato.fade.length; - Legato.msg = LM_CatchUp; - REALTYPE catchupfreq = Legato.param.freq - * (Legato.param.freq / Legato.lastfreq); //This freq should make this now silent note to catch-up (or should I say resync ?) with the heard note for the same length it stayed at the previous freq during the fadeout. - ADlegatonote(catchupfreq, - Legato.param.vel, - Legato.param.portamento, - Legato.param.midinote, - false); - break; - } - Legato.fade.m -= Legato.fade.step; - outl[i] *= Legato.fade.m; - outr[i] *= Legato.fade.m; - } - break; - default: - break; - } - - -// Check if the global amplitude is finished. -// If it does, disable the note - if(NoteGlobalPar.AmpEnvelope->finished() != 0) { - for(i = 0; i < SOUND_BUFFER_SIZE; i++) { //fade-out - REALTYPE tmp = 1.0 - (REALTYPE)i / (REALTYPE)SOUND_BUFFER_SIZE; - outl[i] *= tmp; - outr[i] *= tmp; - } - KillNote(); - } - return 1; -} - - -/* - * Relase the key (NoteOff) - */ -void ADnote::relasekey() -{ - int nvoice; - for(nvoice = 0; nvoice < NUM_VOICES; nvoice++) { - if(NoteVoicePar[nvoice].Enabled == 0) - continue; - if(NoteVoicePar[nvoice].AmpEnvelope != NULL) - NoteVoicePar[nvoice].AmpEnvelope->relasekey(); - if(NoteVoicePar[nvoice].FreqEnvelope != NULL) - NoteVoicePar[nvoice].FreqEnvelope->relasekey(); - if(NoteVoicePar[nvoice].FilterEnvelope != NULL) - NoteVoicePar[nvoice].FilterEnvelope->relasekey(); - if(NoteVoicePar[nvoice].FMFreqEnvelope != NULL) - NoteVoicePar[nvoice].FMFreqEnvelope->relasekey(); - if(NoteVoicePar[nvoice].FMAmpEnvelope != NULL) - NoteVoicePar[nvoice].FMAmpEnvelope->relasekey(); - } - NoteGlobalPar.FreqEnvelope->relasekey(); - NoteGlobalPar.FilterEnvelope->relasekey(); - NoteGlobalPar.AmpEnvelope->relasekey(); -} - -/* - * Check if the note is finished - */ -int ADnote::finished() const -{ - if(NoteEnabled == ON) - return 0; - else - return 1; -} - diff --git a/plugins/zynaddsubfx/src/Synth/ADnote.h b/plugins/zynaddsubfx/src/Synth/ADnote.h deleted file mode 100644 index 9f494a906..000000000 --- a/plugins/zynaddsubfx/src/Synth/ADnote.h +++ /dev/null @@ -1,349 +0,0 @@ -/* - ZynAddSubFX - a software synthesizer - - ADnote.h - The "additive" synthesizer - Copyright (C) 2002-2005 Nasca Octavian Paul - Author: Nasca Octavian Paul - - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License - as published by the Free Software Foundation. - - 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 (version 2 or later) for more details. - - You should have received a copy of the GNU General Public License (version 2) - along with this program; if not, write to the Free Software Foundation, - Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -*/ - -#ifndef AD_NOTE_H -#define AD_NOTE_H - -#include "../globals.h" -#include "Envelope.h" -#include "LFO.h" -#include "../DSP/Filter.h" -#include "../Params/ADnoteParameters.h" -#include "../Params/Controller.h" - -//Globals - -/**FM amplitude tune*/ -#define FM_AMP_MULTIPLIER 14.71280603 - -#define OSCIL_SMP_EXTRA_SAMPLES 5 - -/**The "additive" synthesizer*/ -class ADnote //ADDitive note -{ - public: - /**Constructor. - * @param pars Note Parameters - * @param ctl_ Pointer to system Controller - * @param freq Base frequency for note - * @param velocity Velocity of note - * @param portamento_ 1 if the note has portamento - * @param midinote_ The midi number of the note - * @param besilent Start silent note if true*/ - ADnote(ADnoteParameters *pars, Controller *ctl_, REALTYPE freq, - REALTYPE velocity, int portamento_, int midinote_, - bool besilent); - /**Destructor*/ - ~ADnote(); - - /**Alters the playing note for legato effect*/ - void ADlegatonote(REALTYPE freq, REALTYPE velocity, int portamento_, - int midinote_, bool externcall); - - /**Compute ADnote Samples. - * @return 0 if note is finished*/ - int noteout(REALTYPE *outl, REALTYPE *outr); - - /**Release the key for the note and start release portion of envelopes.*/ - void relasekey(); - /**Return if note is finished. - * @return finished=1 unfinished=0*/ - int finished() const; - - - /**Nonzero when ready for output(the parameters has been computed) - * zero when parameters need to be computed.*/ - char ready; - - private: - - /**Changes the frequency of an oscillator. - * @param nvoice voice to run computations on - * @param in_freq new frequency*/ - void setfreq(int nvoice, REALTYPE in_freq); - /**Set the frequency of the modulator oscillator*/ - void setfreqFM(int nvoice, REALTYPE in_freq); - /**Computes relative frequency for unison and unison's vibratto. - * Note: Must be called before setfreq* functions.*/ - void compute_unison_freq_rap(int nvoice); - /**Compute parameters for next tick*/ - void computecurrentparameters(); - /**Initializes All Parameters*/ - void initparameters(); - /**Deallocate/Cleanup given voice*/ - void KillVoice(int nvoice); - /**Deallocate Note resources and voice resources*/ - void KillNote(); - /**Get the Voice's base frequency*/ - inline REALTYPE getvoicebasefreq(int nvoice) const; - /**Get modulator's base frequency*/ - inline REALTYPE getFMvoicebasefreq(int nvoice) const; - /**Compute the Oscillator's samples. - * Affects tmpwave_unison and updates oscposhi/oscposlo*/ - inline void ComputeVoiceOscillator_LinearInterpolation(int nvoice); - /**Compute the Oscillator's samples. - * Affects tmpwave_unison and updates oscposhi/oscposlo - * @todo remove this declaration if it is commented out*/ - inline void ComputeVoiceOscillator_CubicInterpolation(int nvoice); - /**Computes the Oscillator samples with morphing. - * updates tmpwave_unison*/ - inline void ComputeVoiceOscillatorMorph(int nvoice); - /**Computes the Ring Modulated Oscillator.*/ - inline void ComputeVoiceOscillatorRingModulation(int nvoice); - /**Computes the Frequency Modulated Oscillator. - * @param FMmode modulation type 0=Phase 1=Frequency*/ - inline void ComputeVoiceOscillatorFrequencyModulation(int nvoice, - int FMmode); //FMmode=0 for phase modulation, 1 for Frequency modulation - // inline void ComputeVoiceOscillatorFrequencyModulation(int nvoice); - /**TODO*/ - inline void ComputeVoiceOscillatorPitchModulation(int nvoice); - - /**Generate Noise Samples for Voice*/ - inline void ComputeVoiceNoise(int nvoice); - - /**Fadein in a way that removes clicks but keep sound "punchy"*/ - inline void fadein(REALTYPE *smps) const; - - - //GLOBALS - ADnoteParameters *partparams; - unsigned char stereo; //if the note is stereo (allows note Panning) - int midinote; - REALTYPE velocity, basefreq; - - ONOFFTYPE NoteEnabled; - Controller *ctl; - - /*****************************************************************/ - /* GLOBAL PARAMETERS */ - /*****************************************************************/ - - struct ADnoteGlobal { - /****************************************** - * FREQUENCY GLOBAL PARAMETERS * - ******************************************/ - REALTYPE Detune; //cents - - Envelope *FreqEnvelope; - LFO *FreqLfo; - - /******************************************** - * AMPLITUDE GLOBAL PARAMETERS * - ********************************************/ - REALTYPE Volume; // [ 0 .. 1 ] - - REALTYPE Panning; // [ 0 .. 1 ] - - Envelope *AmpEnvelope; - LFO *AmpLfo; - - struct { - int Enabled; - REALTYPE initialvalue, dt, t; - } Punch; - - /****************************************** - * FILTER GLOBAL PARAMETERS * - ******************************************/ - Filter *GlobalFilterL, *GlobalFilterR; - - REALTYPE FilterCenterPitch; //octaves - REALTYPE FilterQ; - REALTYPE FilterFreqTracking; - - Envelope *FilterEnvelope; - - LFO *FilterLfo; - } NoteGlobalPar; - - - - /***********************************************************/ - /* VOICE PARAMETERS */ - /***********************************************************/ - struct ADnoteVoice { - /* If the voice is enabled */ - ONOFFTYPE Enabled; - - /* Voice Type (sound/noise)*/ - int noisetype; - - /* Filter Bypass */ - int filterbypass; - - /* Delay (ticks) */ - int DelayTicks; - - /* Waveform of the Voice */ - REALTYPE *OscilSmp; - - /************************************ - * FREQUENCY PARAMETERS * - ************************************/ - int fixedfreq; //if the frequency is fixed to 440 Hz - int fixedfreqET; //if the "fixed" frequency varies according to the note (ET) - - // cents = basefreq*VoiceDetune - REALTYPE Detune, FineDetune; - - Envelope *FreqEnvelope; - LFO *FreqLfo; - - - /*************************** - * AMPLITUDE PARAMETERS * - ***************************/ - - /* Panning 0.0=left, 0.5 - center, 1.0 = right */ - REALTYPE Panning; - REALTYPE Volume; // [-1.0 .. 1.0] - - Envelope *AmpEnvelope; - LFO *AmpLfo; - - /************************* - * FILTER PARAMETERS * - *************************/ - - Filter *VoiceFilterL; - Filter *VoiceFilterR; - - REALTYPE FilterCenterPitch; /* Filter center Pitch*/ - REALTYPE FilterFreqTracking; - - Envelope *FilterEnvelope; - LFO *FilterLfo; - - - /**************************** - * MODULLATOR PARAMETERS * - ****************************/ - - FMTYPE FMEnabled; - - int FMVoice; - - // Voice Output used by other voices if use this as modullator - REALTYPE *VoiceOut; - - /* Wave of the Voice */ - REALTYPE *FMSmp; - - REALTYPE FMVolume; - REALTYPE FMDetune; //in cents - - Envelope *FMFreqEnvelope; - Envelope *FMAmpEnvelope; - } NoteVoicePar[NUM_VOICES]; - - - /********************************************************/ - /* INTERNAL VALUES OF THE NOTE AND OF THE VOICES */ - /********************************************************/ - - //time from the start of the note - REALTYPE time; - - //the size of unison for a single voice - int unison_size[NUM_VOICES]; - - //the stereo spread of the unison subvoices (0.0=mono,1.0=max) - REALTYPE unison_stereo_spread[NUM_VOICES]; - - //fractional part (skip) - REALTYPE *oscposlo[NUM_VOICES], *oscfreqlo[NUM_VOICES]; - - //integer part (skip) - int *oscposhi[NUM_VOICES], *oscfreqhi[NUM_VOICES]; - - //fractional part (skip) of the Modullator - REALTYPE *oscposloFM[NUM_VOICES], *oscfreqloFM[NUM_VOICES]; - - //the unison base_value - REALTYPE *unison_base_freq_rap[NUM_VOICES]; - - //how the unison subvoice's frequency is changed (1.0 for no change) - REALTYPE *unison_freq_rap[NUM_VOICES]; - - //which subvoice has phase inverted - bool *unison_invert_phase[NUM_VOICES]; - - //unison vibratto - struct { - REALTYPE amplitude; //amplitude which be added to unison_freq_rap - REALTYPE *step; //value which increments the position - REALTYPE *position; //between -1.0 and 1.0 - } unison_vibratto[NUM_VOICES]; - - - //integer part (skip) of the Modullator - unsigned int *oscposhiFM[NUM_VOICES], *oscfreqhiFM[NUM_VOICES]; - - //used to compute and interpolate the amplitudes of voices and modullators - REALTYPE oldamplitude[NUM_VOICES], - newamplitude[NUM_VOICES], - FMoldamplitude[NUM_VOICES], - FMnewamplitude[NUM_VOICES]; - - //used by Frequency Modulation (for integration) - REALTYPE *FMoldsmp[NUM_VOICES]; - - //temporary buffer - REALTYPE *tmpwavel; - REALTYPE *tmpwaver; - int max_unison; - REALTYPE **tmpwave_unison; - - //Filter bypass samples - REALTYPE *bypassl, *bypassr; - - //interpolate the amplitudes - REALTYPE globaloldamplitude, globalnewamplitude; - - //1 - if it is the fitst tick (used to fade in the sound) - char firsttick[NUM_VOICES]; - - //1 if the note has portamento - int portamento; - - //how the fine detunes are made bigger or smaller - REALTYPE bandwidthDetuneMultiplier; - - // Legato vars - struct { - bool silent; - REALTYPE lastfreq; - LegatoMsg msg; - int decounter; - struct { // Fade In/Out vars - int length; - REALTYPE m, step; - } fade; - struct { // Note parameters - REALTYPE freq, vel; - int portamento, midinote; - } param; - } Legato; -}; - -#endif - diff --git a/plugins/zynaddsubfx/src/Synth/CMakeLists.txt b/plugins/zynaddsubfx/src/Synth/CMakeLists.txt deleted file mode 100644 index 486554b9f..000000000 --- a/plugins/zynaddsubfx/src/Synth/CMakeLists.txt +++ /dev/null @@ -1,16 +0,0 @@ -set(zynaddsubfx_synth_SRCS - ADnote.cpp - Envelope.cpp - LFO.cpp - OscilGen.cpp - PADnote.cpp - Resonance.cpp - SUBnote.cpp -) - -add_library(zynaddsubfx_synth STATIC - ${zynaddsubfx_synth_SRCS} - ) - -target_link_libraries(zynaddsubfx_synth) - diff --git a/plugins/zynaddsubfx/src/Synth/Envelope.cpp b/plugins/zynaddsubfx/src/Synth/Envelope.cpp deleted file mode 100644 index 86ea3119c..000000000 --- a/plugins/zynaddsubfx/src/Synth/Envelope.cpp +++ /dev/null @@ -1,199 +0,0 @@ -/* - ZynAddSubFX - a software synthesizer - - Envelope.cpp - Envelope implementation - Copyright (C) 2002-2005 Nasca Octavian Paul - Author: Nasca Octavian Paul - - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License - as published by the Free Software Foundation. - - 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 (version 2 or later) for more details. - - You should have received a copy of the GNU General Public License (version 2) - along with this program; if not, write to the Free Software Foundation, - Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -*/ - -#include -#include "Envelope.h" -#include "../Params/EnvelopeParams.h" - -Envelope::Envelope(EnvelopeParams *envpars, REALTYPE basefreq) -{ - int i; - envpoints = envpars->Penvpoints; - if(envpoints > MAX_ENVELOPE_POINTS) - envpoints = MAX_ENVELOPE_POINTS; - envsustain = (envpars->Penvsustain == 0) ? -1 : envpars->Penvsustain; - forcedrelase = envpars->Pforcedrelease; - envstretch = pow(440.0 / basefreq, envpars->Penvstretch / 64.0); - linearenvelope = envpars->Plinearenvelope; - - if(envpars->Pfreemode == 0) - envpars->converttofree(); - - REALTYPE bufferdt = SOUND_BUFFER_SIZE / (REALTYPE)SAMPLE_RATE; - - int mode = envpars->Envmode; - - //for amplitude envelopes - if((mode == 1) && (linearenvelope == 0)) - mode = 2; //change to log envelope - if((mode == 2) && (linearenvelope != 0)) - mode = 1; //change to linear - - for(i = 0; i < MAX_ENVELOPE_POINTS; i++) { - REALTYPE tmp = envpars->getdt(i) / 1000.0 * envstretch; - if(tmp > bufferdt) - envdt[i] = bufferdt / tmp; - else - envdt[i] = 2.0; //any value larger than 1 - - switch(mode) { - case 2: - envval[i] = (1.0 - envpars->Penvval[i] / 127.0) * -40; - break; - case 3: - envval[i] = - (pow(2, 6.0 - * fabs(envpars->Penvval[i] - 64.0) / 64.0) - 1.0) * 100.0; - if(envpars->Penvval[i] < 64) - envval[i] = -envval[i]; - break; - case 4: - envval[i] = (envpars->Penvval[i] - 64.0) / 64.0 * 6.0; //6 octaves (filtru) - break; - case 5: - envval[i] = (envpars->Penvval[i] - 64.0) / 64.0 * 10; - break; - default: - envval[i] = envpars->Penvval[i] / 127.0; - } - } - - envdt[0] = 1.0; - - currentpoint = 1; //the envelope starts from 1 - keyreleased = 0; - t = 0.0; - envfinish = 0; - inct = envdt[1]; - envoutval = 0.0; -} - -Envelope::~Envelope() -{} - - -/* - * Relase the key (note envelope) - */ -void Envelope::relasekey() -{ - if(keyreleased == 1) - return; - keyreleased = 1; - if(forcedrelase != 0) - t = 0.0; -} - -/* - * Envelope Output - */ -REALTYPE Envelope::envout() -{ - REALTYPE out; - - if(envfinish != 0) { //if the envelope is finished - envoutval = envval[envpoints - 1]; - return envoutval; - } - if((currentpoint == envsustain + 1) && (keyreleased == 0)) { //if it is sustaining now - envoutval = envval[envsustain]; - return envoutval; - } - - if((keyreleased != 0) && (forcedrelase != 0)) { //do the forced release - int tmp = (envsustain < 0) ? (envpoints - 1) : (envsustain + 1); //if there is no sustain point, use the last point for release - - if(envdt[tmp] < 0.00000001) - out = envval[tmp]; - else - out = envoutval + (envval[tmp] - envoutval) * t; - t += envdt[tmp] * envstretch; - - if(t >= 1.0) { - currentpoint = envsustain + 2; - forcedrelase = 0; - t = 0.0; - inct = envdt[currentpoint]; - if((currentpoint >= envpoints) || (envsustain < 0)) - envfinish = 1; - } - return out; - } - if(inct >= 1.0) - out = envval[currentpoint]; - else - out = - envval[currentpoint - - 1] + (envval[currentpoint] - envval[currentpoint - 1]) * t; - - t += inct; - if(t >= 1.0) { - if(currentpoint >= envpoints - 1) - envfinish = 1; - else - currentpoint++; - t = 0.0; - inct = envdt[currentpoint]; - } - - envoutval = out; - return out; -} - -/* - * Envelope Output (dB) - */ -REALTYPE Envelope::envout_dB() -{ - REALTYPE out; - if(linearenvelope != 0) - return envout(); - - if((currentpoint == 1) && ((keyreleased == 0) || (forcedrelase == 0))) { //first point is always lineary interpolated - REALTYPE v1 = dB2rap(envval[0]); - REALTYPE v2 = dB2rap(envval[1]); - out = v1 + (v2 - v1) * t; - - t += inct; - if(t >= 1.0) { - t = 0.0; - inct = envdt[2]; - currentpoint++; - out = v2; - } - - if(out > 0.001) - envoutval = rap2dB(out); - else - envoutval = MIN_ENVELOPE_DB; - } - else - out = dB2rap(envout()); - - return out; -} - -int Envelope::finished() -{ - return envfinish; -} - diff --git a/plugins/zynaddsubfx/src/Synth/Envelope.h b/plugins/zynaddsubfx/src/Synth/Envelope.h deleted file mode 100644 index dc3b6f259..000000000 --- a/plugins/zynaddsubfx/src/Synth/Envelope.h +++ /dev/null @@ -1,65 +0,0 @@ -/* - ZynAddSubFX - a software synthesizer - - Envelope.h - Envelope implementation - Copyright (C) 2002-2005 Nasca Octavian Paul - Author: Nasca Octavian Paul - - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License - as published by the Free Software Foundation. - - 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 (version 2 or later) for more details. - - You should have received a copy of the GNU General Public License (version 2) - along with this program; if not, write to the Free Software Foundation, - Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -*/ - -#ifndef ENVELOPE_H -#define ENVELOPE_H - -#include "../globals.h" -#include "../Params/EnvelopeParams.h" - -/**Implementation of a general Envelope*/ -class Envelope -{ - public: - - /**Constructor*/ - Envelope(class EnvelopeParams *envpars, REALTYPE basefreq); - /**Destructor*/ - ~Envelope(); - void relasekey(); - REALTYPE envout(); - REALTYPE envout_dB(); - /**Determines the status of the Envelope - * - *\todo see if this can be changed to use a boolean - * @return returns 1 if the envelope is finished*/ - int finished(); - private: - int envpoints; - int envsustain; //"-1" means disabled - REALTYPE envdt[MAX_ENVELOPE_POINTS]; //millisecons - REALTYPE envval[MAX_ENVELOPE_POINTS]; // [0.0 .. 1.0] - REALTYPE envstretch; - int linearenvelope; - - int currentpoint; //current envelope point (starts from 1) - int forcedrelase; - char keyreleased; //if the key was released /** \todo figure out WHY IS THIS A CHAR*/ - char envfinish; /** \todo figure out WHY IS THIS A CHAR*/ - REALTYPE t; // the time from the last point - REALTYPE inct; // the time increment - REALTYPE envoutval; //used to do the forced release -}; - - -#endif - diff --git a/plugins/zynaddsubfx/src/Synth/LFO.cpp b/plugins/zynaddsubfx/src/Synth/LFO.cpp deleted file mode 100644 index 6dcf47f9f..000000000 --- a/plugins/zynaddsubfx/src/Synth/LFO.cpp +++ /dev/null @@ -1,184 +0,0 @@ -/* - ZynAddSubFX - a software synthesizer - - LFO.cpp - LFO implementation - Copyright (C) 2002-2005 Nasca Octavian Paul - Author: Nasca Octavian Paul - - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License - as published by the Free Software Foundation. - - 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 (version 2 or later) for more details. - - You should have received a copy of the GNU General Public License (version 2) - along with this program; if not, write to the Free Software Foundation, - Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -*/ - -#include -#include -#include - -#include "LFO.h" - - -LFO::LFO(LFOParams *lfopars, REALTYPE basefreq) -{ - if(lfopars->Pstretch == 0) - lfopars->Pstretch = 1; - REALTYPE lfostretch = pow(basefreq / 440.0, - (lfopars->Pstretch - 64.0) / 63.0); //max 2x/octave - - REALTYPE lfofreq = - (pow(2, lfopars->Pfreq * 10.0) - 1.0) / 12.0 * lfostretch; - incx = fabs(lfofreq) * (REALTYPE)SOUND_BUFFER_SIZE / (REALTYPE)SAMPLE_RATE; - - if(lfopars->Pcontinous == 0) { - if(lfopars->Pstartphase == 0) - x = RND; - else - x = fmod((lfopars->Pstartphase - 64.0) / 127.0 + 1.0, 1.0); - } - else { - REALTYPE tmp = fmod(lfopars->time * incx, 1.0); - x = fmod((lfopars->Pstartphase - 64.0) / 127.0 + 1.0 + tmp, 1.0); - } - - //Limit the Frequency(or else...) - if(incx > 0.49999999) - incx = 0.499999999; - - - lfornd = lfopars->Prandomness / 127.0; - if(lfornd < 0.0) - lfornd = 0.0; - else - if(lfornd > 1.0) - lfornd = 1.0; - -// lfofreqrnd=pow(lfopars->Pfreqrand/127.0,2.0)*2.0*4.0; - lfofreqrnd = pow(lfopars->Pfreqrand / 127.0, 2.0) * 4.0; - - switch(lfopars->fel) { - case 1: - lfointensity = lfopars->Pintensity / 127.0; - break; - case 2: - lfointensity = lfopars->Pintensity / 127.0 * 4.0; - break; //in octave - default: - lfointensity = pow(2, lfopars->Pintensity / 127.0 * 11.0) - 1.0; //in centi - x -= 0.25; //chance the starting phase - break; - } - - amp1 = (1 - lfornd) + lfornd * RND; - amp2 = (1 - lfornd) + lfornd * RND; - lfotype = lfopars->PLFOtype; - lfodelay = lfopars->Pdelay / 127.0 * 4.0; //0..4 sec - incrnd = nextincrnd = 1.0; - freqrndenabled = (lfopars->Pfreqrand != 0); - computenextincrnd(); - computenextincrnd(); //twice because I want incrnd & nextincrnd to be random -} - -LFO::~LFO() -{} - -/* - * LFO out - */ -REALTYPE LFO::lfoout() -{ - REALTYPE out; - switch(lfotype) { - case 1: //LFO_TRIANGLE - if((x >= 0.0) && (x < 0.25)) - out = 4.0 * x; - else - if((x > 0.25) && (x < 0.75)) - out = 2 - 4 * x; - else - out = 4.0 * x - 4.0; - break; - case 2: //LFO_SQUARE - if(x < 0.5) - out = -1; - else - out = 1; - break; - case 3: //LFO_RAMPUP - out = (x - 0.5) * 2.0; - break; - case 4: //LFO_RAMPDOWN - out = (0.5 - x) * 2.0; - break; - case 5: //LFO_EXP_DOWN 1 - out = pow(0.05, x) * 2.0 - 1.0; - break; - case 6: //LFO_EXP_DOWN 2 - out = pow(0.001, x) * 2.0 - 1.0; - break; - default: - out = cos(x * 2.0 * PI); //LFO_SINE - } - - - if((lfotype == 0) || (lfotype == 1)) - out *= lfointensity * (amp1 + x * (amp2 - amp1)); - else - out *= lfointensity * amp2; - if(lfodelay < 0.00001) { - if(freqrndenabled == 0) - x += incx; - else { - float tmp = (incrnd * (1.0 - x) + nextincrnd * x); - if(tmp > 1.0) - tmp = 1.0; - else - if(tmp < 0.0) - tmp = 0.0; - x += incx * tmp; - } - if(x >= 1) { - x = fmod(x, 1.0); - amp1 = amp2; - amp2 = (1 - lfornd) + lfornd * RND; - - computenextincrnd(); - } - } - else - lfodelay -= (REALTYPE)SOUND_BUFFER_SIZE / (REALTYPE)SAMPLE_RATE; - return out; -} - -/* - * LFO out (for amplitude) - */ -REALTYPE LFO::amplfoout() -{ - REALTYPE out; - out = 1.0 - lfointensity + lfoout(); - if(out < -1.0) - out = -1.0; - else - if(out > 1.0) - out = 1.0; - return out; -} - - -void LFO::computenextincrnd() -{ - if(freqrndenabled == 0) - return; - incrnd = nextincrnd; - nextincrnd = pow(0.5, lfofreqrnd) + RND * (pow(2.0, lfofreqrnd) - 1.0); -} - diff --git a/plugins/zynaddsubfx/src/Synth/LFO.h b/plugins/zynaddsubfx/src/Synth/LFO.h deleted file mode 100644 index 9dd984bcf..000000000 --- a/plugins/zynaddsubfx/src/Synth/LFO.h +++ /dev/null @@ -1,59 +0,0 @@ -/* - ZynAddSubFX - a software synthesizer - - LFO.h - LFO implementation - Copyright (C) 2002-2005 Nasca Octavian Paul - Author: Nasca Octavian Paul - - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License - as published by the Free Software Foundation. - - 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 (version 2 or later) for more details. - - You should have received a copy of the GNU General Public License (version 2) - along with this program; if not, write to the Free Software Foundation, - Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -*/ - -#ifndef LFO_H -#define LFO_H - -#include "../globals.h" -#include "../Params/LFOParams.h" - -/**Class for creating Low Frequency Ocillators*/ -class LFO -{ - public: - /**Constructor - * - * @param lfopars pointer to a LFOParams object - * @param basefreq base frequency of LFO - */ - LFO(LFOParams *lfopars, REALTYPE basefreq); - /**Deconstructor*/ - ~LFO(); - REALTYPE lfoout(); - REALTYPE amplfoout(); - private: - REALTYPE x; - REALTYPE incx, incrnd, nextincrnd; - REALTYPE amp1, amp2; // used for randomness - REALTYPE lfointensity; - REALTYPE lfornd, lfofreqrnd; - REALTYPE lfodelay; - /**\todo see if an enum would be better here*/ - char lfotype; - int freqrndenabled; - - - void computenextincrnd(); -}; - -#endif - diff --git a/plugins/zynaddsubfx/src/Synth/OscilGen.cpp b/plugins/zynaddsubfx/src/Synth/OscilGen.cpp deleted file mode 100644 index 47a1ec253..000000000 --- a/plugins/zynaddsubfx/src/Synth/OscilGen.cpp +++ /dev/null @@ -1,1475 +0,0 @@ -/* - ZynAddSubFX - a software synthesizer - - OscilGen.cpp - Waveform generator for ADnote - Copyright (C) 2002-2005 Nasca Octavian Paul - Author: Nasca Octavian Paul - - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License - as published by the Free Software Foundation. - - 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 (version 2 or later) for more details. - - You should have received a copy of the GNU General Public License (version 2) - along with this program; if not, write to the Free Software Foundation, - Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -*/ - -#include -#include -#include - -#include "OscilGen.h" -#include "../Effects/Distorsion.h" - -OscilGen::OscilGen(FFTwrapper *fft_, Resonance *res_):Presets() -{ - setpresettype("Poscilgen"); - fft = fft_; - res = res_; - - tmpsmps = new REALTYPE[OSCIL_SIZE]; - newFFTFREQS(&outoscilFFTfreqs, OSCIL_SIZE / 2); - newFFTFREQS(&oscilFFTfreqs, OSCIL_SIZE / 2); - newFFTFREQS(&basefuncFFTfreqs, OSCIL_SIZE / 2); - - randseed = 1; - ADvsPAD = false; - - defaults(); -} - -OscilGen::~OscilGen() -{ - delete[] tmpsmps; - deleteFFTFREQS(&outoscilFFTfreqs); - deleteFFTFREQS(&basefuncFFTfreqs); - deleteFFTFREQS(&oscilFFTfreqs); -} - - -void OscilGen::defaults() -{ - oldbasefunc = 0; - oldbasepar = 64; - oldhmagtype = 0; - oldwaveshapingfunction = 0; - oldwaveshaping = 64; - oldbasefuncmodulation = 0; - oldharmonicshift = 0; - oldbasefuncmodulationpar1 = 0; - oldbasefuncmodulationpar2 = 0; - oldbasefuncmodulationpar3 = 0; - oldmodulation = 0; - oldmodulationpar1 = 0; - oldmodulationpar2 = 0; - oldmodulationpar3 = 0; - - for(int i = 0; i < MAX_AD_HARMONICS; i++) { - hmag[i] = 0.0; - hphase[i] = 0.0; - Phmag[i] = 64; - Phphase[i] = 64; - } - Phmag[0] = 127; - Phmagtype = 0; - if(ADvsPAD) - Prand = 127; //max phase randomness (usefull if the oscil will be imported to a ADsynth from a PADsynth - else - Prand = 64; //no randomness - - Pcurrentbasefunc = 0; - Pbasefuncpar = 64; - - Pbasefuncmodulation = 0; - Pbasefuncmodulationpar1 = 64; - Pbasefuncmodulationpar2 = 64; - Pbasefuncmodulationpar3 = 32; - - Pmodulation = 0; - Pmodulationpar1 = 64; - Pmodulationpar2 = 64; - Pmodulationpar3 = 32; - - Pwaveshapingfunction = 0; - Pwaveshaping = 64; - Pfiltertype = 0; - Pfilterpar1 = 64; - Pfilterpar2 = 64; - Pfilterbeforews = 0; - Psatype = 0; - Psapar = 64; - - Pamprandpower = 64; - Pamprandtype = 0; - - Pharmonicshift = 0; - Pharmonicshiftfirst = 0; - - Padaptiveharmonics = 0; - Padaptiveharmonicspower = 100; - Padaptiveharmonicsbasefreq = 128; - Padaptiveharmonicspar = 50; - - for(int i = 0; i < OSCIL_SIZE / 2; i++) { - oscilFFTfreqs.s[i] = 0.0; - oscilFFTfreqs.c[i] = 0.0; - basefuncFFTfreqs.s[i] = 0.0; - basefuncFFTfreqs.c[i] = 0.0; - } - oscilprepared = 0; - oldfilterpars = 0; - oldsapars = 0; - prepare(); -} - -void OscilGen::convert2sine(int magtype) -{ - REALTYPE mag[MAX_AD_HARMONICS], phase[MAX_AD_HARMONICS]; - REALTYPE oscil[OSCIL_SIZE]; - FFTFREQS freqs; - newFFTFREQS(&freqs, OSCIL_SIZE / 2); - - get(oscil, -1.0); - FFTwrapper *fft = new FFTwrapper(OSCIL_SIZE); - fft->smps2freqs(oscil, freqs); - delete (fft); - - REALTYPE max = 0.0; - - mag[0] = 0; - phase[0] = 0; - for(int i = 0; i < MAX_AD_HARMONICS; i++) { - mag[i] = sqrt(pow(freqs.s[i + 1], 2) + pow(freqs.c[i + 1], 2.0)); - phase[i] = atan2(freqs.c[i + 1], freqs.s[i + 1]); - if(max < mag[i]) - max = mag[i]; - } - if(max < 0.00001) - max = 1.0; - - defaults(); - - for(int i = 0; i < MAX_AD_HARMONICS - 1; i++) { - REALTYPE newmag = mag[i] / max; - REALTYPE newphase = phase[i]; - - Phmag[i] = (int) ((newmag) * 64.0) + 64; - - Phphase[i] = 64 - (int) (64.0 * newphase / PI); - if(Phphase[i] > 127) - Phphase[i] = 127; - - if(Phmag[i] == 64) - Phphase[i] = 64; - } - deleteFFTFREQS(&freqs); - prepare(); -} - -/* - * Base Functions - START - */ -REALTYPE OscilGen::basefunc_pulse(REALTYPE x, REALTYPE a) -{ - return (fmod(x, 1.0) < a) ? -1.0 : 1.0; -} - -REALTYPE OscilGen::basefunc_saw(REALTYPE x, REALTYPE a) -{ - if(a < 0.00001) - a = 0.00001; - else - if(a > 0.99999) - a = 0.99999; - x = fmod(x, 1); - if(x < a) - return x / a * 2.0 - 1.0; - else - return (1.0 - x) / (1.0 - a) * 2.0 - 1.0; -} - -REALTYPE OscilGen::basefunc_triangle(REALTYPE x, REALTYPE a) -{ - x = fmod(x + 0.25, 1); - a = 1 - a; - if(a < 0.00001) - a = 0.00001; - if(x < 0.5) - x = x * 4 - 1.0; - else - x = (1.0 - x) * 4 - 1.0; - x /= -a; - if(x < -1.0) - x = -1.0; - if(x > 1.0) - x = 1.0; - return x; -} - -REALTYPE OscilGen::basefunc_power(REALTYPE x, REALTYPE a) -{ - x = fmod(x, 1); - if(a < 0.00001) - a = 0.00001; - else - if(a > 0.99999) - a = 0.99999; - return pow(x, exp((a - 0.5) * 10.0)) * 2.0 - 1.0; -} - -REALTYPE OscilGen::basefunc_gauss(REALTYPE x, REALTYPE a) -{ - x = fmod(x, 1) * 2.0 - 1.0; - if(a < 0.00001) - a = 0.00001; - return exp(-x * x * (exp(a * 8) + 5.0)) * 2.0 - 1.0; -} - -REALTYPE OscilGen::basefunc_diode(REALTYPE x, REALTYPE a) -{ - if(a < 0.00001) - a = 0.00001; - else - if(a > 0.99999) - a = 0.99999; - a = a * 2.0 - 1.0; - x = cos((x + 0.5) * 2.0 * PI) - a; - if(x < 0.0) - x = 0.0; - return x / (1.0 - a) * 2 - 1.0; -} - -REALTYPE OscilGen::basefunc_abssine(REALTYPE x, REALTYPE a) -{ - x = fmod(x, 1); - if(a < 0.00001) - a = 0.00001; - else - if(a > 0.99999) - a = 0.99999; - return sin(pow(x, exp((a - 0.5) * 5.0)) * PI) * 2.0 - 1.0; -} - -REALTYPE OscilGen::basefunc_pulsesine(REALTYPE x, REALTYPE a) -{ - if(a < 0.00001) - a = 0.00001; - x = (fmod(x, 1) - 0.5) * exp((a - 0.5) * log(128)); - if(x < -0.5) - x = -0.5; - else - if(x > 0.5) - x = 0.5; - x = sin(x * PI * 2.0); - return x; -} - -REALTYPE OscilGen::basefunc_stretchsine(REALTYPE x, REALTYPE a) -{ - x = fmod(x + 0.5, 1) * 2.0 - 1.0; - a = (a - 0.5) * 4; - if(a > 0.0) - a *= 2; - a = pow(3.0, a); - REALTYPE b = pow(fabs(x), a); - if(x < 0) - b = -b; - return -sin(b * PI); -} - -REALTYPE OscilGen::basefunc_chirp(REALTYPE x, REALTYPE a) -{ - x = fmod(x, 1.0) * 2.0 * PI; - a = (a - 0.5) * 4; - if(a < 0.0) - a *= 2.0; - a = pow(3.0, a); - return sin(x / 2.0) * sin(a * x * x); -} - -REALTYPE OscilGen::basefunc_absstretchsine(REALTYPE x, REALTYPE a) -{ - x = fmod(x + 0.5, 1) * 2.0 - 1.0; - a = (a - 0.5) * 9; - a = pow(3.0, a); - REALTYPE b = pow(fabs(x), a); - if(x < 0) - b = -b; - return -pow(sin(b * PI), 2); -} - -REALTYPE OscilGen::basefunc_chebyshev(REALTYPE x, REALTYPE a) -{ - a = a * a * a * 30.0 + 1.0; - return cos(acos(x * 2.0 - 1.0) * a); -} - -REALTYPE OscilGen::basefunc_sqr(REALTYPE x, REALTYPE a) -{ - a = a * a * a * a * 160.0 + 0.001; - return -atan(sin(x * 2.0 * PI) * a); -} -/* - * Base Functions - END - */ - - -/* - * Get the base function - */ -void OscilGen::getbasefunction(REALTYPE *smps) -{ - int i; - REALTYPE par = (Pbasefuncpar + 0.5) / 128.0; - if(Pbasefuncpar == 64) - par = 0.5; - - REALTYPE basefuncmodulationpar1 = Pbasefuncmodulationpar1 / 127.0, - basefuncmodulationpar2 = Pbasefuncmodulationpar2 / 127.0, - basefuncmodulationpar3 = Pbasefuncmodulationpar3 / 127.0; - - switch(Pbasefuncmodulation) { - case 1: - basefuncmodulationpar1 = - (pow(2, basefuncmodulationpar1 * 5.0) - 1.0) / 10.0; - basefuncmodulationpar3 = - floor((pow(2, basefuncmodulationpar3 * 5.0) - 1.0)); - if(basefuncmodulationpar3 < 0.9999) - basefuncmodulationpar3 = -1.0; - break; - case 2: - basefuncmodulationpar1 = - (pow(2, basefuncmodulationpar1 * 5.0) - 1.0) / 10.0; - basefuncmodulationpar3 = 1.0 - + floor((pow(2, basefuncmodulationpar3 - * 5.0) - 1.0)); - break; - case 3: - basefuncmodulationpar1 = - (pow(2, basefuncmodulationpar1 * 7.0) - 1.0) / 10.0; - basefuncmodulationpar3 = 0.01 - + (pow(2, basefuncmodulationpar3 - * 16.0) - 1.0) / 10.0; - break; - } - -// printf("%.5f %.5f\n",basefuncmodulationpar1,basefuncmodulationpar3); - - for(i = 0; i < OSCIL_SIZE; i++) { - REALTYPE t = i * 1.0 / OSCIL_SIZE; - - switch(Pbasefuncmodulation) { - case 1: - t = t * basefuncmodulationpar3 + sin( - (t - + basefuncmodulationpar2) * 2.0 * PI) * basefuncmodulationpar1; //rev - break; - case 2: - t = t + sin( - (t * basefuncmodulationpar3 - + basefuncmodulationpar2) * 2.0 * PI) * basefuncmodulationpar1; //sine - break; - case 3: - t = t + pow((1.0 - cos( - (t + basefuncmodulationpar2) * 2.0 * PI)) * 0.5, - basefuncmodulationpar3) * basefuncmodulationpar1; //power - break; - } - - t = t - floor(t); - - switch(Pcurrentbasefunc) { - case 1: - smps[i] = basefunc_triangle(t, par); - break; - case 2: - smps[i] = basefunc_pulse(t, par); - break; - case 3: - smps[i] = basefunc_saw(t, par); - break; - case 4: - smps[i] = basefunc_power(t, par); - break; - case 5: - smps[i] = basefunc_gauss(t, par); - break; - case 6: - smps[i] = basefunc_diode(t, par); - break; - case 7: - smps[i] = basefunc_abssine(t, par); - break; - case 8: - smps[i] = basefunc_pulsesine(t, par); - break; - case 9: - smps[i] = basefunc_stretchsine(t, par); - break; - case 10: - smps[i] = basefunc_chirp(t, par); - break; - case 11: - smps[i] = basefunc_absstretchsine(t, par); - break; - case 12: - smps[i] = basefunc_chebyshev(t, par); - break; - case 13: - smps[i] = basefunc_sqr(t, par); - break; - default: - smps[i] = -sin(2.0 * PI * i / OSCIL_SIZE); - } - } -} - -/* - * Filter the oscillator - */ -void OscilGen::oscilfilter() -{ - if(Pfiltertype == 0) - return; - REALTYPE par = 1.0 - Pfilterpar1 / 128.0; - REALTYPE par2 = Pfilterpar2 / 127.0; - REALTYPE max = 0.0, tmp = 0.0, p2, x; - for(int i = 1; i < OSCIL_SIZE / 2; i++) { - REALTYPE gain = 1.0; - switch(Pfiltertype) { - case 1: - gain = pow(1.0 - par * par * par * 0.99, i); //lp - tmp = par2 * par2 * par2 * par2 * 0.5 + 0.0001; - if(gain < tmp) - gain = pow(gain, 10.0) / pow(tmp, 9.0); - break; - case 2: - gain = 1.0 - pow(1.0 - par * par, i + 1); //hp1 - gain = pow(gain, par2 * 2.0 + 0.1); - break; - case 3: - if(par < 0.2) - par = par * 0.25 + 0.15; - gain = 1.0 - pow(1.0 - par * par * 0.999 + 0.001, - i * 0.05 * i + 1.0); //hp1b - tmp = pow(5.0, par2 * 2.0); - gain = pow(gain, tmp); - break; - case 4: - gain = i + 1 - pow(2, (1.0 - par) * 7.5); //bp1 - gain = 1.0 / (1.0 + gain * gain / (i + 1.0)); - tmp = pow(5.0, par2 * 2.0); - gain = pow(gain, tmp); - if(gain < 1e-5) - gain = 1e-5; - break; - case 5: - gain = i + 1 - pow(2, (1.0 - par) * 7.5); //bs1 - gain = pow(atan(gain / (i / 10.0 + 1)) / 1.57, 6); - gain = pow(gain, par2 * par2 * 3.9 + 0.1); - break; - case 6: - tmp = pow(par2, 0.33); - gain = - (i + 1 > - pow(2, (1.0 - par) * 10) ? 0.0 : 1.0) * par2 + (1.0 - par2); //lp2 - break; - case 7: - tmp = pow(par2, 0.33); - //tmp=1.0-(1.0-par2)*(1.0-par2); - gain = - (i + 1 > - pow(2, (1.0 - par) * 7) ? 1.0 : 0.0) * par2 + (1.0 - par2); //hp2 - if(Pfilterpar1 == 0) - gain = 1.0; - break; - case 8: - tmp = pow(par2, 0.33); - //tmp=1.0-(1.0-par2)*(1.0-par2); - gain = - (fabs(pow(2, - (1.0 - - par) - * 7) - i) > i / 2 + 1 ? 0.0 : 1.0) * par2 + (1.0 - par2); //bp2 - break; - case 9: - tmp = pow(par2, 0.33); - gain = - (fabs(pow(2, - (1.0 - - par) - * 7) - i) < i / 2 + 1 ? 0.0 : 1.0) * par2 + (1.0 - par2); //bs2 - break; - case 10: - tmp = pow(5.0, par2 * 2.0 - 1.0); - tmp = pow(i / 32.0, tmp) * 32.0; - if(Pfilterpar2 == 64) - tmp = i; - gain = cos(par * par * PI / 2.0 * tmp); //cos - gain *= gain; - break; - case 11: - tmp = pow(5.0, par2 * 2.0 - 1.0); - tmp = pow(i / 32.0, tmp) * 32.0; - if(Pfilterpar2 == 64) - tmp = i; - gain = sin(par * par * PI / 2.0 * tmp); //sin - gain *= gain; - break; - case 12: - p2 = 1.0 - par + 0.2; - x = i / (64.0 * p2 * p2); - if(x < 0.0) - x = 0.0; - else - if(x > 1.0) - x = 1.0; - tmp = pow(1.0 - par2, 2.0); - gain = cos(x * PI) * (1.0 - tmp) + 1.01 + tmp; //low shelf - break; - case 13: - tmp = (int) (pow(2.0, (1.0 - par) * 7.2)); - gain = 1.0; - if(i == (int) (tmp)) - gain = pow(2.0, par2 * par2 * 8.0); - break; - } - - - oscilFFTfreqs.s[i] *= gain; - oscilFFTfreqs.c[i] *= gain; - REALTYPE tmp = oscilFFTfreqs.s[i] * oscilFFTfreqs.s[i] - + oscilFFTfreqs.c[i] * oscilFFTfreqs.c[i]; - if(max < tmp) - max = tmp; - } - - max = sqrt(max); - if(max < 1e-10) - max = 1.0; - REALTYPE imax = 1.0 / max; - for(int i = 1; i < OSCIL_SIZE / 2; i++) { - oscilFFTfreqs.s[i] *= imax; - oscilFFTfreqs.c[i] *= imax; - } -} - -/* - * Change the base function - */ -void OscilGen::changebasefunction() -{ - if(Pcurrentbasefunc != 0) { - getbasefunction(tmpsmps); - fft->smps2freqs(tmpsmps, basefuncFFTfreqs); - basefuncFFTfreqs.c[0] = 0.0; - } - else { - for(int i = 0; i < OSCIL_SIZE / 2; i++) { - basefuncFFTfreqs.s[i] = 0.0; - basefuncFFTfreqs.c[i] = 0.0; - } - //in this case basefuncFFTfreqs_ are not used - } - oscilprepared = 0; - oldbasefunc = Pcurrentbasefunc; - oldbasepar = Pbasefuncpar; - oldbasefuncmodulation = Pbasefuncmodulation; - oldbasefuncmodulationpar1 = Pbasefuncmodulationpar1; - oldbasefuncmodulationpar2 = Pbasefuncmodulationpar2; - oldbasefuncmodulationpar3 = Pbasefuncmodulationpar3; -} - -/* - * Waveshape - */ -void OscilGen::waveshape() -{ - int i; - - oldwaveshapingfunction = Pwaveshapingfunction; - oldwaveshaping = Pwaveshaping; - if(Pwaveshapingfunction == 0) - return; - - oscilFFTfreqs.c[0] = 0.0; //remove the DC - //reduce the amplitude of the freqs near the nyquist - for(i = 1; i < OSCIL_SIZE / 8; i++) { - REALTYPE tmp = i / (OSCIL_SIZE / 8.0); - oscilFFTfreqs.s[OSCIL_SIZE / 2 - i] *= tmp; - oscilFFTfreqs.c[OSCIL_SIZE / 2 - i] *= tmp; - } - fft->freqs2smps(oscilFFTfreqs, tmpsmps); - - //Normalize - REALTYPE max = 0.0; - for(i = 0; i < OSCIL_SIZE; i++) - if(max < fabs(tmpsmps[i])) - max = fabs(tmpsmps[i]); - if(max < 0.00001) - max = 1.0; - max = 1.0 / max; - for(i = 0; i < OSCIL_SIZE; i++) - tmpsmps[i] *= max; - - //Do the waveshaping - waveshapesmps(OSCIL_SIZE, tmpsmps, Pwaveshapingfunction, Pwaveshaping); - - fft->smps2freqs(tmpsmps, oscilFFTfreqs); //perform FFT -} - - -/* - * Do the Frequency Modulation of the Oscil - */ -void OscilGen::modulation() -{ - int i; - - oldmodulation = Pmodulation; - oldmodulationpar1 = Pmodulationpar1; - oldmodulationpar2 = Pmodulationpar2; - oldmodulationpar3 = Pmodulationpar3; - if(Pmodulation == 0) - return; - - - REALTYPE modulationpar1 = Pmodulationpar1 / 127.0, - modulationpar2 = 0.5 - Pmodulationpar2 / 127.0, - modulationpar3 = Pmodulationpar3 / 127.0; - - switch(Pmodulation) { - case 1: - modulationpar1 = (pow(2, modulationpar1 * 7.0) - 1.0) / 100.0; - modulationpar3 = floor((pow(2, modulationpar3 * 5.0) - 1.0)); - if(modulationpar3 < 0.9999) - modulationpar3 = -1.0; - break; - case 2: - modulationpar1 = (pow(2, modulationpar1 * 7.0) - 1.0) / 100.0; - modulationpar3 = 1.0 + floor((pow(2, modulationpar3 * 5.0) - 1.0)); - break; - case 3: - modulationpar1 = (pow(2, modulationpar1 * 9.0) - 1.0) / 100.0; - modulationpar3 = 0.01 + (pow(2, modulationpar3 * 16.0) - 1.0) / 10.0; - break; - } - - oscilFFTfreqs.c[0] = 0.0; //remove the DC - //reduce the amplitude of the freqs near the nyquist - for(i = 1; i < OSCIL_SIZE / 8; i++) { - REALTYPE tmp = i / (OSCIL_SIZE / 8.0); - oscilFFTfreqs.s[OSCIL_SIZE / 2 - i] *= tmp; - oscilFFTfreqs.c[OSCIL_SIZE / 2 - i] *= tmp; - } - fft->freqs2smps(oscilFFTfreqs, tmpsmps); - int extra_points = 2; - REALTYPE *in = new REALTYPE[OSCIL_SIZE + extra_points]; - - //Normalize - REALTYPE max = 0.0; - for(i = 0; i < OSCIL_SIZE; i++) - if(max < fabs(tmpsmps[i])) - max = fabs(tmpsmps[i]); - if(max < 0.00001) - max = 1.0; - max = 1.0 / max; - for(i = 0; i < OSCIL_SIZE; i++) - in[i] = tmpsmps[i] * max; - for(i = 0; i < extra_points; i++) - in[i + OSCIL_SIZE] = tmpsmps[i] * max; - - //Do the modulation - for(i = 0; i < OSCIL_SIZE; i++) { - REALTYPE t = i * 1.0 / OSCIL_SIZE; - - switch(Pmodulation) { - case 1: - t = t * modulationpar3 - + sin((t + modulationpar2) * 2.0 * PI) * modulationpar1; //rev - break; - case 2: - t = t - + sin((t * modulationpar3 - + modulationpar2) * 2.0 * PI) * modulationpar1; //sine - break; - case 3: - t = t + pow((1.0 - cos( - (t + modulationpar2) * 2.0 * PI)) * 0.5, - modulationpar3) * modulationpar1; //power - break; - } - - t = (t - floor(t)) * OSCIL_SIZE; - - int poshi = (int) t; - REALTYPE poslo = t - floor(t); - - tmpsmps[i] = in[poshi] * (1.0 - poslo) + in[poshi + 1] * poslo; - } - - delete [] in; - fft->smps2freqs(tmpsmps, oscilFFTfreqs); //perform FFT -} - - - -/* - * Adjust the spectrum - */ -void OscilGen::spectrumadjust() -{ - if(Psatype == 0) - return; - REALTYPE par = Psapar / 127.0; - switch(Psatype) { - case 1: - par = 1.0 - par * 2.0; - if(par >= 0.0) - par = pow(5.0, par); - else - par = pow(8.0, par); - break; - case 2: - par = pow(10.0, (1.0 - par) * 3.0) * 0.25; - break; - case 3: - par = pow(10.0, (1.0 - par) * 3.0) * 0.25; - break; - } - - - REALTYPE max = 0.0; - for(int i = 0; i < OSCIL_SIZE / 2; i++) { - REALTYPE tmp = pow(oscilFFTfreqs.c[i], 2) + pow(oscilFFTfreqs.s[i], 2.0); - if(max < tmp) - max = tmp; - } - max = sqrt(max) / OSCIL_SIZE * 2.0; - if(max < 1e-8) - max = 1.0; - - - for(int i = 0; i < OSCIL_SIZE / 2; i++) { - REALTYPE mag = - sqrt(pow(oscilFFTfreqs.s[i], - 2) + pow(oscilFFTfreqs.c[i], 2.0)) / max; - REALTYPE phase = atan2(oscilFFTfreqs.s[i], oscilFFTfreqs.c[i]); - - switch(Psatype) { - case 1: - mag = pow(mag, par); - break; - case 2: - if(mag < par) - mag = 0.0; - break; - case 3: - mag /= par; - if(mag > 1.0) - mag = 1.0; - break; - } - oscilFFTfreqs.c[i] = mag * cos(phase); - oscilFFTfreqs.s[i] = mag * sin(phase); - } -} - -void OscilGen::shiftharmonics() -{ - if(Pharmonicshift == 0) - return; - - REALTYPE hc, hs; - int harmonicshift = -Pharmonicshift; - - if(harmonicshift > 0) { - for(int i = OSCIL_SIZE / 2 - 2; i >= 0; i--) { - int oldh = i - harmonicshift; - if(oldh < 0) { - hc = 0.0; - hs = 0.0; - } - else { - hc = oscilFFTfreqs.c[oldh + 1]; - hs = oscilFFTfreqs.s[oldh + 1]; - } - oscilFFTfreqs.c[i + 1] = hc; - oscilFFTfreqs.s[i + 1] = hs; - } - } - else { - for(int i = 0; i < OSCIL_SIZE / 2 - 1; i++) { - int oldh = i + abs(harmonicshift); - if(oldh >= (OSCIL_SIZE / 2 - 1)) { - hc = 0.0; - hs = 0.0; - } - else { - hc = oscilFFTfreqs.c[oldh + 1]; - hs = oscilFFTfreqs.s[oldh + 1]; - if(fabs(hc) < 0.000001) - hc = 0.0; - if(fabs(hs) < 0.000001) - hs = 0.0; - } - - oscilFFTfreqs.c[i + 1] = hc; - oscilFFTfreqs.s[i + 1] = hs; - } - } - - oscilFFTfreqs.c[0] = 0.0; -} - -/* - * Prepare the Oscillator - */ -void OscilGen::prepare() -{ - int i, j, k; - REALTYPE a, b, c, d, hmagnew; - - if((oldbasepar != Pbasefuncpar) || (oldbasefunc != Pcurrentbasefunc) - || (oldbasefuncmodulation != Pbasefuncmodulation) - || (oldbasefuncmodulationpar1 != Pbasefuncmodulationpar1) - || (oldbasefuncmodulationpar2 != Pbasefuncmodulationpar2) - || (oldbasefuncmodulationpar3 != Pbasefuncmodulationpar3)) - changebasefunction(); - - for(i = 0; i < MAX_AD_HARMONICS; i++) - hphase[i] = (Phphase[i] - 64.0) / 64.0 * PI / (i + 1); - - for(i = 0; i < MAX_AD_HARMONICS; i++) { - hmagnew = 1.0 - fabs(Phmag[i] / 64.0 - 1.0); - switch(Phmagtype) { - case 1: - hmag[i] = exp(hmagnew * log(0.01)); - break; - case 2: - hmag[i] = exp(hmagnew * log(0.001)); - break; - case 3: - hmag[i] = exp(hmagnew * log(0.0001)); - break; - case 4: - hmag[i] = exp(hmagnew * log(0.00001)); - break; - default: - hmag[i] = 1.0 - hmagnew; - break; - } - - if(Phmag[i] < 64) - hmag[i] = -hmag[i]; - } - - //remove the harmonics where Phmag[i]==64 - for(i = 0; i < MAX_AD_HARMONICS; i++) - if(Phmag[i] == 64) - hmag[i] = 0.0; - - - for(i = 0; i < OSCIL_SIZE / 2; i++) { - oscilFFTfreqs.c[i] = 0.0; - oscilFFTfreqs.s[i] = 0.0; - } - if(Pcurrentbasefunc == 0) { //the sine case - for(i = 0; i < MAX_AD_HARMONICS; i++) { - oscilFFTfreqs.c[i + 1] = -hmag[i] * sin(hphase[i] * (i + 1)) / 2.0; - oscilFFTfreqs.s[i + 1] = hmag[i] * cos(hphase[i] * (i + 1)) / 2.0; - } - } - else { - for(j = 0; j < MAX_AD_HARMONICS; j++) { - if(Phmag[j] == 64) - continue; - for(i = 1; i < OSCIL_SIZE / 2; i++) { - k = i * (j + 1); - if(k >= OSCIL_SIZE / 2) - break; - a = basefuncFFTfreqs.c[i]; - b = basefuncFFTfreqs.s[i]; - c = hmag[j] * cos(hphase[j] * k); - d = hmag[j] * sin(hphase[j] * k); - oscilFFTfreqs.c[k] += a * c - b * d; - oscilFFTfreqs.s[k] += a * d + b * c; - } - } - } - - if(Pharmonicshiftfirst != 0) - shiftharmonics(); - - - - if(Pfilterbeforews == 0) { - waveshape(); - oscilfilter(); - } - else { - oscilfilter(); - waveshape(); - } - - modulation(); - spectrumadjust(); - if(Pharmonicshiftfirst == 0) - shiftharmonics(); - - oscilFFTfreqs.c[0] = 0.0; - - oldhmagtype = Phmagtype; - oldharmonicshift = Pharmonicshift + Pharmonicshiftfirst * 256; - - oscilprepared = 1; -} - -void OscilGen::adaptiveharmonic(FFTFREQS f, REALTYPE freq) -{ - if(Padaptiveharmonics == 0 /*||(freq<1.0)*/) - return; - if(freq < 1.0) - freq = 440.0; - - FFTFREQS inf; - newFFTFREQS(&inf, OSCIL_SIZE / 2); - for(int i = 0; i < OSCIL_SIZE / 2; i++) { - inf.s[i] = f.s[i]; - inf.c[i] = f.c[i]; - f.s[i] = 0.0; - f.c[i] = 0.0; - } - inf.c[0] = 0.0; - inf.s[0] = 0.0; - - REALTYPE hc = 0.0, hs = 0.0; - REALTYPE basefreq = 30.0 * pow(10.0, Padaptiveharmonicsbasefreq / 128.0); - REALTYPE power = (Padaptiveharmonicspower + 1.0) / 101.0; - - REALTYPE rap = freq / basefreq; - - rap = pow(rap, power); - - bool down = false; - if(rap > 1.0) { - rap = 1.0 / rap; - down = true; - } - - for(int i = 0; i < OSCIL_SIZE / 2 - 2; i++) { - REALTYPE h = i * rap; - int high = (int)(i * rap); - REALTYPE low = fmod(h, 1.0); - - if(high >= (OSCIL_SIZE / 2 - 2)) - break; - else { - if(down) { - f.c[high] += inf.c[i] * (1.0 - low); - f.s[high] += inf.s[i] * (1.0 - low); - f.c[high + 1] += inf.c[i] * low; - f.s[high + 1] += inf.s[i] * low; - } - else { - hc = inf.c[high] * (1.0 - low) + inf.c[high + 1] * low; - hs = inf.s[high] * (1.0 - low) + inf.s[high + 1] * low; - } - if(fabs(hc) < 0.000001) - hc = 0.0; - if(fabs(hs) < 0.000001) - hs = 0.0; - } - - if(!down) { - if(i == 0) { //corect the aplitude of the first harmonic - hc *= rap; - hs *= rap; - } - f.c[i] = hc; - f.s[i] = hs; - } - } - - f.c[1] += f.c[0]; - f.s[1] += f.s[0]; - f.c[0] = 0.0; - f.s[0] = 0.0; - deleteFFTFREQS(&inf); -} - -void OscilGen::adaptiveharmonicpostprocess(REALTYPE *f, int size) -{ - if(Padaptiveharmonics <= 1) - return; - REALTYPE *inf = new REALTYPE[size]; - REALTYPE par = Padaptiveharmonicspar * 0.01; - par = 1.0 - pow((1.0 - par), 1.5); - - for(int i = 0; i < size; i++) { - inf[i] = f[i] * par; - f[i] = f[i] * (1.0 - par); - } - - - if(Padaptiveharmonics == 2) { //2n+1 - for(int i = 0; i < size; i++) - if((i % 2) == 0) - f[i] += inf[i]; //i=0 pt prima armonica,etc. - } - else { //celelalte moduri - int nh = (Padaptiveharmonics - 3) / 2 + 2; - int sub_vs_add = (Padaptiveharmonics - 3) % 2; - if(sub_vs_add == 0) { - for(int i = 0; i < size; i++) { - if(((i + 1) % nh) == 0) - f[i] += inf[i]; - ; - } - } - else { - for(int i = 0; i < size / nh - 1; i++) - f[(i + 1) * nh - 1] += inf[i]; - ; - } - } - - delete[] inf; -} - - - -/* - * Get the oscillator function - */ -short int OscilGen::get(REALTYPE *smps, REALTYPE freqHz) -{ - return this->get(smps, freqHz, 0); -} - -void OscilGen::newrandseed(unsigned int randseed) -{ - this->randseed = randseed; -} - -/* - * Get the oscillator function - */ -short int OscilGen::get(REALTYPE *smps, REALTYPE freqHz, int resonance) -{ - int i; - int nyquist, outpos; - - if((oldbasepar != Pbasefuncpar) || (oldbasefunc != Pcurrentbasefunc) - || (oldhmagtype != Phmagtype) - || (oldwaveshaping != Pwaveshaping) - || (oldwaveshapingfunction != Pwaveshapingfunction)) - oscilprepared = 0; - if(oldfilterpars != Pfiltertype * 256 + Pfilterpar1 + Pfilterpar2 * 65536 - + Pfilterbeforews * 16777216) { - oscilprepared = 0; - oldfilterpars = Pfiltertype * 256 + Pfilterpar1 + Pfilterpar2 * 65536 - + Pfilterbeforews * 16777216; - } - if(oldsapars != Psatype * 256 + Psapar) { - oscilprepared = 0; - oldsapars = Psatype * 256 + Psapar; - } - - if((oldbasefuncmodulation != Pbasefuncmodulation) - || (oldbasefuncmodulationpar1 != Pbasefuncmodulationpar1) - || (oldbasefuncmodulationpar2 != Pbasefuncmodulationpar2) - || (oldbasefuncmodulationpar3 != Pbasefuncmodulationpar3)) - oscilprepared = 0; - - if((oldmodulation != Pmodulation) - || (oldmodulationpar1 != Pmodulationpar1) - || (oldmodulationpar2 != Pmodulationpar2) - || (oldmodulationpar3 != Pmodulationpar3)) - oscilprepared = 0; - - if(oldharmonicshift != Pharmonicshift + Pharmonicshiftfirst * 256) - oscilprepared = 0; - - if(oscilprepared != 1) - prepare(); - - outpos = - (int)((RND * 2.0 - 1.0) * (REALTYPE) OSCIL_SIZE * (Prand - 64.0) / 64.0); - outpos = (outpos + 2 * OSCIL_SIZE) % OSCIL_SIZE; - - - for(i = 0; i < OSCIL_SIZE / 2; i++) { - outoscilFFTfreqs.c[i] = 0.0; - outoscilFFTfreqs.s[i] = 0.0; - } - - nyquist = (int)(0.5 * SAMPLE_RATE / fabs(freqHz)) + 2; - if(ADvsPAD) - nyquist = (int)(OSCIL_SIZE / 2); - if(nyquist > OSCIL_SIZE / 2) - nyquist = OSCIL_SIZE / 2; - - - int realnyquist = nyquist; - - if(Padaptiveharmonics != 0) - nyquist = OSCIL_SIZE / 2; - for(i = 1; i < nyquist - 1; i++) { - outoscilFFTfreqs.c[i] = oscilFFTfreqs.c[i]; - outoscilFFTfreqs.s[i] = oscilFFTfreqs.s[i]; - } - - adaptiveharmonic(outoscilFFTfreqs, freqHz); - adaptiveharmonicpostprocess(&outoscilFFTfreqs.c[1], OSCIL_SIZE / 2 - 1); - adaptiveharmonicpostprocess(&outoscilFFTfreqs.s[1], OSCIL_SIZE / 2 - 1); - - nyquist = realnyquist; - if(Padaptiveharmonics) { //do the antialiasing in the case of adaptive harmonics - for(i = nyquist; i < OSCIL_SIZE / 2; i++) { - outoscilFFTfreqs.s[i] = 0; - outoscilFFTfreqs.c[i] = 0; - } - } - - // Randomness (each harmonic), the block type is computed - // in ADnote by setting start position according to this setting - if((Prand > 64) && (freqHz >= 0.0) && (!ADvsPAD)) { - REALTYPE rnd, angle, a, b, c, d; - rnd = PI * pow((Prand - 64.0) / 64.0, 2.0); - for(i = 1; i < nyquist - 1; i++) { //to Nyquist only for AntiAliasing - angle = rnd * i * RND; - a = outoscilFFTfreqs.c[i]; - b = outoscilFFTfreqs.s[i]; - c = cos(angle); - d = sin(angle); - outoscilFFTfreqs.c[i] = a * c - b * d; - outoscilFFTfreqs.s[i] = a * d + b * c; - } - } - - //Harmonic Amplitude Randomness - if((freqHz > 0.1) && (!ADvsPAD)) { - unsigned int realrnd = rand(); - srand(randseed); - REALTYPE power = Pamprandpower / 127.0; - REALTYPE normalize = 1.0 / (1.2 - power); - switch(Pamprandtype) { - case 1: - power = power * 2.0 - 0.5; - power = pow(15.0, power); - for(i = 1; i < nyquist - 1; i++) { - REALTYPE amp = pow(RND, power) * normalize; - outoscilFFTfreqs.c[i] *= amp; - outoscilFFTfreqs.s[i] *= amp; - } - break; - case 2: - power = power * 2.0 - 0.5; - power = pow(15.0, power) * 2.0; - REALTYPE rndfreq = 2 * PI * RND; - for(i = 1; i < nyquist - 1; i++) { - REALTYPE amp = pow(fabs(sin(i * rndfreq)), power) * normalize; - outoscilFFTfreqs.c[i] *= amp; - outoscilFFTfreqs.s[i] *= amp; - } - break; - } - srand(realrnd + 1); - } - - if((freqHz > 0.1) && (resonance != 0)) - res->applyres(nyquist - 1, outoscilFFTfreqs, freqHz); - - //Full RMS normalize - REALTYPE sum = 0; - for(int j = 1; j < OSCIL_SIZE / 2; j++) { - REALTYPE term = outoscilFFTfreqs.c[j] * outoscilFFTfreqs.c[j] - + outoscilFFTfreqs.s[j] * outoscilFFTfreqs.s[j]; - sum += term; - } - if(sum < 0.000001) - sum = 1.0; - sum = 1.0 / sqrt(sum); - for(int j = 1; j < OSCIL_SIZE / 2; j++) { - outoscilFFTfreqs.c[j] *= sum; - outoscilFFTfreqs.s[j] *= sum; - } - - - if((ADvsPAD) && (freqHz > 0.1)) //in this case the smps will contain the freqs - for(i = 1; i < OSCIL_SIZE / 2; i++) - smps[i - 1] = sqrt(outoscilFFTfreqs.c[i] * outoscilFFTfreqs.c[i] - + outoscilFFTfreqs.s[i] * outoscilFFTfreqs.s[i]); - else { - fft->freqs2smps(outoscilFFTfreqs, smps); - for(i = 0; i < OSCIL_SIZE; i++) - smps[i] *= 0.25; //correct the amplitude - } - - if(Prand < 64) - return outpos; - else - return 0; -} - - -/* - * Get the spectrum of the oscillator for the UI - */ -void OscilGen::getspectrum(int n, REALTYPE *spc, int what) -{ - if(n > OSCIL_SIZE / 2) - n = OSCIL_SIZE / 2; - - for(int i = 1; i < n; i++) { - if(what == 0) - spc[i - 1] = sqrt(oscilFFTfreqs.c[i] * oscilFFTfreqs.c[i] - + oscilFFTfreqs.s[i] * oscilFFTfreqs.s[i]); - else { - if(Pcurrentbasefunc == 0) - spc[i - 1] = ((i == 1) ? (1.0) : (0.0)); - else - spc[i - 1] = sqrt(basefuncFFTfreqs.c[i] * basefuncFFTfreqs.c[i] - + basefuncFFTfreqs.s[i] - * basefuncFFTfreqs.s[i]); - } - } - - if(what == 0) { - for(int i = 0; i < n; i++) - outoscilFFTfreqs.s[i] = outoscilFFTfreqs.c[i] = spc[i]; - for(int i = n; i < OSCIL_SIZE / 2; i++) - outoscilFFTfreqs.s[i] = outoscilFFTfreqs.c[i] = 0.0; - adaptiveharmonic(outoscilFFTfreqs, 0.0); - for(int i = 0; i < n; i++) - spc[i] = outoscilFFTfreqs.s[i]; - adaptiveharmonicpostprocess(spc, n - 1); - } -} - - -/* - * Convert the oscillator as base function - */ -void OscilGen::useasbase() -{ - int i; - - for(i = 0; i < OSCIL_SIZE / 2; i++) { - basefuncFFTfreqs.c[i] = oscilFFTfreqs.c[i]; - basefuncFFTfreqs.s[i] = oscilFFTfreqs.s[i]; - } - - oldbasefunc = Pcurrentbasefunc = 127; - - prepare(); -} - - -/* - * Get the base function for UI - */ -void OscilGen::getcurrentbasefunction(REALTYPE *smps) -{ - if(Pcurrentbasefunc != 0) - fft->freqs2smps(basefuncFFTfreqs, smps); - else - getbasefunction(smps); //the sine case -} - - -void OscilGen::add2XML(XMLwrapper *xml) -{ - xml->addpar("harmonic_mag_type", Phmagtype); - - xml->addpar("base_function", Pcurrentbasefunc); - xml->addpar("base_function_par", Pbasefuncpar); - xml->addpar("base_function_modulation", Pbasefuncmodulation); - xml->addpar("base_function_modulation_par1", Pbasefuncmodulationpar1); - xml->addpar("base_function_modulation_par2", Pbasefuncmodulationpar2); - xml->addpar("base_function_modulation_par3", Pbasefuncmodulationpar3); - - xml->addpar("modulation", Pmodulation); - xml->addpar("modulation_par1", Pmodulationpar1); - xml->addpar("modulation_par2", Pmodulationpar2); - xml->addpar("modulation_par3", Pmodulationpar3); - - xml->addpar("wave_shaping", Pwaveshaping); - xml->addpar("wave_shaping_function", Pwaveshapingfunction); - - xml->addpar("filter_type", Pfiltertype); - xml->addpar("filter_par1", Pfilterpar1); - xml->addpar("filter_par2", Pfilterpar2); - xml->addpar("filter_before_wave_shaping", Pfilterbeforews); - - xml->addpar("spectrum_adjust_type", Psatype); - xml->addpar("spectrum_adjust_par", Psapar); - - xml->addpar("rand", Prand); - xml->addpar("amp_rand_type", Pamprandtype); - xml->addpar("amp_rand_power", Pamprandpower); - - xml->addpar("harmonic_shift", Pharmonicshift); - xml->addparbool("harmonic_shift_first", Pharmonicshiftfirst); - - xml->addpar("adaptive_harmonics", Padaptiveharmonics); - xml->addpar("adaptive_harmonics_base_frequency", Padaptiveharmonicsbasefreq); - xml->addpar("adaptive_harmonics_power", Padaptiveharmonicspower); - - xml->beginbranch("HARMONICS"); - for(int n = 0; n < MAX_AD_HARMONICS; n++) { - if((Phmag[n] == 64) && (Phphase[n] == 64)) - continue; - xml->beginbranch("HARMONIC", n + 1); - xml->addpar("mag", Phmag[n]); - xml->addpar("phase", Phphase[n]); - xml->endbranch(); - } - xml->endbranch(); - - if(Pcurrentbasefunc == 127) { - REALTYPE max = 0.0; - - for(int i = 0; i < OSCIL_SIZE / 2; i++) { - if(max < fabs(basefuncFFTfreqs.c[i])) - max = fabs(basefuncFFTfreqs.c[i]); - if(max < fabs(basefuncFFTfreqs.s[i])) - max = fabs(basefuncFFTfreqs.s[i]); - } - if(max < 0.00000001) - max = 1.0; - - xml->beginbranch("BASE_FUNCTION"); - for(int i = 1; i < OSCIL_SIZE / 2; i++) { - REALTYPE xc = basefuncFFTfreqs.c[i] / max; - REALTYPE xs = basefuncFFTfreqs.s[i] / max; - if((fabs(xs) > 0.00001) && (fabs(xs) > 0.00001)) { - xml->beginbranch("BF_HARMONIC", i); - xml->addparreal("cos", xc); - xml->addparreal("sin", xs); - xml->endbranch(); - } - } - xml->endbranch(); - } -} - - -void OscilGen::getfromXML(XMLwrapper *xml) -{ - Phmagtype = xml->getpar127("harmonic_mag_type", Phmagtype); - - Pcurrentbasefunc = xml->getpar127("base_function", Pcurrentbasefunc); - Pbasefuncpar = xml->getpar127("base_function_par", Pbasefuncpar); - - Pbasefuncmodulation = xml->getpar127("base_function_modulation", - Pbasefuncmodulation); - Pbasefuncmodulationpar1 = xml->getpar127("base_function_modulation_par1", - Pbasefuncmodulationpar1); - Pbasefuncmodulationpar2 = xml->getpar127("base_function_modulation_par2", - Pbasefuncmodulationpar2); - Pbasefuncmodulationpar3 = xml->getpar127("base_function_modulation_par3", - Pbasefuncmodulationpar3); - - Pmodulation = xml->getpar127("modulation", Pmodulation); - Pmodulationpar1 = xml->getpar127("modulation_par1", - Pmodulationpar1); - Pmodulationpar2 = xml->getpar127("modulation_par2", - Pmodulationpar2); - Pmodulationpar3 = xml->getpar127("modulation_par3", - Pmodulationpar3); - - Pwaveshaping = xml->getpar127("wave_shaping", Pwaveshaping); - Pwaveshapingfunction = xml->getpar127("wave_shaping_function", - Pwaveshapingfunction); - - Pfiltertype = xml->getpar127("filter_type", Pfiltertype); - Pfilterpar1 = xml->getpar127("filter_par1", Pfilterpar1); - Pfilterpar2 = xml->getpar127("filter_par2", Pfilterpar2); - Pfilterbeforews = xml->getpar127("filter_before_wave_shaping", - Pfilterbeforews); - - Psatype = xml->getpar127("spectrum_adjust_type", Psatype); - Psapar = xml->getpar127("spectrum_adjust_par", Psapar); - - Prand = xml->getpar127("rand", Prand); - Pamprandtype = xml->getpar127("amp_rand_type", Pamprandtype); - Pamprandpower = xml->getpar127("amp_rand_power", Pamprandpower); - - Pharmonicshift = xml->getpar("harmonic_shift", - Pharmonicshift, - -64, - 64); - Pharmonicshiftfirst = xml->getparbool("harmonic_shift_first", - Pharmonicshiftfirst); - - Padaptiveharmonics = xml->getpar("adaptive_harmonics", - Padaptiveharmonics, - 0, - 127); - Padaptiveharmonicsbasefreq = xml->getpar( - "adaptive_harmonics_base_frequency", - Padaptiveharmonicsbasefreq, - 0, - 255); - Padaptiveharmonicspower = xml->getpar("adaptive_harmonics_power", - Padaptiveharmonicspower, - 0, - 200); - - - if(xml->enterbranch("HARMONICS")) { - Phmag[0] = 64; - Phphase[0] = 64; - for(int n = 0; n < MAX_AD_HARMONICS; n++) { - if(xml->enterbranch("HARMONIC", n + 1) == 0) - continue; - Phmag[n] = xml->getpar127("mag", 64); - Phphase[n] = xml->getpar127("phase", 64); - xml->exitbranch(); - } - xml->exitbranch(); - } - - if(Pcurrentbasefunc != 0) - changebasefunction(); - - - if(xml->enterbranch("BASE_FUNCTION")) { - for(int i = 1; i < OSCIL_SIZE / 2; i++) { - if(xml->enterbranch("BF_HARMONIC", i)) { - basefuncFFTfreqs.c[i] = xml->getparreal("cos", 0.0); - basefuncFFTfreqs.s[i] = xml->getparreal("sin", 0.0); - xml->exitbranch(); - } - } - xml->exitbranch(); - - REALTYPE max = 0.0; - - basefuncFFTfreqs.c[0] = 0.0; - for(int i = 0; i < OSCIL_SIZE / 2; i++) { - if(max < fabs(basefuncFFTfreqs.c[i])) - max = fabs(basefuncFFTfreqs.c[i]); - if(max < fabs(basefuncFFTfreqs.s[i])) - max = fabs(basefuncFFTfreqs.s[i]); - } - if(max < 0.00000001) - max = 1.0; - - for(int i = 0; i < OSCIL_SIZE / 2; i++) { - if(basefuncFFTfreqs.c[i]) - basefuncFFTfreqs.c[i] /= max; - if(basefuncFFTfreqs.s[i]) - basefuncFFTfreqs.s[i] /= max; - } - } -} - diff --git a/plugins/zynaddsubfx/src/Synth/OscilGen.h b/plugins/zynaddsubfx/src/Synth/OscilGen.h deleted file mode 100644 index 5c08d629f..000000000 --- a/plugins/zynaddsubfx/src/Synth/OscilGen.h +++ /dev/null @@ -1,183 +0,0 @@ -/* - ZynAddSubFX - a software synthesizer - - OscilGen.h - Waveform generator for ADnote - Copyright (C) 2002-2005 Nasca Octavian Paul - Author: Nasca Octavian Paul - - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License - as published by the Free Software Foundation. - - 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 (version 2 or later) for more details. - - You should have received a copy of the GNU General Public License (version 2) - along with this program; if not, write to the Free Software Foundation, - Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -*/ - -#ifndef OSCIL_GEN_H -#define OSCIL_GEN_H - -#include "../globals.h" -#include "../Misc/XMLwrapper.h" -#include "Resonance.h" -#include "../DSP/FFTwrapper.h" -#include "../Params/Presets.h" - -class OscilGen:public Presets -{ - public: - OscilGen(FFTwrapper *fft_, Resonance *res_); - ~OscilGen(); - - /**computes the full spectrum of oscil from harmonics,phases and basefunc*/ - void prepare(); - - /**do the antialiasing(cut off higher freqs.),apply randomness and do a IFFT*/ - short get(REALTYPE *smps, REALTYPE freqHz); //returns where should I start getting samples, used in block type randomness - short get(REALTYPE *smps, REALTYPE freqHz, int resonance); - //if freqHz is smaller than 0, return the "un-randomized" sample for UI - - void getbasefunction(REALTYPE *smps); - - //called by UI - void getspectrum(int n, REALTYPE *spc, int what); //what=0 pt. oscil,1 pt. basefunc - void getcurrentbasefunction(REALTYPE *smps); - /**convert oscil to base function*/ - void useasbase(); - - void add2XML(XMLwrapper *xml); - void defaults(); - void getfromXML(XMLwrapper *xml); - - void convert2sine(int magtype); - - //Parameters - - /** - * The hmag and hphase starts counting from 0, so the first harmonic(1) has the index 0, - * 2-nd harmonic has index 1, ..the 128 harminic has index 127 - */ - unsigned char Phmag[MAX_AD_HARMONICS], Phphase[MAX_AD_HARMONICS]; //the MIDI parameters for mag. and phases - - - /**The Type of magnitude: - * 0 - Linear - * 1 - dB scale (-40) - * 2 - dB scale (-60) - * 3 - dB scale (-80) - * 4 - dB scale (-100)*/ - unsigned char Phmagtype; - - unsigned char Pcurrentbasefunc; //The base function used - 0=sin, 1=... - unsigned char Pbasefuncpar; //the parameter of the base function - - unsigned char Pbasefuncmodulation; //what modulation is applied to the basefunc - unsigned char Pbasefuncmodulationpar1, Pbasefuncmodulationpar2, - Pbasefuncmodulationpar3; //the parameter of the base function modulation - - /*the Randomness: - 64=no randomness - 63..0 - block type randomness - 0 is maximum - 65..127 - each harmonic randomness - 127 is maximum*/ - unsigned char Prand; - unsigned char Pwaveshaping, Pwaveshapingfunction; - unsigned char Pfiltertype, Pfilterpar1, Pfilterpar2; - unsigned char Pfilterbeforews; - unsigned char Psatype, Psapar; //spectrum adjust - - unsigned char Pamprandpower, Pamprandtype; //amplitude randomness - int Pharmonicshift; //how the harmonics are shifted - int Pharmonicshiftfirst; //if the harmonic shift is done before waveshaping and filter - - unsigned char Padaptiveharmonics; //the adaptive harmonics status (off=0,on=1,etc..) - unsigned char Padaptiveharmonicsbasefreq; //the base frequency of the adaptive harmonic (30..3000Hz) - unsigned char Padaptiveharmonicspower; //the strength of the effect (0=off,100=full) - unsigned char Padaptiveharmonicspar; //the parameters in 2,3,4.. modes of adaptive harmonics - - unsigned char Pmodulation; //what modulation is applied to the oscil - unsigned char Pmodulationpar1, Pmodulationpar2, Pmodulationpar3; //the parameter of the parameters - - - //makes a new random seed for Amplitude Randomness - //this should be called every note on event - void newrandseed(unsigned int randseed); - - bool ADvsPAD; //if it is used by ADsynth or by PADsynth - - private: - //This array stores some termporary data and it has OSCIL_SIZE elements - REALTYPE *tmpsmps; - FFTFREQS outoscilFFTfreqs; - - REALTYPE hmag[MAX_AD_HARMONICS], hphase[MAX_AD_HARMONICS]; //the magnituides and the phases of the sine/nonsine harmonics -// private: - FFTwrapper *fft; - //computes the basefunction and make the FFT; newbasefunc<0 = same basefunc - void changebasefunction(); - //Waveshaping - void waveshape(); - - //Filter the oscillator accotding to Pfiltertype and Pfilterpar - void oscilfilter(); - - //Adjust the spectrum - void spectrumadjust(); - - //Shift the harmonics - void shiftharmonics(); - - //Do the oscil modulation stuff - void modulation(); - - //Do the adaptive harmonic stuff - void adaptiveharmonic(FFTFREQS f, REALTYPE freq); - - //Do the adaptive harmonic postprocessing (2n+1,2xS,2xA,etc..) - //this function is called even for the user interface - //this can be called for the sine and components, and for the spectrum - //(that's why the sine and cosine components should be processed with a separate call) - void adaptiveharmonicpostprocess(REALTYPE *f, int size); - - //Basic/base functions (Functiile De Baza) - REALTYPE basefunc_pulse(REALTYPE x, REALTYPE a); - REALTYPE basefunc_saw(REALTYPE x, REALTYPE a); - REALTYPE basefunc_triangle(REALTYPE x, REALTYPE a); - REALTYPE basefunc_power(REALTYPE x, REALTYPE a); - REALTYPE basefunc_gauss(REALTYPE x, REALTYPE a); - REALTYPE basefunc_diode(REALTYPE x, REALTYPE a); - REALTYPE basefunc_abssine(REALTYPE x, REALTYPE a); - REALTYPE basefunc_pulsesine(REALTYPE x, REALTYPE a); - REALTYPE basefunc_stretchsine(REALTYPE x, REALTYPE a); - REALTYPE basefunc_chirp(REALTYPE x, REALTYPE a); - REALTYPE basefunc_absstretchsine(REALTYPE x, REALTYPE a); - REALTYPE basefunc_chebyshev(REALTYPE x, REALTYPE a); - REALTYPE basefunc_sqr(REALTYPE x, REALTYPE a); - - //Internal Data - unsigned char oldbasefunc, oldbasepar, oldhmagtype, - oldwaveshapingfunction, oldwaveshaping; - int oldfilterpars, oldsapars, oldbasefuncmodulation, - oldbasefuncmodulationpar1, oldbasefuncmodulationpar2, - oldbasefuncmodulationpar3, oldharmonicshift; - int oldmodulation, oldmodulationpar1, oldmodulationpar2, - oldmodulationpar3; - - - FFTFREQS basefuncFFTfreqs; //Base Function Frequencies - FFTFREQS oscilFFTfreqs; //Oscillator Frequencies - this is different than the hamonics set-up by the user, it may contains time-domain data if the antialiasing is turned off - int oscilprepared; //1 if the oscil is prepared, 0 if it is not prepared and is need to call ::prepare() before ::get() - - Resonance *res; - - unsigned int randseed; -}; - - -#endif - diff --git a/plugins/zynaddsubfx/src/Synth/PADnote.cpp b/plugins/zynaddsubfx/src/Synth/PADnote.cpp deleted file mode 100644 index 699085f8c..000000000 --- a/plugins/zynaddsubfx/src/Synth/PADnote.cpp +++ /dev/null @@ -1,614 +0,0 @@ -/* - ZynAddSubFX - a software synthesizer - - PADnote.cpp - The "pad" synthesizer - Copyright (C) 2002-2005 Nasca Octavian Paul - Author: Nasca Octavian Paul - - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License - as published by the Free Software Foundation. - - 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 (version 2 or later) for more details. - - You should have received a copy of the GNU General Public License (version 2) - along with this program; if not, write to the Free Software Foundation, - Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ -#include -#include "PADnote.h" -#include "../Misc/Config.h" - -PADnote::PADnote(PADnoteParameters *parameters, - Controller *ctl_, - REALTYPE freq, - REALTYPE velocity, - int portamento_, - int midinote, - bool besilent) -{ - ready = 0; - - // Initialise some legato-specific vars - Legato.msg = LM_Norm; - Legato.fade.length = (int)(SAMPLE_RATE * 0.005); // 0.005 seems ok. - if(Legato.fade.length < 1) - Legato.fade.length = 1; // (if something's fishy) - Legato.fade.step = (1.0 / Legato.fade.length); - Legato.decounter = -10; - Legato.param.freq = freq; - Legato.param.vel = velocity; - Legato.param.portamento = portamento_; - Legato.param.midinote = midinote; - Legato.silent = besilent; - - pars = parameters; - portamento = portamento_; - ctl = ctl_; - this->velocity = velocity; - finished_ = false; - - - if(pars->Pfixedfreq == 0) - basefreq = freq; - else { - basefreq = 440.0; - int fixedfreqET = pars->PfixedfreqET; - if(fixedfreqET != 0) { //if the frequency varies according the keyboard note - REALTYPE tmp = - (midinote - - 69.0) / 12.0 * (pow(2.0, (fixedfreqET - 1) / 63.0) - 1.0); - if(fixedfreqET <= 64) - basefreq *= pow(2.0, tmp); - else - basefreq *= pow(3.0, tmp); - } - } - - firsttime = true; - released = false; - realfreq = basefreq; - NoteGlobalPar.Detune = getdetune(pars->PDetuneType, - pars->PCoarseDetune, pars->PDetune); - - - //find out the closest note - REALTYPE logfreq = log(basefreq * pow(2.0, NoteGlobalPar.Detune / 1200.0)); - REALTYPE mindist = fabs(logfreq - log(pars->sample[0].basefreq + 0.0001)); - nsample = 0; - for(int i = 1; i < PAD_MAX_SAMPLES; i++) { - if(pars->sample[i].smp == NULL) - break; - REALTYPE dist = fabs(logfreq - log(pars->sample[i].basefreq + 0.0001)); -// printf("(mindist=%g) %i %g %g\n",mindist,i,dist,pars->sample[i].basefreq); - - if(dist < mindist) { - nsample = i; - mindist = dist; - } - } - - int size = pars->sample[nsample].size; - if(size == 0) - size = 1; - - - poshi_l = (int)(RND * (size - 1)); - if(pars->PStereo != 0) - poshi_r = (poshi_l + size / 2) % size; - else - poshi_r = poshi_l; - poslo = 0.0; - - tmpwave = new REALTYPE [SOUND_BUFFER_SIZE]; - - - - if(pars->PPanning == 0) - NoteGlobalPar.Panning = RND; - else - NoteGlobalPar.Panning = pars->PPanning / 128.0; - - NoteGlobalPar.FilterCenterPitch = pars->GlobalFilter->getfreq() //center freq - + pars->PFilterVelocityScale / 127.0 - * 6.0 //velocity sensing - * (VelF(velocity, - pars-> - PFilterVelocityScaleFunction) - 1); - - if(pars->PPunchStrength != 0) { - NoteGlobalPar.Punch.Enabled = 1; - NoteGlobalPar.Punch.t = 1.0; //start from 1.0 and to 0.0 - NoteGlobalPar.Punch.initialvalue = - ((pow(10, 1.5 * pars->PPunchStrength / 127.0) - 1.0) - * VelF(velocity, - pars->PPunchVelocitySensing)); - REALTYPE time = pow(10, 3.0 * pars->PPunchTime / 127.0) / 10000.0; //0.1 .. 100 ms - REALTYPE stretch = pow(440.0 / freq, pars->PPunchStretch / 64.0); - NoteGlobalPar.Punch.dt = 1.0 / (time * SAMPLE_RATE * stretch); - } - else - NoteGlobalPar.Punch.Enabled = 0; - - - - NoteGlobalPar.FreqEnvelope = new Envelope(pars->FreqEnvelope, basefreq); - NoteGlobalPar.FreqLfo = new LFO(pars->FreqLfo, basefreq); - - NoteGlobalPar.AmpEnvelope = new Envelope(pars->AmpEnvelope, basefreq); - NoteGlobalPar.AmpLfo = new LFO(pars->AmpLfo, basefreq); - - NoteGlobalPar.Volume = 4.0 * pow(0.1, 3.0 * (1.0 - pars->PVolume / 96.0)) //-60 dB .. 0 dB - * VelF(velocity, pars->PAmpVelocityScaleFunction); //velocity sensing - - NoteGlobalPar.AmpEnvelope->envout_dB(); //discard the first envelope output - globaloldamplitude = globalnewamplitude = NoteGlobalPar.Volume - * NoteGlobalPar.AmpEnvelope-> - envout_dB() - * NoteGlobalPar.AmpLfo->amplfoout(); - - NoteGlobalPar.GlobalFilterL = new Filter(pars->GlobalFilter); - NoteGlobalPar.GlobalFilterR = new Filter(pars->GlobalFilter); - - NoteGlobalPar.FilterEnvelope = new Envelope(pars->FilterEnvelope, - basefreq); - NoteGlobalPar.FilterLfo = new LFO(pars->FilterLfo, basefreq); - NoteGlobalPar.FilterQ = pars->GlobalFilter->getq(); - NoteGlobalPar.FilterFreqTracking = pars->GlobalFilter->getfreqtracking( - basefreq); - - ready = 1; ///sa il pun pe asta doar cand e chiar gata - - if(parameters->sample[nsample].smp == NULL) { - finished_ = true; - return; - } -} - - -// PADlegatonote: This function is (mostly) a copy of PADnote(...) -// with some lines removed so that it only alter the already playing -// note (to perform legato). It is possible I left stuff that is not -// required for this. -void PADnote::PADlegatonote(REALTYPE freq, - REALTYPE velocity, - int portamento_, - int midinote, - bool externcall) -{ - PADnoteParameters *parameters = pars; - //Controller *ctl_=ctl; - - // Manage legato stuff - if(externcall) - Legato.msg = LM_Norm; - if(Legato.msg != LM_CatchUp) { - Legato.lastfreq = Legato.param.freq; - Legato.param.freq = freq; - Legato.param.vel = velocity; - Legato.param.portamento = portamento_; - Legato.param.midinote = midinote; - if(Legato.msg == LM_Norm) { - if(Legato.silent) { - Legato.fade.m = 0.0; - Legato.msg = LM_FadeIn; - } - else { - Legato.fade.m = 1.0; - Legato.msg = LM_FadeOut; - return; - } - } - if(Legato.msg == LM_ToNorm) - Legato.msg = LM_Norm; - } - - portamento = portamento_; - this->velocity = velocity; - finished_ = false; - - if(pars->Pfixedfreq == 0) - basefreq = freq; - else { - basefreq = 440.0; - int fixedfreqET = pars->PfixedfreqET; - if(fixedfreqET != 0) { //if the frequency varies according the keyboard note - REALTYPE tmp = - (midinote - - 69.0) / 12.0 * (pow(2.0, (fixedfreqET - 1) / 63.0) - 1.0); - if(fixedfreqET <= 64) - basefreq *= pow(2.0, tmp); - else - basefreq *= pow(3.0, tmp); - } - } - - released = false; - realfreq = basefreq; - - getdetune(pars->PDetuneType, pars->PCoarseDetune, pars->PDetune); - - - //find out the closest note - REALTYPE logfreq = log(basefreq * pow(2.0, NoteGlobalPar.Detune / 1200.0)); - REALTYPE mindist = fabs(logfreq - log(pars->sample[0].basefreq + 0.0001)); - nsample = 0; - for(int i = 1; i < PAD_MAX_SAMPLES; i++) { - if(pars->sample[i].smp == NULL) - break; - REALTYPE dist = fabs(logfreq - log(pars->sample[i].basefreq + 0.0001)); - - if(dist < mindist) { - nsample = i; - mindist = dist; - } - } - - int size = pars->sample[nsample].size; - if(size == 0) - size = 1; - - if(pars->PPanning == 0) - NoteGlobalPar.Panning = RND; - else - NoteGlobalPar.Panning = pars->PPanning / 128.0; - - NoteGlobalPar.FilterCenterPitch = pars->GlobalFilter->getfreq() //center freq - + pars->PFilterVelocityScale / 127.0 - * 6.0 //velocity sensing - * (VelF(velocity, - pars-> - PFilterVelocityScaleFunction) - 1); - - - NoteGlobalPar.Volume = 4.0 * pow(0.1, 3.0 * (1.0 - pars->PVolume / 96.0)) //-60 dB .. 0 dB - * VelF(velocity, pars->PAmpVelocityScaleFunction); //velocity sensing - - NoteGlobalPar.AmpEnvelope->envout_dB(); //discard the first envelope output - globaloldamplitude = globalnewamplitude = NoteGlobalPar.Volume - * NoteGlobalPar.AmpEnvelope-> - envout_dB() - * NoteGlobalPar.AmpLfo->amplfoout(); - - NoteGlobalPar.FilterQ = pars->GlobalFilter->getq(); - NoteGlobalPar.FilterFreqTracking = pars->GlobalFilter->getfreqtracking( - basefreq); - - - if(parameters->sample[nsample].smp == NULL) { - finished_ = true; - return; - } - - // End of the PADlegatonote function. -} - - -PADnote::~PADnote() -{ - delete (NoteGlobalPar.FreqEnvelope); - delete (NoteGlobalPar.FreqLfo); - delete (NoteGlobalPar.AmpEnvelope); - delete (NoteGlobalPar.AmpLfo); - delete (NoteGlobalPar.GlobalFilterL); - delete (NoteGlobalPar.GlobalFilterR); - delete (NoteGlobalPar.FilterEnvelope); - delete (NoteGlobalPar.FilterLfo); - delete [] tmpwave; -} - - -inline void PADnote::fadein(REALTYPE *smps) -{ - int zerocrossings = 0; - for(int i = 1; i < SOUND_BUFFER_SIZE; i++) - if((smps[i - 1] < 0.0) && (smps[i] > 0.0)) - zerocrossings++; //this is only the possitive crossings - - REALTYPE tmp = (SOUND_BUFFER_SIZE - 1.0) / (zerocrossings + 1) / 3.0; - if(tmp < 8.0) - tmp = 8.0; - - int n; - F2I(tmp, n); //how many samples is the fade-in - if(n > SOUND_BUFFER_SIZE) - n = SOUND_BUFFER_SIZE; - for(int i = 0; i < n; i++) { //fade-in - REALTYPE tmp = 0.5 - cos((REALTYPE)i / (REALTYPE) n * PI) * 0.5; - smps[i] *= tmp; - } -} - - -void PADnote::computecurrentparameters() -{ - REALTYPE globalpitch, globalfilterpitch; - globalpitch = 0.01 * (NoteGlobalPar.FreqEnvelope->envout() - + NoteGlobalPar.FreqLfo->lfoout() - * ctl->modwheel.relmod + NoteGlobalPar.Detune); - globaloldamplitude = globalnewamplitude; - globalnewamplitude = NoteGlobalPar.Volume - * NoteGlobalPar.AmpEnvelope->envout_dB() - * NoteGlobalPar.AmpLfo->amplfoout(); - - globalfilterpitch = NoteGlobalPar.FilterEnvelope->envout() - + NoteGlobalPar.FilterLfo->lfoout() - + NoteGlobalPar.FilterCenterPitch; - - REALTYPE tmpfilterfreq = globalfilterpitch + ctl->filtercutoff.relfreq - + NoteGlobalPar.FilterFreqTracking; - - tmpfilterfreq = NoteGlobalPar.GlobalFilterL->getrealfreq(tmpfilterfreq); - - REALTYPE globalfilterq = NoteGlobalPar.FilterQ * ctl->filterq.relq; - NoteGlobalPar.GlobalFilterL->setfreq_and_q(tmpfilterfreq, globalfilterq); - NoteGlobalPar.GlobalFilterR->setfreq_and_q(tmpfilterfreq, globalfilterq); - - //compute the portamento, if it is used by this note - REALTYPE portamentofreqrap = 1.0; - if(portamento != 0) { //this voice use portamento - portamentofreqrap = ctl->portamento.freqrap; - if(ctl->portamento.used == 0) //the portamento has finished - portamento = 0; //this note is no longer "portamented" - ; - } - - realfreq = basefreq * portamentofreqrap - * pow(2.0, globalpitch / 12.0) * ctl->pitchwheel.relfreq; -} - - -int PADnote::Compute_Linear(REALTYPE *outl, - REALTYPE *outr, - int freqhi, - REALTYPE freqlo) -{ - REALTYPE *smps = pars->sample[nsample].smp; - if(smps == NULL) { - finished_ = true; - return 1; - } - int size = pars->sample[nsample].size; - for(int i = 0; i < SOUND_BUFFER_SIZE; i++) { - poshi_l += freqhi; - poshi_r += freqhi; - poslo += freqlo; - if(poslo >= 1.0) { - poshi_l += 1; - poshi_r += 1; - poslo -= 1.0; - } - if(poshi_l >= size) - poshi_l %= size; - if(poshi_r >= size) - poshi_r %= size; - - outl[i] = smps[poshi_l] * (1.0 - poslo) + smps[poshi_l + 1] * poslo; - outr[i] = smps[poshi_r] * (1.0 - poslo) + smps[poshi_r + 1] * poslo; - } - return 1; -} -int PADnote::Compute_Cubic(REALTYPE *outl, - REALTYPE *outr, - int freqhi, - REALTYPE freqlo) -{ - REALTYPE *smps = pars->sample[nsample].smp; - if(smps == NULL) { - finished_ = true; - return 1; - } - int size = pars->sample[nsample].size; - REALTYPE xm1, x0, x1, x2, a, b, c; - for(int i = 0; i < SOUND_BUFFER_SIZE; i++) { - poshi_l += freqhi; - poshi_r += freqhi; - poslo += freqlo; - if(poslo >= 1.0) { - poshi_l += 1; - poshi_r += 1; - poslo -= 1.0; - } - if(poshi_l >= size) - poshi_l %= size; - if(poshi_r >= size) - poshi_r %= size; - - - //left - xm1 = smps[poshi_l]; - x0 = smps[poshi_l + 1]; - x1 = smps[poshi_l + 2]; - x2 = smps[poshi_l + 3]; - a = (3.0 * (x0 - x1) - xm1 + x2) * 0.5; - b = 2.0 * x1 + xm1 - (5.0 * x0 + x2) * 0.5; - c = (x1 - xm1) * 0.5; - outl[i] = (((a * poslo) + b) * poslo + c) * poslo + x0; - //right - xm1 = smps[poshi_r]; - x0 = smps[poshi_r + 1]; - x1 = smps[poshi_r + 2]; - x2 = smps[poshi_r + 3]; - a = (3.0 * (x0 - x1) - xm1 + x2) * 0.5; - b = 2.0 * x1 + xm1 - (5.0 * x0 + x2) * 0.5; - c = (x1 - xm1) * 0.5; - outr[i] = (((a * poslo) + b) * poslo + c) * poslo + x0; - } - return 1; -} - - -int PADnote::noteout(REALTYPE *outl, REALTYPE *outr) -{ - computecurrentparameters(); - REALTYPE *smps = pars->sample[nsample].smp; - if(smps == NULL) { - for(int i = 0; i < SOUND_BUFFER_SIZE; i++) { - outl[i] = 0.0; - outr[i] = 0.0; - } - return 1; - } - REALTYPE smpfreq = pars->sample[nsample].basefreq; - - - REALTYPE freqrap = realfreq / smpfreq; - int freqhi = (int) (floor(freqrap)); - REALTYPE freqlo = freqrap - floor(freqrap); - - - if(config.cfg.Interpolation) - Compute_Cubic(outl, outr, freqhi, freqlo); - else - Compute_Linear(outl, outr, freqhi, freqlo); - - - if(firsttime) { - fadein(outl); - fadein(outr); - firsttime = false; - } - - NoteGlobalPar.GlobalFilterL->filterout(outl); - NoteGlobalPar.GlobalFilterR->filterout(outr); - - //Apply the punch - if(NoteGlobalPar.Punch.Enabled != 0) { - for(int i = 0; i < SOUND_BUFFER_SIZE; i++) { - REALTYPE punchamp = NoteGlobalPar.Punch.initialvalue - * NoteGlobalPar.Punch.t + 1.0; - outl[i] *= punchamp; - outr[i] *= punchamp; - NoteGlobalPar.Punch.t -= NoteGlobalPar.Punch.dt; - if(NoteGlobalPar.Punch.t < 0.0) { - NoteGlobalPar.Punch.Enabled = 0; - break; - } - } - } - - if(ABOVE_AMPLITUDE_THRESHOLD(globaloldamplitude, globalnewamplitude)) { - // Amplitude Interpolation - for(int i = 0; i < SOUND_BUFFER_SIZE; i++) { - REALTYPE tmpvol = INTERPOLATE_AMPLITUDE(globaloldamplitude, - globalnewamplitude, - i, - SOUND_BUFFER_SIZE); - outl[i] *= tmpvol * NoteGlobalPar.Panning; - outr[i] *= tmpvol * (1.0 - NoteGlobalPar.Panning); - } - } - else { - for(int i = 0; i < SOUND_BUFFER_SIZE; i++) { - outl[i] *= globalnewamplitude * NoteGlobalPar.Panning; - outr[i] *= globalnewamplitude * (1.0 - NoteGlobalPar.Panning); - } - } - - - // Apply legato-specific sound signal modifications - if(Legato.silent) // Silencer - if(Legato.msg != LM_FadeIn) - for(int i = 0; i < SOUND_BUFFER_SIZE; i++) { - outl[i] = 0.0; - outr[i] = 0.0; - } - switch(Legato.msg) { - case LM_CatchUp: // Continue the catch-up... - if(Legato.decounter == -10) - Legato.decounter = Legato.fade.length; - for(int i = 0; i < SOUND_BUFFER_SIZE; i++) { //Yea, could be done without the loop... - Legato.decounter--; - if(Legato.decounter < 1) { - // Catching-up done, we can finally set - // the note to the actual parameters. - Legato.decounter = -10; - Legato.msg = LM_ToNorm; - PADlegatonote(Legato.param.freq, - Legato.param.vel, - Legato.param.portamento, - Legato.param.midinote, - false); - break; - } - } - break; - case LM_FadeIn: // Fade-in - if(Legato.decounter == -10) - Legato.decounter = Legato.fade.length; - Legato.silent = false; - for(int i = 0; i < SOUND_BUFFER_SIZE; i++) { - Legato.decounter--; - if(Legato.decounter < 1) { - Legato.decounter = -10; - Legato.msg = LM_Norm; - break; - } - Legato.fade.m += Legato.fade.step; - outl[i] *= Legato.fade.m; - outr[i] *= Legato.fade.m; - } - break; - case LM_FadeOut: // Fade-out, then set the catch-up - if(Legato.decounter == -10) - Legato.decounter = Legato.fade.length; - for(int i = 0; i < SOUND_BUFFER_SIZE; i++) { - Legato.decounter--; - if(Legato.decounter < 1) { - for(int j = i; j < SOUND_BUFFER_SIZE; j++) { - outl[j] = 0.0; - outr[j] = 0.0; - } - Legato.decounter = -10; - Legato.silent = true; - // Fading-out done, now set the catch-up : - Legato.decounter = Legato.fade.length; - Legato.msg = LM_CatchUp; - REALTYPE catchupfreq = Legato.param.freq - * (Legato.param.freq / Legato.lastfreq); //This freq should make this now silent note to catch-up (or should I say resync ?) with the heard note for the same length it stayed at the previous freq during the fadeout. - PADlegatonote(catchupfreq, - Legato.param.vel, - Legato.param.portamento, - Legato.param.midinote, - false); - break; - } - Legato.fade.m -= Legato.fade.step; - outl[i] *= Legato.fade.m; - outr[i] *= Legato.fade.m; - } - break; - default: - break; - } - - - // Check if the global amplitude is finished. - // If it does, disable the note - if(NoteGlobalPar.AmpEnvelope->finished() != 0) { - for(int i = 0; i < SOUND_BUFFER_SIZE; i++) { //fade-out - REALTYPE tmp = 1.0 - (REALTYPE)i / (REALTYPE)SOUND_BUFFER_SIZE; - outl[i] *= tmp; - outr[i] *= tmp; - } - finished_ = 1; - } - - return 1; -} - -int PADnote::finished() -{ - return finished_; -} - -void PADnote::relasekey() -{ - NoteGlobalPar.FreqEnvelope->relasekey(); - NoteGlobalPar.FilterEnvelope->relasekey(); - NoteGlobalPar.AmpEnvelope->relasekey(); -} - diff --git a/plugins/zynaddsubfx/src/Synth/PADnote.h b/plugins/zynaddsubfx/src/Synth/PADnote.h deleted file mode 100644 index 956353218..000000000 --- a/plugins/zynaddsubfx/src/Synth/PADnote.h +++ /dev/null @@ -1,143 +0,0 @@ -/* - ZynAddSubFX - a software synthesizer - - PADnote.h - The "pad" synthesizer - Copyright (C) 2002-2005 Nasca Octavian Paul - Author: Nasca Octavian Paul - - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License - as published by the Free Software Foundation. - - 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 (version 2 or later) for more details. - - You should have received a copy of the GNU General Public License (version 2) - along with this program; if not, write to the Free Software Foundation, - Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ -#ifndef PAD_NOTE_H -#define PAD_NOTE_H - -#include "../globals.h" -#include "../Params/PADnoteParameters.h" -#include "../Params/Controller.h" -#include "Envelope.h" -#include "LFO.h" -#include "../DSP/Filter.h" -#include "../Params/Controller.h" - -/**The "pad" synthesizer*/ -class PADnote -{ - public: - PADnote(PADnoteParameters *parameters, - Controller *ctl_, - REALTYPE freq, - REALTYPE velocity, - int portamento_, - int midinote, - bool besilent); - ~PADnote(); - - void PADlegatonote(REALTYPE freq, - REALTYPE velocity, - int portamento_, - int midinote, - bool externcall); - - int noteout(REALTYPE *outl, REALTYPE *outr); - int finished(); - void relasekey(); - - int ready; - - private: - void fadein(REALTYPE *smps); - void computecurrentparameters(); - bool finished_; - PADnoteParameters *pars; - - int poshi_l, poshi_r; - REALTYPE poslo; - - REALTYPE basefreq; - bool firsttime, released; - - int nsample, portamento; - - int Compute_Linear(REALTYPE *outl, - REALTYPE *outr, - int freqhi, - REALTYPE freqlo); - int Compute_Cubic(REALTYPE *outl, - REALTYPE *outr, - int freqhi, - REALTYPE freqlo); - - - struct { - /****************************************** - * FREQUENCY GLOBAL PARAMETERS * - ******************************************/ - REALTYPE Detune; //cents - - Envelope *FreqEnvelope; - LFO *FreqLfo; - - /******************************************** - * AMPLITUDE GLOBAL PARAMETERS * - ********************************************/ - REALTYPE Volume; // [ 0 .. 1 ] - - REALTYPE Panning; // [ 0 .. 1 ] - - Envelope *AmpEnvelope; - LFO *AmpLfo; - - struct { - int Enabled; - REALTYPE initialvalue, dt, t; - } Punch; - - /****************************************** - * FILTER GLOBAL PARAMETERS * - ******************************************/ - Filter *GlobalFilterL, *GlobalFilterR; - - REALTYPE FilterCenterPitch; //octaves - REALTYPE FilterQ; - REALTYPE FilterFreqTracking; - - Envelope *FilterEnvelope; - - LFO *FilterLfo; - } NoteGlobalPar; - - - REALTYPE globaloldamplitude, globalnewamplitude, velocity, realfreq; - REALTYPE *tmpwave; - Controller *ctl; - - // Legato vars - struct { - bool silent; - REALTYPE lastfreq; - LegatoMsg msg; - int decounter; - struct { // Fade In/Out vars - int length; - REALTYPE m, step; - } fade; - struct { // Note parameters - REALTYPE freq, vel; - int portamento, midinote; - } param; - } Legato; -}; - - -#endif - diff --git a/plugins/zynaddsubfx/src/Synth/Resonance.cpp b/plugins/zynaddsubfx/src/Synth/Resonance.cpp deleted file mode 100644 index 2bf8c633c..000000000 --- a/plugins/zynaddsubfx/src/Synth/Resonance.cpp +++ /dev/null @@ -1,282 +0,0 @@ -/* - ZynAddSubFX - a software synthesizer - - Resonance.cpp - Resonance - Copyright (C) 2002-2005 Nasca Octavian Paul - Author: Nasca Octavian Paul - - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License - as published by the Free Software Foundation. - - 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 (version 2 or later) for more details. - - You should have received a copy of the GNU General Public License (version 2) - along with this program; if not, write to the Free Software Foundation, - Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#include -#include -#include "Resonance.h" - - -#include - -Resonance::Resonance():Presets() -{ - setpresettype("Presonance"); - defaults(); -} - -Resonance::~Resonance() -{} - - -void Resonance::defaults() -{ - Penabled = 0; - PmaxdB = 20; - Pcenterfreq = 64; //1 kHz - Poctavesfreq = 64; - Pprotectthefundamental = 0; - ctlcenter = 1.0; - ctlbw = 1.0; - for(int i = 0; i < N_RES_POINTS; i++) - Prespoints[i] = 64; -} - -/* - * Set a point of resonance function with a value - */ -void Resonance::setpoint(int n, unsigned char p) -{ - if((n < 0) || (n >= N_RES_POINTS)) - return; - Prespoints[n] = p; -} - -/* - * Apply the resonance to FFT data - */ -void Resonance::applyres(int n, FFTFREQS fftdata, REALTYPE freq) -{ - if(Penabled == 0) - return; //if the resonance is disabled - REALTYPE sum = 0.0, - l1 = log(getfreqx(0.0) * ctlcenter), - l2 = log(2.0) * getoctavesfreq() * ctlbw; - - for(int i = 0; i < N_RES_POINTS; i++) - if(sum < Prespoints[i]) - sum = Prespoints[i]; - if(sum < 1.0) - sum = 1.0; - - for(int i = 1; i < n; i++) { - REALTYPE x = (log(freq * i) - l1) / l2; //compute where the n-th hamonics fits to the graph - if(x < 0.0) - x = 0.0; - - x *= N_RES_POINTS; - REALTYPE dx = x - floor(x); - x = floor(x); - int kx1 = (int)x; - if(kx1 >= N_RES_POINTS) - kx1 = N_RES_POINTS - 1; - int kx2 = kx1 + 1; - if(kx2 >= N_RES_POINTS) - kx2 = N_RES_POINTS - 1; - REALTYPE y = - (Prespoints[kx1] - * (1.0 - dx) + Prespoints[kx2] * dx) / 127.0 - sum / 127.0; - - y = pow(10.0, y * PmaxdB / 20.0); - - if((Pprotectthefundamental != 0) && (i == 1)) - y = 1.0; - - fftdata.c[i] *= y; - fftdata.s[i] *= y; - } -} - -/* - * Gets the response at the frequency "freq" - */ - -REALTYPE Resonance::getfreqresponse(REALTYPE freq) -{ - REALTYPE l1 = log(getfreqx(0.0) * ctlcenter), - l2 = log(2.0) * getoctavesfreq() * ctlbw, sum = 0.0; - - for(int i = 0; i < N_RES_POINTS; i++) - if(sum < Prespoints[i]) - sum = Prespoints[i]; - if(sum < 1.0) - sum = 1.0; - - REALTYPE x = (log(freq) - l1) / l2; //compute where the n-th hamonics fits to the graph - if(x < 0.0) - x = 0.0; - x *= N_RES_POINTS; - REALTYPE dx = x - floor(x); - x = floor(x); - int kx1 = (int)x; - if(kx1 >= N_RES_POINTS) - kx1 = N_RES_POINTS - 1; - int kx2 = kx1 + 1; - if(kx2 >= N_RES_POINTS) - kx2 = N_RES_POINTS - 1; - REALTYPE result = - (Prespoints[kx1] - * (1.0 - dx) + Prespoints[kx2] * dx) / 127.0 - sum / 127.0; - result = pow(10.0, result * PmaxdB / 20.0); - return result; -} - - -/* - * Smooth the resonance function - */ -void Resonance::smooth() -{ - REALTYPE old = Prespoints[0]; - for(int i = 0; i < N_RES_POINTS; i++) { - old = old * 0.4 + Prespoints[i] * 0.6; - Prespoints[i] = (int) old; - } - old = Prespoints[N_RES_POINTS - 1]; - for(int i = N_RES_POINTS - 1; i > 0; i--) { - old = old * 0.4 + Prespoints[i] * 0.6; - Prespoints[i] = (int) old + 1; - if(Prespoints[i] > 127) - Prespoints[i] = 127; - } -} - -/* - * Randomize the resonance function - */ -void Resonance::randomize(int type) -{ - int r = (int)(RND * 127.0); - for(int i = 0; i < N_RES_POINTS; i++) { - Prespoints[i] = r; - if((RND < 0.1) && (type == 0)) - r = (int)(RND * 127.0); - if((RND < 0.3) && (type == 1)) - r = (int)(RND * 127.0); - if(type == 2) - r = (int)(RND * 127.0); - } - smooth(); -} - -/* - * Interpolate the peaks - */ -void Resonance::interpolatepeaks(int type) -{ - int x1 = 0, y1 = Prespoints[0]; - for(int i = 1; i < N_RES_POINTS; i++) { - if((Prespoints[i] != 64) || (i + 1 == N_RES_POINTS)) { - int y2 = Prespoints[i]; - for(int k = 0; k < i - x1; k++) { - float x = (float) k / (i - x1); - if(type == 0) - x = (1 - cos(x * PI)) * 0.5; - Prespoints[x1 + k] = (int)(y1 * (1.0 - x) + y2 * x); - } - x1 = i; - y1 = y2; - } - } -} - -/* - * Get the frequency from x, where x is [0..1]; x is the x coordinate - */ -REALTYPE Resonance::getfreqx(REALTYPE x) -{ - if(x > 1.0) - x = 1.0; - REALTYPE octf = pow(2.0, getoctavesfreq()); - return getcenterfreq() / sqrt(octf) * pow(octf, x); -} - -/* - * Get the x coordinate from frequency (used by the UI) - */ -REALTYPE Resonance::getfreqpos(REALTYPE freq) -{ - return (log(freq) - log(getfreqx(0.0))) / log(2.0) / getoctavesfreq(); -} - -/* - * Get the center frequency of the resonance graph - */ -REALTYPE Resonance::getcenterfreq() -{ - return 10000.0 * pow(10, -(1.0 - Pcenterfreq / 127.0) * 2.0); -} - -/* - * Get the number of octave that the resonance functions applies to - */ -REALTYPE Resonance::getoctavesfreq() -{ - return 0.25 + 10.0 * Poctavesfreq / 127.0; -} - -void Resonance::sendcontroller(MidiControllers ctl, REALTYPE par) -{ - if(ctl == C_resonance_center) - ctlcenter = par; - else - ctlbw = par; -} - - - - -void Resonance::add2XML(XMLwrapper *xml) -{ - xml->addparbool("enabled", Penabled); - - if((Penabled == 0) && (xml->minimal)) - return; - - xml->addpar("max_db", PmaxdB); - xml->addpar("center_freq", Pcenterfreq); - xml->addpar("octaves_freq", Poctavesfreq); - xml->addparbool("protect_fundamental_frequency", Pprotectthefundamental); - xml->addpar("resonance_points", N_RES_POINTS); - for(int i = 0; i < N_RES_POINTS; i++) { - xml->beginbranch("RESPOINT", i); - xml->addpar("val", Prespoints[i]); - xml->endbranch(); - } -} - - -void Resonance::getfromXML(XMLwrapper *xml) -{ - Penabled = xml->getparbool("enabled", Penabled); - - PmaxdB = xml->getpar127("max_db", PmaxdB); - Pcenterfreq = xml->getpar127("center_freq", Pcenterfreq); - Poctavesfreq = xml->getpar127("octaves_freq", Poctavesfreq); - Pprotectthefundamental = xml->getparbool("protect_fundamental_frequency", - Pprotectthefundamental); - for(int i = 0; i < N_RES_POINTS; i++) { - if(xml->enterbranch("RESPOINT", i) == 0) - continue; - Prespoints[i] = xml->getpar127("val", Prespoints[i]); - xml->exitbranch(); - } -} - diff --git a/plugins/zynaddsubfx/src/Synth/Resonance.h b/plugins/zynaddsubfx/src/Synth/Resonance.h deleted file mode 100644 index 6df43093d..000000000 --- a/plugins/zynaddsubfx/src/Synth/Resonance.h +++ /dev/null @@ -1,70 +0,0 @@ -/* - ZynAddSubFX - a software synthesizer - - Resonance.h - Resonance - Copyright (C) 2002-2005 Nasca Octavian Paul - Author: Nasca Octavian Paul - - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License - as published by the Free Software Foundation. - - 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 (version 2 or later) for more details. - - You should have received a copy of the GNU General Public License (version 2) - along with this program; if not, write to the Free Software Foundation, - Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -*/ -#ifndef RESONANCE_H -#define RESONANCE_H - -#include "../globals.h" -#include "../Misc/Util.h" -#include "../Misc/XMLwrapper.h" -#include "../Params/Presets.h" - -#define N_RES_POINTS 256 - -class Resonance:public Presets -{ - public: - Resonance(); - ~Resonance(); - void setpoint(int n, unsigned char p); - void applyres(int n, FFTFREQS fftdata, REALTYPE freq); - void smooth(); - void interpolatepeaks(int type); - void randomize(int type); - - void add2XML(XMLwrapper *xml); - void defaults(); - void getfromXML(XMLwrapper *xml); - - - REALTYPE getfreqpos(REALTYPE freq); - REALTYPE getfreqx(REALTYPE x); - REALTYPE getfreqresponse(REALTYPE freq); - REALTYPE getcenterfreq(); - REALTYPE getoctavesfreq(); - void sendcontroller(MidiControllers ctl, REALTYPE par); - - //parameters - unsigned char Penabled; //if the ressonance is enabled - unsigned char Prespoints[N_RES_POINTS]; //how many points define the resonance function - unsigned char PmaxdB; //how many dB the signal may be amplified - unsigned char Pcenterfreq, Poctavesfreq; //the center frequency of the res. func., and the number of octaves - unsigned char Pprotectthefundamental; //the fundamental (1-st harmonic) is not damped, even it resonance function is low - - //controllers - REALTYPE ctlcenter; //center frequency(relative) - REALTYPE ctlbw; //bandwidth(relative) - - private: -}; - -#endif - diff --git a/plugins/zynaddsubfx/src/Synth/SUBnote.cpp b/plugins/zynaddsubfx/src/Synth/SUBnote.cpp deleted file mode 100644 index 0ef075701..000000000 --- a/plugins/zynaddsubfx/src/Synth/SUBnote.cpp +++ /dev/null @@ -1,790 +0,0 @@ -/* - ZynAddSubFX - a software synthesizer - - SUBnote.cpp - The "subtractive" synthesizer - Copyright (C) 2002-2005 Nasca Octavian Paul - Author: Nasca Octavian Paul - - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License - as published by the Free Software Foundation. - - 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 (version 2 or later) for more details. - - You should have received a copy of the GNU General Public License (version 2) - along with this program; if not, write to the Free Software Foundation, - Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -*/ - -#include -#include -#include -#include "../globals.h" -#include "SUBnote.h" -#include "../Misc/Util.h" - -SUBnote::SUBnote(SUBnoteParameters *parameters, - Controller *ctl_, - REALTYPE freq, - REALTYPE velocity, - int portamento_, - int midinote, - bool besilent) -{ - ready = 0; - - tmpsmp = new REALTYPE[SOUND_BUFFER_SIZE]; - tmprnd = new REALTYPE[SOUND_BUFFER_SIZE]; - - // Initialise some legato-specific vars - Legato.msg = LM_Norm; - Legato.fade.length = (int)(SAMPLE_RATE * 0.005); // 0.005 seems ok. - if(Legato.fade.length < 1) - Legato.fade.length = 1; // (if something's fishy) - Legato.fade.step = (1.0 / Legato.fade.length); - Legato.decounter = -10; - Legato.param.freq = freq; - Legato.param.vel = velocity; - Legato.param.portamento = portamento_; - Legato.param.midinote = midinote; - Legato.silent = besilent; - - pars = parameters; - ctl = ctl_; - portamento = portamento_; - NoteEnabled = ON; - volume = pow(0.1, 3.0 * (1.0 - pars->PVolume / 96.0)); //-60 dB .. 0 dB - volume *= VelF(velocity, pars->PAmpVelocityScaleFunction); - if(pars->PPanning != 0) - panning = pars->PPanning / 127.0; - else - panning = RND; - numstages = pars->Pnumstages; - stereo = pars->Pstereo; - start = pars->Pstart; - firsttick = 1; - int pos[MAX_SUB_HARMONICS]; - - if(pars->Pfixedfreq == 0) - basefreq = freq; - else { - basefreq = 440.0; - int fixedfreqET = pars->PfixedfreqET; - if(fixedfreqET != 0) { //if the frequency varies according the keyboard note - REALTYPE tmp = - (midinote - - 69.0) / 12.0 * (pow(2.0, (fixedfreqET - 1) / 63.0) - 1.0); - if(fixedfreqET <= 64) - basefreq *= pow(2.0, tmp); - else - basefreq *= pow(3.0, tmp); - } - } - REALTYPE detune = getdetune(pars->PDetuneType, - pars->PCoarseDetune, - pars->PDetune); - basefreq *= pow(2.0, detune / 1200.0); //detune -// basefreq*=ctl->pitchwheel.relfreq;//pitch wheel - - //global filter - GlobalFilterCenterPitch = pars->GlobalFilter->getfreq() //center freq - + (pars->PGlobalFilterVelocityScale / 127.0 * 6.0) //velocity sensing - * (VelF(velocity, - pars->PGlobalFilterVelocityScaleFunction) - - 1); - - GlobalFilterL = NULL; - GlobalFilterR = NULL; - GlobalFilterEnvelope = NULL; - - //select only harmonics that desire to compute - numharmonics = 0; - for(int n = 0; n < MAX_SUB_HARMONICS; n++) { - if(pars->Phmag[n] == 0) - continue; - if(n * basefreq > SAMPLE_RATE / 2.0) - break; //remove the freqs above the Nyquist freq - pos[numharmonics++] = n; - } - firstnumharmonics = numharmonics; //(gf)Useful in legato mode. - - if(numharmonics == 0) { - NoteEnabled = OFF; - return; - } - - - lfilter = new bpfilter[numstages * numharmonics]; - if(stereo != 0) - rfilter = new bpfilter[numstages * numharmonics]; - - //how much the amplitude is normalised (because the harmonics) - REALTYPE reduceamp = 0.0; - - for(int n = 0; n < numharmonics; n++) { - REALTYPE freq = basefreq * (pos[n] + 1); - - //the bandwidth is not absolute(Hz); it is relative to frequency - REALTYPE bw = - pow(10, (pars->Pbandwidth - 127.0) / 127.0 * 4) * numstages; - - //Bandwidth Scale - bw *= pow(1000 / freq, (pars->Pbwscale - 64.0) / 64.0 * 3.0); - - //Relative BandWidth - bw *= pow(100, (pars->Phrelbw[pos[n]] - 64.0) / 64.0); - - if(bw > 25.0) - bw = 25.0; - - //try to keep same amplitude on all freqs and bw. (empirically) - REALTYPE gain = sqrt(1500.0 / (bw * freq)); - - REALTYPE hmagnew = 1.0 - pars->Phmag[pos[n]] / 127.0; - REALTYPE hgain; - - switch(pars->Phmagtype) { - case 1: - hgain = exp(hmagnew * log(0.01)); - break; - case 2: - hgain = exp(hmagnew * log(0.001)); - break; - case 3: - hgain = exp(hmagnew * log(0.0001)); - break; - case 4: - hgain = exp(hmagnew * log(0.00001)); - break; - default: - hgain = 1.0 - hmagnew; - } - gain *= hgain; - reduceamp += hgain; - - for(int nph = 0; nph < numstages; nph++) { - REALTYPE amp = 1.0; - if(nph == 0) - amp = gain; - initfilter(lfilter[nph + n * numstages], freq, bw, amp, hgain); - if(stereo != 0) - initfilter(rfilter[nph + n * numstages], freq, bw, amp, hgain); - } - } - - if(reduceamp < 0.001) - reduceamp = 1.0; - volume /= reduceamp; - - oldpitchwheel = 0; - oldbandwidth = 64; - if(pars->Pfixedfreq == 0) - initparameters(basefreq); - else - initparameters(basefreq / 440.0 * freq); - - oldamplitude = newamplitude; - ready = 1; -} - - -// SUBlegatonote: This function is (mostly) a copy of SUBnote(...) and -// initparameters(...) stuck together with some lines removed so that -// it only alter the already playing note (to perform legato). It is -// possible I left stuff that is not required for this. -void SUBnote::SUBlegatonote(REALTYPE freq, - REALTYPE velocity, - int portamento_, - int midinote, - bool externcall) -{ - //SUBnoteParameters *parameters=pars; - //Controller *ctl_=ctl; - - // Manage legato stuff - if(externcall) - Legato.msg = LM_Norm; - if(Legato.msg != LM_CatchUp) { - Legato.lastfreq = Legato.param.freq; - Legato.param.freq = freq; - Legato.param.vel = velocity; - Legato.param.portamento = portamento_; - Legato.param.midinote = midinote; - if(Legato.msg == LM_Norm) { - if(Legato.silent) { - Legato.fade.m = 0.0; - Legato.msg = LM_FadeIn; - } - else { - Legato.fade.m = 1.0; - Legato.msg = LM_FadeOut; - return; - } - } - if(Legato.msg == LM_ToNorm) - Legato.msg = LM_Norm; - } - - portamento = portamento_; - - volume = pow(0.1, 3.0 * (1.0 - pars->PVolume / 96.0)); //-60 dB .. 0 dB - volume *= VelF(velocity, pars->PAmpVelocityScaleFunction); - if(pars->PPanning != 0) - panning = pars->PPanning / 127.0; - else - panning = RND; - - ///start=pars->Pstart; - - int pos[MAX_SUB_HARMONICS]; - - if(pars->Pfixedfreq == 0) - basefreq = freq; - else { - basefreq = 440.0; - int fixedfreqET = pars->PfixedfreqET; - if(fixedfreqET != 0) { //if the frequency varies according the keyboard note - REALTYPE tmp = - (midinote - - 69.0) / 12.0 * (pow(2.0, (fixedfreqET - 1) / 63.0) - 1.0); - if(fixedfreqET <= 64) - basefreq *= pow(2.0, tmp); - else - basefreq *= pow(3.0, tmp); - } - } - REALTYPE detune = getdetune(pars->PDetuneType, - pars->PCoarseDetune, - pars->PDetune); - basefreq *= pow(2.0, detune / 1200.0); //detune - - //global filter - GlobalFilterCenterPitch = pars->GlobalFilter->getfreq() //center freq - + (pars->PGlobalFilterVelocityScale / 127.0 * 6.0) //velocity sensing - * (VelF(velocity, - pars->PGlobalFilterVelocityScaleFunction) - - 1); - - - int legatonumharmonics = 0; - for(int n = 0; n < MAX_SUB_HARMONICS; n++) { - if(pars->Phmag[n] == 0) - continue; - if(n * basefreq > SAMPLE_RATE / 2.0) - break; //remove the freqs above the Nyquist freq - pos[legatonumharmonics++] = n; - } - if(legatonumharmonics > firstnumharmonics) - numharmonics = firstnumharmonics; - else - numharmonics = legatonumharmonics; - - if(numharmonics == 0) { - NoteEnabled = OFF; - return; - } - - - //how much the amplitude is normalised (because the harmonics) - REALTYPE reduceamp = 0.0; - - for(int n = 0; n < numharmonics; n++) { - REALTYPE freq = basefreq * (pos[n] + 1); - - //the bandwidth is not absolute(Hz); it is relative to frequency - REALTYPE bw = - pow(10, (pars->Pbandwidth - 127.0) / 127.0 * 4) * numstages; - - //Bandwidth Scale - bw *= pow(1000 / freq, (pars->Pbwscale - 64.0) / 64.0 * 3.0); - - //Relative BandWidth - bw *= pow(100, (pars->Phrelbw[pos[n]] - 64.0) / 64.0); - - if(bw > 25.0) - bw = 25.0; - - //try to keep same amplitude on all freqs and bw. (empirically) - REALTYPE gain = sqrt(1500.0 / (bw * freq)); - - REALTYPE hmagnew = 1.0 - pars->Phmag[pos[n]] / 127.0; - REALTYPE hgain; - - switch(pars->Phmagtype) { - case 1: - hgain = exp(hmagnew * log(0.01)); - break; - case 2: - hgain = exp(hmagnew * log(0.001)); - break; - case 3: - hgain = exp(hmagnew * log(0.0001)); - break; - case 4: - hgain = exp(hmagnew * log(0.00001)); - break; - default: - hgain = 1.0 - hmagnew; - } - gain *= hgain; - reduceamp += hgain; - - for(int nph = 0; nph < numstages; nph++) { - REALTYPE amp = 1.0; - if(nph == 0) - amp = gain; - initfilter(lfilter[nph + n * numstages], freq, bw, amp, hgain); - if(stereo != 0) - initfilter(rfilter[nph + n * numstages], freq, bw, amp, hgain); - } - } - - if(reduceamp < 0.001) - reduceamp = 1.0; - volume /= reduceamp; - - oldpitchwheel = 0; - oldbandwidth = 64; - - if(pars->Pfixedfreq == 0) - freq = basefreq; - else - freq *= basefreq / 440.0; - - - /////////////// - // Altered initparameters(...) content: - - if(pars->PGlobalFilterEnabled != 0) { - globalfiltercenterq = pars->GlobalFilter->getq(); - GlobalFilterFreqTracking = pars->GlobalFilter->getfreqtracking(basefreq); - } - - // end of the altered initparameters function content. - /////////////// - - oldamplitude = newamplitude; - - // End of the SUBlegatonote function. -} - - -SUBnote::~SUBnote() -{ - if(NoteEnabled != OFF) - KillNote(); - delete [] tmpsmp; - delete [] tmprnd; -} - -/* - * Kill the note - */ -void SUBnote::KillNote() -{ - if(NoteEnabled != OFF) { - delete [] lfilter; - lfilter = NULL; - if(stereo != 0) - delete [] rfilter; - rfilter = NULL; - delete (AmpEnvelope); - if(FreqEnvelope != NULL) - delete (FreqEnvelope); - if(BandWidthEnvelope != NULL) - delete (BandWidthEnvelope); - NoteEnabled = OFF; - } -} - - -/* - * Compute the filters coefficients - */ -void SUBnote::computefiltercoefs(bpfilter &filter, - REALTYPE freq, - REALTYPE bw, - REALTYPE gain) -{ - if(freq > SAMPLE_RATE / 2.0 - 200.0) - freq = SAMPLE_RATE / 2.0 - 200.0; - ; - - REALTYPE omega = 2.0 * PI * freq / SAMPLE_RATE; - REALTYPE sn = sin(omega); - REALTYPE cs = cos(omega); - REALTYPE alpha = sn * sinh(LOG_2 / 2.0 * bw * omega / sn); - - if(alpha > 1) - alpha = 1; - if(alpha > bw) - alpha = bw; - - filter.b0 = alpha / (1.0 + alpha) * filter.amp * gain; - filter.b2 = -alpha / (1.0 + alpha) * filter.amp * gain; - filter.a1 = -2.0 * cs / (1.0 + alpha); - filter.a2 = (1.0 - alpha) / (1.0 + alpha); -} - - -/* - * Initialise the filters - */ -void SUBnote::initfilter(bpfilter &filter, - REALTYPE freq, - REALTYPE bw, - REALTYPE amp, - REALTYPE mag) -{ - filter.xn1 = 0.0; - filter.xn2 = 0.0; - - if(start == 0) { - filter.yn1 = 0.0; - filter.yn2 = 0.0; - } - else { - REALTYPE a = 0.1 * mag; //empirically - REALTYPE p = RND * 2.0 * PI; - if(start == 1) - a *= RND; - filter.yn1 = a * cos(p); - filter.yn2 = a * cos(p + freq * 2.0 * PI / SAMPLE_RATE); - - //correct the error of computation the start amplitude - //at very high frequencies - if(freq > SAMPLE_RATE * 0.96) { - filter.yn1 = 0.0; - filter.yn2 = 0.0; - } - } - - filter.amp = amp; - filter.freq = freq; - filter.bw = bw; - computefiltercoefs(filter, freq, bw, 1.0); -} - -/* - * Do the filtering - */ -void SUBnote::filter(bpfilter &filter, REALTYPE *smps) -{ - int i; - REALTYPE out; - for(i = 0; i < SOUND_BUFFER_SIZE; i++) { - out = smps[i] * filter.b0 + filter.b2 * filter.xn2 - - filter.a1 * filter.yn1 - filter.a2 * filter.yn2; - filter.xn2 = filter.xn1; - filter.xn1 = smps[i]; - filter.yn2 = filter.yn1; - filter.yn1 = out; - smps[i] = out; - } -} - -/* - * Init Parameters - */ -void SUBnote::initparameters(REALTYPE freq) -{ - AmpEnvelope = new Envelope(pars->AmpEnvelope, freq); - if(pars->PFreqEnvelopeEnabled != 0) - FreqEnvelope = new Envelope(pars->FreqEnvelope, freq); - else - FreqEnvelope = NULL; - if(pars->PBandWidthEnvelopeEnabled != 0) - BandWidthEnvelope = new Envelope(pars->BandWidthEnvelope, freq); - else - BandWidthEnvelope = NULL; - if(pars->PGlobalFilterEnabled != 0) { - globalfiltercenterq = pars->GlobalFilter->getq(); - GlobalFilterL = new Filter(pars->GlobalFilter); - if(stereo != 0) - GlobalFilterR = new Filter(pars->GlobalFilter); - GlobalFilterEnvelope = new Envelope(pars->GlobalFilterEnvelope, - freq); - GlobalFilterFreqTracking = pars->GlobalFilter->getfreqtracking(basefreq); - } - computecurrentparameters(); -} - - -/* - * Compute Parameters of SUBnote for each tick - */ -void SUBnote::computecurrentparameters() -{ - if((FreqEnvelope != NULL) || (BandWidthEnvelope != NULL) - || (oldpitchwheel != ctl->pitchwheel.data) - || (oldbandwidth != ctl->bandwidth.data) - || (portamento != 0)) { - REALTYPE envfreq = 1.0; - REALTYPE envbw = 1.0; - REALTYPE gain = 1.0; - - if(FreqEnvelope != NULL) { - envfreq = FreqEnvelope->envout() / 1200; - envfreq = pow(2.0, envfreq); - } - envfreq *= ctl->pitchwheel.relfreq; //pitch wheel - if(portamento != 0) { //portamento is used - envfreq *= ctl->portamento.freqrap; - if(ctl->portamento.used == 0) //the portamento has finished - portamento = 0; //this note is no longer "portamented" - ; - } - - if(BandWidthEnvelope != NULL) { - envbw = BandWidthEnvelope->envout(); - envbw = pow(2, envbw); - } - envbw *= ctl->bandwidth.relbw; //bandwidth controller - - REALTYPE tmpgain = 1.0 / sqrt(envbw * envfreq); - - for(int n = 0; n < numharmonics; n++) { - for(int nph = 0; nph < numstages; nph++) { - if(nph == 0) - gain = tmpgain; - else - gain = 1.0; - computefiltercoefs(lfilter[nph + n * numstages], - lfilter[nph + n * numstages].freq * envfreq, - lfilter[nph + n * numstages].bw * envbw, - gain); - } - } - if(stereo != 0) - for(int n = 0; n < numharmonics; n++) { - for(int nph = 0; nph < numstages; nph++) { - if(nph == 0) - gain = tmpgain; - else - gain = 1.0; - computefiltercoefs( - rfilter[nph + n * numstages], - rfilter[nph + n - * numstages].freq * envfreq, - rfilter[nph + n * numstages].bw * envbw, - gain); - } - } - ; - oldbandwidth = ctl->bandwidth.data; - oldpitchwheel = ctl->pitchwheel.data; - } - newamplitude = volume * AmpEnvelope->envout_dB() * 2.0; - - //Filter - if(GlobalFilterL != NULL) { - REALTYPE globalfilterpitch = GlobalFilterCenterPitch - + GlobalFilterEnvelope->envout(); - REALTYPE filterfreq = globalfilterpitch + ctl->filtercutoff.relfreq - + GlobalFilterFreqTracking; - filterfreq = GlobalFilterL->getrealfreq(filterfreq); - - GlobalFilterL->setfreq_and_q(filterfreq, - globalfiltercenterq * ctl->filterq.relq); - if(GlobalFilterR != NULL) - GlobalFilterR->setfreq_and_q( - filterfreq, - globalfiltercenterq - * ctl->filterq.relq); - } -} - -/* - * Note Output - */ -int SUBnote::noteout(REALTYPE *outl, REALTYPE *outr) -{ - int i; - - memcpy(outl, denormalkillbuf, SOUND_BUFFER_SIZE * sizeof(REALTYPE)); - memcpy(outr, denormalkillbuf, SOUND_BUFFER_SIZE * sizeof(REALTYPE)); - - if(NoteEnabled == OFF) - return 0; - - //left channel - for(i = 0; i < SOUND_BUFFER_SIZE; i++) - tmprnd[i] = RND * 2.0 - 1.0; - for(int n = 0; n < numharmonics; n++) { - memcpy(tmpsmp, tmprnd, SOUND_BUFFER_SIZE * sizeof(REALTYPE)); - for(int nph = 0; nph < numstages; nph++) - filter(lfilter[nph + n * numstages], tmpsmp); - for(i = 0; i < SOUND_BUFFER_SIZE; i++) - outl[i] += tmpsmp[i]; - } - - if(GlobalFilterL != NULL) - GlobalFilterL->filterout(&outl[0]); - - //right channel - if(stereo != 0) { - for(i = 0; i < SOUND_BUFFER_SIZE; i++) - tmprnd[i] = RND * 2.0 - 1.0; - for(int n = 0; n < numharmonics; n++) { - memcpy(tmpsmp, tmprnd, SOUND_BUFFER_SIZE * sizeof(REALTYPE)); - for(int nph = 0; nph < numstages; nph++) - filter(rfilter[nph + n * numstages], tmpsmp); - for(i = 0; i < SOUND_BUFFER_SIZE; i++) - outr[i] += tmpsmp[i]; - } - if(GlobalFilterR != NULL) - GlobalFilterR->filterout(&outr[0]); - } - else - memcpy(outr, outl, SOUND_BUFFER_SIZE * sizeof(REALTYPE)); - - if(firsttick != 0) { - int n = 10; - if(n > SOUND_BUFFER_SIZE) - n = SOUND_BUFFER_SIZE; - for(i = 0; i < n; i++) { - REALTYPE ampfadein = 0.5 - 0.5 * cos( - (REALTYPE) i / (REALTYPE) n * PI); - outl[i] *= ampfadein; - outr[i] *= ampfadein; - } - firsttick = 0; - } - - if(ABOVE_AMPLITUDE_THRESHOLD(oldamplitude, newamplitude)) { - // Amplitude interpolation - for(i = 0; i < SOUND_BUFFER_SIZE; i++) { - REALTYPE tmpvol = INTERPOLATE_AMPLITUDE(oldamplitude, - newamplitude, - i, - SOUND_BUFFER_SIZE); - outl[i] *= tmpvol * panning; - outr[i] *= tmpvol * (1.0 - panning); - } - } - else { - for(i = 0; i < SOUND_BUFFER_SIZE; i++) { - outl[i] *= newamplitude * panning; - outr[i] *= newamplitude * (1.0 - panning); - } - } - - oldamplitude = newamplitude; - computecurrentparameters(); - - // Apply legato-specific sound signal modifications - if(Legato.silent) // Silencer - if(Legato.msg != LM_FadeIn) { - memset(outl, 0, SOUND_BUFFER_SIZE * sizeof(REALTYPE)); - memset(outr, 0, SOUND_BUFFER_SIZE * sizeof(REALTYPE)); - } - switch(Legato.msg) { - case LM_CatchUp: // Continue the catch-up... - if(Legato.decounter == -10) - Legato.decounter = Legato.fade.length; - for(i = 0; i < SOUND_BUFFER_SIZE; i++) { //Yea, could be done without the loop... - Legato.decounter--; - if(Legato.decounter < 1) { - // Catching-up done, we can finally set - // the note to the actual parameters. - Legato.decounter = -10; - Legato.msg = LM_ToNorm; - SUBlegatonote(Legato.param.freq, - Legato.param.vel, - Legato.param.portamento, - Legato.param.midinote, - false); - break; - } - } - break; - case LM_FadeIn: // Fade-in - if(Legato.decounter == -10) - Legato.decounter = Legato.fade.length; - Legato.silent = false; - for(i = 0; i < SOUND_BUFFER_SIZE; i++) { - Legato.decounter--; - if(Legato.decounter < 1) { - Legato.decounter = -10; - Legato.msg = LM_Norm; - break; - } - Legato.fade.m += Legato.fade.step; - outl[i] *= Legato.fade.m; - outr[i] *= Legato.fade.m; - } - break; - case LM_FadeOut: // Fade-out, then set the catch-up - if(Legato.decounter == -10) - Legato.decounter = Legato.fade.length; - for(i = 0; i < SOUND_BUFFER_SIZE; i++) { - Legato.decounter--; - if(Legato.decounter < 1) { - for(int j = i; j < SOUND_BUFFER_SIZE; j++) { - outl[j] = 0.0; - outr[j] = 0.0; - } - Legato.decounter = -10; - Legato.silent = true; - // Fading-out done, now set the catch-up : - Legato.decounter = Legato.fade.length; - Legato.msg = LM_CatchUp; - REALTYPE catchupfreq = Legato.param.freq - * (Legato.param.freq / Legato.lastfreq); //This freq should make this now silent note to catch-up (or should I say resync ?) with the heard note for the same length it stayed at the previous freq during the fadeout. - SUBlegatonote(catchupfreq, - Legato.param.vel, - Legato.param.portamento, - Legato.param.midinote, - false); - break; - } - Legato.fade.m -= Legato.fade.step; - outl[i] *= Legato.fade.m; - outr[i] *= Legato.fade.m; - } - break; - default: - break; - } - - // Check if the note needs to be computed more - if(AmpEnvelope->finished() != 0) { - for(i = 0; i < SOUND_BUFFER_SIZE; i++) { //fade-out - REALTYPE tmp = 1.0 - (REALTYPE)i / (REALTYPE)SOUND_BUFFER_SIZE; - outl[i] *= tmp; - outr[i] *= tmp; - } - KillNote(); - } - return 1; -} - -/* - * Relase Key (Note Off) - */ -void SUBnote::relasekey() -{ - AmpEnvelope->relasekey(); - if(FreqEnvelope != NULL) - FreqEnvelope->relasekey(); - if(BandWidthEnvelope != NULL) - BandWidthEnvelope->relasekey(); - if(GlobalFilterEnvelope != NULL) - GlobalFilterEnvelope->relasekey(); -} - -/* - * Check if the note is finished - */ -int SUBnote::finished() -{ - if(NoteEnabled == OFF) - return 1; - else - return 0; -} - diff --git a/plugins/zynaddsubfx/src/Synth/SUBnote.h b/plugins/zynaddsubfx/src/Synth/SUBnote.h deleted file mode 100644 index e6b875e48..000000000 --- a/plugins/zynaddsubfx/src/Synth/SUBnote.h +++ /dev/null @@ -1,135 +0,0 @@ -/* - ZynAddSubFX - a software synthesizer - - SUBnote.h - The subtractive synthesizer - Copyright (C) 2002-2005 Nasca Octavian Paul - Author: Nasca Octavian Paul - - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License - as published by the Free Software Foundation. - - 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 (version 2 or later) for more details. - - You should have received a copy of the GNU General Public License (version 2) - along with this program; if not, write to the Free Software Foundation, - Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -*/ - -#ifndef SUB_NOTE_H -#define SUB_NOTE_H - -#include "../globals.h" -#include "../Params/SUBnoteParameters.h" -#include "../Params/Controller.h" -#include "Envelope.h" -#include "../DSP/Filter.h" - -class SUBnote -{ - public: - SUBnote(SUBnoteParameters *parameters, - Controller *ctl_, - REALTYPE freq, - REALTYPE velocity, - int portamento_, - int midinote, - bool besilent); - ~SUBnote(); - - void SUBlegatonote(REALTYPE freq, - REALTYPE velocity, - int portamento_, - int midinote, - bool externcall); - - int noteout(REALTYPE *outl, REALTYPE *outr); //note output,return 0 if the note is finished - void relasekey(); - int finished(); - - int ready; //if I can get the sampledata - - private: - - void computecurrentparameters(); - void initparameters(REALTYPE freq); - void KillNote(); - - SUBnoteParameters *pars; - - //parameters - int stereo; - int numstages; //number of stages of filters - int numharmonics; //number of harmonics (after the too higher hamonics are removed) - int firstnumharmonics; //To keep track of the first note's numharmonics value, useful in legato mode. - int start; //how the harmonics start - REALTYPE basefreq; - REALTYPE panning; - Envelope *AmpEnvelope; - Envelope *FreqEnvelope; - Envelope *BandWidthEnvelope; - - Filter *GlobalFilterL, *GlobalFilterR; - - Envelope *GlobalFilterEnvelope; - - //internal values - ONOFFTYPE NoteEnabled; - int firsttick, portamento; - REALTYPE volume, oldamplitude, newamplitude; - - REALTYPE GlobalFilterCenterPitch; //octaves - REALTYPE GlobalFilterFreqTracking; - - struct bpfilter { - REALTYPE freq, bw, amp; //filter parameters - REALTYPE a1, a2, b0, b2; //filter coefs. b1=0 - REALTYPE xn1, xn2, yn1, yn2; //filter internal values - }; - - void initfilter(bpfilter &filter, - REALTYPE freq, - REALTYPE bw, - REALTYPE amp, - REALTYPE mag); - void computefiltercoefs(bpfilter &filter, - REALTYPE freq, - REALTYPE bw, - REALTYPE gain); - inline void filter(bpfilter &filter, REALTYPE *smps); - - bpfilter *lfilter, *rfilter; - - REALTYPE *tmpsmp; - REALTYPE *tmprnd; //this is filled with random numbers - - Controller *ctl; - int oldpitchwheel, oldbandwidth; - REALTYPE globalfiltercenterq; - - // Legato vars - struct { - bool silent; - REALTYPE lastfreq; - LegatoMsg msg; - int decounter; - struct { // Fade In/Out vars - int length; - REALTYPE m, step; - } fade; - struct { // Note parameters - REALTYPE freq, vel; - int portamento, midinote; - } param; - } Legato; -}; - - - - -#endif - diff --git a/plugins/zynaddsubfx/src/UI/ADnoteUI.cc b/plugins/zynaddsubfx/src/UI/ADnoteUI.cc deleted file mode 100644 index bf32baa2b..000000000 --- a/plugins/zynaddsubfx/src/UI/ADnoteUI.cc +++ /dev/null @@ -1,2202 +0,0 @@ -// generated by Fast Light User Interface Designer (fluid) version 1.0300 - -#include "ADnoteUI.h" -//Copyright (c) 2002-2005 Nasca Octavian Paul -//License: GNU GPL version 2 or later -#include -#include -#include -#include - -void ADvoicelistitem::cb_voicevolume_i(Fl_Value_Slider* o, void*) { - pars->VoicePar[nvoice].PVolume=(int)o->value(); -} -void ADvoicelistitem::cb_voicevolume(Fl_Value_Slider* o, void* v) { - ((ADvoicelistitem*)(o->parent()->parent()->user_data()))->cb_voicevolume_i(o,v); -} - -void ADvoicelistitem::cb_voiceresonanceenabled_i(Fl_Check_Button* o, void*) { - pars->VoicePar[nvoice].Presonance=(int)o->value(); -} -void ADvoicelistitem::cb_voiceresonanceenabled(Fl_Check_Button* o, void* v) { - ((ADvoicelistitem*)(o->parent()->parent()->user_data()))->cb_voiceresonanceenabled_i(o,v); -} - -void ADvoicelistitem::cb_voicelfofreq_i(Fl_Value_Slider* o, void*) { - pars->VoicePar[nvoice].FreqLfo->Pintensity=(int)o->value(); -} -void ADvoicelistitem::cb_voicelfofreq(Fl_Value_Slider* o, void* v) { - ((ADvoicelistitem*)(o->parent()->parent()->user_data()))->cb_voicelfofreq_i(o,v); -} - -void ADvoicelistitem::cb_voicepanning_i(WidgetPDial* o, void*) { - pars->VoicePar[nvoice].PPanning=(int) o->value(); -} -void ADvoicelistitem::cb_voicepanning(WidgetPDial* o, void* v) { - ((ADvoicelistitem*)(o->parent()->parent()->user_data()))->cb_voicepanning_i(o,v); -} - -void ADvoicelistitem::cb_detunevalueoutput_i(Fl_Value_Output* o, void*) { - o->value(getdetune((pars->VoicePar[nvoice].PDetuneType==0)?(pars->GlobalPar.PDetuneType) : (pars->VoicePar[nvoice].PDetuneType),0,pars->VoicePar[nvoice].PDetune)*pars->getBandwidthDetuneMultiplier()); -} -void ADvoicelistitem::cb_detunevalueoutput(Fl_Value_Output* o, void* v) { - ((ADvoicelistitem*)(o->parent()->parent()->user_data()))->cb_detunevalueoutput_i(o,v); -} - -void ADvoicelistitem::cb_voicedetune_i(Fl_Slider* o, void*) { - pars->VoicePar[nvoice].PDetune=(int)o->value()+8192; -detunevalueoutput->do_callback(); -} -void ADvoicelistitem::cb_voicedetune(Fl_Slider* o, void* v) { - ((ADvoicelistitem*)(o->parent()->parent()->user_data()))->cb_voicedetune_i(o,v); -} - -void ADvoicelistitem::cb_noiselabel_i(Fl_Box* o, void*) { - if (pars->VoicePar[nvoice].Type==0) { - o->hide(); - voiceresonanceenabled->activate(); - detunevalueoutput->activate(); - voicedetune->activate(); - voicelfofreq->activate(); - voiceoscil->activate(); -} else { - o->show(); - voiceresonanceenabled->deactivate(); - detunevalueoutput->deactivate(); - voicedetune->deactivate(); - voicelfofreq->deactivate(); - voiceoscil->deactivate(); -}; -} -void ADvoicelistitem::cb_noiselabel(Fl_Box* o, void* v) { - ((ADvoicelistitem*)(o->parent()->parent()->user_data()))->cb_noiselabel_i(o,v); -} - -void ADvoicelistitem::cb_voiceenabled_i(Fl_Check_Button* o, void*) { - pars->VoicePar[nvoice].Enabled=(int)o->value(); -if (o->value()==0) voicelistitemgroup->deactivate(); -else voicelistitemgroup->activate(); -o->redraw(); -} -void ADvoicelistitem::cb_voiceenabled(Fl_Check_Button* o, void* v) { - ((ADvoicelistitem*)(o->parent()->user_data()))->cb_voiceenabled_i(o,v); -} - -Fl_Group* ADvoicelistitem::make_window() { - { ADnoteVoiceListItem = new Fl_Group(0, 0, 615, 30); - ADnoteVoiceListItem->box(FL_FLAT_BOX); - ADnoteVoiceListItem->color(FL_BACKGROUND_COLOR); - ADnoteVoiceListItem->selection_color(FL_BACKGROUND_COLOR); - ADnoteVoiceListItem->labeltype(FL_NO_LABEL); - ADnoteVoiceListItem->labelfont(0); - ADnoteVoiceListItem->labelsize(14); - ADnoteVoiceListItem->labelcolor(FL_FOREGROUND_COLOR); - ADnoteVoiceListItem->user_data((void*)(this)); - ADnoteVoiceListItem->align(Fl_Align(FL_ALIGN_TOP)); - ADnoteVoiceListItem->when(FL_WHEN_RELEASE); - { Fl_Group* o = voicelistitemgroup = new Fl_Group(50, 0, 570, 25); - voicelistitemgroup->box(FL_FLAT_BOX); - { Fl_Value_Slider* o = voicevolume = new Fl_Value_Slider(90, 5, 115, 20); - voicevolume->tooltip("Volume"); - voicevolume->type(5); - voicevolume->box(FL_FLAT_BOX); - voicevolume->labelsize(8); - voicevolume->maximum(127); - voicevolume->step(1); - voicevolume->callback((Fl_Callback*)cb_voicevolume); - voicevolume->align(Fl_Align(FL_ALIGN_TOP_LEFT)); - o->value(pars->VoicePar[nvoice].PVolume); - } // Fl_Value_Slider* voicevolume - { Fl_Check_Button* o = voiceresonanceenabled = new Fl_Check_Button(245, 7, 15, 17); - voiceresonanceenabled->tooltip("Resonance On/Off"); - voiceresonanceenabled->down_box(FL_DOWN_BOX); - voiceresonanceenabled->labeltype(FL_EMBOSSED_LABEL); - voiceresonanceenabled->labelfont(1); - voiceresonanceenabled->labelsize(11); - voiceresonanceenabled->callback((Fl_Callback*)cb_voiceresonanceenabled); - voiceresonanceenabled->align(Fl_Align(FL_ALIGN_LEFT)); - o->value(pars->VoicePar[nvoice].Presonance); - } // Fl_Check_Button* voiceresonanceenabled - { Fl_Value_Slider* o = voicelfofreq = new Fl_Value_Slider(500, 5, 115, 20); - voicelfofreq->tooltip("Frequency LFO amount"); - voicelfofreq->type(5); - voicelfofreq->box(FL_FLAT_BOX); - voicelfofreq->labelsize(8); - voicelfofreq->maximum(127); - voicelfofreq->step(1); - voicelfofreq->callback((Fl_Callback*)cb_voicelfofreq); - voicelfofreq->align(Fl_Align(FL_ALIGN_TOP_LEFT)); - o->value(pars->VoicePar[nvoice].FreqLfo->Pintensity); - } // Fl_Value_Slider* voicelfofreq - { WidgetPDial* o = voicepanning = new WidgetPDial(215, 5, 20, 20); - voicepanning->tooltip("Panning (leftmost is Random)"); - voicepanning->box(FL_ROUND_UP_BOX); - voicepanning->color(FL_BACKGROUND_COLOR); - voicepanning->selection_color(FL_INACTIVE_COLOR); - voicepanning->labeltype(FL_NORMAL_LABEL); - voicepanning->labelfont(0); - voicepanning->labelsize(10); - voicepanning->labelcolor(FL_FOREGROUND_COLOR); - voicepanning->maximum(127); - voicepanning->step(1); - voicepanning->callback((Fl_Callback*)cb_voicepanning); - voicepanning->align(Fl_Align(FL_ALIGN_LEFT)); - voicepanning->when(FL_WHEN_CHANGED); - o->value(pars->VoicePar[nvoice].PPanning); - } // WidgetPDial* voicepanning - { Fl_Group* o = voiceoscil = new Fl_Group(60, 5, 30, 20); - voiceoscil->box(FL_THIN_DOWN_BOX); - voiceoscil->color(FL_GRAY0); - voiceoscil->selection_color((Fl_Color)71); - voiceoscil->labelcolor((Fl_Color)179); - osc=new Oscilloscope(o->x(),o->y(),o->w(),o->h(),""); - osc->init(pars->VoicePar[nvoice].OscilSmp,0,pars->VoicePar[nvoice].Poscilphase,master); - if (pars->VoicePar[nvoice].Pextoscil != -1) {osc->init(pars->VoicePar[pars->VoicePar[nvoice].Pextoscil].OscilSmp,master);} - voiceoscil->end(); - } // Fl_Group* voiceoscil - { Fl_Value_Output* o = detunevalueoutput = new Fl_Value_Output(265, 5, 45, 20); - detunevalueoutput->labelsize(10); - detunevalueoutput->minimum(-5000); - detunevalueoutput->maximum(5000); - detunevalueoutput->step(0.01); - detunevalueoutput->textfont(1); - detunevalueoutput->textsize(10); - detunevalueoutput->callback((Fl_Callback*)cb_detunevalueoutput); - detunevalueoutput->align(Fl_Align(FL_ALIGN_TOP_LEFT)); - o->value(getdetune(pars->VoicePar[nvoice].PDetuneType,0,pars->VoicePar[nvoice].PDetune)*pars->getBandwidthDetuneMultiplier()); - } // Fl_Value_Output* detunevalueoutput - { Fl_Slider* o = voicedetune = new Fl_Slider(315, 5, 185, 20); - voicedetune->tooltip("Fine Detune (cents)"); - voicedetune->type(5); - voicedetune->box(FL_FLAT_BOX); - voicedetune->minimum(-8192); - voicedetune->maximum(8191); - voicedetune->step(1); - voicedetune->callback((Fl_Callback*)cb_voicedetune); - o->value(pars->VoicePar[nvoice].PDetune-8192); - } // Fl_Slider* voicedetune - { Fl_Box* o = noiselabel = new Fl_Box(65, 5, 20, 20, "N"); - noiselabel->labelfont(1); - noiselabel->labelsize(13); - noiselabel->labelcolor(FL_BACKGROUND2_COLOR); - noiselabel->callback((Fl_Callback*)cb_noiselabel); - if (pars->VoicePar[nvoice].Type==0) o->hide(); - } // Fl_Box* noiselabel - if (pars->VoicePar[nvoice].Enabled==0) o->deactivate(); - voicelistitemgroup->end(); - } // Fl_Group* voicelistitemgroup - { Fl_Check_Button* o = voiceenabled = new Fl_Check_Button(30, 5, 20, 20, "01"); - voiceenabled->down_box(FL_DOWN_BOX); - voiceenabled->labeltype(FL_EMBOSSED_LABEL); - voiceenabled->labelfont(1); - voiceenabled->labelsize(13); - voiceenabled->callback((Fl_Callback*)cb_voiceenabled); - voiceenabled->align(Fl_Align(FL_ALIGN_LEFT)); - char tmp[10];snprintf(tmp,10,"%d",nvoice+1);o->label(strdup(tmp)); - o->value(pars->VoicePar[nvoice].Enabled); - } // Fl_Check_Button* voiceenabled - ADnoteVoiceListItem->end(); - } // Fl_Group* ADnoteVoiceListItem - return ADnoteVoiceListItem; -} - -ADvoicelistitem::ADvoicelistitem(int x,int y, int w, int h, const char *label):Fl_Group(x,y,w,h,label) { - nvoice=0; - pars=NULL; -} - -void ADvoicelistitem::init(ADnoteParameters *parameters,int nvoice_,Master *master_) { - pars=parameters; - nvoice=nvoice_; - master=master_; - make_window(); - ADnoteVoiceListItem->show(); - end(); -} - -void ADvoicelistitem::refreshlist() { - voiceenabled->value(pars->VoicePar[nvoice].Enabled); - voiceresonanceenabled->value(pars->VoicePar[nvoice].Presonance); - voicevolume->value(pars->VoicePar[nvoice].PVolume); - voicedetune->value(pars->VoicePar[nvoice].PDetune-8192); - voicepanning->value(pars->VoicePar[nvoice].PPanning); - voicelfofreq->value(pars->VoicePar[nvoice].FreqLfo->Pintensity); - if (pars->VoicePar[nvoice].Pextoscil != -1) { - osc->init(pars->VoicePar[pars->VoicePar[nvoice].Pextoscil].OscilSmp,0,pars->VoicePar[nvoice].Poscilphase,master); - } else - osc->init(pars->VoicePar[nvoice].OscilSmp,0,pars->VoicePar[nvoice].Poscilphase,master); - if (pars->VoicePar[nvoice].Enabled==0) voicelistitemgroup->deactivate(); - else voicelistitemgroup->activate(); - detunevalueoutput->do_callback(); - noiselabel->do_callback(); - ADnoteVoiceListItem->redraw(); -} - -ADvoicelistitem::~ADvoicelistitem() { - ADnoteVoiceListItem->hide(); - //delete(ADnoteVoiceListItem); -} - -void ADvoiceUI::cb_Enable_i(Fl_Check_Button* o, void*) { - pars->VoicePar[nvoice].PFMFreqEnvelopeEnabled=(int)o->value(); -if (o->value()==0) voiceFMfreqenvgroup->deactivate(); -else voiceFMfreqenvgroup->activate(); -o->redraw(); -} -void ADvoiceUI::cb_Enable(Fl_Check_Button* o, void* v) { - ((ADvoiceUI*)(o->parent()->parent()->parent()->parent()->parent()->user_data()))->cb_Enable_i(o,v); -} - -void ADvoiceUI::cb_Coarse_i(Fl_Counter* o, void*) { - int k=(int) o->value(); -if (k<0) k+=1024; -pars->VoicePar[nvoice].PFMCoarseDetune = k+ - (pars->VoicePar[nvoice].PFMCoarseDetune/1024)*1024; -} -void ADvoiceUI::cb_Coarse(Fl_Counter* o, void* v) { - ((ADvoiceUI*)(o->parent()->parent()->parent()->parent()->parent()->user_data()))->cb_Coarse_i(o,v); -} - -void ADvoiceUI::cb_Octave_i(Fl_Counter* o, void*) { - int k=(int) o->value(); -if (k<0) k+=16; -pars->VoicePar[nvoice].PFMCoarseDetune = k*1024+ - pars->VoicePar[nvoice].PFMCoarseDetune%1024; -} -void ADvoiceUI::cb_Octave(Fl_Counter* o, void* v) { - ((ADvoiceUI*)(o->parent()->parent()->parent()->parent()->parent()->user_data()))->cb_Octave_i(o,v); -} - -void ADvoiceUI::cb__i(Fl_Slider* o, void*) { - pars->VoicePar[nvoice].PFMDetune=(int)o->value()+8192; -fmdetunevalueoutput->do_callback(); -} -void ADvoiceUI::cb_(Fl_Slider* o, void* v) { - ((ADvoiceUI*)(o->parent()->parent()->parent()->parent()->parent()->user_data()))->cb__i(o,v); -} - -void ADvoiceUI::cb_fmdetunevalueoutput_i(Fl_Value_Output* o, void*) { - o->value(getdetune((pars->VoicePar[nvoice].PFMDetuneType==0)?(pars->GlobalPar.PDetuneType) : (pars->VoicePar[nvoice].PFMDetuneType),0,pars->VoicePar[nvoice].PFMDetune)); -} -void ADvoiceUI::cb_fmdetunevalueoutput(Fl_Value_Output* o, void* v) { - ((ADvoiceUI*)(o->parent()->parent()->parent()->parent()->parent()->user_data()))->cb_fmdetunevalueoutput_i(o,v); -} - -void ADvoiceUI::cb_Detune_i(Fl_Choice* o, void*) { - pars->VoicePar[nvoice].PFMDetuneType=(int) o->value(); -fmdetunevalueoutput->do_callback(); -} -void ADvoiceUI::cb_Detune(Fl_Choice* o, void* v) { - ((ADvoiceUI*)(o->parent()->parent()->parent()->parent()->parent()->user_data()))->cb_Detune_i(o,v); -} - -void ADvoiceUI::cb_Vol_i(Fl_Value_Slider* o, void*) { - pars->VoicePar[nvoice].PFMVolume=(int)o->value(); -} -void ADvoiceUI::cb_Vol(Fl_Value_Slider* o, void* v) { - ((ADvoiceUI*)(o->parent()->parent()->parent()->parent()->parent()->user_data()))->cb_Vol_i(o,v); -} - -void ADvoiceUI::cb_V_i(Fl_Value_Slider* o, void*) { - pars->VoicePar[nvoice].PFMVelocityScaleFunction=(int) o->value(); -} -void ADvoiceUI::cb_V(Fl_Value_Slider* o, void* v) { - ((ADvoiceUI*)(o->parent()->parent()->parent()->parent()->parent()->user_data()))->cb_V_i(o,v); -} - -void ADvoiceUI::cb_Enable1_i(Fl_Check_Button* o, void*) { - pars->VoicePar[nvoice].PFMAmpEnvelopeEnabled=(int)o->value(); -if (o->value()==0) voiceFMampenvgroup->deactivate(); -else voiceFMampenvgroup->activate(); -o->redraw(); -} -void ADvoiceUI::cb_Enable1(Fl_Check_Button* o, void* v) { - ((ADvoiceUI*)(o->parent()->parent()->parent()->parent()->parent()->user_data()))->cb_Enable1_i(o,v); -} - -void ADvoiceUI::cb_F_i(Fl_Value_Slider* o, void*) { - pars->VoicePar[nvoice].PFMVolumeDamp=(int) o->value()+64; -} -void ADvoiceUI::cb_F(Fl_Value_Slider* o, void* v) { - ((ADvoiceUI*)(o->parent()->parent()->parent()->parent()->parent()->user_data()))->cb_F_i(o,v); -} - -void ADvoiceUI::cb_changeFMoscilbutton_i(Fl_Button*, void*) { - if (oscedit!=NULL) delete(oscedit); - -int nv=nvoice; -if (pars->VoicePar[nvoice].PextFMoscil>=0) nv=pars->VoicePar[nvoice].PextFMoscil; - -oscedit=new OscilEditor(pars->VoicePar[nv].FMSmp,fmoscil,NULL,NULL,master); -} -void ADvoiceUI::cb_changeFMoscilbutton(Fl_Button* o, void* v) { - ((ADvoiceUI*)(o->parent()->parent()->parent()->parent()->parent()->user_data()))->cb_changeFMoscilbutton_i(o,v); -} - -void ADvoiceUI::cb_Phase_i(Fl_Slider* o, void*) { - pars->VoicePar[nvoice].PFMoscilphase=64-(int)o->value(); -oscFM->phase=64-(int) o->value(); -fmoscil->redraw(); -} -void ADvoiceUI::cb_Phase(Fl_Slider* o, void* v) { - ((ADvoiceUI*)(o->parent()->parent()->parent()->parent()->parent()->user_data()))->cb_Phase_i(o,v); -} - -void ADvoiceUI::cb_Use_i(Fl_Choice* o, void*) { - pars->VoicePar[nvoice].PextFMoscil=(int)o->value()-1; -if ((int) o->value() != 0) { - oscFM->init(pars->VoicePar[(int) o->value()-1].FMSmp,master); - changeFMoscilbutton->labelcolor(FL_BLUE); -} else { - oscFM->init(pars->VoicePar[nvoice].FMSmp,master); - changeFMoscilbutton->labelcolor(FL_BLACK); -}; -voiceFMparametersgroup->redraw(); -} -void ADvoiceUI::cb_Use(Fl_Choice* o, void* v) { - ((ADvoiceUI*)(o->parent()->parent()->parent()->parent()->parent()->user_data()))->cb_Use_i(o,v); -} - -void ADvoiceUI::cb_External_i(Fl_Choice* o, void*) { - pars->VoicePar[nvoice].PFMVoice=(int)o->value()-1; -if ((int) o->value() != 0) { - modoscil->deactivate(); - modfrequency->deactivate(); -} else { - modoscil->activate(); - modfrequency->activate(); -}; -voiceFMparametersgroup->redraw(); -} -void ADvoiceUI::cb_External(Fl_Choice* o, void* v) { - ((ADvoiceUI*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_External_i(o,v); -} - -void ADvoiceUI::cb_Type_i(Fl_Choice* o, void*) { - pars->VoicePar[nvoice].PFMEnabled=(int)o->value(); -if (o->value()==0) voiceFMparametersgroup->deactivate(); -else voiceFMparametersgroup->activate(); -o->redraw(); -} -void ADvoiceUI::cb_Type(Fl_Choice* o, void* v) { - ((ADvoiceUI*)(o->parent()->parent()->parent()->user_data()))->cb_Type_i(o,v); -} - -Fl_Menu_Item ADvoiceUI::menu_Type[] = { - {"OFF", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 14, 0}, - {"MORPH", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 14, 0}, - {"RING", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 14, 0}, - {"PM", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 14, 0}, - {"FM", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 14, 0}, - {"PITCH", 0, 0, 0, 1, FL_NORMAL_LABEL, 1, 14, 0}, - {0,0,0,0,0,0,0,0,0} -}; - -void ADvoiceUI::cb_Enable2_i(Fl_Check_Button* o, void*) { - pars->VoicePar[nvoice].PFreqEnvelopeEnabled=(int)o->value(); -if (o->value()==0) voicefreqenvgroup->deactivate(); -else voicefreqenvgroup->activate(); -o->redraw(); -} -void ADvoiceUI::cb_Enable2(Fl_Check_Button* o, void* v) { - ((ADvoiceUI*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_Enable2_i(o,v); -} - -void ADvoiceUI::cb_Enable3_i(Fl_Check_Button* o, void*) { - pars->VoicePar[nvoice].PFreqLfoEnabled=(int)o->value(); -if (o->value()==0) voicefreqlfogroup->deactivate(); -else voicefreqlfogroup->activate(); -o->redraw(); -} -void ADvoiceUI::cb_Enable3(Fl_Check_Button* o, void* v) { - ((ADvoiceUI*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_Enable3_i(o,v); -} - -void ADvoiceUI::cb_Octave1_i(Fl_Counter* o, void*) { - int k=(int) o->value(); -if (k<0) k+=16; -pars->VoicePar[nvoice].PCoarseDetune = k*1024+ - pars->VoicePar[nvoice].PCoarseDetune%1024; -} -void ADvoiceUI::cb_Octave1(Fl_Counter* o, void* v) { - ((ADvoiceUI*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_Octave1_i(o,v); -} - -void ADvoiceUI::cb_Coarse1_i(Fl_Counter* o, void*) { - int k=(int) o->value(); -if (k<0) k+=1024; -pars->VoicePar[nvoice].PCoarseDetune = k+ - (pars->VoicePar[nvoice].PCoarseDetune/1024)*1024; -} -void ADvoiceUI::cb_Coarse1(Fl_Counter* o, void* v) { - ((ADvoiceUI*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_Coarse1_i(o,v); -} - -void ADvoiceUI::cb_1_i(Fl_Slider* o, void*) { - pars->VoicePar[nvoice].PDetune=(int)o->value()+8192; -detunevalueoutput->do_callback(); -} -void ADvoiceUI::cb_1(Fl_Slider* o, void* v) { - ((ADvoiceUI*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_1_i(o,v); -} - -void ADvoiceUI::cb_detunevalueoutput1_i(Fl_Value_Output* o, void*) { - o->value(getdetune((pars->VoicePar[nvoice].PDetuneType==0)?(pars->GlobalPar.PDetuneType) : (pars->VoicePar[nvoice].PDetuneType),0,pars->VoicePar[nvoice].PDetune)*pars->getBandwidthDetuneMultiplier()); -} -void ADvoiceUI::cb_detunevalueoutput1(Fl_Value_Output* o, void* v) { - ((ADvoiceUI*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_detunevalueoutput1_i(o,v); -} - -void ADvoiceUI::cb_440Hz_i(Fl_Check_Button* o, void*) { - int x=(int) o->value(); -pars->VoicePar[nvoice].Pfixedfreq=x; -if (x==0) fixedfreqetdial->deactivate(); - else fixedfreqetdial->activate(); -} -void ADvoiceUI::cb_440Hz(Fl_Check_Button* o, void* v) { - ((ADvoiceUI*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_440Hz_i(o,v); -} - -void ADvoiceUI::cb_fixedfreqetdial_i(WidgetPDial* o, void*) { - pars->VoicePar[nvoice].PfixedfreqET=(int) o->value(); -} -void ADvoiceUI::cb_fixedfreqetdial(WidgetPDial* o, void* v) { - ((ADvoiceUI*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_fixedfreqetdial_i(o,v); -} - -void ADvoiceUI::cb_Detune1_i(Fl_Choice* o, void*) { - pars->VoicePar[nvoice].PDetuneType=(int) o->value(); -detunevalueoutput->do_callback(); -} -void ADvoiceUI::cb_Detune1(Fl_Choice* o, void* v) { - ((ADvoiceUI*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_Detune1_i(o,v); -} - -void ADvoiceUI::cb_changevoiceoscilbutton_i(Fl_Button*, void*) { - if (oscedit!=NULL) delete(oscedit); - -int nv=nvoice; -if (pars->VoicePar[nvoice].Pextoscil>=0) nv=pars->VoicePar[nvoice].Pextoscil; - -oscedit=new OscilEditor(pars->VoicePar[nv].OscilSmp,voiceoscil,NULL,NULL,master); -} -void ADvoiceUI::cb_changevoiceoscilbutton(Fl_Button* o, void* v) { - ((ADvoiceUI*)(o->parent()->parent()->parent()->user_data()))->cb_changevoiceoscilbutton_i(o,v); -} - -void ADvoiceUI::cb_Phase1_i(Fl_Slider* o, void*) { - pars->VoicePar[nvoice].Poscilphase=64-(int)o->value(); -osc->phase=64-(int) o->value(); -voiceoscil->redraw(); -} -void ADvoiceUI::cb_Phase1(Fl_Slider* o, void* v) { - ((ADvoiceUI*)(o->parent()->parent()->parent()->user_data()))->cb_Phase1_i(o,v); -} - -void ADvoiceUI::cb_R_i(Fl_Check_Button* o, void*) { - pars->VoicePar[nvoice].Presonance=(int) o->value(); -} -void ADvoiceUI::cb_R(Fl_Check_Button* o, void* v) { - ((ADvoiceUI*)(o->parent()->parent()->parent()->user_data()))->cb_R_i(o,v); -} - -void ADvoiceUI::cb_Use1_i(Fl_Choice* o, void*) { - pars->VoicePar[nvoice].Pextoscil=(int)o->value()-1; -if ((int) o->value() != 0) { - osc->init(pars->VoicePar[(int) o->value()-1].OscilSmp,master); - changevoiceoscilbutton->labelcolor(FL_BLUE); -} else { - osc->init(pars->VoicePar[nvoice].OscilSmp,master); - changevoiceoscilbutton->labelcolor(FL_BLACK); -}; - -voiceparametersgroup->redraw(); -voiceonbutton->redraw(); -} -void ADvoiceUI::cb_Use1(Fl_Choice* o, void* v) { - ((ADvoiceUI*)(o->parent()->parent()->parent()->user_data()))->cb_Use1_i(o,v); -} - -void ADvoiceUI::cb_Stereo_i(WidgetPDial* o, void*) { - pars->VoicePar[nvoice].Unison_stereo_spread=(int)o->value(); -} -void ADvoiceUI::cb_Stereo(WidgetPDial* o, void* v) { - ((ADvoiceUI*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_Stereo_i(o,v); -} - -void ADvoiceUI::cb_Unison_i(Fl_Choice* o, void*) { - pars->set_unison_size_index(nvoice,(int) o->value()); -} -void ADvoiceUI::cb_Unison(Fl_Choice* o, void* v) { - ((ADvoiceUI*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_Unison_i(o,v); -} - -void ADvoiceUI::cb_Vibratto_i(WidgetPDial* o, void*) { - pars->VoicePar[nvoice].Unison_vibratto=(int)o->value(); -} -void ADvoiceUI::cb_Vibratto(WidgetPDial* o, void* v) { - ((ADvoiceUI*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_Vibratto_i(o,v); -} - -void ADvoiceUI::cb_Invert_i(Fl_Choice* o, void*) { - pars->VoicePar[nvoice].Unison_invert_phase=(int) o->value(); -} -void ADvoiceUI::cb_Invert(Fl_Choice* o, void* v) { - ((ADvoiceUI*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_Invert_i(o,v); -} - -void ADvoiceUI::cb_Frequency_i(Fl_Slider* o, void*) { - pars->VoicePar[nvoice].Unison_frequency_spread=(int)o->value(); -unisonspreadoutput->do_callback(); -} -void ADvoiceUI::cb_Frequency(Fl_Slider* o, void* v) { - ((ADvoiceUI*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_Frequency_i(o,v); -} - -void ADvoiceUI::cb_unisonspreadoutput_i(Fl_Value_Output* o, void*) { - o->value(pars->getUnisonFrequencySpreadCents(nvoice)); -} -void ADvoiceUI::cb_unisonspreadoutput(Fl_Value_Output* o, void* v) { - ((ADvoiceUI*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_unisonspreadoutput_i(o,v); -} - -void ADvoiceUI::cb_Vib_i(WidgetPDial* o, void*) { - pars->VoicePar[nvoice].Unison_vibratto_speed=(int)o->value(); -} -void ADvoiceUI::cb_Vib(WidgetPDial* o, void* v) { - ((ADvoiceUI*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_Vib_i(o,v); -} - -void ADvoiceUI::cb_Vol1_i(Fl_Value_Slider* o, void*) { - pars->VoicePar[nvoice].PVolume=(int)o->value(); -} -void ADvoiceUI::cb_Vol1(Fl_Value_Slider* o, void* v) { - ((ADvoiceUI*)(o->parent()->parent()->parent()->user_data()))->cb_Vol1_i(o,v); -} - -void ADvoiceUI::cb_V1_i(Fl_Value_Slider* o, void*) { - pars->VoicePar[nvoice].PAmpVelocityScaleFunction=(int) o->value(); -} -void ADvoiceUI::cb_V1(Fl_Value_Slider* o, void* v) { - ((ADvoiceUI*)(o->parent()->parent()->parent()->user_data()))->cb_V1_i(o,v); -} - -void ADvoiceUI::cb_Pan_i(WidgetPDial* o, void*) { - pars->VoicePar[nvoice].PPanning=(int) o->value(); -} -void ADvoiceUI::cb_Pan(WidgetPDial* o, void* v) { - ((ADvoiceUI*)(o->parent()->parent()->parent()->user_data()))->cb_Pan_i(o,v); -} - -void ADvoiceUI::cb_Enable4_i(Fl_Check_Button* o, void*) { - pars->VoicePar[nvoice].PAmpEnvelopeEnabled=(int)o->value(); -if (o->value()==0) voiceampenvgroup->deactivate(); -else voiceampenvgroup->activate(); -o->redraw(); -} -void ADvoiceUI::cb_Enable4(Fl_Check_Button* o, void* v) { - ((ADvoiceUI*)(o->parent()->parent()->parent()->user_data()))->cb_Enable4_i(o,v); -} - -void ADvoiceUI::cb_Enable5_i(Fl_Check_Button* o, void*) { - pars->VoicePar[nvoice].PAmpLfoEnabled=(int)o->value(); -if (o->value()==0) voiceamplfogroup->deactivate(); -else voiceamplfogroup->activate(); -o->redraw(); -} -void ADvoiceUI::cb_Enable5(Fl_Check_Button* o, void* v) { - ((ADvoiceUI*)(o->parent()->parent()->parent()->user_data()))->cb_Enable5_i(o,v); -} - -void ADvoiceUI::cb_Minus_i(Fl_Check_Button* o, void*) { - pars->VoicePar[nvoice].PVolumeminus=(int)o->value(); -} -void ADvoiceUI::cb_Minus(Fl_Check_Button* o, void* v) { - ((ADvoiceUI*)(o->parent()->parent()->parent()->user_data()))->cb_Minus_i(o,v); -} - -void ADvoiceUI::cb_Enable6_i(Fl_Check_Button* o, void*) { - pars->VoicePar[nvoice].PFilterEnvelopeEnabled=(int)o->value(); -if (o->value()==0) voicefilterenvgroup->deactivate(); -else voicefilterenvgroup->activate(); -o->redraw(); -} -void ADvoiceUI::cb_Enable6(Fl_Check_Button* o, void* v) { - ((ADvoiceUI*)(o->parent()->parent()->parent()->user_data()))->cb_Enable6_i(o,v); -} - -void ADvoiceUI::cb_Enable7_i(Fl_Check_Button* o, void*) { - pars->VoicePar[nvoice].PFilterLfoEnabled=(int)o->value(); -if (o->value()==0) voicefilterlfogroup->deactivate(); -else voicefilterlfogroup->activate(); -o->redraw(); -} -void ADvoiceUI::cb_Enable7(Fl_Check_Button* o, void* v) { - ((ADvoiceUI*)(o->parent()->parent()->parent()->user_data()))->cb_Enable7_i(o,v); -} - -void ADvoiceUI::cb_2_i(Fl_Choice* o, void*) { - int x=(int) o->value(); -pars->VoicePar[nvoice].Type=x; -if (x==0) voicemodegroup->activate(); - else voicemodegroup->deactivate(); -noiselabel->do_callback(); -} -void ADvoiceUI::cb_2(Fl_Choice* o, void* v) { - ((ADvoiceUI*)(o->parent()->parent()->user_data()))->cb_2_i(o,v); -} - -Fl_Menu_Item ADvoiceUI::menu_[] = { - {"Sound", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 11, 0}, - {"NOISE", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 11, 1}, - {0,0,0,0,0,0,0,0,0} -}; - -void ADvoiceUI::cb_bypassfiltercheckbutton_i(Fl_Check_Button* o, void*) { - pars->VoicePar[nvoice].Pfilterbypass=(int)o->value(); -} -void ADvoiceUI::cb_bypassfiltercheckbutton(Fl_Check_Button* o, void* v) { - ((ADvoiceUI*)(o->parent()->parent()->user_data()))->cb_bypassfiltercheckbutton_i(o,v); -} - -void ADvoiceUI::cb_Delay_i(Fl_Value_Slider* o, void*) { - pars->VoicePar[nvoice].PDelay=(int)o->value(); -} -void ADvoiceUI::cb_Delay(Fl_Value_Slider* o, void* v) { - ((ADvoiceUI*)(o->parent()->parent()->parent()->user_data()))->cb_Delay_i(o,v); -} - -void ADvoiceUI::cb_Enable8_i(Fl_Check_Button* o, void*) { - pars->VoicePar[nvoice].PFilterEnabled=(int)o->value(); -if (o->value()==0) voicefiltergroup->deactivate(); -else voicefiltergroup->activate(); -o->redraw(); -bypassfiltercheckbutton->redraw(); -} -void ADvoiceUI::cb_Enable8(Fl_Check_Button* o, void* v) { - ((ADvoiceUI*)(o->parent()->parent()->user_data()))->cb_Enable8_i(o,v); -} - -void ADvoiceUI::cb_noiselabel1_i(Fl_Box* o, void*) { - if (pars->VoicePar[nvoice].Type==0) o->hide(); else o->show(); -} -void ADvoiceUI::cb_noiselabel1(Fl_Box* o, void* v) { - ((ADvoiceUI*)(o->parent()->parent()->user_data()))->cb_noiselabel1_i(o,v); -} - -void ADvoiceUI::cb_voiceonbutton_i(Fl_Check_Button* o, void*) { - pars->VoicePar[nvoice].Enabled=(int)o->value(); -if (o->value()==0) voiceparametersgroup->deactivate(); -else voiceparametersgroup->activate(); -o->redraw(); -} -void ADvoiceUI::cb_voiceonbutton(Fl_Check_Button* o, void* v) { - ((ADvoiceUI*)(o->parent()->user_data()))->cb_voiceonbutton_i(o,v); -} - -Fl_Group* ADvoiceUI::make_window() { - { ADnoteVoiceParameters = new Fl_Group(0, 0, 765, 575, "Voice"); - ADnoteVoiceParameters->box(FL_FLAT_BOX); - ADnoteVoiceParameters->color(FL_BACKGROUND_COLOR); - ADnoteVoiceParameters->selection_color(FL_BACKGROUND_COLOR); - ADnoteVoiceParameters->labeltype(FL_NO_LABEL); - ADnoteVoiceParameters->labelfont(0); - ADnoteVoiceParameters->labelsize(14); - ADnoteVoiceParameters->labelcolor(FL_FOREGROUND_COLOR); - ADnoteVoiceParameters->user_data((void*)(this)); - ADnoteVoiceParameters->align(Fl_Align(FL_ALIGN_TOP)); - ADnoteVoiceParameters->when(FL_WHEN_RELEASE); - { Fl_Group* o = voiceparametersgroup = new Fl_Group(0, 0, 765, 580); - voiceparametersgroup->box(FL_THIN_UP_BOX); - voiceparametersgroup->color((Fl_Color)48); - { voicemodegroup = new Fl_Group(0, 5, 760, 575); - { Fl_Group* o = voiceFMparametersgroup = new Fl_Group(530, 5, 230, 565, "MODULATOR"); - voiceFMparametersgroup->box(FL_THIN_UP_FRAME); - voiceFMparametersgroup->color((Fl_Color)48); - voiceFMparametersgroup->labeltype(FL_EMBOSSED_LABEL); - voiceFMparametersgroup->labelfont(1); - voiceFMparametersgroup->labelsize(13); - voiceFMparametersgroup->align(Fl_Align(FL_ALIGN_TOP|FL_ALIGN_INSIDE)); - { modfrequency = new Fl_Group(535, 220, 220, 145, "Mod.FREQUENCY"); - modfrequency->box(FL_THIN_UP_BOX); - modfrequency->labeltype(FL_EMBOSSED_LABEL); - modfrequency->labelfont(1); - modfrequency->labelsize(13); - modfrequency->align(Fl_Align(FL_ALIGN_TOP|FL_ALIGN_INSIDE)); - { EnvelopeUI* o = voiceFMfreqenvgroup = new EnvelopeUI(540, 290, 205, 70, "ADSynth Modulator - Frequency Envelope"); - voiceFMfreqenvgroup->box(FL_FLAT_BOX); - voiceFMfreqenvgroup->color((Fl_Color)51); - voiceFMfreqenvgroup->selection_color(FL_BACKGROUND_COLOR); - voiceFMfreqenvgroup->labeltype(FL_NORMAL_LABEL); - voiceFMfreqenvgroup->labelfont(0); - voiceFMfreqenvgroup->labelsize(14); - voiceFMfreqenvgroup->labelcolor(FL_FOREGROUND_COLOR); - voiceFMfreqenvgroup->align(Fl_Align(FL_ALIGN_WRAP|FL_ALIGN_INSIDE)); - voiceFMfreqenvgroup->when(FL_WHEN_RELEASE); - o->init(pars->VoicePar[nvoice].FMFreqEnvelope); - if (pars->VoicePar[nvoice].PFMFreqEnvelopeEnabled==0) o->deactivate(); - voiceFMfreqenvgroup->end(); - } // EnvelopeUI* voiceFMfreqenvgroup - { Fl_Check_Button* o = new Fl_Check_Button(545, 295, 50, 10, "Enable"); - o->tooltip("Forced Relase"); - o->down_box(FL_DOWN_BOX); - o->labelfont(1); - o->labelsize(10); - o->callback((Fl_Callback*)cb_Enable); - o->value(pars->VoicePar[nvoice].PFMFreqEnvelopeEnabled); - } // Fl_Check_Button* o - { Fl_Counter* o = new Fl_Counter(685, 270, 60, 15, "Coarse Det."); - o->tooltip("Coarse Detune"); - o->labelsize(10); - o->minimum(-64); - o->maximum(63); - o->step(1); - o->textfont(1); - o->textsize(11); - o->callback((Fl_Callback*)cb_Coarse); - o->align(Fl_Align(FL_ALIGN_TOP)); - int k=pars->VoicePar[nvoice].PFMCoarseDetune%1024; - if (k>=512) k-=1024; - o->value(k); - o->lstep(10); - } // Fl_Counter* o - { Fl_Counter* o = new Fl_Counter(625, 270, 45, 15, "Octave"); - o->tooltip("Octave"); - o->type(1); - o->labelsize(10); - o->minimum(-8); - o->maximum(7); - o->step(1); - o->textfont(1); - o->textsize(11); - o->callback((Fl_Callback*)cb_Octave); - o->align(Fl_Align(FL_ALIGN_TOP)); - int k=pars->VoicePar[nvoice].PFMCoarseDetune/1024; - if (k>=8) k-=16; - o->value(k); - } // Fl_Counter* o - { Fl_Slider* o = new Fl_Slider(590, 245, 160, 10); - o->tooltip("Fine Detune (cents)"); - o->type(5); - o->box(FL_FLAT_BOX); - o->minimum(-8192); - o->maximum(8191); - o->step(1); - o->callback((Fl_Callback*)cb_); - o->value(pars->VoicePar[nvoice].PFMDetune-8192); - } // Fl_Slider* o - { Fl_Value_Output* o = fmdetunevalueoutput = new Fl_Value_Output(540, 245, 45, 13, "Detune"); - fmdetunevalueoutput->labelsize(8); - fmdetunevalueoutput->minimum(-5000); - fmdetunevalueoutput->maximum(5000); - fmdetunevalueoutput->step(0.01); - fmdetunevalueoutput->textfont(1); - fmdetunevalueoutput->textsize(8); - fmdetunevalueoutput->callback((Fl_Callback*)cb_fmdetunevalueoutput); - fmdetunevalueoutput->align(Fl_Align(FL_ALIGN_TOP_LEFT)); - o->value(getdetune((pars->VoicePar[nvoice].PFMDetuneType==0)?(pars->GlobalPar.PDetuneType) : (pars->VoicePar[nvoice].PFMDetuneType),0,pars->VoicePar[nvoice].PFMDetune)); - //o->value(getdetune(pars->VoicePar[nvoice].PFMDetuneType,0,pars->VoicePar[nvoice].PFMDetune)); - } // Fl_Value_Output* fmdetunevalueoutput - { Fl_Choice* o = new Fl_Choice(540, 270, 75, 15, "Detune Type"); - o->down_box(FL_BORDER_BOX); - o->labelsize(10); - o->textfont(1); - o->textsize(10); - o->callback((Fl_Callback*)cb_Detune); - o->align(Fl_Align(FL_ALIGN_TOP_LEFT)); - o->add("Default");o->add("L35cents");o->add("L10cents");o->add("E100cents");o->add("E1200cents"); - o->value(pars->VoicePar[nvoice].PFMDetuneType); - } // Fl_Choice* o - modfrequency->end(); - } // Fl_Group* modfrequency - { Fl_Group* o = new Fl_Group(535, 60, 220, 160, "Mod.AMPLITUDE"); - o->box(FL_THIN_UP_BOX); - o->labeltype(FL_EMBOSSED_LABEL); - o->labelfont(1); - o->labelsize(13); - o->align(Fl_Align(FL_ALIGN_TOP|FL_ALIGN_INSIDE)); - { Fl_Value_Slider* o = new Fl_Value_Slider(540, 80, 160, 15, "Vol"); - o->tooltip("Volume"); - o->type(5); - o->box(FL_FLAT_BOX); - o->labelsize(11); - o->maximum(127); - o->step(1); - o->callback((Fl_Callback*)cb_Vol); - o->align(Fl_Align(FL_ALIGN_RIGHT)); - o->value(pars->VoicePar[nvoice].PFMVolume); - } // Fl_Value_Slider* o - { Fl_Value_Slider* o = new Fl_Value_Slider(540, 100, 160, 15, "V.Sns"); - o->tooltip("Velocity Sensing Function (rightmost to disable)"); - o->type(5); - o->box(FL_FLAT_BOX); - o->labelsize(11); - o->maximum(127); - o->step(1); - o->callback((Fl_Callback*)cb_V); - o->align(Fl_Align(FL_ALIGN_RIGHT)); - o->value(pars->VoicePar[nvoice].PFMVelocityScaleFunction); - } // Fl_Value_Slider* o - { EnvelopeUI* o = voiceFMampenvgroup = new EnvelopeUI(540, 145, 205, 70, "ADSynth Modulator - Amplitude Envelope"); - voiceFMampenvgroup->box(FL_FLAT_BOX); - voiceFMampenvgroup->color((Fl_Color)51); - voiceFMampenvgroup->selection_color(FL_BACKGROUND_COLOR); - voiceFMampenvgroup->labeltype(FL_NORMAL_LABEL); - voiceFMampenvgroup->labelfont(0); - voiceFMampenvgroup->labelsize(14); - voiceFMampenvgroup->labelcolor(FL_FOREGROUND_COLOR); - voiceFMampenvgroup->align(Fl_Align(FL_ALIGN_WRAP|FL_ALIGN_INSIDE)); - voiceFMampenvgroup->when(FL_WHEN_RELEASE); - o->init(pars->VoicePar[nvoice].FMAmpEnvelope); - if (pars->VoicePar[nvoice].PFMAmpEnvelopeEnabled==0) o->deactivate(); - voiceFMampenvgroup->end(); - } // EnvelopeUI* voiceFMampenvgroup - { Fl_Check_Button* o = new Fl_Check_Button(545, 150, 50, 10, "Enable"); - o->tooltip("Forced Relase"); - o->down_box(FL_DOWN_BOX); - o->labelfont(1); - o->labelsize(10); - o->callback((Fl_Callback*)cb_Enable1); - o->value(pars->VoicePar[nvoice].PFMAmpEnvelopeEnabled); - } // Fl_Check_Button* o - { Fl_Value_Slider* o = new Fl_Value_Slider(540, 120, 160, 15, "F.Damp"); - o->tooltip("Modulator Damp at Higher frequency"); - o->type(5); - o->box(FL_FLAT_BOX); - o->labelsize(11); - o->minimum(-64); - o->maximum(63); - o->step(1); - o->callback((Fl_Callback*)cb_F); - o->align(Fl_Align(FL_ALIGN_RIGHT)); - o->value(pars->VoicePar[nvoice].PFMVolumeDamp-64); - } // Fl_Value_Slider* o - o->end(); - } // Fl_Group* o - { modoscil = new Fl_Group(535, 365, 220, 200); - { Fl_Group* o = fmoscil = new Fl_Group(535, 425, 220, 140); - fmoscil->box(FL_THIN_DOWN_BOX); - fmoscil->color(FL_GRAY0); - fmoscil->selection_color((Fl_Color)71); - fmoscil->labelcolor((Fl_Color)179); - oscFM=new Oscilloscope(o->x(),o->y(),o->w(),o->h(),""); - int nv=nvoice; if (pars->VoicePar[nvoice].PextFMoscil>=0) nv=pars->VoicePar[nvoice].PextFMoscil; - oscFM->init(pars->VoicePar[nv].FMSmp,0,pars->VoicePar[nvoice].PFMoscilphase,master); - fmoscil->end(); - } // Fl_Group* fmoscil - { Fl_Box* o = new Fl_Box(535, 365, 155, 20, "Mod.Oscillator"); - o->labelfont(1); - o->align(Fl_Align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE)); - } // Fl_Box* o - { Fl_Button* o = changeFMoscilbutton = new Fl_Button(700, 370, 55, 15, "Change"); - changeFMoscilbutton->box(FL_THIN_UP_BOX); - changeFMoscilbutton->labelfont(1); - changeFMoscilbutton->labelsize(11); - changeFMoscilbutton->callback((Fl_Callback*)cb_changeFMoscilbutton); - if (pars->VoicePar[nvoice].PextFMoscil>=0) o->labelcolor(FL_BLUE); - } // Fl_Button* changeFMoscilbutton - { Fl_Slider* o = new Fl_Slider(665, 400, 65, 10, "Phase"); - o->type(5); - o->box(FL_FLAT_BOX); - o->labelsize(10); - o->minimum(-64); - o->maximum(63); - o->step(1); - o->callback((Fl_Callback*)cb_Phase); - o->align(Fl_Align(FL_ALIGN_TOP_LEFT)); - o->value(64-pars->VoicePar[nvoice].PFMoscilphase); - } // Fl_Slider* o - { Fl_Choice* o = new Fl_Choice(560, 395, 75, 15, "Use"); - o->down_box(FL_BORDER_BOX); - o->labelsize(10); - o->textfont(1); - o->textsize(10); - o->callback((Fl_Callback*)cb_Use); - o->add("Internal"); - char tmp[50]; for (int i=0;iadd(tmp);}; - o->value(pars->VoicePar[nvoice].PextFMoscil+1); - } // Fl_Choice* o - modoscil->end(); - } // Fl_Group* modoscil - { Fl_Choice* o = new Fl_Choice(635, 40, 85, 20, "External Mod."); - o->down_box(FL_BORDER_BOX); - o->labelsize(10); - o->textfont(1); - o->textsize(10); - o->callback((Fl_Callback*)cb_External); - o->align(Fl_Align(FL_ALIGN_TOP_LEFT)); - o->add("OFF"); - char tmp[50]; for (int i=0;iadd(tmp);}; - o->value(pars->VoicePar[nvoice].PFMVoice+1); - if ((int) o->value() != 0) {modoscil->deactivate();modfrequency->deactivate();} - } // Fl_Choice* o - if (pars->VoicePar[nvoice].PFMEnabled==0) o->deactivate(); - voiceFMparametersgroup->end(); - } // Fl_Group* voiceFMparametersgroup - { Fl_Choice* o = new Fl_Choice(535, 40, 80, 20, "Type:"); - o->down_box(FL_BORDER_BOX); - o->callback((Fl_Callback*)cb_Type); - o->align(Fl_Align(FL_ALIGN_TOP_LEFT)); - o->menu(menu_Type); - o->value(pars->VoicePar[nvoice].PFMEnabled); - } // Fl_Choice* o - { Fl_Group* o = new Fl_Group(5, 250, 525, 120, "FREQUENCY"); - o->box(FL_THIN_UP_BOX); - o->labeltype(FL_EMBOSSED_LABEL); - o->labelfont(1); - o->labelsize(13); - o->align(Fl_Align(FL_ALIGN_TOP|FL_ALIGN_INSIDE)); - { EnvelopeUI* o = voicefreqenvgroup = new EnvelopeUI(10, 290, 205, 70, "ADSynth Voice - Frequency Envelope"); - voicefreqenvgroup->box(FL_FLAT_BOX); - voicefreqenvgroup->color((Fl_Color)51); - voicefreqenvgroup->selection_color(FL_BACKGROUND_COLOR); - voicefreqenvgroup->labeltype(FL_NORMAL_LABEL); - voicefreqenvgroup->labelfont(0); - voicefreqenvgroup->labelsize(14); - voicefreqenvgroup->labelcolor(FL_FOREGROUND_COLOR); - voicefreqenvgroup->align(Fl_Align(FL_ALIGN_WRAP|FL_ALIGN_INSIDE)); - voicefreqenvgroup->when(FL_WHEN_RELEASE); - o->init(pars->VoicePar[nvoice].FreqEnvelope); - if (pars->VoicePar[nvoice].PFreqEnvelopeEnabled==0) o->deactivate(); - voicefreqenvgroup->end(); - } // EnvelopeUI* voicefreqenvgroup - { Fl_Check_Button* o = new Fl_Check_Button(15, 295, 50, 10, "Enable"); - o->tooltip("Forced Relase"); - o->down_box(FL_DOWN_BOX); - o->labelfont(1); - o->labelsize(10); - o->callback((Fl_Callback*)cb_Enable2); - o->value(pars->VoicePar[nvoice].PFreqEnvelopeEnabled); - } // Fl_Check_Button* o - { LFOUI* o = voicefreqlfogroup = new LFOUI(215, 290, 230, 70, "Frequency LFO "); - voicefreqlfogroup->box(FL_FLAT_BOX); - voicefreqlfogroup->color(FL_DARK1); - voicefreqlfogroup->selection_color(FL_BACKGROUND_COLOR); - voicefreqlfogroup->labeltype(FL_NORMAL_LABEL); - voicefreqlfogroup->labelfont(0); - voicefreqlfogroup->labelsize(14); - voicefreqlfogroup->labelcolor(FL_FOREGROUND_COLOR); - voicefreqlfogroup->align(Fl_Align(FL_ALIGN_WRAP|FL_ALIGN_INSIDE)); - voicefreqlfogroup->when(FL_WHEN_RELEASE); - o->init(pars->VoicePar[nvoice].FreqLfo); - if (pars->VoicePar[nvoice].PFreqLfoEnabled==0) o->deactivate(); - voicefreqlfogroup->end(); - } // LFOUI* voicefreqlfogroup - { Fl_Check_Button* o = new Fl_Check_Button(220, 295, 55, 10, "Enable"); - o->tooltip("Forced Relase"); - o->down_box(FL_DOWN_BOX); - o->labelfont(1); - o->labelsize(10); - o->callback((Fl_Callback*)cb_Enable3); - o->value(pars->VoicePar[nvoice].PFreqLfoEnabled); - } // Fl_Check_Button* o - { Fl_Counter* o = new Fl_Counter(470, 270, 45, 15, "Octave"); - o->tooltip("Octave"); - o->type(1); - o->labelsize(10); - o->minimum(-8); - o->maximum(7); - o->step(1); - o->textfont(1); - o->textsize(11); - o->callback((Fl_Callback*)cb_Octave1); - o->align(Fl_Align(FL_ALIGN_TOP)); - int k=pars->VoicePar[nvoice].PCoarseDetune/1024; - if (k>=8) k-=16; - o->value(k); - } // Fl_Counter* o - { Fl_Counter* o = new Fl_Counter(455, 340, 60, 20, "Coarse Det."); - o->tooltip("Coarse Detune"); - o->labelsize(10); - o->minimum(-64); - o->maximum(63); - o->step(1); - o->textfont(1); - o->textsize(11); - o->callback((Fl_Callback*)cb_Coarse1); - o->align(Fl_Align(FL_ALIGN_TOP)); - int k=pars->VoicePar[nvoice].PCoarseDetune%1024; - if (k>=512) k-=1024; - o->value(k); - o->lstep(10); - } // Fl_Counter* o - { Fl_Slider* o = new Fl_Slider(58, 272, 392, 13); - o->tooltip("Fine Detune (cents)"); - o->type(5); - o->box(FL_FLAT_BOX); - o->minimum(-8192); - o->maximum(8191); - o->step(1); - o->callback((Fl_Callback*)cb_1); - o->value(pars->VoicePar[nvoice].PDetune-8192); - } // Fl_Slider* o - { Fl_Value_Output* o = detunevalueoutput = new Fl_Value_Output(10, 272, 45, 15, "Detune"); - detunevalueoutput->labelsize(10); - detunevalueoutput->minimum(-5000); - detunevalueoutput->maximum(5000); - detunevalueoutput->step(0.01); - detunevalueoutput->textfont(1); - detunevalueoutput->textsize(10); - detunevalueoutput->callback((Fl_Callback*)cb_detunevalueoutput1); - detunevalueoutput->align(Fl_Align(FL_ALIGN_TOP_LEFT)); - o->value(getdetune((pars->VoicePar[nvoice].PDetuneType==0)?(pars->GlobalPar.PDetuneType) : (pars->VoicePar[nvoice].PDetuneType),0,pars->VoicePar[nvoice].PDetune)*pars->getBandwidthDetuneMultiplier()); - } // Fl_Value_Output* detunevalueoutput - { Fl_Check_Button* o = new Fl_Check_Button(345, 253, 55, 15, "440Hz"); - o->tooltip("Set the voice base frequency to 440Hz"); - o->down_box(FL_DOWN_BOX); - o->labelfont(1); - o->labelsize(11); - o->callback((Fl_Callback*)cb_440Hz); - o->value(pars->VoicePar[nvoice].Pfixedfreq); - } // Fl_Check_Button* o - { WidgetPDial* o = fixedfreqetdial = new WidgetPDial(405, 255, 15, 15, "Eq.T."); - fixedfreqetdial->tooltip("How the frequency varies acording to the keyboard (leftmost for fixed frequen\ -cy)"); - fixedfreqetdial->box(FL_ROUND_UP_BOX); - fixedfreqetdial->color(FL_BACKGROUND_COLOR); - fixedfreqetdial->selection_color(FL_INACTIVE_COLOR); - fixedfreqetdial->labeltype(FL_NORMAL_LABEL); - fixedfreqetdial->labelfont(0); - fixedfreqetdial->labelsize(10); - fixedfreqetdial->labelcolor(FL_FOREGROUND_COLOR); - fixedfreqetdial->maximum(127); - fixedfreqetdial->step(1); - fixedfreqetdial->callback((Fl_Callback*)cb_fixedfreqetdial); - fixedfreqetdial->align(Fl_Align(FL_ALIGN_RIGHT)); - fixedfreqetdial->when(FL_WHEN_CHANGED); - o->value(pars->VoicePar[nvoice].PfixedfreqET); - if (pars->VoicePar[nvoice].Pfixedfreq==0) o->deactivate(); - } // WidgetPDial* fixedfreqetdial - { Fl_Choice* o = new Fl_Choice(450, 305, 75, 15, "Detune Type"); - o->down_box(FL_BORDER_BOX); - o->labelsize(10); - o->textfont(1); - o->textsize(10); - o->callback((Fl_Callback*)cb_Detune1); - o->align(Fl_Align(FL_ALIGN_TOP_LEFT)); - o->add("Default");o->add("L35cents");o->add("L10cents");o->add("E100cents");o->add("E1200cents"); - o->value(pars->VoicePar[nvoice].PDetuneType); - } // Fl_Choice* o - o->end(); - } // Fl_Group* o - { Fl_Group* o = voiceoscil = new Fl_Group(80, 375, 445, 145); - voiceoscil->box(FL_THIN_DOWN_BOX); - voiceoscil->color(FL_GRAY0); - voiceoscil->selection_color((Fl_Color)71); - voiceoscil->labelcolor((Fl_Color)179); - osc=new Oscilloscope(o->x(),o->y(),o->w(),o->h(),""); - int nv=nvoice; if (pars->VoicePar[nvoice].Pextoscil>=0) nv=pars->VoicePar[nvoice].Pextoscil; - osc->init(pars->VoicePar[nv].OscilSmp,0,pars->VoicePar[nvoice].Poscilphase,master); - voiceoscil->end(); - } // Fl_Group* voiceoscil - { Fl_Button* o = changevoiceoscilbutton = new Fl_Button(5, 475, 65, 20, "Change"); - changevoiceoscilbutton->box(FL_THIN_UP_BOX); - changevoiceoscilbutton->labelfont(1); - changevoiceoscilbutton->labelsize(11); - changevoiceoscilbutton->callback((Fl_Callback*)cb_changevoiceoscilbutton); - if (pars->VoicePar[nvoice].Pextoscil>=0) o->labelcolor(FL_BLUE); - } // Fl_Button* changevoiceoscilbutton - { Fl_Box* o = new Fl_Box(5, 375, 75, 35, "Voice Oscillator"); - o->labelfont(1); - o->labelsize(12); - o->align(Fl_Align(FL_ALIGN_WRAP)); - } // Fl_Box* o - { Fl_Slider* o = new Fl_Slider(10, 420, 65, 10, "Phase"); - o->type(5); - o->box(FL_FLAT_BOX); - o->labelsize(10); - o->minimum(-64); - o->maximum(63); - o->step(1); - o->callback((Fl_Callback*)cb_Phase1); - o->align(Fl_Align(FL_ALIGN_TOP_LEFT)); - o->value(64-pars->VoicePar[nvoice].Poscilphase); - } // Fl_Slider* o - { Fl_Check_Button* o = new Fl_Check_Button(210, 5, 35, 35, "R."); - o->tooltip("Resonance On/Off"); - o->box(FL_THIN_UP_BOX); - o->down_box(FL_DOWN_BOX); - o->labelfont(1); - o->labelsize(11); - o->callback((Fl_Callback*)cb_R); - o->value(pars->VoicePar[nvoice].Presonance); - } // Fl_Check_Button* o - { Fl_Choice* o = new Fl_Choice(5, 455, 65, 15, "Use Oscil."); - o->down_box(FL_BORDER_BOX); - o->labelsize(10); - o->textfont(1); - o->textsize(10); - o->callback((Fl_Callback*)cb_Use1); - o->align(Fl_Align(FL_ALIGN_TOP_LEFT)); - o->add("Internal"); - char tmp[50]; for (int i=0;iadd(tmp);}; - o->value(pars->VoicePar[nvoice].Pextoscil+1); - } // Fl_Choice* o - { Fl_Group* o = new Fl_Group(5, 525, 515, 45); - o->box(FL_ENGRAVED_BOX); - { WidgetPDial* o = new WidgetPDial(285, 540, 25, 25, "Stereo"); - o->tooltip("Stereo Spread"); - o->box(FL_ROUND_UP_BOX); - o->color(FL_BACKGROUND_COLOR); - o->selection_color(FL_INACTIVE_COLOR); - o->labeltype(FL_NORMAL_LABEL); - o->labelfont(0); - o->labelsize(10); - o->labelcolor(FL_FOREGROUND_COLOR); - o->maximum(127); - o->step(1); - o->callback((Fl_Callback*)cb_Stereo); - o->align(Fl_Align(FL_ALIGN_TOP)); - o->when(FL_WHEN_CHANGED); - o->value(pars->VoicePar[nvoice].Unison_stereo_spread); - } // WidgetPDial* o - { Fl_Choice* o = new Fl_Choice(10, 545, 75, 20, "Unison"); - o->tooltip("Unison size"); - o->down_box(FL_BORDER_BOX); - o->labelfont(1); - o->textfont(1); - o->textsize(10); - o->callback((Fl_Callback*)cb_Unison); - o->align(Fl_Align(FL_ALIGN_TOP_LEFT)); - o->add("OFF");char tmp[100];for (int i=1;ADnote_unison_sizes[i];i++){snprintf(tmp,100,"size %d",ADnote_unison_sizes[i]);o->add(tmp);}; - o->value(pars->get_unison_size_index(nvoice)); - } // Fl_Choice* o - { WidgetPDial* o = new WidgetPDial(340, 540, 25, 25, "Vibratto"); - o->tooltip("Vibratto"); - o->box(FL_ROUND_UP_BOX); - o->color(FL_BACKGROUND_COLOR); - o->selection_color(FL_INACTIVE_COLOR); - o->labeltype(FL_NORMAL_LABEL); - o->labelfont(0); - o->labelsize(10); - o->labelcolor(FL_FOREGROUND_COLOR); - o->maximum(127); - o->step(1); - o->callback((Fl_Callback*)cb_Vibratto); - o->align(Fl_Align(FL_ALIGN_TOP)); - o->when(FL_WHEN_CHANGED); - o->value(pars->VoicePar[nvoice].Unison_vibratto); - } // WidgetPDial* o - { Fl_Choice* o = new Fl_Choice(445, 545, 65, 15, "Invert"); - o->tooltip("Phase Invert"); - o->down_box(FL_BORDER_BOX); - o->labelsize(11); - o->textfont(1); - o->textsize(10); - o->callback((Fl_Callback*)cb_Invert); - o->align(Fl_Align(FL_ALIGN_TOP_LEFT)); - o->add("None");o->add("Random");char tmp[100];for (int i=2;i<=5;i++){snprintf(tmp,100,"%d %%",100/i);o->add(tmp);}; - o->value(pars->VoicePar[nvoice].Unison_invert_phase); - } // Fl_Choice* o - { Fl_Slider* o = new Fl_Slider(95, 547, 125, 13, "Frequency Spread"); - o->tooltip("Frequency Spread of the Unison"); - o->type(5); - o->box(FL_FLAT_BOX); - o->labelsize(12); - o->maximum(127); - o->step(1); - o->value(64); - o->callback((Fl_Callback*)cb_Frequency); - o->align(Fl_Align(FL_ALIGN_TOP)); - o->value(pars->VoicePar[nvoice].Unison_frequency_spread); - } // Fl_Slider* o - { Fl_Value_Output* o = unisonspreadoutput = new Fl_Value_Output(225, 545, 40, 15, "(cents)"); - unisonspreadoutput->labelsize(10); - unisonspreadoutput->maximum(1000); - unisonspreadoutput->step(0.1); - unisonspreadoutput->textfont(1); - unisonspreadoutput->textsize(10); - unisonspreadoutput->callback((Fl_Callback*)cb_unisonspreadoutput); - unisonspreadoutput->align(Fl_Align(FL_ALIGN_TOP_LEFT)); - o->value(pars->getUnisonFrequencySpreadCents(nvoice)); - } // Fl_Value_Output* unisonspreadoutput - { WidgetPDial* o = new WidgetPDial(390, 540, 25, 25, "Vib.speed"); - o->tooltip("Vibratto Average Speed"); - o->box(FL_ROUND_UP_BOX); - o->color(FL_BACKGROUND_COLOR); - o->selection_color(FL_INACTIVE_COLOR); - o->labeltype(FL_NORMAL_LABEL); - o->labelfont(0); - o->labelsize(10); - o->labelcolor(FL_FOREGROUND_COLOR); - o->maximum(127); - o->step(1); - o->callback((Fl_Callback*)cb_Vib); - o->align(Fl_Align(FL_ALIGN_TOP)); - o->when(FL_WHEN_CHANGED); - o->value(pars->VoicePar[nvoice].Unison_vibratto_speed); - } // WidgetPDial* o - o->end(); - } // Fl_Group* o - voicemodegroup->end(); - } // Fl_Group* voicemodegroup - { Fl_Group* o = new Fl_Group(5, 40, 240, 210, "AMPLITUDE"); - o->box(FL_THIN_UP_BOX); - o->labeltype(FL_EMBOSSED_LABEL); - o->labelfont(1); - o->labelsize(13); - o->align(Fl_Align(FL_ALIGN_TOP|FL_ALIGN_INSIDE)); - { Fl_Value_Slider* o = new Fl_Value_Slider(10, 60, 160, 15, "Vol"); - o->tooltip("Volume"); - o->type(5); - o->box(FL_FLAT_BOX); - o->labelsize(11); - o->maximum(127); - o->step(1); - o->callback((Fl_Callback*)cb_Vol1); - o->align(Fl_Align(FL_ALIGN_RIGHT)); - o->value(pars->VoicePar[nvoice].PVolume); - } // Fl_Value_Slider* o - { Fl_Value_Slider* o = new Fl_Value_Slider(10, 80, 160, 15, "V.Sns"); - o->tooltip("Velocity Sensing Function (rightmost to disable)"); - o->type(5); - o->box(FL_FLAT_BOX); - o->labelsize(11); - o->maximum(127); - o->step(1); - o->callback((Fl_Callback*)cb_V1); - o->align(Fl_Align(FL_ALIGN_RIGHT)); - o->value(pars->VoicePar[nvoice].PAmpVelocityScaleFunction); - } // Fl_Value_Slider* o - { EnvelopeUI* o = voiceampenvgroup = new EnvelopeUI(10, 105, 205, 70, "ADSynth Voice - Amplitude Envelope"); - voiceampenvgroup->box(FL_FLAT_BOX); - voiceampenvgroup->color((Fl_Color)51); - voiceampenvgroup->selection_color(FL_BACKGROUND_COLOR); - voiceampenvgroup->labeltype(FL_NORMAL_LABEL); - voiceampenvgroup->labelfont(0); - voiceampenvgroup->labelsize(14); - voiceampenvgroup->labelcolor(FL_FOREGROUND_COLOR); - voiceampenvgroup->align(Fl_Align(FL_ALIGN_WRAP|FL_ALIGN_INSIDE)); - voiceampenvgroup->when(FL_WHEN_RELEASE); - o->init(pars->VoicePar[nvoice].AmpEnvelope); - if (pars->VoicePar[nvoice].PAmpEnvelopeEnabled==0) o->deactivate(); - voiceampenvgroup->end(); - } // EnvelopeUI* voiceampenvgroup - { WidgetPDial* o = new WidgetPDial(210, 60, 30, 30, "Pan"); - o->tooltip("Panning (leftmost is Random)"); - o->box(FL_ROUND_UP_BOX); - o->color(FL_BACKGROUND_COLOR); - o->selection_color(FL_INACTIVE_COLOR); - o->labeltype(FL_NORMAL_LABEL); - o->labelfont(0); - o->labelsize(10); - o->labelcolor(FL_FOREGROUND_COLOR); - o->maximum(127); - o->step(1); - o->callback((Fl_Callback*)cb_Pan); - o->align(Fl_Align(FL_ALIGN_BOTTOM)); - o->when(FL_WHEN_CHANGED); - o->value(pars->VoicePar[nvoice].PPanning); - } // WidgetPDial* o - { Fl_Check_Button* o = new Fl_Check_Button(15, 110, 50, 10, "Enable"); - o->tooltip("Forced Relase"); - o->down_box(FL_DOWN_BOX); - o->labelfont(1); - o->labelsize(10); - o->callback((Fl_Callback*)cb_Enable4); - o->value(pars->VoicePar[nvoice].PAmpEnvelopeEnabled); - } // Fl_Check_Button* o - { LFOUI* o = voiceamplfogroup = new LFOUI(10, 175, 230, 70, "Amplitude LFO "); - voiceamplfogroup->box(FL_FLAT_BOX); - voiceamplfogroup->color(FL_DARK1); - voiceamplfogroup->selection_color(FL_BACKGROUND_COLOR); - voiceamplfogroup->labeltype(FL_NORMAL_LABEL); - voiceamplfogroup->labelfont(0); - voiceamplfogroup->labelsize(14); - voiceamplfogroup->labelcolor(FL_FOREGROUND_COLOR); - voiceamplfogroup->align(Fl_Align(FL_ALIGN_WRAP|FL_ALIGN_INSIDE)); - voiceamplfogroup->when(FL_WHEN_RELEASE); - o->init(pars->VoicePar[nvoice].AmpLfo); - if (pars->VoicePar[nvoice].PAmpLfoEnabled==0) o->deactivate(); - voiceamplfogroup->end(); - } // LFOUI* voiceamplfogroup - { Fl_Check_Button* o = new Fl_Check_Button(15, 180, 55, 10, "Enable"); - o->tooltip("Forced Relase"); - o->down_box(FL_DOWN_BOX); - o->labelfont(1); - o->labelsize(10); - o->callback((Fl_Callback*)cb_Enable5); - o->value(pars->VoicePar[nvoice].PAmpLfoEnabled); - } // Fl_Check_Button* o - { Fl_Check_Button* o = new Fl_Check_Button(10, 45, 50, 10, "Minus"); - o->down_box(FL_DOWN_BOX); - o->labelfont(1); - o->labelsize(10); - o->callback((Fl_Callback*)cb_Minus); - o->value(pars->VoicePar[nvoice].PVolumeminus); - } // Fl_Check_Button* o - o->end(); - } // Fl_Group* o - { Fl_Group* o = voicefiltergroup = new Fl_Group(245, 5, 285, 245, "FILTER"); - voicefiltergroup->box(FL_THIN_UP_BOX); - voicefiltergroup->labeltype(FL_EMBOSSED_LABEL); - voicefiltergroup->labelfont(1); - voicefiltergroup->labelsize(13); - voicefiltergroup->align(Fl_Align(FL_ALIGN_TOP|FL_ALIGN_INSIDE)); - { FilterUI* o = new FilterUI(250, 30, 275, 75, "ADsynth Voice - Filter"); - o->box(FL_FLAT_BOX); - o->color(FL_LIGHT1); - o->selection_color(FL_BACKGROUND_COLOR); - o->labeltype(FL_NORMAL_LABEL); - o->labelfont(0); - o->labelsize(14); - o->labelcolor(FL_FOREGROUND_COLOR); - o->align(Fl_Align(FL_ALIGN_WRAP|FL_ALIGN_INSIDE)); - o->when(FL_WHEN_RELEASE); - o->init(pars->VoicePar[nvoice].VoiceFilter,NULL,NULL); - o->end(); - } // FilterUI* o - { EnvelopeUI* o = voicefilterenvgroup = new EnvelopeUI(250, 105, 275, 70, "ADSynth Voice - Filter Envelope"); - voicefilterenvgroup->box(FL_FLAT_BOX); - voicefilterenvgroup->color((Fl_Color)51); - voicefilterenvgroup->selection_color(FL_BACKGROUND_COLOR); - voicefilterenvgroup->labeltype(FL_NORMAL_LABEL); - voicefilterenvgroup->labelfont(0); - voicefilterenvgroup->labelsize(14); - voicefilterenvgroup->labelcolor(FL_FOREGROUND_COLOR); - voicefilterenvgroup->align(Fl_Align(FL_ALIGN_WRAP|FL_ALIGN_INSIDE)); - voicefilterenvgroup->when(FL_WHEN_RELEASE); - o->init(pars->VoicePar[nvoice].FilterEnvelope); - if (pars->VoicePar[nvoice].PFilterEnvelopeEnabled==0) o->deactivate(); - voicefilterenvgroup->end(); - } // EnvelopeUI* voicefilterenvgroup - { Fl_Check_Button* o = new Fl_Check_Button(255, 110, 55, 10, "Enable"); - o->tooltip("Forced Relase"); - o->down_box(FL_DOWN_BOX); - o->labelfont(1); - o->labelsize(10); - o->callback((Fl_Callback*)cb_Enable6); - o->value(pars->VoicePar[nvoice].PFilterEnvelopeEnabled); - } // Fl_Check_Button* o - { LFOUI* o = voicefilterlfogroup = new LFOUI(250, 175, 230, 70, "Filter LFO "); - voicefilterlfogroup->box(FL_FLAT_BOX); - voicefilterlfogroup->color(FL_DARK1); - voicefilterlfogroup->selection_color(FL_BACKGROUND_COLOR); - voicefilterlfogroup->labeltype(FL_NORMAL_LABEL); - voicefilterlfogroup->labelfont(0); - voicefilterlfogroup->labelsize(14); - voicefilterlfogroup->labelcolor(FL_FOREGROUND_COLOR); - voicefilterlfogroup->align(Fl_Align(FL_ALIGN_WRAP|FL_ALIGN_INSIDE)); - voicefilterlfogroup->when(FL_WHEN_RELEASE); - o->init(pars->VoicePar[nvoice].FilterLfo); - if (pars->VoicePar[nvoice].PFilterLfoEnabled==0) o->deactivate(); - voicefilterlfogroup->end(); - } // LFOUI* voicefilterlfogroup - { Fl_Check_Button* o = new Fl_Check_Button(255, 180, 55, 10, "Enable"); - o->tooltip("Forced Relase"); - o->down_box(FL_DOWN_BOX); - o->labelfont(1); - o->labelsize(10); - o->callback((Fl_Callback*)cb_Enable7); - o->value(pars->VoicePar[nvoice].PFilterLfoEnabled); - } // Fl_Check_Button* o - if (pars->VoicePar[nvoice].PFilterEnabled==0) o->deactivate(); - voicefiltergroup->end(); - } // Fl_Group* voicefiltergroup - { Fl_Group* o = new Fl_Group(5, 5, 55, 35, "01"); - o->box(FL_THIN_UP_BOX); - o->labeltype(FL_EMBOSSED_LABEL); - o->labelfont(1); - o->labelsize(22); - o->align(Fl_Align(FL_ALIGN_CENTER|FL_ALIGN_INSIDE)); - char tmp[10];snprintf(tmp,10,"%d",nvoice+1);o->label(strdup(tmp)); - o->end(); - } // Fl_Group* o - { Fl_Choice* o = new Fl_Choice(5, 500, 65, 20); - o->tooltip("Oscillator Type (sound/noise)"); - o->down_box(FL_BORDER_BOX); - o->labelsize(10); - o->textfont(1); - o->textsize(10); - o->callback((Fl_Callback*)cb_2); - o->menu(menu_); - o->value(pars->VoicePar[nvoice].Type); - if (pars->VoicePar[nvoice].Type!=0) voicemodegroup->deactivate(); - } // Fl_Choice* o - { Fl_Check_Button* o = bypassfiltercheckbutton = new Fl_Check_Button(425, 10, 100, 20, "Bypass Global F."); - bypassfiltercheckbutton->down_box(FL_DOWN_BOX); - bypassfiltercheckbutton->labelfont(1); - bypassfiltercheckbutton->labelsize(10); - bypassfiltercheckbutton->callback((Fl_Callback*)cb_bypassfiltercheckbutton); - bypassfiltercheckbutton->align(Fl_Align(132|FL_ALIGN_INSIDE)); - o->value(pars->VoicePar[nvoice].Pfilterbypass); - } // Fl_Check_Button* bypassfiltercheckbutton - { Fl_Group* o = new Fl_Group(115, 5, 95, 35); - o->box(FL_THIN_UP_BOX); - { Fl_Value_Slider* o = new Fl_Value_Slider(120, 21, 84, 12, "Delay"); - o->tooltip("Volume"); - o->type(5); - o->box(FL_FLAT_BOX); - o->labelsize(11); - o->maximum(127); - o->step(1); - o->callback((Fl_Callback*)cb_Delay); - o->align(Fl_Align(FL_ALIGN_TOP_LEFT)); - o->value(pars->VoicePar[nvoice].PDelay); - } // Fl_Value_Slider* o - o->end(); - } // Fl_Group* o - { Fl_Check_Button* o = new Fl_Check_Button(250, 15, 60, 15, "Enable"); - o->tooltip("Enable Filter"); - o->down_box(FL_DOWN_BOX); - o->labelfont(1); - o->labelsize(10); - o->callback((Fl_Callback*)cb_Enable8); - o->value(pars->VoicePar[nvoice].PFilterEnabled); - } // Fl_Check_Button* o - { Fl_Box* o = noiselabel = new Fl_Box(150, 415, 300, 65, "White Noise"); - noiselabel->labelfont(1); - noiselabel->labelsize(50); - noiselabel->labelcolor(FL_BACKGROUND2_COLOR); - noiselabel->callback((Fl_Callback*)cb_noiselabel1); - if (pars->VoicePar[nvoice].Type==0) o->hide(); else o->show(); - } // Fl_Box* noiselabel - if (pars->VoicePar[nvoice].Enabled==0) o->deactivate(); - voiceparametersgroup->end(); - } // Fl_Group* voiceparametersgroup - { Fl_Check_Button* o = voiceonbutton = new Fl_Check_Button(60, 5, 55, 35, "On"); - voiceonbutton->box(FL_THIN_UP_BOX); - voiceonbutton->down_box(FL_DOWN_BOX); - voiceonbutton->labelfont(1); - voiceonbutton->labelsize(13); - voiceonbutton->callback((Fl_Callback*)cb_voiceonbutton); - o->value(pars->VoicePar[nvoice].Enabled); - } // Fl_Check_Button* voiceonbutton - ADnoteVoiceParameters->end(); - } // Fl_Group* ADnoteVoiceParameters - return ADnoteVoiceParameters; -} - -ADvoiceUI::ADvoiceUI(int x,int y, int w, int h, const char *label):Fl_Group(x,y,w,h,label) { - nvoice=0; - pars=NULL; - oscedit=NULL; -} - -void ADvoiceUI::init(ADnoteParameters *parameters,int nvoice_,Master *master_) { - pars=parameters; - nvoice=nvoice_; - master=master_; - make_window(); - end(); - ADnoteVoiceParameters->show(); -} - -ADvoiceUI::~ADvoiceUI() { - ADnoteVoiceParameters->hide(); - hide(); - if (oscedit!=NULL) { - delete(oscedit); - }; - //delete (ADnoteVoiceParameters); -} - -void ADnoteUI::cb_octave_i(Fl_Counter* o, void*) { - int k=(int) o->value(); -if (k<0) k+=16; -pars->GlobalPar.PCoarseDetune = k*1024+ - pars->GlobalPar.PCoarseDetune%1024; -} -void ADnoteUI::cb_octave(Fl_Counter* o, void* v) { - ((ADnoteUI*)(o->parent()->parent()->user_data()))->cb_octave_i(o,v); -} - -void ADnoteUI::cb_coarsedet_i(Fl_Counter* o, void*) { - int k=(int) o->value(); -if (k<0) k+=1024; -pars->GlobalPar.PCoarseDetune = k+ - (pars->GlobalPar.PCoarseDetune/1024)*1024; -} -void ADnoteUI::cb_coarsedet(Fl_Counter* o, void* v) { - ((ADnoteUI*)(o->parent()->parent()->user_data()))->cb_coarsedet_i(o,v); -} - -void ADnoteUI::cb_freq_i(Fl_Slider* o, void*) { - pars->GlobalPar.PDetune=(int)o->value()+8192; -detunevalueoutput->do_callback(); -} -void ADnoteUI::cb_freq(Fl_Slider* o, void* v) { - ((ADnoteUI*)(o->parent()->parent()->user_data()))->cb_freq_i(o,v); -} - -void ADnoteUI::cb_detunevalueoutput2_i(Fl_Value_Output* o, void*) { - o->value(getdetune(pars->GlobalPar.PDetuneType,0,pars->GlobalPar.PDetune)); -} -void ADnoteUI::cb_detunevalueoutput2(Fl_Value_Output* o, void* v) { - ((ADnoteUI*)(o->parent()->parent()->user_data()))->cb_detunevalueoutput2_i(o,v); -} - -void ADnoteUI::cb_detunetype_i(Fl_Choice* o, void*) { - pars->GlobalPar.PDetuneType=(int) o->value()+1; -detunevalueoutput->do_callback(); -} -void ADnoteUI::cb_detunetype(Fl_Choice* o, void* v) { - ((ADnoteUI*)(o->parent()->parent()->user_data()))->cb_detunetype_i(o,v); -} - -void ADnoteUI::cb_relBW_i(WidgetPDial* o, void*) { - pars->GlobalPar.PBandwidth=(int) o->value(); - -pars->getBandwidthDetuneMultiplier(); - -for (int i=0;irefreshlist(); -}; -} -void ADnoteUI::cb_relBW(WidgetPDial* o, void* v) { - ((ADnoteUI*)(o->parent()->parent()->user_data()))->cb_relBW_i(o,v); -} - -void ADnoteUI::cb_volume_i(Fl_Value_Slider* o, void*) { - pars->GlobalPar.PVolume=(int)o->value(); -} -void ADnoteUI::cb_volume(Fl_Value_Slider* o, void* v) { - ((ADnoteUI*)(o->parent()->parent()->user_data()))->cb_volume_i(o,v); -} - -void ADnoteUI::cb_vsns_i(Fl_Value_Slider* o, void*) { - pars->GlobalPar.PAmpVelocityScaleFunction=(int) o->value(); -} -void ADnoteUI::cb_vsns(Fl_Value_Slider* o, void* v) { - ((ADnoteUI*)(o->parent()->parent()->user_data()))->cb_vsns_i(o,v); -} - -void ADnoteUI::cb_pan_i(WidgetPDial* o, void*) { - pars->GlobalPar.PPanning=(int) o->value(); -} -void ADnoteUI::cb_pan(WidgetPDial* o, void* v) { - ((ADnoteUI*)(o->parent()->parent()->user_data()))->cb_pan_i(o,v); -} - -void ADnoteUI::cb_pstr_i(WidgetPDial* o, void*) { - pars->GlobalPar.PPunchStrength=(int) o->value(); -} -void ADnoteUI::cb_pstr(WidgetPDial* o, void* v) { - ((ADnoteUI*)(o->parent()->parent()->user_data()))->cb_pstr_i(o,v); -} - -void ADnoteUI::cb_pt_i(WidgetPDial* o, void*) { - pars->GlobalPar.PPunchTime=(int) o->value(); -} -void ADnoteUI::cb_pt(WidgetPDial* o, void* v) { - ((ADnoteUI*)(o->parent()->parent()->user_data()))->cb_pt_i(o,v); -} - -void ADnoteUI::cb_pstc_i(WidgetPDial* o, void*) { - pars->GlobalPar.PPunchStretch=(int) o->value(); -} -void ADnoteUI::cb_pstc(WidgetPDial* o, void* v) { - ((ADnoteUI*)(o->parent()->parent()->user_data()))->cb_pstc_i(o,v); -} - -void ADnoteUI::cb_pvel_i(WidgetPDial* o, void*) { - pars->GlobalPar.PPunchVelocitySensing=(int) o->value(); -} -void ADnoteUI::cb_pvel(WidgetPDial* o, void* v) { - ((ADnoteUI*)(o->parent()->parent()->user_data()))->cb_pvel_i(o,v); -} - -void ADnoteUI::cb_rndgrp_i(Fl_Check_Button* o, void*) { - pars->GlobalPar.Hrandgrouping=(int) o->value(); -} -void ADnoteUI::cb_rndgrp(Fl_Check_Button* o, void* v) { - ((ADnoteUI*)(o->parent()->parent()->user_data()))->cb_rndgrp_i(o,v); -} - -void ADnoteUI::cb_stereo_i(Fl_Check_Button* o, void*) { - pars->GlobalPar.PStereo=(int) o->value(); -} -void ADnoteUI::cb_stereo(Fl_Check_Button* o, void* v) { - ((ADnoteUI*)(o->parent()->user_data()))->cb_stereo_i(o,v); -} - -void ADnoteUI::cb_Show_i(Fl_Button*, void*) { - for (int i=0;irefreshlist(); -} -ADnoteVoiceList->show(); -} -void ADnoteUI::cb_Show(Fl_Button* o, void* v) { - ((ADnoteUI*)(o->parent()->user_data()))->cb_Show_i(o,v); -} - -void ADnoteUI::cb_Show1_i(Fl_Button*, void*) { - ADnoteVoice->show(); -} -void ADnoteUI::cb_Show1(Fl_Button* o, void* v) { - ((ADnoteUI*)(o->parent()->user_data()))->cb_Show1_i(o,v); -} - -void ADnoteUI::cb_Close_i(Fl_Button*, void*) { - ADnoteGlobalParameters->hide(); -} -void ADnoteUI::cb_Close(Fl_Button* o, void* v) { - ((ADnoteUI*)(o->parent()->user_data()))->cb_Close_i(o,v); -} - -void ADnoteUI::cb_Resonance_i(Fl_Button*, void*) { - resui->resonancewindow->redraw(); -resui->resonancewindow->show(); -} -void ADnoteUI::cb_Resonance(Fl_Button* o, void* v) { - ((ADnoteUI*)(o->parent()->user_data()))->cb_Resonance_i(o,v); -} - -void ADnoteUI::cb_C_i(Fl_Button*, void*) { - presetsui->copy(pars); -} -void ADnoteUI::cb_C(Fl_Button* o, void* v) { - ((ADnoteUI*)(o->parent()->user_data()))->cb_C_i(o,v); -} - -void ADnoteUI::cb_P_i(Fl_Button*, void*) { - presetsui->paste(pars,this); -} -void ADnoteUI::cb_P(Fl_Button* o, void* v) { - ((ADnoteUI*)(o->parent()->user_data()))->cb_P_i(o,v); -} - -void ADnoteUI::cb_Close1_i(Fl_Button*, void*) { - ADnoteVoice->hide(); -} -void ADnoteUI::cb_Close1(Fl_Button* o, void* v) { - ((ADnoteUI*)(o->parent()->user_data()))->cb_Close1_i(o,v); -} - -void ADnoteUI::cb_currentvoicecounter_i(Fl_Counter* o, void*) { - nvoice=(int)o->value()-1; -advoice->hide(); -ADnoteVoice->remove(advoice); -delete advoice; -advoice=new ADvoiceUI(0,0,765,585); -ADnoteVoice->add(advoice); -advoice->init(pars,nvoice,master); -advoice->show(); -ADnoteVoice->redraw(); -} -void ADnoteUI::cb_currentvoicecounter(Fl_Counter* o, void* v) { - ((ADnoteUI*)(o->parent()->user_data()))->cb_currentvoicecounter_i(o,v); -} - -void ADnoteUI::cb_C1_i(Fl_Button*, void*) { - presetsui->copy(pars,nvoice); -} -void ADnoteUI::cb_C1(Fl_Button* o, void* v) { - ((ADnoteUI*)(o->parent()->user_data()))->cb_C1_i(o,v); -} - -void ADnoteUI::cb_P1_i(Fl_Button*, void*) { - presetsui->paste(pars,this,nvoice); -} -void ADnoteUI::cb_P1(Fl_Button* o, void* v) { - ((ADnoteUI*)(o->parent()->user_data()))->cb_P1_i(o,v); -} - -void ADnoteUI::cb_Hide_i(Fl_Button*, void*) { - ADnoteVoiceList->hide(); -} -void ADnoteUI::cb_Hide(Fl_Button* o, void* v) { - ((ADnoteUI*)(o->parent()->user_data()))->cb_Hide_i(o,v); -} - -Fl_Double_Window* ADnoteUI::make_window() { - { ADnoteGlobalParameters = new Fl_Double_Window(535, 405, "ADsynth Global Parameters of the Instrument"); - ADnoteGlobalParameters->user_data((void*)(this)); - { Fl_Group* o = new Fl_Group(5, 255, 525, 115, "FREQUENCY"); - o->box(FL_THIN_UP_BOX); - o->labeltype(FL_EMBOSSED_LABEL); - o->labelfont(1); - o->labelsize(13); - o->align(Fl_Align(FL_ALIGN_TOP|FL_ALIGN_INSIDE)); - { EnvelopeUI* o = freqenv = new EnvelopeUI(10, 295, 205, 70, "ADSynth Global - Frequency Envelope"); - freqenv->box(FL_FLAT_BOX); - freqenv->color((Fl_Color)51); - freqenv->selection_color(FL_BACKGROUND_COLOR); - freqenv->labeltype(FL_NORMAL_LABEL); - freqenv->labelfont(0); - freqenv->labelsize(14); - freqenv->labelcolor(FL_FOREGROUND_COLOR); - freqenv->align(Fl_Align(FL_ALIGN_WRAP|FL_ALIGN_INSIDE)); - freqenv->when(FL_WHEN_RELEASE); - o->init(pars->GlobalPar.FreqEnvelope); - freqenv->end(); - } // EnvelopeUI* freqenv - { Fl_Counter* o = octave = new Fl_Counter(450, 275, 45, 15, "Octave"); - octave->tooltip("Octave"); - octave->type(1); - octave->labelsize(10); - octave->minimum(-8); - octave->maximum(7); - octave->step(1); - octave->textfont(1); - octave->textsize(11); - octave->callback((Fl_Callback*)cb_octave); - octave->align(Fl_Align(FL_ALIGN_TOP)); - int k=pars->GlobalPar.PCoarseDetune/1024;if (k>=8) k-=16; - o->value(k); - } // Fl_Counter* octave - { Fl_Counter* o = coarsedet = new Fl_Counter(455, 345, 60, 20, "Coarse det."); - coarsedet->tooltip("Coarse Detune"); - coarsedet->labelsize(10); - coarsedet->minimum(-64); - coarsedet->maximum(63); - coarsedet->step(1); - coarsedet->textfont(1); - coarsedet->textsize(11); - coarsedet->callback((Fl_Callback*)cb_coarsedet); - coarsedet->align(Fl_Align(FL_ALIGN_TOP_LEFT)); - int k=pars->GlobalPar.PCoarseDetune%1024;if (k>=512) k-=1024; - o->value(k); - o->lstep(10); - } // Fl_Counter* coarsedet - { LFOUI* o = freqlfo = new LFOUI(215, 295, 230, 70, "Frequency LFO "); - freqlfo->box(FL_FLAT_BOX); - freqlfo->color(FL_DARK1); - freqlfo->selection_color(FL_BACKGROUND_COLOR); - freqlfo->labeltype(FL_NORMAL_LABEL); - freqlfo->labelfont(0); - freqlfo->labelsize(14); - freqlfo->labelcolor(FL_FOREGROUND_COLOR); - freqlfo->align(Fl_Align(FL_ALIGN_WRAP|FL_ALIGN_INSIDE)); - freqlfo->when(FL_WHEN_RELEASE); - o->init(pars->GlobalPar.FreqLfo); - freqlfo->end(); - } // LFOUI* freqlfo - { Fl_Slider* o = freq = new Fl_Slider(60, 275, 385, 15); - freq->tooltip("Fine Detune (cents)"); - freq->type(5); - freq->box(FL_FLAT_BOX); - freq->minimum(-8192); - freq->maximum(8191); - freq->step(1); - freq->callback((Fl_Callback*)cb_freq); - o->value(pars->GlobalPar.PDetune-8192); - } // Fl_Slider* freq - { Fl_Value_Output* o = detunevalueoutput = new Fl_Value_Output(12, 275, 45, 15, "Detune"); - detunevalueoutput->labelsize(10); - detunevalueoutput->minimum(-5000); - detunevalueoutput->maximum(5000); - detunevalueoutput->step(0.01); - detunevalueoutput->textfont(1); - detunevalueoutput->textsize(10); - detunevalueoutput->callback((Fl_Callback*)cb_detunevalueoutput2); - detunevalueoutput->align(Fl_Align(FL_ALIGN_TOP_LEFT)); - o->value(getdetune(pars->GlobalPar.PDetuneType,0,pars->GlobalPar.PDetune)); - } // Fl_Value_Output* detunevalueoutput - { Fl_Choice* o = detunetype = new Fl_Choice(450, 315, 75, 15, "Detune Type"); - detunetype->down_box(FL_BORDER_BOX); - detunetype->labelsize(10); - detunetype->textfont(1); - detunetype->textsize(10); - detunetype->callback((Fl_Callback*)cb_detunetype); - detunetype->align(Fl_Align(FL_ALIGN_TOP_LEFT)); - o->add("L35cents");o->add("L10cents");o->add("E100cents");o->add("E1200cents"); - o->value(pars->GlobalPar.PDetuneType-1); - } // Fl_Choice* detunetype - { WidgetPDial* o = new WidgetPDial(500, 270, 25, 25, "relBW"); - o->tooltip("Bandwidth - how the relative fine detune of the voice are changed"); - o->box(FL_ROUND_UP_BOX); - o->color(FL_BACKGROUND_COLOR); - o->selection_color(FL_INACTIVE_COLOR); - o->labeltype(FL_NORMAL_LABEL); - o->labelfont(0); - o->labelsize(10); - o->labelcolor(FL_FOREGROUND_COLOR); - o->maximum(127); - o->step(1); - o->callback((Fl_Callback*)cb_relBW); - o->align(Fl_Align(FL_ALIGN_TOP)); - o->when(FL_WHEN_CHANGED); - o->value(pars->GlobalPar.PBandwidth); - } // WidgetPDial* o - o->end(); - } // Fl_Group* o - { Fl_Group* o = new Fl_Group(5, 5, 240, 250, "AMPLITUDE"); - o->box(FL_THIN_UP_FRAME); - o->labeltype(FL_EMBOSSED_LABEL); - o->labelfont(1); - o->labelsize(13); - o->align(Fl_Align(FL_ALIGN_TOP|FL_ALIGN_INSIDE)); - { Fl_Value_Slider* o = volume = new Fl_Value_Slider(10, 30, 160, 15, "Vol"); - volume->tooltip("Volume"); - volume->type(5); - volume->box(FL_FLAT_BOX); - volume->labelsize(11); - volume->maximum(127); - volume->step(1); - volume->callback((Fl_Callback*)cb_volume); - volume->align(Fl_Align(FL_ALIGN_RIGHT)); - o->value(pars->GlobalPar.PVolume); - } // Fl_Value_Slider* volume - { Fl_Value_Slider* o = vsns = new Fl_Value_Slider(10, 50, 160, 15, "V.Sns"); - vsns->tooltip("Velocity Sensing Function (rightmost to disable)"); - vsns->type(5); - vsns->box(FL_FLAT_BOX); - vsns->labelsize(11); - vsns->maximum(127); - vsns->step(1); - vsns->callback((Fl_Callback*)cb_vsns); - vsns->align(Fl_Align(FL_ALIGN_RIGHT)); - o->value(pars->GlobalPar.PAmpVelocityScaleFunction); - } // Fl_Value_Slider* vsns - { WidgetPDial* o = pan = new WidgetPDial(210, 25, 30, 30, "Pan"); - pan->tooltip("Panning (leftmost is Random)"); - pan->box(FL_ROUND_UP_BOX); - pan->color(FL_BACKGROUND_COLOR); - pan->selection_color(FL_INACTIVE_COLOR); - pan->labeltype(FL_NORMAL_LABEL); - pan->labelfont(0); - pan->labelsize(10); - pan->labelcolor(FL_FOREGROUND_COLOR); - pan->maximum(127); - pan->step(1); - pan->callback((Fl_Callback*)cb_pan); - pan->align(Fl_Align(FL_ALIGN_BOTTOM)); - pan->when(FL_WHEN_CHANGED); - o->value(pars->GlobalPar.PPanning); - } // WidgetPDial* pan - { WidgetPDial* o = pstr = new WidgetPDial(125, 227, 25, 25, "P.Str."); - pstr->tooltip("Punch Strength"); - pstr->box(FL_ROUND_UP_BOX); - pstr->color(FL_BACKGROUND_COLOR); - pstr->selection_color(FL_INACTIVE_COLOR); - pstr->labeltype(FL_NORMAL_LABEL); - pstr->labelfont(0); - pstr->labelsize(10); - pstr->labelcolor(FL_FOREGROUND_COLOR); - pstr->maximum(127); - pstr->step(1); - pstr->callback((Fl_Callback*)cb_pstr); - pstr->align(Fl_Align(FL_ALIGN_TOP)); - pstr->when(FL_WHEN_CHANGED); - o->value(pars->GlobalPar.PPunchStrength); - } // WidgetPDial* pstr - { WidgetPDial* o = pt = new WidgetPDial(155, 227, 25, 25, "P.t."); - pt->tooltip("Punch Time (duration)"); - pt->box(FL_ROUND_UP_BOX); - pt->color(FL_BACKGROUND_COLOR); - pt->selection_color(FL_INACTIVE_COLOR); - pt->labeltype(FL_NORMAL_LABEL); - pt->labelfont(0); - pt->labelsize(10); - pt->labelcolor(FL_FOREGROUND_COLOR); - pt->maximum(127); - pt->step(1); - pt->callback((Fl_Callback*)cb_pt); - pt->align(Fl_Align(FL_ALIGN_TOP)); - pt->when(FL_WHEN_CHANGED); - o->value(pars->GlobalPar.PPunchTime); - } // WidgetPDial* pt - { WidgetPDial* o = pstc = new WidgetPDial(185, 227, 25, 25, "P.Stc."); - pstc->tooltip("Punch Stretch"); - pstc->box(FL_ROUND_UP_BOX); - pstc->color(FL_BACKGROUND_COLOR); - pstc->selection_color(FL_INACTIVE_COLOR); - pstc->labeltype(FL_NORMAL_LABEL); - pstc->labelfont(0); - pstc->labelsize(10); - pstc->labelcolor(FL_FOREGROUND_COLOR); - pstc->maximum(127); - pstc->step(1); - pstc->callback((Fl_Callback*)cb_pstc); - pstc->align(Fl_Align(FL_ALIGN_TOP)); - pstc->when(FL_WHEN_CHANGED); - o->value(pars->GlobalPar.PPunchStretch); - } // WidgetPDial* pstc - { WidgetPDial* o = pvel = new WidgetPDial(215, 227, 25, 25, "P.Vel."); - pvel->tooltip("Punch Velocity Sensing"); - pvel->box(FL_ROUND_UP_BOX); - pvel->color(FL_BACKGROUND_COLOR); - pvel->selection_color(FL_INACTIVE_COLOR); - pvel->labeltype(FL_NORMAL_LABEL); - pvel->labelfont(0); - pvel->labelsize(10); - pvel->labelcolor(FL_FOREGROUND_COLOR); - pvel->maximum(127); - pvel->step(1); - pvel->callback((Fl_Callback*)cb_pvel); - pvel->align(Fl_Align(FL_ALIGN_TOP)); - pvel->when(FL_WHEN_CHANGED); - o->value(pars->GlobalPar.PPunchVelocitySensing); - } // WidgetPDial* pvel - { EnvelopeUI* o = ampenv = new EnvelopeUI(10, 75, 205, 70, "ADSynth Global - Amplitude Envelope"); - ampenv->box(FL_FLAT_BOX); - ampenv->color((Fl_Color)51); - ampenv->selection_color(FL_BACKGROUND_COLOR); - ampenv->labeltype(FL_NORMAL_LABEL); - ampenv->labelfont(0); - ampenv->labelsize(14); - ampenv->labelcolor(FL_FOREGROUND_COLOR); - ampenv->align(Fl_Align(FL_ALIGN_WRAP|FL_ALIGN_INSIDE)); - ampenv->when(FL_WHEN_RELEASE); - o->init(pars->GlobalPar.AmpEnvelope); - ampenv->end(); - } // EnvelopeUI* ampenv - { LFOUI* o = amplfo = new LFOUI(10, 145, 230, 70, "Amplitude LFO "); - amplfo->box(FL_FLAT_BOX); - amplfo->color(FL_DARK1); - amplfo->selection_color(FL_BACKGROUND_COLOR); - amplfo->labeltype(FL_NORMAL_LABEL); - amplfo->labelfont(0); - amplfo->labelsize(14); - amplfo->labelcolor(FL_FOREGROUND_COLOR); - amplfo->align(Fl_Align(FL_ALIGN_WRAP|FL_ALIGN_INSIDE)); - amplfo->when(FL_WHEN_RELEASE); - o->init(pars->GlobalPar.AmpLfo); - amplfo->end(); - } // LFOUI* amplfo - { Fl_Check_Button* o = rndgrp = new Fl_Check_Button(70, 225, 40, 25, "Rnd Grp"); - rndgrp->tooltip("How the Harmonic Amplitude is applied to voices that use the same oscillator"); - rndgrp->down_box(FL_DOWN_BOX); - rndgrp->labelsize(10); - rndgrp->callback((Fl_Callback*)cb_rndgrp); - rndgrp->align(Fl_Align(132|FL_ALIGN_INSIDE)); - o->value(pars->GlobalPar.Hrandgrouping); - } // Fl_Check_Button* rndgrp - o->end(); - } // Fl_Group* o - { Fl_Group* o = new Fl_Group(245, 5, 285, 250, "FILTER"); - o->box(FL_THIN_UP_BOX); - o->labeltype(FL_EMBOSSED_LABEL); - o->labelfont(1); - o->labelsize(13); - o->align(Fl_Align(FL_ALIGN_TOP|FL_ALIGN_INSIDE)); - { EnvelopeUI* o = filterenv = new EnvelopeUI(250, 110, 275, 70, "ADSynth Global - Filter Envelope"); - filterenv->box(FL_FLAT_BOX); - filterenv->color((Fl_Color)51); - filterenv->selection_color(FL_BACKGROUND_COLOR); - filterenv->labeltype(FL_NORMAL_LABEL); - filterenv->labelfont(0); - filterenv->labelsize(14); - filterenv->labelcolor(FL_FOREGROUND_COLOR); - filterenv->align(Fl_Align(FL_ALIGN_WRAP|FL_ALIGN_INSIDE)); - filterenv->when(FL_WHEN_RELEASE); - o->init(pars->GlobalPar.FilterEnvelope); - filterenv->end(); - } // EnvelopeUI* filterenv - { LFOUI* o = filterlfo = new LFOUI(250, 180, 230, 70, "Filter LFO"); - filterlfo->box(FL_FLAT_BOX); - filterlfo->color(FL_DARK1); - filterlfo->selection_color(FL_BACKGROUND_COLOR); - filterlfo->labeltype(FL_NORMAL_LABEL); - filterlfo->labelfont(0); - filterlfo->labelsize(14); - filterlfo->labelcolor(FL_FOREGROUND_COLOR); - filterlfo->align(Fl_Align(FL_ALIGN_WRAP|FL_ALIGN_INSIDE)); - filterlfo->when(FL_WHEN_RELEASE); - o->init(pars->GlobalPar.FilterLfo); - filterlfo->end(); - } // LFOUI* filterlfo - { FilterUI* o = filterui = new FilterUI(250, 35, 275, 75, "ADsynth Global - Filter"); - filterui->box(FL_FLAT_BOX); - filterui->color(FL_LIGHT1); - filterui->selection_color(FL_BACKGROUND_COLOR); - filterui->labeltype(FL_NORMAL_LABEL); - filterui->labelfont(0); - filterui->labelsize(14); - filterui->labelcolor(FL_FOREGROUND_COLOR); - filterui->align(Fl_Align(FL_ALIGN_WRAP|FL_ALIGN_INSIDE)); - filterui->when(FL_WHEN_RELEASE); - o->init(pars->GlobalPar.GlobalFilter,&pars->GlobalPar.PFilterVelocityScale,&pars->GlobalPar.PFilterVelocityScaleFunction); - filterui->end(); - } // FilterUI* filterui - o->end(); - } // Fl_Group* o - { Fl_Check_Button* o = stereo = new Fl_Check_Button(5, 220, 65, 35, "Stereo"); - stereo->box(FL_ENGRAVED_BOX); - stereo->down_box(FL_DOWN_BOX); - stereo->labelfont(1); - stereo->labelsize(11); - stereo->callback((Fl_Callback*)cb_stereo); - o->value(pars->GlobalPar.PStereo); - } // Fl_Check_Button* stereo - { Fl_Button* o = new Fl_Button(180, 375, 125, 25, "Show Voice List"); - o->callback((Fl_Callback*)cb_Show); - } // Fl_Button* o - { Fl_Button* o = new Fl_Button(5, 375, 170, 25, "Show Voice Parameters"); - o->labelfont(1); - o->labelsize(12); - o->callback((Fl_Callback*)cb_Show1); - } // Fl_Button* o - { Fl_Button* o = new Fl_Button(470, 375, 60, 25, "Close"); - o->box(FL_THIN_UP_BOX); - o->callback((Fl_Callback*)cb_Close); - } // Fl_Button* o - { Fl_Button* o = new Fl_Button(309, 375, 86, 25, "Resonance"); - o->tooltip("Resonance"); - o->box(FL_THIN_UP_BOX); - o->callback((Fl_Callback*)cb_Resonance); - } // Fl_Button* o - { Fl_Button* o = new Fl_Button(405, 380, 25, 15, "C"); - o->box(FL_THIN_UP_BOX); - o->color((Fl_Color)179); - o->labelfont(1); - o->labelsize(11); - o->labelcolor(FL_BACKGROUND2_COLOR); - o->callback((Fl_Callback*)cb_C); - } // Fl_Button* o - { Fl_Button* o = new Fl_Button(435, 380, 25, 15, "P"); - o->box(FL_THIN_UP_BOX); - o->color((Fl_Color)179); - o->labelfont(1); - o->labelsize(11); - o->labelcolor(FL_BACKGROUND2_COLOR); - o->callback((Fl_Callback*)cb_P); - } // Fl_Button* o - ADnoteGlobalParameters->end(); - } // Fl_Double_Window* ADnoteGlobalParameters - { ADnoteVoice = new Fl_Double_Window(765, 620, "ADsynth Voice Parameters"); - ADnoteVoice->user_data((void*)(this)); - { ADvoiceUI* o = advoice = new ADvoiceUI(0, 0, 760, 575); - advoice->box(FL_BORDER_BOX); - advoice->color(FL_BACKGROUND_COLOR); - advoice->selection_color(FL_BACKGROUND_COLOR); - advoice->labeltype(FL_NORMAL_LABEL); - advoice->labelfont(0); - advoice->labelsize(14); - advoice->labelcolor(FL_FOREGROUND_COLOR); - advoice->align(Fl_Align(FL_ALIGN_TOP)); - advoice->when(FL_WHEN_RELEASE); - o->init(pars,nvoice,master); - o->show(); - advoice->end(); - } // ADvoiceUI* advoice - { Fl_Button* o = new Fl_Button(300, 585, 195, 25, "Close Window"); - o->box(FL_THIN_UP_BOX); - o->labelfont(1); - o->callback((Fl_Callback*)cb_Close1); - } // Fl_Button* o - { Fl_Counter* o = currentvoicecounter = new Fl_Counter(5, 585, 130, 25, "Current Voice"); - currentvoicecounter->type(1); - currentvoicecounter->labelfont(1); - currentvoicecounter->minimum(0); - currentvoicecounter->maximum(2); - currentvoicecounter->step(1); - currentvoicecounter->value(1); - currentvoicecounter->textfont(1); - currentvoicecounter->textsize(13); - currentvoicecounter->callback((Fl_Callback*)cb_currentvoicecounter); - currentvoicecounter->align(Fl_Align(FL_ALIGN_RIGHT)); - o->bounds(1,NUM_VOICES); - } // Fl_Counter* currentvoicecounter - { Fl_Button* o = new Fl_Button(700, 590, 25, 15, "C"); - o->box(FL_THIN_UP_BOX); - o->color((Fl_Color)179); - o->labelfont(1); - o->labelsize(11); - o->labelcolor(FL_BACKGROUND2_COLOR); - o->callback((Fl_Callback*)cb_C1); - } // Fl_Button* o - { Fl_Button* o = new Fl_Button(730, 590, 25, 15, "P"); - o->box(FL_THIN_UP_BOX); - o->color((Fl_Color)179); - o->labelfont(1); - o->labelsize(11); - o->labelcolor(FL_BACKGROUND2_COLOR); - o->callback((Fl_Callback*)cb_P1); - } // Fl_Button* o - ADnoteVoice->end(); - } // Fl_Double_Window* ADnoteVoice - { ADnoteVoiceList = new Fl_Double_Window(650, 260, "ADsynth Voices list"); - ADnoteVoiceList->user_data((void*)(this)); - { Fl_Text_Display* o = new Fl_Text_Display(10, 15, 30, 10, "No."); - o->box(FL_NO_BOX); - o->labelfont(1); - o->labelsize(11); - } // Fl_Text_Display* o - { Fl_Text_Display* o = new Fl_Text_Display(145, 15, 30, 10, "Vol"); - o->box(FL_NO_BOX); - o->labelfont(1); - o->labelsize(11); - } // Fl_Text_Display* o - { Fl_Text_Display* o = new Fl_Text_Display(384, 15, 25, 10, "Detune"); - o->box(FL_NO_BOX); - o->labelfont(1); - o->labelsize(11); - } // Fl_Text_Display* o - { Fl_Text_Display* o = new Fl_Text_Display(210, 15, 30, 10, "Pan"); - o->box(FL_NO_BOX); - o->labelfont(1); - o->labelsize(11); - } // Fl_Text_Display* o - { Fl_Text_Display* o = new Fl_Text_Display(560, 15, 30, 10, "Vib. Depth"); - o->box(FL_NO_BOX); - o->labelfont(1); - o->labelsize(11); - } // Fl_Text_Display* o - { Fl_Text_Display* o = new Fl_Text_Display(245, 15, 25, 10, "R."); - o->box(FL_NO_BOX); - o->labelfont(1); - o->labelsize(11); - } // Fl_Text_Display* o - { Fl_Button* o = new Fl_Button(255, 237, 125, 20, "Hide Voice List"); - o->callback((Fl_Callback*)cb_Hide); - } // Fl_Button* o - { Fl_Scroll* o = new Fl_Scroll(0, 15, 640, 220); - o->type(2); - o->box(FL_THIN_UP_BOX); - { Fl_Pack* o = new Fl_Pack(0, 20, 620, 210); - for (int i=0;iinit(pars,i,master);} - o->end(); - } // Fl_Pack* o - o->end(); - } // Fl_Scroll* o - ADnoteVoiceList->end(); - } // Fl_Double_Window* ADnoteVoiceList - return ADnoteVoiceList; -} - -ADnoteUI::ADnoteUI(ADnoteParameters *parameters,Master *master_) { - pars=parameters; - master=master_; - nvoice=0; - resui=new ResonanceUI(pars->GlobalPar.Reson); - make_window(); -} - -ADnoteUI::~ADnoteUI() { - ADnoteVoiceList->hide(); - ADnoteGlobalParameters->hide(); - ADnoteVoice->hide(); - delete(ADnoteVoiceList); - delete(ADnoteGlobalParameters); - delete(ADnoteVoice); - delete(resui); -} - -void ADnoteUI::refresh() { - volume->value(pars->GlobalPar.PVolume); - vsns->value(pars->GlobalPar.PAmpVelocityScaleFunction); - pan->value(pars->GlobalPar.PPanning); - - stereo->value(pars->GlobalPar.PStereo); - rndgrp->value(pars->GlobalPar.Hrandgrouping); - - pstr->value(pars->GlobalPar.PPunchStrength); - pt->value(pars->GlobalPar.PPunchTime); - pstc->value(pars->GlobalPar.PPunchStretch); - pvel->value(pars->GlobalPar.PPunchVelocitySensing); - - detunevalueoutput->value(getdetune(pars->GlobalPar.PDetuneType,0,pars->GlobalPar.PDetune)); - freq->value(pars->GlobalPar.PDetune-8192); - - int k=pars->GlobalPar.PCoarseDetune/1024;if (k>=8) k-=16; - octave->value(k); - - detunetype->value(pars->GlobalPar.PDetuneType-1); - k=pars->GlobalPar.PCoarseDetune%1024;if (k>=512) k-=1024; - coarsedet->value(k); - amplfo->refresh(); - freqlfo->refresh(); - filterlfo->refresh(); - - ampenv->refresh(); - freqenv->refresh(); - filterenv->refresh(); - filterui->refresh(); - - for (int i=0;irefreshlist(); - - resui->refresh(); - currentvoicecounter->do_callback(); -} diff --git a/plugins/zynaddsubfx/src/UI/ADnoteUI.fl b/plugins/zynaddsubfx/src/UI/ADnoteUI.fl deleted file mode 100644 index 748156c74..000000000 --- a/plugins/zynaddsubfx/src/UI/ADnoteUI.fl +++ /dev/null @@ -1,1161 +0,0 @@ -# data file for the Fltk User Interface Designer (fluid) -version 1.0109 -header_name {.h} -code_name {.cc} -decl {//Copyright (c) 2002-2005 Nasca Octavian Paul} {} - -decl {//License: GNU GPL version 2 or later} {} - -decl {\#include "../Params/ADnoteParameters.h"} {public -} - -decl {\#include "../Misc/Util.h"} {public -} - -decl {\#include "../Misc/Master.h"} {public -} - -decl {\#include "ResonanceUI.h"} {public -} - -decl {\#include } {public -} - -decl {\#include } {public -} - -decl {\#include } {} - -decl {\#include } {} - -decl {\#include } {} - -decl {\#include } {} - -decl {\#include "WidgetPDial.h"} {public -} - -decl {\#include "EnvelopeUI.h"} {public -} - -decl {\#include "LFOUI.h"} {public -} - -decl {\#include "FilterUI.h"} {public -} - -decl {\#include "OscilGenUI.h"} {public -} - -decl {\#include "PresetsUI.h"} {public -} - -class ADvoicelistitem {: {public Fl_Group} -} { - Function {make_window()} {private - } { - Fl_Window ADnoteVoiceListItem { - private xywh {247 599 615 30} type Double hide - class Fl_Group - } { - Fl_Group voicelistitemgroup { - private xywh {50 0 570 25} box FLAT_BOX - code0 {if (pars->VoicePar[nvoice].Enabled==0) o->deactivate();} - } { - Fl_Value_Slider voicevolume { - callback {pars->VoicePar[nvoice].PVolume=(int)o->value();} - tooltip Volume xywh {90 5 115 20} type {Horz Knob} box FLAT_BOX labelsize 8 align 5 maximum 127 step 1 - code0 {o->value(pars->VoicePar[nvoice].PVolume);} - } - Fl_Check_Button voiceresonanceenabled { - callback {pars->VoicePar[nvoice].Presonance=(int)o->value();} - tooltip {Resonance On/Off} xywh {245 7 15 17} down_box DOWN_BOX labeltype EMBOSSED_LABEL labelfont 1 labelsize 11 align 4 - code0 {o->value(pars->VoicePar[nvoice].Presonance);} - } - Fl_Value_Slider voicelfofreq { - callback {pars->VoicePar[nvoice].FreqLfo->Pintensity=(int)o->value();} - tooltip {Frequency LFO amount} xywh {500 5 115 20} type {Horz Knob} box FLAT_BOX labelsize 8 align 5 maximum 127 step 1 - code0 {o->value(pars->VoicePar[nvoice].FreqLfo->Pintensity);} - } - Fl_Dial voicepanning { - callback {pars->VoicePar[nvoice].PPanning=(int) o->value();} - tooltip {Panning (leftmost is Random)} xywh {215 5 20 20} box ROUND_UP_BOX labelsize 10 align 4 maximum 127 step 1 - code0 {o->value(pars->VoicePar[nvoice].PPanning);} - class WidgetPDial - } - Fl_Group voiceoscil {open - xywh {60 5 30 20} box THIN_DOWN_BOX color 32 selection_color 71 labelcolor 179 - code0 {osc=new Oscilloscope(o->x(),o->y(),o->w(),o->h(),"");} - code1 {osc->init(pars->VoicePar[nvoice].OscilSmp,0,pars->VoicePar[nvoice].Poscilphase,master);} - code2 {if (pars->VoicePar[nvoice].Pextoscil != -1) {osc->init(pars->VoicePar[pars->VoicePar[nvoice].Pextoscil].OscilSmp,master);}} - } {} - Fl_Value_Output detunevalueoutput { - callback {o->value(getdetune((pars->VoicePar[nvoice].PDetuneType==0)?(pars->GlobalPar.PDetuneType) : (pars->VoicePar[nvoice].PDetuneType),0,pars->VoicePar[nvoice].PDetune)*pars->getBandwidthDetuneMultiplier());} - xywh {265 5 45 20} labelsize 10 align 5 minimum -5000 maximum 5000 step 0.01 textfont 1 textsize 10 - code0 {o->value(getdetune(pars->VoicePar[nvoice].PDetuneType,0,pars->VoicePar[nvoice].PDetune)*pars->getBandwidthDetuneMultiplier());} - } - Fl_Slider voicedetune { - callback {pars->VoicePar[nvoice].PDetune=(int)o->value()+8192; -detunevalueoutput->do_callback();} - tooltip {Fine Detune (cents)} xywh {315 5 185 20} type {Horz Knob} box FLAT_BOX minimum -8192 maximum 8191 step 1 - code0 {o->value(pars->VoicePar[nvoice].PDetune-8192);} - } - Fl_Box noiselabel { - label N - callback {if (pars->VoicePar[nvoice].Type==0) { - o->hide(); - voiceresonanceenabled->activate(); - detunevalueoutput->activate(); - voicedetune->activate(); - voicelfofreq->activate(); - voiceoscil->activate(); -} else { - o->show(); - voiceresonanceenabled->deactivate(); - detunevalueoutput->deactivate(); - voicedetune->deactivate(); - voicelfofreq->deactivate(); - voiceoscil->deactivate(); -};} - xywh {65 5 20 20} labelfont 1 labelsize 13 labelcolor 7 - code0 {if (pars->VoicePar[nvoice].Type==0) o->hide();} - } - } - Fl_Check_Button voiceenabled { - label 01 - callback {pars->VoicePar[nvoice].Enabled=(int)o->value(); -if (o->value()==0) voicelistitemgroup->deactivate(); -else voicelistitemgroup->activate(); -o->redraw();} - private xywh {30 5 20 20} down_box DOWN_BOX labeltype EMBOSSED_LABEL labelfont 1 labelsize 13 align 4 - code0 {char tmp[10];snprintf(tmp,10,"%d",nvoice+1);o->label(strdup(tmp));} - code1 {o->value(pars->VoicePar[nvoice].Enabled);} - } - } - } - Function {ADvoicelistitem(int x,int y, int w, int h, const char *label=0):Fl_Group(x,y,w,h,label)} {} { - code {nvoice=0; -pars=NULL;} {} - } - Function {init(ADnoteParameters *parameters,int nvoice_,Master *master_)} {} { - code {pars=parameters; -nvoice=nvoice_; -master=master_; -make_window(); -ADnoteVoiceListItem->show(); -end();} {} - } - Function {refreshlist()} {} { - code {voiceenabled->value(pars->VoicePar[nvoice].Enabled); -voiceresonanceenabled->value(pars->VoicePar[nvoice].Presonance); -voicevolume->value(pars->VoicePar[nvoice].PVolume); -voicedetune->value(pars->VoicePar[nvoice].PDetune-8192); -voicepanning->value(pars->VoicePar[nvoice].PPanning); -voicelfofreq->value(pars->VoicePar[nvoice].FreqLfo->Pintensity); -if (pars->VoicePar[nvoice].Pextoscil != -1) { - osc->init(pars->VoicePar[pars->VoicePar[nvoice].Pextoscil].OscilSmp,0,pars->VoicePar[nvoice].Poscilphase,master); -} else - osc->init(pars->VoicePar[nvoice].OscilSmp,0,pars->VoicePar[nvoice].Poscilphase,master); -if (pars->VoicePar[nvoice].Enabled==0) voicelistitemgroup->deactivate(); - else voicelistitemgroup->activate(); -detunevalueoutput->do_callback(); -noiselabel->do_callback(); -ADnoteVoiceListItem->redraw();} {} - } - Function {~ADvoicelistitem()} {} { - code {ADnoteVoiceListItem->hide(); -//delete(ADnoteVoiceListItem);} {} - } - decl {ADnoteParameters *pars;} {} - decl {int nvoice;} {} - decl {Oscilloscope *osc;} {} - decl {Master *master;} {} -} - -class ADvoiceUI {open : {public Fl_Group} -} { - Function {make_window()} {open - } { - Fl_Window ADnoteVoiceParameters { - label Voice - xywh {69 185 765 575} type Double - class Fl_Group visible - } { - Fl_Group voiceparametersgroup {open - xywh {0 0 765 580} box THIN_UP_BOX color 48 - code0 {if (pars->VoicePar[nvoice].Enabled==0) o->deactivate();} - } { - Fl_Group voicemodegroup {open - xywh {0 5 760 575} - } { - Fl_Group voiceFMparametersgroup { - label MODULATOR - xywh {530 5 230 565} box THIN_UP_FRAME color 48 labeltype EMBOSSED_LABEL labelfont 1 labelsize 13 align 17 - code0 {if (pars->VoicePar[nvoice].PFMEnabled==0) o->deactivate();} - } { - Fl_Group modfrequency { - label {Mod.FREQUENCY} - xywh {535 220 220 145} box THIN_UP_BOX labeltype EMBOSSED_LABEL labelfont 1 labelsize 13 align 17 - } { - Fl_Group voiceFMfreqenvgroup { - label {ADSynth Modulator - Frequency Envelope} - xywh {540 290 205 70} box FLAT_BOX color 51 align 144 - code0 {o->init(pars->VoicePar[nvoice].FMFreqEnvelope);} - code1 {if (pars->VoicePar[nvoice].PFMFreqEnvelopeEnabled==0) o->deactivate();} - class EnvelopeUI - } {} - Fl_Check_Button {} { - label Enable - callback {pars->VoicePar[nvoice].PFMFreqEnvelopeEnabled=(int)o->value(); -if (o->value()==0) voiceFMfreqenvgroup->deactivate(); -else voiceFMfreqenvgroup->activate(); -o->redraw();} - tooltip {Forced Relase} xywh {545 295 50 10} down_box DOWN_BOX labelfont 1 labelsize 10 - code0 {o->value(pars->VoicePar[nvoice].PFMFreqEnvelopeEnabled);} - } - Fl_Counter {} { - label {Coarse Det.} - callback {int k=(int) o->value(); -if (k<0) k+=1024; -pars->VoicePar[nvoice].PFMCoarseDetune = k+ - (pars->VoicePar[nvoice].PFMCoarseDetune/1024)*1024;} - tooltip {Coarse Detune} xywh {685 270 60 15} labelsize 10 align 1 minimum -64 maximum 63 step 1 textfont 1 textsize 11 - code0 {int k=pars->VoicePar[nvoice].PFMCoarseDetune%1024;} - code1 {if (k>=512) k-=1024;} - code2 {o->value(k);} - code3 {o->lstep(10);} - } - Fl_Counter {} { - label Octave - callback {int k=(int) o->value(); -if (k<0) k+=16; -pars->VoicePar[nvoice].PFMCoarseDetune = k*1024+ - pars->VoicePar[nvoice].PFMCoarseDetune%1024;} - tooltip Octave xywh {625 270 45 15} type Simple labelsize 10 align 1 minimum -8 maximum 7 step 1 textfont 1 textsize 11 - code0 {int k=pars->VoicePar[nvoice].PFMCoarseDetune/1024;} - code1 {if (k>=8) k-=16;} - code2 {o->value(k);} - } - Fl_Slider {} { - callback {pars->VoicePar[nvoice].PFMDetune=(int)o->value()+8192; -fmdetunevalueoutput->do_callback();} - tooltip {Fine Detune (cents)} xywh {590 245 160 10} type {Horz Knob} box FLAT_BOX minimum -8192 maximum 8191 step 1 - code0 {o->value(pars->VoicePar[nvoice].PFMDetune-8192);} - } - Fl_Value_Output fmdetunevalueoutput { - label Detune - callback {o->value(getdetune((pars->VoicePar[nvoice].PFMDetuneType==0)?(pars->GlobalPar.PDetuneType) : (pars->VoicePar[nvoice].PFMDetuneType),0,pars->VoicePar[nvoice].PFMDetune));} - xywh {540 245 45 13} labelsize 8 align 5 minimum -5000 maximum 5000 step 0.01 textfont 1 textsize 8 - code0 {o->value(getdetune((pars->VoicePar[nvoice].PFMDetuneType==0)?(pars->GlobalPar.PDetuneType) : (pars->VoicePar[nvoice].PFMDetuneType),0,pars->VoicePar[nvoice].PFMDetune));} - code1 {//o->value(getdetune(pars->VoicePar[nvoice].PFMDetuneType,0,pars->VoicePar[nvoice].PFMDetune));} - } - Fl_Choice {} { - label {Detune Type} - callback {pars->VoicePar[nvoice].PFMDetuneType=(int) o->value(); -fmdetunevalueoutput->do_callback();} open - xywh {540 270 75 15} down_box BORDER_BOX labelsize 10 align 5 textfont 1 textsize 10 - code0 {o->add("Default");o->add("L35cents");o->add("L10cents");o->add("E100cents");o->add("E1200cents");} - code1 {o->value(pars->VoicePar[nvoice].PFMDetuneType);} - } {} - } - Fl_Group {} { - label {Mod.AMPLITUDE} - xywh {535 60 220 160} box THIN_UP_BOX labeltype EMBOSSED_LABEL labelfont 1 labelsize 13 align 17 - } { - Fl_Value_Slider {} { - label Vol - callback {pars->VoicePar[nvoice].PFMVolume=(int)o->value();} - tooltip Volume xywh {540 80 160 15} type {Horz Knob} box FLAT_BOX labelsize 11 align 8 maximum 127 step 1 - code0 {o->value(pars->VoicePar[nvoice].PFMVolume);} - } - Fl_Value_Slider {} { - label {V.Sns} - callback {pars->VoicePar[nvoice].PFMVelocityScaleFunction=(int) o->value();} - tooltip {Velocity Sensing Function (rightmost to disable)} xywh {540 100 160 15} type {Horz Knob} box FLAT_BOX labelsize 11 align 8 maximum 127 step 1 - code0 {o->value(pars->VoicePar[nvoice].PFMVelocityScaleFunction);} - } - Fl_Group voiceFMampenvgroup { - label {ADSynth Modulator - Amplitude Envelope} open - xywh {540 145 205 70} box FLAT_BOX color 51 align 144 - code0 {o->init(pars->VoicePar[nvoice].FMAmpEnvelope);} - code1 {if (pars->VoicePar[nvoice].PFMAmpEnvelopeEnabled==0) o->deactivate();} - class EnvelopeUI - } {} - Fl_Check_Button {} { - label Enable - callback {pars->VoicePar[nvoice].PFMAmpEnvelopeEnabled=(int)o->value(); -if (o->value()==0) voiceFMampenvgroup->deactivate(); -else voiceFMampenvgroup->activate(); -o->redraw();} - tooltip {Forced Relase} xywh {545 150 50 10} down_box DOWN_BOX labelfont 1 labelsize 10 - code0 {o->value(pars->VoicePar[nvoice].PFMAmpEnvelopeEnabled);} - } - Fl_Value_Slider {} { - label {F.Damp} - callback {pars->VoicePar[nvoice].PFMVolumeDamp=(int) o->value()+64;} - tooltip {Modulator Damp at Higher frequency} xywh {540 120 160 15} type {Horz Knob} box FLAT_BOX labelsize 11 align 8 minimum -64 maximum 63 step 1 - code0 {o->value(pars->VoicePar[nvoice].PFMVolumeDamp-64);} - } - } - Fl_Group modoscil { - xywh {535 365 220 200} - } { - Fl_Group fmoscil {open - xywh {535 425 220 140} box THIN_DOWN_BOX color 32 selection_color 71 labelcolor 179 - code0 {oscFM=new Oscilloscope(o->x(),o->y(),o->w(),o->h(),"");} - code1 {int nv=nvoice; if (pars->VoicePar[nvoice].PextFMoscil>=0) nv=pars->VoicePar[nvoice].PextFMoscil;} - code2 {oscFM->init(pars->VoicePar[nv].FMSmp,0,pars->VoicePar[nvoice].PFMoscilphase,master);} - } {} - Fl_Box {} { - label {Mod.Oscillator} - xywh {535 365 155 20} labelfont 1 align 20 - } - Fl_Button changeFMoscilbutton { - label Change - callback {if (oscedit!=NULL) delete(oscedit); - -int nv=nvoice; -if (pars->VoicePar[nvoice].PextFMoscil>=0) nv=pars->VoicePar[nvoice].PextFMoscil; - -oscedit=new OscilEditor(pars->VoicePar[nv].FMSmp,fmoscil,NULL,NULL,master);} - xywh {700 370 55 15} box THIN_UP_BOX labelfont 1 labelsize 11 - code0 {if (pars->VoicePar[nvoice].PextFMoscil>=0) o->labelcolor(FL_BLUE);} - } - Fl_Slider {} { - label Phase - callback {pars->VoicePar[nvoice].PFMoscilphase=64-(int)o->value(); -oscFM->phase=64-(int) o->value(); -fmoscil->redraw();} - xywh {665 400 65 10} type {Horz Knob} box FLAT_BOX labelsize 10 align 5 minimum -64 maximum 63 step 1 - code0 {o->value(64-pars->VoicePar[nvoice].PFMoscilphase);} - } - Fl_Choice {} { - label Use - callback {pars->VoicePar[nvoice].PextFMoscil=(int)o->value()-1; -if ((int) o->value() != 0) { - oscFM->init(pars->VoicePar[(int) o->value()-1].FMSmp,master); - changeFMoscilbutton->labelcolor(FL_BLUE); -} else { - oscFM->init(pars->VoicePar[nvoice].FMSmp,master); - changeFMoscilbutton->labelcolor(FL_BLACK); -}; -voiceFMparametersgroup->redraw();} open - xywh {560 395 75 15} down_box BORDER_BOX labelsize 10 textfont 1 textsize 10 - code0 {o->add("Internal");} - code1 {char tmp[50]; for (int i=0;iadd(tmp);};} - code3 {o->value(pars->VoicePar[nvoice].PextFMoscil+1);} - } {} - } - Fl_Choice {} { - label {External Mod.} - callback {pars->VoicePar[nvoice].PFMVoice=(int)o->value()-1; -if ((int) o->value() != 0) { - modoscil->deactivate(); - modfrequency->deactivate(); -} else { - modoscil->activate(); - modfrequency->activate(); -}; -voiceFMparametersgroup->redraw();} open - xywh {635 40 85 20} down_box BORDER_BOX labelsize 10 align 5 textfont 1 textsize 10 - code0 {o->add("OFF");} - code1 {char tmp[50]; for (int i=0;iadd(tmp);};} - code2 {o->value(pars->VoicePar[nvoice].PFMVoice+1);} - code3 {if ((int) o->value() != 0) {modoscil->deactivate();modfrequency->deactivate();}} - } {} - } - Fl_Choice {} { - label {Type:} - callback {pars->VoicePar[nvoice].PFMEnabled=(int)o->value(); -if (o->value()==0) voiceFMparametersgroup->deactivate(); -else voiceFMparametersgroup->activate(); -o->redraw();} - xywh {535 40 80 20} down_box BORDER_BOX align 5 - code0 {o->value(pars->VoicePar[nvoice].PFMEnabled);} - } { - MenuItem {} { - label OFF - xywh {40 40 100 20} labelfont 1 - } - MenuItem {} { - label MORPH - xywh {50 50 100 20} labelfont 1 - } - MenuItem {} { - label RING - xywh {60 60 100 20} labelfont 1 - } - MenuItem {} { - label PM - xywh {70 70 100 20} labelfont 1 - } - MenuItem {} { - label FM - xywh {80 80 100 20} labelfont 1 - } - MenuItem {} { - label PITCH - xywh {90 90 100 20} labelfont 1 deactivate - } - } - Fl_Group {} { - label FREQUENCY - xywh {5 250 525 120} box THIN_UP_BOX labeltype EMBOSSED_LABEL labelfont 1 labelsize 13 align 17 - } { - Fl_Group voicefreqenvgroup { - label {ADSynth Voice - Frequency Envelope} open - xywh {10 290 205 70} box FLAT_BOX color 51 align 144 - code0 {o->init(pars->VoicePar[nvoice].FreqEnvelope);} - code1 {if (pars->VoicePar[nvoice].PFreqEnvelopeEnabled==0) o->deactivate();} - class EnvelopeUI - } {} - Fl_Check_Button {} { - label Enable - callback {pars->VoicePar[nvoice].PFreqEnvelopeEnabled=(int)o->value(); -if (o->value()==0) voicefreqenvgroup->deactivate(); -else voicefreqenvgroup->activate(); -o->redraw();} - tooltip {Forced Relase} xywh {15 295 50 10} down_box DOWN_BOX labelfont 1 labelsize 10 - code0 {o->value(pars->VoicePar[nvoice].PFreqEnvelopeEnabled);} - } - Fl_Group voicefreqlfogroup { - label {Frequency LFO } open - xywh {215 290 230 70} box FLAT_BOX color 47 align 144 - code0 {o->init(pars->VoicePar[nvoice].FreqLfo);} - code1 {if (pars->VoicePar[nvoice].PFreqLfoEnabled==0) o->deactivate();} - class LFOUI - } {} - Fl_Check_Button {} { - label Enable - callback {pars->VoicePar[nvoice].PFreqLfoEnabled=(int)o->value(); -if (o->value()==0) voicefreqlfogroup->deactivate(); -else voicefreqlfogroup->activate(); -o->redraw();} - tooltip {Forced Relase} xywh {220 295 55 10} down_box DOWN_BOX labelfont 1 labelsize 10 - code0 {o->value(pars->VoicePar[nvoice].PFreqLfoEnabled);} - } - Fl_Counter {} { - label Octave - callback {int k=(int) o->value(); -if (k<0) k+=16; -pars->VoicePar[nvoice].PCoarseDetune = k*1024+ - pars->VoicePar[nvoice].PCoarseDetune%1024;} - tooltip Octave xywh {470 270 45 15} type Simple labelsize 10 align 1 minimum -8 maximum 7 step 1 textfont 1 textsize 11 - code0 {int k=pars->VoicePar[nvoice].PCoarseDetune/1024;} - code1 {if (k>=8) k-=16;} - code2 {o->value(k);} - } - Fl_Counter {} { - label {Coarse Det.} - callback {int k=(int) o->value(); -if (k<0) k+=1024; -pars->VoicePar[nvoice].PCoarseDetune = k+ - (pars->VoicePar[nvoice].PCoarseDetune/1024)*1024;} - tooltip {Coarse Detune} xywh {455 340 60 20} labelsize 10 align 1 minimum -64 maximum 63 step 1 textfont 1 textsize 11 - code0 {int k=pars->VoicePar[nvoice].PCoarseDetune%1024;} - code1 {if (k>=512) k-=1024;} - code2 {o->value(k);} - code3 {o->lstep(10);} - } - Fl_Slider {} { - callback {pars->VoicePar[nvoice].PDetune=(int)o->value()+8192; -detunevalueoutput->do_callback();} - tooltip {Fine Detune (cents)} xywh {58 272 392 13} type {Horz Knob} box FLAT_BOX minimum -8192 maximum 8191 step 1 - code0 {o->value(pars->VoicePar[nvoice].PDetune-8192);} - } - Fl_Value_Output detunevalueoutput { - label Detune - callback {o->value(getdetune((pars->VoicePar[nvoice].PDetuneType==0)?(pars->GlobalPar.PDetuneType) : (pars->VoicePar[nvoice].PDetuneType),0,pars->VoicePar[nvoice].PDetune)*pars->getBandwidthDetuneMultiplier());} - xywh {10 272 45 15} labelsize 10 align 5 minimum -5000 maximum 5000 step 0.01 textfont 1 textsize 10 - code0 {o->value(getdetune((pars->VoicePar[nvoice].PDetuneType==0)?(pars->GlobalPar.PDetuneType) : (pars->VoicePar[nvoice].PDetuneType),0,pars->VoicePar[nvoice].PDetune)*pars->getBandwidthDetuneMultiplier());} - } - Fl_Check_Button {} { - label 440Hz - callback {int x=(int) o->value(); -pars->VoicePar[nvoice].Pfixedfreq=x; -if (x==0) fixedfreqetdial->deactivate(); - else fixedfreqetdial->activate();} - tooltip {Set the voice base frequency to 440Hz} xywh {345 253 55 15} down_box DOWN_BOX labelfont 1 labelsize 11 - code0 {o->value(pars->VoicePar[nvoice].Pfixedfreq);} - } - Fl_Dial fixedfreqetdial { - label {Eq.T.} - callback {pars->VoicePar[nvoice].PfixedfreqET=(int) o->value();} - tooltip {How the frequency varies acording to the keyboard (leftmost for fixed frequency)} xywh {405 255 15 15} box ROUND_UP_BOX labelsize 10 align 8 maximum 127 step 1 - code0 {o->value(pars->VoicePar[nvoice].PfixedfreqET);} - code1 {if (pars->VoicePar[nvoice].Pfixedfreq==0) o->deactivate();} - class WidgetPDial - } - Fl_Choice {} { - label {Detune Type} - callback {pars->VoicePar[nvoice].PDetuneType=(int) o->value(); -detunevalueoutput->do_callback();} open - xywh {450 305 75 15} down_box BORDER_BOX labelsize 10 align 5 textfont 1 textsize 10 - code0 {o->add("Default");o->add("L35cents");o->add("L10cents");o->add("E100cents");o->add("E1200cents");} - code1 {o->value(pars->VoicePar[nvoice].PDetuneType);} - } {} - } - Fl_Group voiceoscil { - xywh {80 375 445 145} box THIN_DOWN_BOX color 32 selection_color 71 labelcolor 179 - code0 {osc=new Oscilloscope(o->x(),o->y(),o->w(),o->h(),"");} - code1 {int nv=nvoice; if (pars->VoicePar[nvoice].Pextoscil>=0) nv=pars->VoicePar[nvoice].Pextoscil;} - code2 {osc->init(pars->VoicePar[nv].OscilSmp,0,pars->VoicePar[nvoice].Poscilphase,master);} - } {} - Fl_Button changevoiceoscilbutton { - label Change - callback {if (oscedit!=NULL) delete(oscedit); - -int nv=nvoice; -if (pars->VoicePar[nvoice].Pextoscil>=0) nv=pars->VoicePar[nvoice].Pextoscil; - -oscedit=new OscilEditor(pars->VoicePar[nv].OscilSmp,voiceoscil,NULL,NULL,master);} - xywh {5 475 65 20} box THIN_UP_BOX labelfont 1 labelsize 11 - code0 {if (pars->VoicePar[nvoice].Pextoscil>=0) o->labelcolor(FL_BLUE);} - } - Fl_Box {} { - label {Voice Oscillator} - xywh {5 375 75 35} labelfont 1 labelsize 12 align 128 - } - Fl_Slider {} { - label Phase - callback {pars->VoicePar[nvoice].Poscilphase=64-(int)o->value(); -osc->phase=64-(int) o->value(); -voiceoscil->redraw();} - xywh {10 420 65 10} type {Horz Knob} box FLAT_BOX labelsize 10 align 5 minimum -64 maximum 63 step 1 - code0 {o->value(64-pars->VoicePar[nvoice].Poscilphase);} - } - Fl_Check_Button {} { - label {R.} - callback {pars->VoicePar[nvoice].Presonance=(int) o->value();} - tooltip {Resonance On/Off} xywh {210 5 35 35} box THIN_UP_BOX down_box DOWN_BOX labelfont 1 labelsize 11 - code0 {o->value(pars->VoicePar[nvoice].Presonance);} - } - Fl_Choice {} { - label {Use Oscil.} - callback {pars->VoicePar[nvoice].Pextoscil=(int)o->value()-1; -if ((int) o->value() != 0) { - osc->init(pars->VoicePar[(int) o->value()-1].OscilSmp,master); - changevoiceoscilbutton->labelcolor(FL_BLUE); -} else { - osc->init(pars->VoicePar[nvoice].OscilSmp,master); - changevoiceoscilbutton->labelcolor(FL_BLACK); -}; - -voiceparametersgroup->redraw(); -voiceonbutton->redraw();} open - xywh {5 455 65 15} down_box BORDER_BOX labelsize 10 align 5 textfont 1 textsize 10 - code0 {o->add("Internal");} - code1 {char tmp[50]; for (int i=0;iadd(tmp);};} - code3 {o->value(pars->VoicePar[nvoice].Pextoscil+1);} - } {} - Fl_Group {} {open - xywh {5 525 515 45} box ENGRAVED_BOX - } { - Fl_Dial {} { - label Stereo - callback {pars->VoicePar[nvoice].Unison_stereo_spread=(int)o->value();} - tooltip {Stereo Spread} xywh {285 540 25 25} box ROUND_UP_BOX labelsize 10 align 1 maximum 127 step 1 - code0 {o->value(pars->VoicePar[nvoice].Unison_stereo_spread);} - class WidgetPDial - } - Fl_Choice {} { - label Unison - callback {pars->set_unison_size_index(nvoice,(int) o->value());} open selected - tooltip {Unison size} xywh {10 545 75 20} down_box BORDER_BOX labelfont 1 align 5 textfont 1 textsize 10 - code0 {o->add("OFF");char tmp[100];for (int i=1;ADnote_unison_sizes[i];i++){snprintf(tmp,100,"size %d",ADnote_unison_sizes[i]);o->add(tmp);};} - code1 {o->value(pars->get_unison_size_index(nvoice));} - } {} - Fl_Dial {} { - label Vibratto - callback {pars->VoicePar[nvoice].Unison_vibratto=(int)o->value();} - tooltip Vibratto xywh {340 540 25 25} box ROUND_UP_BOX labelsize 10 align 1 maximum 127 step 1 - code0 {o->value(pars->VoicePar[nvoice].Unison_vibratto);} - class WidgetPDial - } - Fl_Choice {} { - label Invert - callback {pars->VoicePar[nvoice].Unison_invert_phase=(int) o->value();} open - tooltip {Phase Invert} xywh {445 545 65 15} down_box BORDER_BOX labelsize 11 align 5 textfont 1 textsize 10 - code0 {o->add("None");o->add("Random");char tmp[100];for (int i=2;i<=5;i++){snprintf(tmp,100,"%d %%",100/i);o->add(tmp);};} - code1 {o->value(pars->VoicePar[nvoice].Unison_invert_phase);} - } {} - Fl_Slider {} { - label {Frequency Spread} - callback {pars->VoicePar[nvoice].Unison_frequency_spread=(int)o->value(); -unisonspreadoutput->do_callback();} - tooltip {Frequency Spread of the Unison} xywh {95 547 125 13} type {Horz Knob} box FLAT_BOX labelsize 12 align 1 maximum 127 step 1 value 64 - code0 {o->value(pars->VoicePar[nvoice].Unison_frequency_spread);} - } - Fl_Value_Output unisonspreadoutput { - label {(cents)} - callback {o->value(pars->getUnisonFrequencySpreadCents(nvoice));} - xywh {225 545 40 15} labelsize 10 align 5 maximum 1000 step 0.1 textfont 1 textsize 10 - code0 {o->value(pars->getUnisonFrequencySpreadCents(nvoice));} - } - Fl_Dial {} { - label {Vib.speed} - callback {pars->VoicePar[nvoice].Unison_vibratto_speed=(int)o->value();} - tooltip {Vibratto Average Speed} xywh {390 540 25 25} box ROUND_UP_BOX labelsize 10 align 1 maximum 127 step 1 - code0 {o->value(pars->VoicePar[nvoice].Unison_vibratto_speed);} - class WidgetPDial - } - } - } - Fl_Group {} { - label AMPLITUDE - xywh {5 40 240 210} box THIN_UP_BOX labeltype EMBOSSED_LABEL labelfont 1 labelsize 13 align 17 - } { - Fl_Value_Slider {} { - label Vol - callback {pars->VoicePar[nvoice].PVolume=(int)o->value();} - tooltip Volume xywh {10 60 160 15} type {Horz Knob} box FLAT_BOX labelsize 11 align 8 maximum 127 step 1 - code0 {o->value(pars->VoicePar[nvoice].PVolume);} - } - Fl_Value_Slider {} { - label {V.Sns} - callback {pars->VoicePar[nvoice].PAmpVelocityScaleFunction=(int) o->value();} - tooltip {Velocity Sensing Function (rightmost to disable)} xywh {10 80 160 15} type {Horz Knob} box FLAT_BOX labelsize 11 align 8 maximum 127 step 1 - code0 {o->value(pars->VoicePar[nvoice].PAmpVelocityScaleFunction);} - } - Fl_Group voiceampenvgroup { - label {ADSynth Voice - Amplitude Envelope} open - xywh {10 105 205 70} box FLAT_BOX color 51 align 144 - code0 {o->init(pars->VoicePar[nvoice].AmpEnvelope);} - code1 {if (pars->VoicePar[nvoice].PAmpEnvelopeEnabled==0) o->deactivate();} - class EnvelopeUI - } {} - Fl_Dial {} { - label Pan - callback {pars->VoicePar[nvoice].PPanning=(int) o->value();} - tooltip {Panning (leftmost is Random)} xywh {210 60 30 30} box ROUND_UP_BOX labelsize 10 maximum 127 step 1 - code0 {o->value(pars->VoicePar[nvoice].PPanning);} - class WidgetPDial - } - Fl_Check_Button {} { - label Enable - callback {pars->VoicePar[nvoice].PAmpEnvelopeEnabled=(int)o->value(); -if (o->value()==0) voiceampenvgroup->deactivate(); -else voiceampenvgroup->activate(); -o->redraw();} - tooltip {Forced Relase} xywh {15 110 50 10} down_box DOWN_BOX labelfont 1 labelsize 10 - code0 {o->value(pars->VoicePar[nvoice].PAmpEnvelopeEnabled);} - } - Fl_Group voiceamplfogroup { - label {Amplitude LFO } open - xywh {10 175 230 70} box FLAT_BOX color 47 align 144 - code0 {o->init(pars->VoicePar[nvoice].AmpLfo);} - code1 {if (pars->VoicePar[nvoice].PAmpLfoEnabled==0) o->deactivate();} - class LFOUI - } {} - Fl_Check_Button {} { - label Enable - callback {pars->VoicePar[nvoice].PAmpLfoEnabled=(int)o->value(); -if (o->value()==0) voiceamplfogroup->deactivate(); -else voiceamplfogroup->activate(); -o->redraw();} - tooltip {Forced Relase} xywh {15 180 55 10} down_box DOWN_BOX labelfont 1 labelsize 10 - code0 {o->value(pars->VoicePar[nvoice].PAmpLfoEnabled);} - } - Fl_Check_Button {} { - label Minus - callback {pars->VoicePar[nvoice].PVolumeminus=(int)o->value();} - xywh {10 45 50 10} down_box DOWN_BOX labelfont 1 labelsize 10 - code0 {o->value(pars->VoicePar[nvoice].PVolumeminus);} - } - } - Fl_Group voicefiltergroup { - label FILTER - xywh {245 5 285 245} box THIN_UP_BOX labeltype EMBOSSED_LABEL labelfont 1 labelsize 13 align 17 - code0 {if (pars->VoicePar[nvoice].PFilterEnabled==0) o->deactivate();} - } { - Fl_Group {} { - label {ADsynth Voice - Filter} open - xywh {250 30 275 75} box FLAT_BOX color 50 align 144 - code0 {o->init(pars->VoicePar[nvoice].VoiceFilter,NULL,NULL);} - class FilterUI - } {} - Fl_Group voicefilterenvgroup { - label {ADSynth Voice - Filter Envelope} open - xywh {250 105 275 70} box FLAT_BOX color 51 align 144 - code0 {o->init(pars->VoicePar[nvoice].FilterEnvelope);} - code1 {if (pars->VoicePar[nvoice].PFilterEnvelopeEnabled==0) o->deactivate();} - class EnvelopeUI - } {} - Fl_Check_Button {} { - label Enable - callback {pars->VoicePar[nvoice].PFilterEnvelopeEnabled=(int)o->value(); -if (o->value()==0) voicefilterenvgroup->deactivate(); -else voicefilterenvgroup->activate(); -o->redraw();} - tooltip {Forced Relase} xywh {255 110 55 10} down_box DOWN_BOX labelfont 1 labelsize 10 - code0 {o->value(pars->VoicePar[nvoice].PFilterEnvelopeEnabled);} - } - Fl_Group voicefilterlfogroup { - label {Filter LFO } open - xywh {250 175 230 70} box FLAT_BOX color 47 align 144 - code0 {o->init(pars->VoicePar[nvoice].FilterLfo);} - code1 {if (pars->VoicePar[nvoice].PFilterLfoEnabled==0) o->deactivate();} - class LFOUI - } {} - Fl_Check_Button {} { - label Enable - callback {pars->VoicePar[nvoice].PFilterLfoEnabled=(int)o->value(); -if (o->value()==0) voicefilterlfogroup->deactivate(); -else voicefilterlfogroup->activate(); -o->redraw();} - tooltip {Forced Relase} xywh {255 180 55 10} down_box DOWN_BOX labelfont 1 labelsize 10 - code0 {o->value(pars->VoicePar[nvoice].PFilterLfoEnabled);} - } - } - Fl_Group {} { - label 01 - xywh {5 5 55 35} box THIN_UP_BOX labeltype EMBOSSED_LABEL labelfont 1 labelsize 22 align 16 - code0 {char tmp[10];snprintf(tmp,10,"%d",nvoice+1);o->label(strdup(tmp));} - } {} - Fl_Choice {} { - callback {int x=(int) o->value(); -pars->VoicePar[nvoice].Type=x; -if (x==0) voicemodegroup->activate(); - else voicemodegroup->deactivate(); -noiselabel->do_callback();} - tooltip {Oscillator Type (sound/noise)} xywh {5 500 65 20} down_box BORDER_BOX labelsize 10 textfont 1 textsize 10 - code0 {o->value(pars->VoicePar[nvoice].Type);} - code1 {if (pars->VoicePar[nvoice].Type!=0) voicemodegroup->deactivate();} - } { - MenuItem {} { - label Sound - xywh {5 5 100 20} labelfont 1 labelsize 11 - } - MenuItem {} { - label NOISE - xywh {15 15 100 20} labelfont 1 labelsize 11 labelcolor 1 - } - } - Fl_Check_Button bypassfiltercheckbutton { - label {Bypass Global F.} - callback {pars->VoicePar[nvoice].Pfilterbypass=(int)o->value();} - xywh {425 10 100 20} down_box DOWN_BOX labelfont 1 labelsize 10 align 148 - code0 {o->value(pars->VoicePar[nvoice].Pfilterbypass);} - } - Fl_Group {} { - xywh {115 5 95 35} box THIN_UP_BOX - } { - Fl_Value_Slider {} { - label Delay - callback {pars->VoicePar[nvoice].PDelay=(int)o->value();} - tooltip Volume xywh {120 21 84 12} type {Horz Knob} box FLAT_BOX labelsize 11 align 5 maximum 127 step 1 - code0 {o->value(pars->VoicePar[nvoice].PDelay);} - } - } - Fl_Check_Button {} { - label Enable - callback {pars->VoicePar[nvoice].PFilterEnabled=(int)o->value(); -if (o->value()==0) voicefiltergroup->deactivate(); -else voicefiltergroup->activate(); -o->redraw(); -bypassfiltercheckbutton->redraw();} - tooltip {Enable Filter} xywh {250 15 60 15} down_box DOWN_BOX labelfont 1 labelsize 10 - code0 {o->value(pars->VoicePar[nvoice].PFilterEnabled);} - } - Fl_Box noiselabel { - label {White Noise} - callback {if (pars->VoicePar[nvoice].Type==0) o->hide(); else o->show();} - xywh {150 415 300 65} labelfont 1 labelsize 50 labelcolor 7 - code0 {if (pars->VoicePar[nvoice].Type==0) o->hide(); else o->show();} - } - } - Fl_Check_Button voiceonbutton { - label On - callback {pars->VoicePar[nvoice].Enabled=(int)o->value(); -if (o->value()==0) voiceparametersgroup->deactivate(); -else voiceparametersgroup->activate(); -o->redraw();} - xywh {60 5 55 35} box THIN_UP_BOX down_box DOWN_BOX labelfont 1 labelsize 13 - code0 {o->value(pars->VoicePar[nvoice].Enabled);} - } - } - } - Function {ADvoiceUI(int x,int y, int w, int h, const char *label=0):Fl_Group(x,y,w,h,label)} {} { - code {nvoice=0; -pars=NULL; -oscedit=NULL;} {} - } - Function {init(ADnoteParameters *parameters,int nvoice_,Master *master_)} {open - } { - code {pars=parameters; -nvoice=nvoice_; -master=master_; -make_window(); -end(); -ADnoteVoiceParameters->show();} {} - } - Function {~ADvoiceUI()} {} { - code {ADnoteVoiceParameters->hide(); -hide(); -if (oscedit!=NULL) { - delete(oscedit); -}; -//delete (ADnoteVoiceParameters);} {} - } - decl {int nvoice;} {} - decl {ADnoteParameters *pars;} {} - decl {OscilEditor *oscedit;} {} - decl {Oscilloscope *osc;} {} - decl {Oscilloscope *oscFM;} {} - decl {Master *master;} {} -} - -class ADnoteUI {open : {public PresetsUI_} -} { - Function {make_window()} {open private - } { - Fl_Window ADnoteGlobalParameters { - label {ADsynth Global Parameters of the Instrument} - xywh {462 186 535 405} type Double hide - } { - Fl_Group {} { - label FREQUENCY - xywh {5 255 525 115} box THIN_UP_BOX labeltype EMBOSSED_LABEL labelfont 1 labelsize 13 align 17 - } { - Fl_Group freqenv { - label {ADSynth Global - Frequency Envelope} open - xywh {10 295 205 70} box FLAT_BOX color 51 align 144 - code0 {o->init(pars->GlobalPar.FreqEnvelope);} - class EnvelopeUI - } {} - Fl_Counter octave { - label Octave - callback {int k=(int) o->value(); -if (k<0) k+=16; -pars->GlobalPar.PCoarseDetune = k*1024+ - pars->GlobalPar.PCoarseDetune%1024;} - tooltip Octave xywh {450 275 45 15} type Simple labelsize 10 align 1 minimum -8 maximum 7 step 1 textfont 1 textsize 11 - code0 {int k=pars->GlobalPar.PCoarseDetune/1024;if (k>=8) k-=16;} - code2 {o->value(k);} - } - Fl_Counter coarsedet { - label {Coarse det.} - callback {int k=(int) o->value(); -if (k<0) k+=1024; -pars->GlobalPar.PCoarseDetune = k+ - (pars->GlobalPar.PCoarseDetune/1024)*1024;} - tooltip {Coarse Detune} xywh {455 345 60 20} labelsize 10 align 5 minimum -64 maximum 63 step 1 textfont 1 textsize 11 - code0 {int k=pars->GlobalPar.PCoarseDetune%1024;if (k>=512) k-=1024;} - code2 {o->value(k);} - code3 {o->lstep(10);} - } - Fl_Group freqlfo { - label {Frequency LFO } open - xywh {215 295 230 70} box FLAT_BOX color 47 align 144 - code0 {o->init(pars->GlobalPar.FreqLfo);} - class LFOUI - } {} - Fl_Slider freq { - callback {pars->GlobalPar.PDetune=(int)o->value()+8192; -detunevalueoutput->do_callback();} - tooltip {Fine Detune (cents)} xywh {60 275 385 15} type {Horz Knob} box FLAT_BOX minimum -8192 maximum 8191 step 1 - code0 {o->value(pars->GlobalPar.PDetune-8192);} - } - Fl_Value_Output detunevalueoutput { - label Detune - callback {o->value(getdetune(pars->GlobalPar.PDetuneType,0,pars->GlobalPar.PDetune));} - xywh {12 275 45 15} labelsize 10 align 5 minimum -5000 maximum 5000 step 0.01 textfont 1 textsize 10 - code0 {o->value(getdetune(pars->GlobalPar.PDetuneType,0,pars->GlobalPar.PDetune));} - } - Fl_Choice detunetype { - label {Detune Type} - callback {pars->GlobalPar.PDetuneType=(int) o->value()+1; -detunevalueoutput->do_callback();} open - xywh {450 315 75 15} down_box BORDER_BOX labelsize 10 align 5 textfont 1 textsize 10 - code0 {o->add("L35cents");o->add("L10cents");o->add("E100cents");o->add("E1200cents");} - code1 {o->value(pars->GlobalPar.PDetuneType-1);} - } {} - Fl_Dial {} { - label relBW - callback {pars->GlobalPar.PBandwidth=(int) o->value(); - -pars->getBandwidthDetuneMultiplier(); - -for (int i=0;irefreshlist(); -};} - tooltip {Bandwidth - how the relative fine detune of the voice are changed} xywh {500 270 25 25} box ROUND_UP_BOX labelsize 10 align 1 maximum 127 step 1 - code0 {o->value(pars->GlobalPar.PBandwidth);} - class WidgetPDial - } - } - Fl_Group {} { - label AMPLITUDE - xywh {5 5 240 250} box THIN_UP_FRAME labeltype EMBOSSED_LABEL labelfont 1 labelsize 13 align 17 - } { - Fl_Value_Slider volume { - label Vol - callback {pars->GlobalPar.PVolume=(int)o->value();} - tooltip Volume xywh {10 30 160 15} type {Horz Knob} box FLAT_BOX labelsize 11 align 8 maximum 127 step 1 - code0 {o->value(pars->GlobalPar.PVolume);} - } - Fl_Value_Slider vsns { - label {V.Sns} - callback {pars->GlobalPar.PAmpVelocityScaleFunction=(int) o->value();} - tooltip {Velocity Sensing Function (rightmost to disable)} xywh {10 50 160 15} type {Horz Knob} box FLAT_BOX labelsize 11 align 8 maximum 127 step 1 - code0 {o->value(pars->GlobalPar.PAmpVelocityScaleFunction);} - } - Fl_Dial pan { - label Pan - callback {pars->GlobalPar.PPanning=(int) o->value();} - tooltip {Panning (leftmost is Random)} xywh {210 25 30 30} box ROUND_UP_BOX labelsize 10 maximum 127 step 1 - code0 {o->value(pars->GlobalPar.PPanning);} - class WidgetPDial - } - Fl_Dial pstr { - label {P.Str.} - callback {pars->GlobalPar.PPunchStrength=(int) o->value();} - tooltip {Punch Strength} xywh {125 227 25 25} box ROUND_UP_BOX labelsize 10 align 1 maximum 127 step 1 - code0 {o->value(pars->GlobalPar.PPunchStrength);} - class WidgetPDial - } - Fl_Dial pt { - label {P.t.} - callback {pars->GlobalPar.PPunchTime=(int) o->value();} - tooltip {Punch Time (duration)} xywh {155 227 25 25} box ROUND_UP_BOX labelsize 10 align 1 maximum 127 step 1 - code0 {o->value(pars->GlobalPar.PPunchTime);} - class WidgetPDial - } - Fl_Dial pstc { - label {P.Stc.} - callback {pars->GlobalPar.PPunchStretch=(int) o->value();} - tooltip {Punch Stretch} xywh {185 227 25 25} box ROUND_UP_BOX labelsize 10 align 1 maximum 127 step 1 - code0 {o->value(pars->GlobalPar.PPunchStretch);} - class WidgetPDial - } - Fl_Dial pvel { - label {P.Vel.} - callback {pars->GlobalPar.PPunchVelocitySensing=(int) o->value();} - tooltip {Punch Velocity Sensing} xywh {215 227 25 25} box ROUND_UP_BOX labelsize 10 align 1 maximum 127 step 1 - code0 {o->value(pars->GlobalPar.PPunchVelocitySensing);} - class WidgetPDial - } - Fl_Group ampenv { - label {ADSynth Global - Amplitude Envelope} open - xywh {10 75 205 70} box FLAT_BOX color 51 align 144 - code0 {o->init(pars->GlobalPar.AmpEnvelope);} - class EnvelopeUI - } {} - Fl_Group amplfo { - label {Amplitude LFO } open - xywh {10 145 230 70} box FLAT_BOX color 47 align 144 - code0 {o->init(pars->GlobalPar.AmpLfo);} - class LFOUI - } {} - Fl_Check_Button rndgrp { - label {Rnd Grp} - callback {pars->GlobalPar.Hrandgrouping=(int) o->value();} - tooltip {How the Harmonic Amplitude is applied to voices that use the same oscillator} xywh {70 225 40 25} down_box DOWN_BOX labelsize 10 align 148 - code0 {o->value(pars->GlobalPar.Hrandgrouping);} - } - } - Fl_Group {} { - label FILTER - xywh {245 5 285 250} box THIN_UP_BOX labeltype EMBOSSED_LABEL labelfont 1 labelsize 13 align 17 - } { - Fl_Group filterenv { - label {ADSynth Global - Filter Envelope} open - xywh {250 110 275 70} box FLAT_BOX color 51 align 144 - code0 {o->init(pars->GlobalPar.FilterEnvelope);} - class EnvelopeUI - } {} - Fl_Group filterlfo { - label {Filter LFO} open - xywh {250 180 230 70} box FLAT_BOX color 47 align 144 - code0 {o->init(pars->GlobalPar.FilterLfo);} - class LFOUI - } {} - Fl_Group filterui { - label {ADsynth Global - Filter} open - xywh {250 35 275 75} box FLAT_BOX color 50 align 144 - code0 {o->init(pars->GlobalPar.GlobalFilter,&pars->GlobalPar.PFilterVelocityScale,&pars->GlobalPar.PFilterVelocityScaleFunction);} - class FilterUI - } {} - } - Fl_Check_Button stereo { - label Stereo - callback {pars->GlobalPar.PStereo=(int) o->value();} - xywh {5 220 65 35} box ENGRAVED_BOX down_box DOWN_BOX labelfont 1 labelsize 11 - code0 {o->value(pars->GlobalPar.PStereo);} - } - Fl_Button {} { - label {Show Voice List} - callback {for (int i=0;irefreshlist(); -} -ADnoteVoiceList->show();} - xywh {180 375 125 25} - } - Fl_Button {} { - label {Show Voice Parameters} - callback {ADnoteVoice->show();} - xywh {5 375 170 25} labelfont 1 labelsize 12 - } - Fl_Button {} { - label Close - callback {ADnoteGlobalParameters->hide();} - xywh {470 375 60 25} box THIN_UP_BOX - } - Fl_Button {} { - label Resonance - callback {resui->resonancewindow->redraw(); -resui->resonancewindow->show();} - tooltip Resonance xywh {309 375 86 25} box THIN_UP_BOX - } - Fl_Button {} { - label C - callback {presetsui->copy(pars);} - xywh {405 380 25 15} box THIN_UP_BOX color 179 labelfont 1 labelsize 11 labelcolor 7 - } - Fl_Button {} { - label P - callback {presetsui->paste(pars,this);} - xywh {435 380 25 15} box THIN_UP_BOX color 179 labelfont 1 labelsize 11 labelcolor 7 - } - } - Fl_Window ADnoteVoice { - label {ADsynth Voice Parameters} - xywh {152 271 765 620} type Double visible - } { - Fl_Group advoice { - xywh {0 0 760 575} box BORDER_BOX - code0 {o->init(pars,nvoice,master);} - code1 {o->show();} - class ADvoiceUI - } {} - Fl_Button {} { - label {Close Window} - callback {ADnoteVoice->hide();} - xywh {300 585 195 25} box THIN_UP_BOX labelfont 1 - } - Fl_Counter currentvoicecounter { - label {Current Voice} - callback {nvoice=(int)o->value()-1; -advoice->hide(); -ADnoteVoice->remove(advoice); -delete advoice; -advoice=new ADvoiceUI(0,0,765,585); -ADnoteVoice->add(advoice); -advoice->init(pars,nvoice,master); -advoice->show(); -ADnoteVoice->redraw();} - xywh {5 585 130 25} type Simple labelfont 1 align 8 minimum 0 maximum 2 step 1 value 1 textfont 1 textsize 13 - code0 {o->bounds(1,NUM_VOICES);} - } - Fl_Button {} { - label C - callback {presetsui->copy(pars,nvoice);} - xywh {700 590 25 15} box THIN_UP_BOX color 179 labelfont 1 labelsize 11 labelcolor 7 - } - Fl_Button {} { - label P - callback {presetsui->paste(pars,this,nvoice);} - xywh {730 590 25 15} box THIN_UP_BOX color 179 labelfont 1 labelsize 11 labelcolor 7 - } - } - Fl_Window ADnoteVoiceList { - label {ADsynth Voices list} - xywh {32 266 650 260} type Double hide - } { - Fl_Text_Display {} { - label {No.} - xywh {10 15 30 10} box NO_BOX labelfont 1 labelsize 11 - } - Fl_Text_Display {} { - label Vol - xywh {145 15 30 10} box NO_BOX labelfont 1 labelsize 11 - } - Fl_Text_Display {} { - label Detune - xywh {384 15 25 10} box NO_BOX labelfont 1 labelsize 11 - } - Fl_Text_Display {} { - label Pan - xywh {210 15 30 10} box NO_BOX labelfont 1 labelsize 11 - } - Fl_Text_Display {} { - label {Vib. Depth} - xywh {560 15 30 10} box NO_BOX labelfont 1 labelsize 11 - } - Fl_Text_Display {} { - label {R.} - xywh {245 15 25 10} box NO_BOX labelfont 1 labelsize 11 - } - Fl_Button {} { - label {Hide Voice List} - callback {ADnoteVoiceList->hide();} - xywh {255 237 125 20} - } - Fl_Scroll {} {open - xywh {0 15 640 220} type VERTICAL box THIN_UP_BOX - } { - Fl_Pack {} {open - xywh {0 20 620 210} - code0 {for (int i=0;iinit(pars,i,master);}} - } {} - } - } - } - Function {ADnoteUI(ADnoteParameters *parameters,Master *master_)} {} { - code {pars=parameters; -master=master_; -nvoice=0; -resui=new ResonanceUI(pars->GlobalPar.Reson); -make_window();} {} - } - Function {~ADnoteUI()} {} { - code {ADnoteVoiceList->hide(); -ADnoteGlobalParameters->hide(); -ADnoteVoice->hide(); -delete(ADnoteVoiceList); -delete(ADnoteGlobalParameters); -delete(ADnoteVoice); -delete(resui);} {} - } - Function {refresh()} {} { - code {volume->value(pars->GlobalPar.PVolume); -vsns->value(pars->GlobalPar.PAmpVelocityScaleFunction); -pan->value(pars->GlobalPar.PPanning); - -stereo->value(pars->GlobalPar.PStereo); -rndgrp->value(pars->GlobalPar.Hrandgrouping); - -pstr->value(pars->GlobalPar.PPunchStrength); -pt->value(pars->GlobalPar.PPunchTime); -pstc->value(pars->GlobalPar.PPunchStretch); -pvel->value(pars->GlobalPar.PPunchVelocitySensing); - -detunevalueoutput->value(getdetune(pars->GlobalPar.PDetuneType,0,pars->GlobalPar.PDetune)); -freq->value(pars->GlobalPar.PDetune-8192); - -int k=pars->GlobalPar.PCoarseDetune/1024;if (k>=8) k-=16; -octave->value(k); - -detunetype->value(pars->GlobalPar.PDetuneType-1); -k=pars->GlobalPar.PCoarseDetune%1024;if (k>=512) k-=1024; -coarsedet->value(k); -amplfo->refresh(); -freqlfo->refresh(); -filterlfo->refresh(); - -ampenv->refresh(); -freqenv->refresh(); -filterenv->refresh(); -filterui->refresh(); - -for (int i=0;irefreshlist(); - -resui->refresh(); -currentvoicecounter->do_callback();} {} - } - decl {ADnoteParameters *pars;} {} - decl {ResonanceUI *resui;} {} - decl {Master *master;} {} - decl {int nvoice;} {} - decl {ADvoicelistitem *voicelistitem[NUM_VOICES];} {} -} diff --git a/plugins/zynaddsubfx/src/UI/ADnoteUI.h b/plugins/zynaddsubfx/src/UI/ADnoteUI.h deleted file mode 100644 index a9a573d60..000000000 --- a/plugins/zynaddsubfx/src/UI/ADnoteUI.h +++ /dev/null @@ -1,387 +0,0 @@ -// generated by Fast Light User Interface Designer (fluid) version 1.0300 - -#ifndef ADnoteUI_h -#define ADnoteUI_h -#include -#include "../Params/ADnoteParameters.h" -#include "../Misc/Util.h" -#include "../Misc/Master.h" -#include "ResonanceUI.h" -#include -#include -#include "WidgetPDial.h" -#include "EnvelopeUI.h" -#include "LFOUI.h" -#include "FilterUI.h" -#include "OscilGenUI.h" -#include "PresetsUI.h" -#include -#include -#include -#include -#include -#include - -class ADvoicelistitem : public Fl_Group { - Fl_Group* make_window(); - Fl_Group *ADnoteVoiceListItem; - Fl_Group *voicelistitemgroup; -public: - Fl_Value_Slider *voicevolume; -private: - void cb_voicevolume_i(Fl_Value_Slider*, void*); - static void cb_voicevolume(Fl_Value_Slider*, void*); -public: - Fl_Check_Button *voiceresonanceenabled; -private: - void cb_voiceresonanceenabled_i(Fl_Check_Button*, void*); - static void cb_voiceresonanceenabled(Fl_Check_Button*, void*); -public: - Fl_Value_Slider *voicelfofreq; -private: - void cb_voicelfofreq_i(Fl_Value_Slider*, void*); - static void cb_voicelfofreq(Fl_Value_Slider*, void*); -public: - WidgetPDial *voicepanning; -private: - void cb_voicepanning_i(WidgetPDial*, void*); - static void cb_voicepanning(WidgetPDial*, void*); -public: - Fl_Group *voiceoscil; - Fl_Value_Output *detunevalueoutput; -private: - void cb_detunevalueoutput_i(Fl_Value_Output*, void*); - static void cb_detunevalueoutput(Fl_Value_Output*, void*); -public: - Fl_Slider *voicedetune; -private: - void cb_voicedetune_i(Fl_Slider*, void*); - static void cb_voicedetune(Fl_Slider*, void*); -public: - Fl_Box *noiselabel; -private: - void cb_noiselabel_i(Fl_Box*, void*); - static void cb_noiselabel(Fl_Box*, void*); - Fl_Check_Button *voiceenabled; - void cb_voiceenabled_i(Fl_Check_Button*, void*); - static void cb_voiceenabled(Fl_Check_Button*, void*); -public: - ADvoicelistitem(int x,int y, int w, int h, const char *label=0); - void init(ADnoteParameters *parameters,int nvoice_,Master *master_); - void refreshlist(); - ~ADvoicelistitem(); -private: - ADnoteParameters *pars; - int nvoice; - Oscilloscope *osc; - Master *master; -}; -#include -#include -#include - -class ADvoiceUI : public Fl_Group { -public: - Fl_Group* make_window(); - Fl_Group *ADnoteVoiceParameters; - Fl_Group *voiceparametersgroup; - Fl_Group *voicemodegroup; - Fl_Group *voiceFMparametersgroup; - Fl_Group *modfrequency; - EnvelopeUI *voiceFMfreqenvgroup; -private: - void cb_Enable_i(Fl_Check_Button*, void*); - static void cb_Enable(Fl_Check_Button*, void*); - void cb_Coarse_i(Fl_Counter*, void*); - static void cb_Coarse(Fl_Counter*, void*); - void cb_Octave_i(Fl_Counter*, void*); - static void cb_Octave(Fl_Counter*, void*); - void cb__i(Fl_Slider*, void*); - static void cb_(Fl_Slider*, void*); -public: - Fl_Value_Output *fmdetunevalueoutput; -private: - void cb_fmdetunevalueoutput_i(Fl_Value_Output*, void*); - static void cb_fmdetunevalueoutput(Fl_Value_Output*, void*); - void cb_Detune_i(Fl_Choice*, void*); - static void cb_Detune(Fl_Choice*, void*); - void cb_Vol_i(Fl_Value_Slider*, void*); - static void cb_Vol(Fl_Value_Slider*, void*); - void cb_V_i(Fl_Value_Slider*, void*); - static void cb_V(Fl_Value_Slider*, void*); -public: - EnvelopeUI *voiceFMampenvgroup; -private: - void cb_Enable1_i(Fl_Check_Button*, void*); - static void cb_Enable1(Fl_Check_Button*, void*); - void cb_F_i(Fl_Value_Slider*, void*); - static void cb_F(Fl_Value_Slider*, void*); -public: - Fl_Group *modoscil; - Fl_Group *fmoscil; - Fl_Button *changeFMoscilbutton; -private: - void cb_changeFMoscilbutton_i(Fl_Button*, void*); - static void cb_changeFMoscilbutton(Fl_Button*, void*); - void cb_Phase_i(Fl_Slider*, void*); - static void cb_Phase(Fl_Slider*, void*); - void cb_Use_i(Fl_Choice*, void*); - static void cb_Use(Fl_Choice*, void*); - void cb_External_i(Fl_Choice*, void*); - static void cb_External(Fl_Choice*, void*); - void cb_Type_i(Fl_Choice*, void*); - static void cb_Type(Fl_Choice*, void*); - static Fl_Menu_Item menu_Type[]; -public: - EnvelopeUI *voicefreqenvgroup; -private: - void cb_Enable2_i(Fl_Check_Button*, void*); - static void cb_Enable2(Fl_Check_Button*, void*); -public: - LFOUI *voicefreqlfogroup; -private: - void cb_Enable3_i(Fl_Check_Button*, void*); - static void cb_Enable3(Fl_Check_Button*, void*); - void cb_Octave1_i(Fl_Counter*, void*); - static void cb_Octave1(Fl_Counter*, void*); - void cb_Coarse1_i(Fl_Counter*, void*); - static void cb_Coarse1(Fl_Counter*, void*); - void cb_1_i(Fl_Slider*, void*); - static void cb_1(Fl_Slider*, void*); -public: - Fl_Value_Output *detunevalueoutput; -private: - void cb_detunevalueoutput1_i(Fl_Value_Output*, void*); - static void cb_detunevalueoutput1(Fl_Value_Output*, void*); - void cb_440Hz_i(Fl_Check_Button*, void*); - static void cb_440Hz(Fl_Check_Button*, void*); -public: - WidgetPDial *fixedfreqetdial; -private: - void cb_fixedfreqetdial_i(WidgetPDial*, void*); - static void cb_fixedfreqetdial(WidgetPDial*, void*); - void cb_Detune1_i(Fl_Choice*, void*); - static void cb_Detune1(Fl_Choice*, void*); -public: - Fl_Group *voiceoscil; - Fl_Button *changevoiceoscilbutton; -private: - void cb_changevoiceoscilbutton_i(Fl_Button*, void*); - static void cb_changevoiceoscilbutton(Fl_Button*, void*); - void cb_Phase1_i(Fl_Slider*, void*); - static void cb_Phase1(Fl_Slider*, void*); - void cb_R_i(Fl_Check_Button*, void*); - static void cb_R(Fl_Check_Button*, void*); - void cb_Use1_i(Fl_Choice*, void*); - static void cb_Use1(Fl_Choice*, void*); - void cb_Stereo_i(WidgetPDial*, void*); - static void cb_Stereo(WidgetPDial*, void*); - void cb_Unison_i(Fl_Choice*, void*); - static void cb_Unison(Fl_Choice*, void*); - void cb_Vibratto_i(WidgetPDial*, void*); - static void cb_Vibratto(WidgetPDial*, void*); - void cb_Invert_i(Fl_Choice*, void*); - static void cb_Invert(Fl_Choice*, void*); - void cb_Frequency_i(Fl_Slider*, void*); - static void cb_Frequency(Fl_Slider*, void*); -public: - Fl_Value_Output *unisonspreadoutput; -private: - void cb_unisonspreadoutput_i(Fl_Value_Output*, void*); - static void cb_unisonspreadoutput(Fl_Value_Output*, void*); - void cb_Vib_i(WidgetPDial*, void*); - static void cb_Vib(WidgetPDial*, void*); - void cb_Vol1_i(Fl_Value_Slider*, void*); - static void cb_Vol1(Fl_Value_Slider*, void*); - void cb_V1_i(Fl_Value_Slider*, void*); - static void cb_V1(Fl_Value_Slider*, void*); -public: - EnvelopeUI *voiceampenvgroup; -private: - void cb_Pan_i(WidgetPDial*, void*); - static void cb_Pan(WidgetPDial*, void*); - void cb_Enable4_i(Fl_Check_Button*, void*); - static void cb_Enable4(Fl_Check_Button*, void*); -public: - LFOUI *voiceamplfogroup; -private: - void cb_Enable5_i(Fl_Check_Button*, void*); - static void cb_Enable5(Fl_Check_Button*, void*); - void cb_Minus_i(Fl_Check_Button*, void*); - static void cb_Minus(Fl_Check_Button*, void*); -public: - Fl_Group *voicefiltergroup; - EnvelopeUI *voicefilterenvgroup; -private: - void cb_Enable6_i(Fl_Check_Button*, void*); - static void cb_Enable6(Fl_Check_Button*, void*); -public: - LFOUI *voicefilterlfogroup; -private: - void cb_Enable7_i(Fl_Check_Button*, void*); - static void cb_Enable7(Fl_Check_Button*, void*); - void cb_2_i(Fl_Choice*, void*); - static void cb_2(Fl_Choice*, void*); - static Fl_Menu_Item menu_[]; -public: - Fl_Check_Button *bypassfiltercheckbutton; -private: - void cb_bypassfiltercheckbutton_i(Fl_Check_Button*, void*); - static void cb_bypassfiltercheckbutton(Fl_Check_Button*, void*); - void cb_Delay_i(Fl_Value_Slider*, void*); - static void cb_Delay(Fl_Value_Slider*, void*); - void cb_Enable8_i(Fl_Check_Button*, void*); - static void cb_Enable8(Fl_Check_Button*, void*); -public: - Fl_Box *noiselabel; -private: - void cb_noiselabel1_i(Fl_Box*, void*); - static void cb_noiselabel1(Fl_Box*, void*); -public: - Fl_Check_Button *voiceonbutton; -private: - void cb_voiceonbutton_i(Fl_Check_Button*, void*); - static void cb_voiceonbutton(Fl_Check_Button*, void*); -public: - ADvoiceUI(int x,int y, int w, int h, const char *label=0); - void init(ADnoteParameters *parameters,int nvoice_,Master *master_); - ~ADvoiceUI(); -private: - int nvoice; - ADnoteParameters *pars; - OscilEditor *oscedit; - Oscilloscope *osc; - Oscilloscope *oscFM; - Master *master; -}; -#include -#include -#include -#include - -class ADnoteUI : public PresetsUI_ { - Fl_Double_Window* make_window(); -public: - Fl_Double_Window *ADnoteGlobalParameters; - EnvelopeUI *freqenv; - Fl_Counter *octave; -private: - void cb_octave_i(Fl_Counter*, void*); - static void cb_octave(Fl_Counter*, void*); -public: - Fl_Counter *coarsedet; -private: - void cb_coarsedet_i(Fl_Counter*, void*); - static void cb_coarsedet(Fl_Counter*, void*); -public: - LFOUI *freqlfo; - Fl_Slider *freq; -private: - void cb_freq_i(Fl_Slider*, void*); - static void cb_freq(Fl_Slider*, void*); -public: - Fl_Value_Output *detunevalueoutput; -private: - void cb_detunevalueoutput2_i(Fl_Value_Output*, void*); - static void cb_detunevalueoutput2(Fl_Value_Output*, void*); -public: - Fl_Choice *detunetype; -private: - void cb_detunetype_i(Fl_Choice*, void*); - static void cb_detunetype(Fl_Choice*, void*); - void cb_relBW_i(WidgetPDial*, void*); - static void cb_relBW(WidgetPDial*, void*); -public: - Fl_Value_Slider *volume; -private: - void cb_volume_i(Fl_Value_Slider*, void*); - static void cb_volume(Fl_Value_Slider*, void*); -public: - Fl_Value_Slider *vsns; -private: - void cb_vsns_i(Fl_Value_Slider*, void*); - static void cb_vsns(Fl_Value_Slider*, void*); -public: - WidgetPDial *pan; -private: - void cb_pan_i(WidgetPDial*, void*); - static void cb_pan(WidgetPDial*, void*); -public: - WidgetPDial *pstr; -private: - void cb_pstr_i(WidgetPDial*, void*); - static void cb_pstr(WidgetPDial*, void*); -public: - WidgetPDial *pt; -private: - void cb_pt_i(WidgetPDial*, void*); - static void cb_pt(WidgetPDial*, void*); -public: - WidgetPDial *pstc; -private: - void cb_pstc_i(WidgetPDial*, void*); - static void cb_pstc(WidgetPDial*, void*); -public: - WidgetPDial *pvel; -private: - void cb_pvel_i(WidgetPDial*, void*); - static void cb_pvel(WidgetPDial*, void*); -public: - EnvelopeUI *ampenv; - LFOUI *amplfo; - Fl_Check_Button *rndgrp; -private: - void cb_rndgrp_i(Fl_Check_Button*, void*); - static void cb_rndgrp(Fl_Check_Button*, void*); -public: - EnvelopeUI *filterenv; - LFOUI *filterlfo; - FilterUI *filterui; - Fl_Check_Button *stereo; -private: - void cb_stereo_i(Fl_Check_Button*, void*); - static void cb_stereo(Fl_Check_Button*, void*); - void cb_Show_i(Fl_Button*, void*); - static void cb_Show(Fl_Button*, void*); - void cb_Show1_i(Fl_Button*, void*); - static void cb_Show1(Fl_Button*, void*); - void cb_Close_i(Fl_Button*, void*); - static void cb_Close(Fl_Button*, void*); - void cb_Resonance_i(Fl_Button*, void*); - static void cb_Resonance(Fl_Button*, void*); - void cb_C_i(Fl_Button*, void*); - static void cb_C(Fl_Button*, void*); - void cb_P_i(Fl_Button*, void*); - static void cb_P(Fl_Button*, void*); -public: - Fl_Double_Window *ADnoteVoice; - ADvoiceUI *advoice; -private: - void cb_Close1_i(Fl_Button*, void*); - static void cb_Close1(Fl_Button*, void*); -public: - Fl_Counter *currentvoicecounter; -private: - void cb_currentvoicecounter_i(Fl_Counter*, void*); - static void cb_currentvoicecounter(Fl_Counter*, void*); - void cb_C1_i(Fl_Button*, void*); - static void cb_C1(Fl_Button*, void*); - void cb_P1_i(Fl_Button*, void*); - static void cb_P1(Fl_Button*, void*); -public: - Fl_Double_Window *ADnoteVoiceList; -private: - void cb_Hide_i(Fl_Button*, void*); - static void cb_Hide(Fl_Button*, void*); -public: - ADnoteUI(ADnoteParameters *parameters,Master *master_); - ~ADnoteUI(); - void refresh(); -private: - ADnoteParameters *pars; - ResonanceUI *resui; - Master *master; - int nvoice; - ADvoicelistitem *voicelistitem[NUM_VOICES]; -}; -#endif diff --git a/plugins/zynaddsubfx/src/UI/BankUI.cc b/plugins/zynaddsubfx/src/UI/BankUI.cc deleted file mode 100644 index de79932bc..000000000 --- a/plugins/zynaddsubfx/src/UI/BankUI.cc +++ /dev/null @@ -1,421 +0,0 @@ -// generated by Fast Light User Interface Designer (fluid) version 1.0300 - -#include "BankUI.h" -//Copyright (c) 2002-2005 Nasca Octavian Paul -//License: GNU GPL version 2 or later - -void BankProcess_::process() { - ; -} - -BankSlot::BankSlot(int x,int y, int w, int h, const char *label):Fl_Button(x,y,w,h,label) { - what=NULL; - whatslot=NULL; - nslot=0; - nselected=NULL; -} - -int BankSlot::handle(int event) { - if (what==NULL) return(0); - if (Fl::event_inside(this)){ - *what=0;*whatslot=nslot; - if ((event==FL_RELEASE)&&(Fl::event_button()==1))*what=1; - if ((event==FL_RELEASE)&&(Fl::event_button()==3))*what=2; - if (event==FL_PUSH) highlight=1; - }else highlight=0; - - int tmp=Fl_Button::handle(event); - if ((*what!=0) && Fl::event_inside(this)) (bp->*fnc)(); - return(tmp); -} - -void BankSlot::init(int nslot_, int *what_, int *whatslot_,void (BankProcess_:: *fnc_)(void),BankProcess_ *bp_,Bank *bank_,int *nselected_) { - nslot=nslot_; - what=what_; - whatslot=whatslot_; - fnc=fnc_; - bp=bp_; - bank=bank_; - nselected=nselected_; - box(FL_THIN_UP_BOX); - labelfont(0); - labelsize(13); - align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE|FL_ALIGN_CLIP); - - highlight=0; - refresh(); -} - -void BankSlot::refresh() { - if (bank->emptyslot(nslot)) { - color(46); - } else { - if (bank->isPADsynth_used(nslot)) color(26); - else color(51); - }; - - if (*nselected==nslot) color(6); - - - label(bank->getnamenumbered(nslot)); -} - -void BankUI::cb_Close_i(Fl_Button*, void*) { - bankuiwindow->hide(); -} -void BankUI::cb_Close(Fl_Button* o, void* v) { - ((BankUI*)(o->parent()->user_data()))->cb_Close_i(o,v); -} - -void BankUI::cb_writebutton_i(Fl_Light_Button* o, void*) { - if (o->value()>0.5) mode=2; -removeselection(); -} -void BankUI::cb_writebutton(Fl_Light_Button* o, void* v) { - ((BankUI*)(o->parent()->parent()->user_data()))->cb_writebutton_i(o,v); -} - -void BankUI::cb_readbutton_i(Fl_Light_Button* o, void*) { - if (o->value()>0.5) mode=1; -removeselection(); -} -void BankUI::cb_readbutton(Fl_Light_Button* o, void* v) { - ((BankUI*)(o->parent()->parent()->user_data()))->cb_readbutton_i(o,v); -} - -void BankUI::cb_clearbutton_i(Fl_Light_Button* o, void*) { - if (o->value()>0.5) mode=3; -removeselection(); -} -void BankUI::cb_clearbutton(Fl_Light_Button* o, void* v) { - ((BankUI*)(o->parent()->parent()->user_data()))->cb_clearbutton_i(o,v); -} - -void BankUI::cb_swapbutton_i(Fl_Light_Button* o, void*) { - if (o->value()>0.5) mode=4; -removeselection(); -} -void BankUI::cb_swapbutton(Fl_Light_Button* o, void* v) { - ((BankUI*)(o->parent()->parent()->user_data()))->cb_swapbutton_i(o,v); -} - -void BankUI::cb_New_i(Fl_Button*, void*) { - const char *dirname; - -dirname=fl_input("New empty Bank:"); -if (dirname==NULL) return; - - -int result=bank->newbank(dirname); - -if (result!=0) fl_alert("Error: Could not make a new bank (directory).."); - -refreshmainwindow(); -} -void BankUI::cb_New(Fl_Button* o, void* v) { - ((BankUI*)(o->parent()->user_data()))->cb_New_i(o,v); -} - -void BankUI::cb_auto_i(Fl_Check_Button* o, void*) { - config.cfg.BankUIAutoClose=(int) o->value(); -} -void BankUI::cb_auto(Fl_Check_Button* o, void* v) { - ((BankUI*)(o->parent()->user_data()))->cb_auto_i(o,v); -} - -void BankUI::cb_banklist_i(Fl_Choice* o, void*) { - int n=o->value(); -char *dirname=bank->banks[n].dir; -if (dirname==NULL) return; - -if (bank->loadbank(dirname)==2) - fl_alert("Error: Could not load the bank from the directory\n%s.",dirname); -for (int i=0;irefresh(); -refreshmainwindow(); -} -void BankUI::cb_banklist(Fl_Choice* o, void* v) { - ((BankUI*)(o->parent()->user_data()))->cb_banklist_i(o,v); -} - -void BankUI::cb_Refresh_i(Fl_Button*, void*) { - rescan_for_banks(); -banklist->value(0); -} -void BankUI::cb_Refresh(Fl_Button* o, void* v) { - ((BankUI*)(o->parent()->user_data()))->cb_Refresh_i(o,v); -} - -void BankUI::cb_Show_i(Fl_Check_Button* o, void*) { - config.cfg.CheckPADsynth=(int) o->value(); -refreshmainwindow(); -} -void BankUI::cb_Show(Fl_Check_Button* o, void* v) { - ((BankUI*)(o->parent()->user_data()))->cb_Show_i(o,v); -} - -Fl_Double_Window* BankUI::make_window() { - { Fl_Double_Window* o = bankuiwindow = new Fl_Double_Window(785, 575, "Bank"); - bankuiwindow->user_data((void*)(this)); - { Fl_Button* o = new Fl_Button(705, 546, 70, 24, "Close"); - o->box(FL_THIN_UP_BOX); - o->callback((Fl_Callback*)cb_Close); - } // Fl_Button* o - { Fl_Group* o = new Fl_Group(5, 34, 772, 491); - o->box(FL_ENGRAVED_FRAME); - { Fl_Pack* o = new Fl_Pack(10, 39, 150, 481); - o->box(FL_BORDER_BOX); - o->box(FL_NO_BOX); - for (int i=0;i<32;i++){bs[i]=new BankSlot (0,0,o->w(),15," ");bs[i]->init(i,&what,&slot,&BankProcess_::process,(BankProcess_ *)this,bank,&nselected);}; - o->end(); - } // Fl_Pack* o - { Fl_Pack* o = new Fl_Pack(163, 39, 150, 481); - o->box(FL_BORDER_BOX); - o->box(FL_NO_BOX); - for (int i=32;i<64;i++){bs[i]=new BankSlot (0,0,o->w(),15," ");bs[i]->init(i,&what,&slot,&BankProcess_::process,(BankProcess_ *)this,bank,&nselected);}; - o->end(); - } // Fl_Pack* o - { Fl_Pack* o = new Fl_Pack(316, 39, 150, 481); - o->box(FL_BORDER_BOX); - o->box(FL_NO_BOX); - for (int i=64;i<96;i++){bs[i]=new BankSlot (0,0,o->w(),15," ");bs[i]->init(i,&what,&slot,&BankProcess_::process,(BankProcess_ *)this,bank,&nselected);}; - o->end(); - } // Fl_Pack* o - { Fl_Pack* o = new Fl_Pack(469, 39, 150, 481); - o->box(FL_BORDER_BOX); - o->box(FL_NO_BOX); - for (int i=96;i<128;i++){bs[i]=new BankSlot (0,0,o->w(),15," ");bs[i]->init(i,&what,&slot,&BankProcess_::process,(BankProcess_ *)this,bank,&nselected);}; - o->end(); - } // Fl_Pack* o - { Fl_Pack* o = new Fl_Pack(622, 39, 150, 481); - o->box(FL_BORDER_BOX); - o->box(FL_NO_BOX); - for (int i=128;i<160;i++){bs[i]=new BankSlot (0,0,o->w(),15," ");bs[i]->init(i,&what,&slot,&BankProcess_::process,(BankProcess_ *)this,bank,&nselected);}; - o->end(); - } // Fl_Pack* o - o->end(); - } // Fl_Group* o - { modeselect = new Fl_Group(5, 528, 425, 42); - modeselect->box(FL_ENGRAVED_BOX); - { Fl_Light_Button* o = writebutton = new Fl_Light_Button(116, 534, 99, 30, "WRITE"); - writebutton->type(102); - writebutton->box(FL_PLASTIC_UP_BOX); - writebutton->down_box(FL_THIN_DOWN_BOX); - writebutton->selection_color((Fl_Color)1); - writebutton->labeltype(FL_ENGRAVED_LABEL); - writebutton->labelfont(1); - writebutton->labelsize(13); - writebutton->callback((Fl_Callback*)cb_writebutton); - if (bank->locked()) o->deactivate(); - } // Fl_Light_Button* writebutton - { Fl_Light_Button* o = readbutton = new Fl_Light_Button(11, 534, 99, 30, "READ"); - readbutton->type(102); - readbutton->box(FL_PLASTIC_UP_BOX); - readbutton->down_box(FL_THIN_DOWN_BOX); - readbutton->selection_color((Fl_Color)101); - readbutton->labeltype(FL_ENGRAVED_LABEL); - readbutton->labelfont(1); - readbutton->labelsize(13); - readbutton->callback((Fl_Callback*)cb_readbutton); - o->value(1); - } // Fl_Light_Button* readbutton - { Fl_Light_Button* o = clearbutton = new Fl_Light_Button(221, 534, 99, 30, "CLEAR"); - clearbutton->type(102); - clearbutton->box(FL_PLASTIC_UP_BOX); - clearbutton->down_box(FL_THIN_DOWN_BOX); - clearbutton->selection_color(FL_FOREGROUND_COLOR); - clearbutton->labeltype(FL_ENGRAVED_LABEL); - clearbutton->labelfont(1); - clearbutton->labelsize(13); - clearbutton->callback((Fl_Callback*)cb_clearbutton); - if (bank->locked()) o->deactivate(); - } // Fl_Light_Button* clearbutton - { Fl_Light_Button* o = swapbutton = new Fl_Light_Button(325, 534, 99, 30, "SWAP"); - swapbutton->type(102); - swapbutton->box(FL_PLASTIC_UP_BOX); - swapbutton->down_box(FL_THIN_DOWN_BOX); - swapbutton->selection_color((Fl_Color)227); - swapbutton->labeltype(FL_ENGRAVED_LABEL); - swapbutton->labelfont(1); - swapbutton->labelsize(13); - swapbutton->callback((Fl_Callback*)cb_swapbutton); - if (bank->locked()) o->deactivate(); - } // Fl_Light_Button* swapbutton - modeselect->end(); - } // Fl_Group* modeselect - { Fl_Button* o = new Fl_Button(685, 5, 93, 25, "New Bank..."); - o->box(FL_PLASTIC_UP_BOX); - o->labelfont(1); - o->labelsize(11); - o->callback((Fl_Callback*)cb_New); - o->align(Fl_Align(FL_ALIGN_WRAP)); - } // Fl_Button* o - { Fl_Check_Button* o = new Fl_Check_Button(705, 529, 60, 15, "auto close"); - o->tooltip("automatically close the bank window if the instrument is loaded"); - o->down_box(FL_DOWN_BOX); - o->labelsize(10); - o->callback((Fl_Callback*)cb_auto); - o->value(config.cfg.BankUIAutoClose); - } // Fl_Check_Button* o - { banklist = new Fl_Choice(5, 8, 220, 20); - banklist->down_box(FL_BORDER_BOX); - banklist->labelfont(1); - banklist->textfont(1); - banklist->textsize(11); - banklist->callback((Fl_Callback*)cb_banklist); - banklist->align(Fl_Align(FL_ALIGN_CENTER)); - } // Fl_Choice* banklist - { Fl_Button* o = new Fl_Button(230, 8, 105, 20, "Refresh bank list"); - o->tooltip("Refresh the bank list (rescan)"); - o->box(FL_THIN_UP_BOX); - o->color(FL_LIGHT1); - o->labelsize(11); - o->callback((Fl_Callback*)cb_Refresh); - } // Fl_Button* o - { Fl_Check_Button* o = new Fl_Check_Button(435, 530, 150, 15, "Show PADsynth status"); - o->down_box(FL_DOWN_BOX); - o->labelsize(11); - o->callback((Fl_Callback*)cb_Show); - o->value(config.cfg.CheckPADsynth); - } // Fl_Check_Button* o - o->label(bank->bankfiletitle); - if (bank->bankfiletitle==NULL) o->label ("Choose a bank from the bank list on the left (or go to settings if to configure the bank location) or choose 'New Bank...' to make a new bank."); - bankuiwindow->end(); - } // Fl_Double_Window* bankuiwindow - return bankuiwindow; -} - -BankUI::BankUI(Master *master_,int *npart_) { - fnc=&BankProcess_::process; - master=master_; - npart=npart_; - bank=&master_->bank; - what=0; - nselected=-1; - make_window(); - mode=1; -} - -BankUI::~BankUI() { - bankuiwindow->hide(); - delete(bankuiwindow); -} - -void BankUI::show() { - bankuiwindow->show(); - simplesetmode(config.cfg.UserInterfaceMode==2); -} - -void BankUI::hide() { - bankuiwindow->hide(); -} - -void BankUI::init(Fl_Valuator *cbwig_) { - cbwig=cbwig_; - rescan_for_banks(); -} - -void BankUI::process() { - int slot=this->slot; - - if ((what==2)&&(bank->emptyslot(slot)==0)&&(mode!=4)) {//Rename slot - const char *tmp=fl_input("Slot (instrument) name:",(const char *)bank->getname(slot)); - if (tmp!=NULL) bank->setname(slot,tmp,-1); - bs[slot]->refresh(); - }; - - if ((what==1)&&(mode==1)&&(!bank->emptyslot(slot))){//Reads from slot - pthread_mutex_lock(&master->mutex); - bank->loadfromslot(slot,master->part[*npart]); - pthread_mutex_unlock(&master->mutex); - master->part[*npart]->applyparameters(); - snprintf((char *)master->part[*npart]->Pname,PART_MAX_NAME_LEN,"%s",bank->getname(slot)); - cbwig->do_callback(); - - if (config.cfg.BankUIAutoClose!=0) - bankuiwindow->hide(); - - }; - - if ((what==1)&&(mode==2)){//save(write) to slot - if (!bank->emptyslot(slot)){ - if (!fl_choice("Overwrite the slot no. %d ?","No","Yes",NULL,slot+1)) goto nooverwriteslot; - }; - pthread_mutex_lock(&master->mutex); - bank->savetoslot(slot,master->part[*npart]); - pthread_mutex_unlock(&master->mutex); - - bs[slot]->refresh(); - mode=1;readbutton->value(1);writebutton->value(0); - nooverwriteslot:; - }; - - - - if ((what==1)&&(mode==3)&&(!bank->emptyslot(slot))){//Clears the slot - if (fl_choice("Clear the slot no. %d ?","No","Yes",NULL,slot+1)){ - bank->clearslot(slot); - bs[slot]->refresh(); - }; - }; - - if (mode==4){//swap - bool done=false; - if ((what==1)&&(nselected>=0)){ - bank->swapslot(nselected,slot); - int ns=nselected; - nselected=-1; - bs[slot]->refresh(); - bs[ns]->refresh(); - done=true; - }; - if (((nselected<0)||(what==2))&&(!done)){ - int ns=nselected; - nselected=slot; - if (ns>0) bs[ns]->refresh(); - bs[slot]->refresh(); - }; - }; - if (mode!=4) refreshmainwindow(); -} - -void BankUI::refreshmainwindow() { - bankuiwindow->label(bank->bankfiletitle); - mode=1;readbutton->value(1);writebutton->value(0);clearbutton->value(0);swapbutton->value(0); - nselected=-1; - if (bank->locked()){ - writebutton->deactivate(); - clearbutton->deactivate(); - swapbutton->deactivate(); - } else { - writebutton->activate(); - clearbutton->activate(); - swapbutton->activate(); - }; - for (int i=0;irefresh(); -} - -void BankUI::removeselection() { - if (nselected>=0) { - int ns=nselected; - nselected=-1; - bs[ns]->refresh(); - }; -} - -void BankUI::rescan_for_banks() { - banklist->clear(); - banklist->add(" "); - bank->rescanforbanks(); - - for (int i=1;ibanks[i].name!=NULL) banklist->add(bank->banks[i].name); - }; -} - -void BankUI::simplesetmode(bool beginnerui) { - readbutton->value(1); - mode=1; - removeselection(); - if (beginnerui) modeselect->hide(); - else modeselect->show(); -} diff --git a/plugins/zynaddsubfx/src/UI/BankUI.fl b/plugins/zynaddsubfx/src/UI/BankUI.fl deleted file mode 100644 index 624450212..000000000 --- a/plugins/zynaddsubfx/src/UI/BankUI.fl +++ /dev/null @@ -1,355 +0,0 @@ -# data file for the Fltk User Interface Designer (fluid) -version 1.0107 -header_name {.h} -code_name {.cc} -decl {//Copyright (c) 2002-2005 Nasca Octavian Paul} {} - -decl {//License: GNU GPL version 2 or later} {} - -decl {\#include } {public -} - -decl {\#include } {public -} - -decl {\#include } {public -} - -decl {\#include } {public -} - -decl {\#include } {public -} - -decl {\#include "../Misc/Master.h"} {public -} - -decl {\#include "../Misc/Bank.h"} {public -} - -decl {\#include "../Misc/Config.h"} {public -} - -class BankProcess_ {} { - Function {process()} {open return_type {virtual void} - } {code{;}} - decl {Bank *bank;} {public - } -} - -class BankSlot {open : {public Fl_Button,BankProcess_} -} { - Function {BankSlot(int x,int y, int w, int h, const char *label=0):Fl_Button(x,y,w,h,label)} {} { - code {what=NULL; -whatslot=NULL; -nslot=0; -nselected=NULL;} {} - } - Function {handle(int event)} {return_type int - } { - code {if (what==NULL) return(0); -if (Fl::event_inside(this)){ - *what=0;*whatslot=nslot; - if ((event==FL_RELEASE)&&(Fl::event_button()==1))*what=1; - if ((event==FL_RELEASE)&&(Fl::event_button()==3))*what=2; - if (event==FL_PUSH) highlight=1; -}else highlight=0; - -int tmp=Fl_Button::handle(event); -if ((*what!=0) && Fl::event_inside(this)) (bp->*fnc)(); -return(tmp);} {} - } - Function {init(int nslot_, int *what_, int *whatslot_,void (BankProcess_:: *fnc_)(void),BankProcess_ *bp_,Bank *bank_,int *nselected_)} {open - } { - code {nslot=nslot_; -what=what_; -whatslot=whatslot_; -fnc=fnc_; -bp=bp_; -bank=bank_; -nselected=nselected_; -box(FL_THIN_UP_BOX); -labelfont(0); -labelsize(13); -align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE|FL_ALIGN_CLIP); - -highlight=0; -refresh();} {selected - } - } - Function {refresh()} {} { - code {if (bank->emptyslot(nslot)) { - color(46); -} else { - if (bank->isPADsynth_used(nslot)) color(26); - else color(51); -}; - -if (*nselected==nslot) color(6); - - -label(bank->getnamenumbered(nslot));} {} - } - decl {int *what,*whatslot,nslot,highlight, *nselected;} {} - decl {void (BankProcess_:: *fnc)(void);} {} - decl {BankProcess_ *bp;} {} -} - -class BankUI {: {public BankProcess_} -} { - Function {make_window()} {} { - Fl_Window bankuiwindow { - label Bank - xywh {4 64 785 575} type Double hide - code0 {o->label(bank->bankfiletitle);} - code1 {if (bank->bankfiletitle==NULL) o->label ("Choose a bank from the bank list on the left (or go to settings if to configure the bank location) or choose 'New Bank...' to make a new bank.");} - } { - Fl_Button {} { - label Close - callback {bankuiwindow->hide();} - xywh {705 546 70 24} box THIN_UP_BOX - } - Fl_Group {} { - xywh {5 34 772 491} box ENGRAVED_FRAME - } { - Fl_Pack {} { - xywh {10 39 150 481} box BORDER_BOX - code0 {o->box(FL_NO_BOX);} - code1 {for (int i=0;i<32;i++){bs[i]=new BankSlot (0,0,o->w(),15," ");bs[i]->init(i,&what,&slot,&BankProcess_::process,(BankProcess_ *)this,bank,&nselected);};} - } {} - Fl_Pack {} { - xywh {163 39 150 481} box BORDER_BOX - code0 {o->box(FL_NO_BOX);} - code1 {for (int i=32;i<64;i++){bs[i]=new BankSlot (0,0,o->w(),15," ");bs[i]->init(i,&what,&slot,&BankProcess_::process,(BankProcess_ *)this,bank,&nselected);};} - } {} - Fl_Pack {} { - xywh {316 39 150 481} box BORDER_BOX - code0 {o->box(FL_NO_BOX);} - code1 {for (int i=64;i<96;i++){bs[i]=new BankSlot (0,0,o->w(),15," ");bs[i]->init(i,&what,&slot,&BankProcess_::process,(BankProcess_ *)this,bank,&nselected);};} - } {} - Fl_Pack {} { - xywh {469 39 150 481} box BORDER_BOX - code0 {o->box(FL_NO_BOX);} - code1 {for (int i=96;i<128;i++){bs[i]=new BankSlot (0,0,o->w(),15," ");bs[i]->init(i,&what,&slot,&BankProcess_::process,(BankProcess_ *)this,bank,&nselected);};} - } {} - Fl_Pack {} { - xywh {622 39 150 481} box BORDER_BOX - code0 {o->box(FL_NO_BOX);} - code1 {for (int i=128;i<160;i++){bs[i]=new BankSlot (0,0,o->w(),15," ");bs[i]->init(i,&what,&slot,&BankProcess_::process,(BankProcess_ *)this,bank,&nselected);};} - } {} - } - Fl_Group modeselect { - xywh {5 528 425 42} box ENGRAVED_BOX - } { - Fl_Light_Button writebutton { - label WRITE - callback {if (o->value()>0.5) mode=2; -removeselection();} - xywh {116 534 99 30} type Radio box PLASTIC_UP_BOX down_box THIN_DOWN_BOX selection_color 1 labeltype ENGRAVED_LABEL labelfont 1 labelsize 13 - code0 {if (bank->locked()) o->deactivate();} - } - Fl_Light_Button readbutton { - label READ - callback {if (o->value()>0.5) mode=1; -removeselection();} - xywh {11 534 99 30} type Radio box PLASTIC_UP_BOX down_box THIN_DOWN_BOX selection_color 101 labeltype ENGRAVED_LABEL labelfont 1 labelsize 13 - code0 {o->value(1);} - } - Fl_Light_Button clearbutton { - label CLEAR - callback {if (o->value()>0.5) mode=3; -removeselection();} - xywh {221 534 99 30} type Radio box PLASTIC_UP_BOX down_box THIN_DOWN_BOX selection_color 0 labeltype ENGRAVED_LABEL labelfont 1 labelsize 13 - code0 {if (bank->locked()) o->deactivate();} - } - Fl_Light_Button swapbutton { - label SWAP - callback {if (o->value()>0.5) mode=4; -removeselection();} - xywh {325 534 99 30} type Radio box PLASTIC_UP_BOX down_box THIN_DOWN_BOX selection_color 227 labeltype ENGRAVED_LABEL labelfont 1 labelsize 13 - code0 {if (bank->locked()) o->deactivate();} - } - } - Fl_Button {} { - label {New Bank...} - callback {const char *dirname; - -dirname=fl_input("New empty Bank:"); -if (dirname==NULL) return; - - -int result=bank->newbank(dirname); - -if (result!=0) fl_alert("Error: Could not make a new bank (directory).."); - -refreshmainwindow();} - xywh {685 5 93 25} box PLASTIC_UP_BOX labelfont 1 labelsize 11 align 128 - } - Fl_Check_Button {} { - label {auto close} - callback {config.cfg.BankUIAutoClose=(int) o->value();} - tooltip {automatically close the bank window if the instrument is loaded} xywh {705 529 60 15} down_box DOWN_BOX labelsize 10 - code0 {o->value(config.cfg.BankUIAutoClose);} - } - Fl_Choice banklist { - callback {int n=o->value(); -char *dirname=bank->banks[n].dir; -if (dirname==NULL) return; - -if (bank->loadbank(dirname)==2) - fl_alert("Error: Could not load the bank from the directory\\n%s.",dirname); -for (int i=0;irefresh(); -refreshmainwindow();} open - xywh {5 8 220 20} down_box BORDER_BOX labelfont 1 align 0 textfont 1 textsize 11 - } {} - Fl_Button {} { - label {Refresh bank list} - callback {rescan_for_banks(); -banklist->value(0);} - tooltip {Refresh the bank list (rescan)} xywh {230 8 105 20} box THIN_UP_BOX color 50 labelsize 11 - } - Fl_Check_Button {} { - label {Show PADsynth status} - callback {config.cfg.CheckPADsynth=(int) o->value(); -refreshmainwindow();} - xywh {435 530 150 15} down_box DOWN_BOX labelsize 11 - code0 {o->value(config.cfg.CheckPADsynth);} - } - } - } - Function {BankUI(Master *master_,int *npart_)} {} { - code {fnc=&BankProcess_::process; -master=master_; -npart=npart_; -bank=&master_->bank; -what=0; -nselected=-1; -make_window(); -mode=1;} {} - } - Function {~BankUI()} {return_type virtual - } { - code {bankuiwindow->hide(); -delete(bankuiwindow);} {} - } - Function {show()} {} { - code {bankuiwindow->show(); -simplesetmode(config.cfg.UserInterfaceMode==2);} {} - } - Function {hide()} {} { - code {bankuiwindow->hide();} {} - } - Function {init(Fl_Valuator *cbwig_)} {} { - code {cbwig=cbwig_; -rescan_for_banks();} {} - } - Function {process()} {return_type void - } { - code {int slot=this->slot; - -if ((what==2)&&(bank->emptyslot(slot)==0)&&(mode!=4)) {//Rename slot - const char *tmp=fl_input("Slot (instrument) name:",(const char *)bank->getname(slot)); - if (tmp!=NULL) bank->setname(slot,tmp,-1); - bs[slot]->refresh(); -}; - -if ((what==1)&&(mode==1)&&(!bank->emptyslot(slot))){//Reads from slot - pthread_mutex_lock(&master->mutex); - bank->loadfromslot(slot,master->part[*npart]); - pthread_mutex_unlock(&master->mutex); - master->part[*npart]->applyparameters(); - snprintf((char *)master->part[*npart]->Pname,PART_MAX_NAME_LEN,"%s",bank->getname(slot)); - cbwig->do_callback(); - - if (config.cfg.BankUIAutoClose!=0) - bankuiwindow->hide(); - -}; - -if ((what==1)&&(mode==2)){//save(write) to slot - if (!bank->emptyslot(slot)){ - if (!fl_choice("Overwrite the slot no. %d ?","No","Yes",NULL,slot+1)) goto nooverwriteslot; - }; - pthread_mutex_lock(&master->mutex); - bank->savetoslot(slot,master->part[*npart]); - pthread_mutex_unlock(&master->mutex); - - bs[slot]->refresh(); - mode=1;readbutton->value(1);writebutton->value(0); - nooverwriteslot:; -}; - - - -if ((what==1)&&(mode==3)&&(!bank->emptyslot(slot))){//Clears the slot - if (fl_choice("Clear the slot no. %d ?","No","Yes",NULL,slot+1)){ - bank->clearslot(slot); - bs[slot]->refresh(); - }; -}; - -if (mode==4){//swap - bool done=false; - if ((what==1)&&(nselected>=0)){ - bank->swapslot(nselected,slot); - int ns=nselected; - nselected=-1; - bs[slot]->refresh(); - bs[ns]->refresh(); - done=true; - }; - if (((nselected<0)||(what==2))&&(!done)){ - int ns=nselected; - nselected=slot; - if (ns>0) bs[ns]->refresh(); - bs[slot]->refresh(); - }; -}; -if (mode!=4) refreshmainwindow();} {} - } - Function {refreshmainwindow()} {} { - code {bankuiwindow->label(bank->bankfiletitle); -mode=1;readbutton->value(1);writebutton->value(0);clearbutton->value(0);swapbutton->value(0); -nselected=-1; -if (bank->locked()){ - writebutton->deactivate(); - clearbutton->deactivate(); - swapbutton->deactivate(); -} else { - writebutton->activate(); - clearbutton->activate(); - swapbutton->activate(); -}; -for (int i=0;irefresh();} {} - } - Function {removeselection()} {} { - code {if (nselected>=0) { - int ns=nselected; - nselected=-1; - bs[ns]->refresh(); -};} {} - } - Function {rescan_for_banks()} {} { - code {banklist->clear(); -banklist->add(" "); -bank->rescanforbanks(); - -for (int i=1;ibanks[i].name!=NULL) banklist->add(bank->banks[i].name); -};} {} - } - Function {simplesetmode(bool beginnerui)} {} { - code {readbutton->value(1); -mode=1; -removeselection(); -if (beginnerui) modeselect->hide(); - else modeselect->show();} {} - } - decl {BankSlot *bs[BANK_SIZE];} {} - decl {int slot,what;//"what"=what button is pressed} {} - decl {int mode,*npart,nselected;} {} - decl {Master *master;} {} - decl {void (BankProcess_::* fnc)(void);} {} - decl {Fl_Valuator *cbwig;} {public - } -} diff --git a/plugins/zynaddsubfx/src/UI/BankUI.h b/plugins/zynaddsubfx/src/UI/BankUI.h deleted file mode 100644 index d498c79bb..000000000 --- a/plugins/zynaddsubfx/src/UI/BankUI.h +++ /dev/null @@ -1,101 +0,0 @@ -// generated by Fast Light User Interface Designer (fluid) version 1.0300 - -#ifndef BankUI_h -#define BankUI_h -#include -#include -#include -#include -#include -#include -#include "../Misc/Master.h" -#include "../Misc/Bank.h" -#include "../Misc/Config.h" - -class BankProcess_ { -public: - virtual void process(); - Bank *bank; -}; - -class BankSlot : public Fl_Button,BankProcess_ { -public: - BankSlot(int x,int y, int w, int h, const char *label=0); - int handle(int event); - void init(int nslot_, int *what_, int *whatslot_,void (BankProcess_:: *fnc_)(void),BankProcess_ *bp_,Bank *bank_,int *nselected_); - void refresh(); -private: - int *what,*whatslot,nslot,highlight, *nselected; - void (BankProcess_:: *fnc)(void); - BankProcess_ *bp; -}; -#include -#include -#include -#include -#include -#include -#include - -class BankUI : public BankProcess_ { -public: - Fl_Double_Window* make_window(); - Fl_Double_Window *bankuiwindow; -private: - void cb_Close_i(Fl_Button*, void*); - static void cb_Close(Fl_Button*, void*); -public: - Fl_Group *modeselect; - Fl_Light_Button *writebutton; -private: - void cb_writebutton_i(Fl_Light_Button*, void*); - static void cb_writebutton(Fl_Light_Button*, void*); -public: - Fl_Light_Button *readbutton; -private: - void cb_readbutton_i(Fl_Light_Button*, void*); - static void cb_readbutton(Fl_Light_Button*, void*); -public: - Fl_Light_Button *clearbutton; -private: - void cb_clearbutton_i(Fl_Light_Button*, void*); - static void cb_clearbutton(Fl_Light_Button*, void*); -public: - Fl_Light_Button *swapbutton; -private: - void cb_swapbutton_i(Fl_Light_Button*, void*); - static void cb_swapbutton(Fl_Light_Button*, void*); - void cb_New_i(Fl_Button*, void*); - static void cb_New(Fl_Button*, void*); - void cb_auto_i(Fl_Check_Button*, void*); - static void cb_auto(Fl_Check_Button*, void*); -public: - Fl_Choice *banklist; -private: - void cb_banklist_i(Fl_Choice*, void*); - static void cb_banklist(Fl_Choice*, void*); - void cb_Refresh_i(Fl_Button*, void*); - static void cb_Refresh(Fl_Button*, void*); - void cb_Show_i(Fl_Check_Button*, void*); - static void cb_Show(Fl_Check_Button*, void*); -public: - BankUI(Master *master_,int *npart_); - virtual ~BankUI(); - void show(); - void hide(); - void init(Fl_Valuator *cbwig_); - void process(); - void refreshmainwindow(); - void removeselection(); - void rescan_for_banks(); - void simplesetmode(bool beginnerui); -private: - BankSlot *bs[BANK_SIZE]; - int slot,what; //"what"=what button is pressed - int mode,*npart,nselected; - Master *master; - void (BankProcess_::* fnc)(void); -public: - Fl_Valuator *cbwig; -}; -#endif diff --git a/plugins/zynaddsubfx/src/UI/CMakeLists.txt b/plugins/zynaddsubfx/src/UI/CMakeLists.txt deleted file mode 100644 index 2c959e446..000000000 --- a/plugins/zynaddsubfx/src/UI/CMakeLists.txt +++ /dev/null @@ -1,32 +0,0 @@ -set(UI_fl_files - ADnoteUI.fl - BankUI.fl - ConfigUI.fl - EffUI.fl - EnvelopeUI.fl - FilterUI.fl - LFOUI.fl - MasterUI.fl - MicrotonalUI.fl - OscilGenUI.fl - PADnoteUI.fl - PartUI.fl - PresetsUI.fl - ResonanceUI.fl - SeqUI.fl - SUBnoteUI.fl - VirKeyboard.fl - WidgetPDial.fl -) - -include_directories("${CMAKE_CURRENT_BINARY_DIR}") - -set_source_files_properties(UI/MasterUI.h PROPERTIES GENERATED 1) -fltk_wrap_ui(zynaddsubfx_gui ${UI_fl_files}) - -add_library(zynaddsubfx_gui STATIC - ${UI_objs} - ${zynaddsubfx_gui_FLTK_UI_SRCS} - ) - -target_link_libraries(zynaddsubfx_gui ${FLTK_LIBRARIES} ${MYFLTK_LIBRARIES}) diff --git a/plugins/zynaddsubfx/src/UI/ConfigUI.cc b/plugins/zynaddsubfx/src/UI/ConfigUI.cc deleted file mode 100644 index 6619f749f..000000000 --- a/plugins/zynaddsubfx/src/UI/ConfigUI.cc +++ /dev/null @@ -1,562 +0,0 @@ -// generated by Fast Light User Interface Designer (fluid) version 1.0300 - -#include "ConfigUI.h" -//Copyright (c) 2002-2005 Nasca Octavian Paul -//License: GNU GPL version 2 or later - -void ConfigUI::cb_configwindow_i(Fl_Double_Window* o, void*) { - writebankcfg(); -o->hide(); -} -void ConfigUI::cb_configwindow(Fl_Double_Window* o, void* v) { - ((ConfigUI*)(o->user_data()))->cb_configwindow_i(o,v); -} - -void ConfigUI::cb__i(Fl_Choice* o, void*) { - if ((int)o->value()==0) samplerateinput->activate(); - else samplerateinput->deactivate(); - -int samplerates[8]={44100,16000,22050,32000,44100,48000,88200,96000}; -config.cfg.SampleRate=samplerates[(int)o->value()]; - -setsamplerateinput(); -} -void ConfigUI::cb_(Fl_Choice* o, void* v) { - ((ConfigUI*)(o->parent()->parent()->parent()->parent()->user_data()))->cb__i(o,v); -} - -Fl_Menu_Item ConfigUI::menu_[] = { - {"Custom", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 14, 0}, - {"16000Hz", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 14, 0}, - {"22050Hz", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 14, 0}, - {"32000Hz", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 14, 0}, - {"44100Hz", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 14, 0}, - {"48000Hz", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 14, 0}, - {"88200Hz", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 14, 0}, - {"96000Hz", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 14, 0}, - {0,0,0,0,0,0,0,0,0} -}; - -void ConfigUI::cb_samplerateinput_i(Fl_Int_Input* o, void*) { - char *tmp; -config.cfg.SampleRate=strtoul(o->value(),&tmp,10); -} -void ConfigUI::cb_samplerateinput(Fl_Int_Input* o, void* v) { - ((ConfigUI*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_samplerateinput_i(o,v); -} - -void ConfigUI::cb_Buffer_i(Fl_Int_Input* o, void*) { - char *tmp; -config.cfg.SoundBufferSize=strtoul(o->value(),&tmp,10); -} -void ConfigUI::cb_Buffer(Fl_Int_Input* o, void* v) { - ((ConfigUI*)(o->parent()->parent()->parent()->user_data()))->cb_Buffer_i(o,v); -} - -void ConfigUI::cb_Swap_i(Fl_Light_Button* o, void*) { - config.cfg.SwapStereo=(int) o->value(); -} -void ConfigUI::cb_Swap(Fl_Light_Button* o, void* v) { - ((ConfigUI*)(o->parent()->parent()->parent()->user_data()))->cb_Swap_i(o,v); -} - -void ConfigUI::cb_OscilSize_i(Fl_Choice* o, void*) { - config.cfg.OscilSize=128<value(); -} -void ConfigUI::cb_OscilSize(Fl_Choice* o, void* v) { - ((ConfigUI*)(o->parent()->parent()->parent()->user_data()))->cb_OscilSize_i(o,v); -} - -Fl_Menu_Item ConfigUI::menu_OscilSize[] = { - {"128", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 14, 0}, - {"256", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 14, 0}, - {"512", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 14, 0}, - {"1024", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 14, 0}, - {"2048", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 14, 0}, - {"4096", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 14, 0}, - {"8192", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 14, 0}, - {"16384", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 14, 0}, - {0,0,0,0,0,0,0,0,0} -}; - -void ConfigUI::cb_Dump_i(Fl_File_Input* o, void*) { - snprintf(config.cfg.DumpFile,config.maxstringsize,"%s",o->value()); -} -void ConfigUI::cb_Dump(Fl_File_Input* o, void* v) { - ((ConfigUI*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_Dump_i(o,v); -} - -void ConfigUI::cb_Dump1_i(Fl_Check_Button* o, void*) { - config.cfg.DumpNotesToFile=(int) o->value(); -dump.startnow();//this has effect only if this option was disabled; -} -void ConfigUI::cb_Dump1(Fl_Check_Button* o, void* v) { - ((ConfigUI*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_Dump1_i(o,v); -} - -void ConfigUI::cb_Append_i(Fl_Check_Button* o, void*) { - config.cfg.DumpAppend=(int) o->value(); -} -void ConfigUI::cb_Append(Fl_Check_Button* o, void* v) { - ((ConfigUI*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_Append_i(o,v); -} - -void ConfigUI::cb_OSS_i(Fl_File_Input* o, void*) { - snprintf(config.cfg.LinuxOSSSeqInDev,config.maxstringsize,"%s",o->value()); -} -void ConfigUI::cb_OSS(Fl_File_Input* o, void* v) { - ((ConfigUI*)(o->parent()->parent()->parent()->parent()->parent()->user_data()))->cb_OSS_i(o,v); -} - -void ConfigUI::cb_OSS1_i(Fl_File_Input* o, void*) { - snprintf(config.cfg.LinuxOSSWaveOutDev,config.maxstringsize,"%s",o->value()); -} -void ConfigUI::cb_OSS1(Fl_File_Input* o, void* v) { - ((ConfigUI*)(o->parent()->parent()->parent()->parent()->parent()->user_data()))->cb_OSS1_i(o,v); -} - -void ConfigUI::cb_Midi_i(Fl_Counter* o, void*) { - config.cfg.WindowsMidiInId=(int) o->value(); -midiinputnamebox->label(config.winmididevices[config.cfg.WindowsMidiInId].name); -} -void ConfigUI::cb_Midi(Fl_Counter* o, void* v) { - ((ConfigUI*)(o->parent()->parent()->parent()->parent()->parent()->user_data()))->cb_Midi_i(o,v); -} - -void ConfigUI::cb_XML_i(Fl_Counter* o, void*) { - config.cfg.GzipCompression=(int) o->value(); -} -void ConfigUI::cb_XML(Fl_Counter* o, void* v) { - ((ConfigUI*)(o->parent()->parent()->parent()->user_data()))->cb_XML_i(o,v); -} - -void ConfigUI::cb_PADsynth_i(Fl_Choice* o, void*) { - config.cfg.Interpolation=(int) o->value(); -} -void ConfigUI::cb_PADsynth(Fl_Choice* o, void* v) { - ((ConfigUI*)(o->parent()->parent()->parent()->user_data()))->cb_PADsynth_i(o,v); -} - -Fl_Menu_Item ConfigUI::menu_PADsynth[] = { - {"Linear(fast)", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {"Cubic(slow)", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {0,0,0,0,0,0,0,0,0} -}; - -void ConfigUI::cb_Virtual_i(Fl_Choice* o, void*) { - config.cfg.VirKeybLayout=(int) o->value();; -} -void ConfigUI::cb_Virtual(Fl_Choice* o, void* v) { - ((ConfigUI*)(o->parent()->parent()->parent()->user_data()))->cb_Virtual_i(o,v); -} - -Fl_Menu_Item ConfigUI::menu_Virtual[] = { - {" ", 0, 0, 0, 1, FL_NORMAL_LABEL, 1, 11, 0}, - {"QWERTY", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 11, 0}, - {"Dvorak", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 11, 0}, - {"QWERTZ", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 11, 0}, - {"AZERTY", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 11, 0}, - {0,0,0,0,0,0,0,0,0} -}; - -void ConfigUI::cb_rootsbrowse_i(Fl_Browser* o, void*) { - activatebutton_rootdir(o->value()!=0); -} -void ConfigUI::cb_rootsbrowse(Fl_Browser* o, void* v) { - ((ConfigUI*)(o->parent()->parent()->parent()->user_data()))->cb_rootsbrowse_i(o,v); -} - -void ConfigUI::cb_Add_i(Fl_Button*, void*) { - const char *dirname; -dirname=fl_dir_chooser("Add a root directory for banks:",NULL,0); -if (dirname==NULL) return; - -rootsbrowse->add(dirname); -} -void ConfigUI::cb_Add(Fl_Button* o, void* v) { - ((ConfigUI*)(o->parent()->parent()->parent()->user_data()))->cb_Add_i(o,v); -} - -void ConfigUI::cb_removerootdirbutton_i(Fl_Button*, void*) { - if (rootsbrowse->value()!=0) { - rootsbrowse->remove(rootsbrowse->value()); -}; -activatebutton_rootdir(false); -} -void ConfigUI::cb_removerootdirbutton(Fl_Button* o, void* v) { - ((ConfigUI*)(o->parent()->parent()->parent()->user_data()))->cb_removerootdirbutton_i(o,v); -} - -void ConfigUI::cb_makedefaultrootdirbutton_i(Fl_Button*, void*) { - int n=rootsbrowse->value(); - -if (n!=0) { - rootsbrowse->move(1,n); - rootsbrowse->value(1); - rootsbrowse->redraw(); -}; -activatebutton_rootdir(true); -} -void ConfigUI::cb_makedefaultrootdirbutton(Fl_Button* o, void* v) { - ((ConfigUI*)(o->parent()->parent()->parent()->user_data()))->cb_makedefaultrootdirbutton_i(o,v); -} - -void ConfigUI::cb_presetbrowse_i(Fl_Browser* o, void*) { - activatebutton_presetdir(o->value()!=0); -} -void ConfigUI::cb_presetbrowse(Fl_Browser* o, void* v) { - ((ConfigUI*)(o->parent()->parent()->parent()->user_data()))->cb_presetbrowse_i(o,v); -} - -void ConfigUI::cb_Add1_i(Fl_Button*, void*) { - const char *dirname; -dirname=fl_dir_chooser("Add a preset directory :",NULL,0); -if (dirname==NULL) return; - -presetbrowse->add(dirname); -} -void ConfigUI::cb_Add1(Fl_Button* o, void* v) { - ((ConfigUI*)(o->parent()->parent()->parent()->user_data()))->cb_Add1_i(o,v); -} - -void ConfigUI::cb_removepresetbutton_i(Fl_Button*, void*) { - if (presetbrowse->value()!=0) { - presetbrowse->remove(presetbrowse->value()); -}; -activatebutton_presetdir(false); -} -void ConfigUI::cb_removepresetbutton(Fl_Button* o, void* v) { - ((ConfigUI*)(o->parent()->parent()->parent()->user_data()))->cb_removepresetbutton_i(o,v); -} - -void ConfigUI::cb_makedefaultpresetbutton_i(Fl_Button*, void*) { - int n=presetbrowse->value(); - -if (n!=0) { - presetbrowse->move(1,n); - presetbrowse->value(1); - presetbrowse->redraw(); -}; -activatebutton_presetdir(true); -} -void ConfigUI::cb_makedefaultpresetbutton(Fl_Button* o, void* v) { - ((ConfigUI*)(o->parent()->parent()->parent()->user_data()))->cb_makedefaultpresetbutton_i(o,v); -} - -void ConfigUI::cb_Close_i(Fl_Button*, void*) { - configwindow->hide(); -writebankcfg(); -writepresetcfg(); -} -void ConfigUI::cb_Close(Fl_Button* o, void* v) { - ((ConfigUI*)(o->parent()->user_data()))->cb_Close_i(o,v); -} - -Fl_Double_Window* ConfigUI::make_window() { - { configwindow = new Fl_Double_Window(510, 340, "ZynAddSubFX Settings"); - configwindow->callback((Fl_Callback*)cb_configwindow, (void*)(this)); - { Fl_Tabs* o = new Fl_Tabs(5, 5, 500, 305); - { Fl_Group* o = new Fl_Group(5, 25, 500, 285, "Main settings"); - { Fl_Group* o = new Fl_Group(15, 45, 165, 30, "Sample Rate"); - o->box(FL_ENGRAVED_FRAME); - { Fl_Choice* o = new Fl_Choice(20, 50, 85, 20); - o->down_box(FL_BORDER_BOX); - o->textsize(10); - o->callback((Fl_Callback*)cb_); - o->menu(menu_); - o->value(getsamplerateorder()); - } // Fl_Choice* o - { Fl_Int_Input* o = samplerateinput = new Fl_Int_Input(115, 50, 60, 20); - samplerateinput->type(2); - samplerateinput->textfont(1); - samplerateinput->callback((Fl_Callback*)cb_samplerateinput); - setsamplerateinput(); - if (getsamplerateorder()!=0) o->deactivate(); - } // Fl_Int_Input* samplerateinput - o->end(); - } // Fl_Group* o - { Fl_Int_Input* o = new Fl_Int_Input(190, 45, 60, 20, "Buffer Size"); - o->tooltip("Internal Sound Buffer Size (samples)"); - o->type(2); - o->labelsize(11); - o->textfont(1); - o->callback((Fl_Callback*)cb_Buffer); - o->align(Fl_Align(129)); - char *tmpbuf=new char[100];o->cut(0,o->maximum_size()); - snprintf(tmpbuf,100,"%d",config.cfg.SoundBufferSize);o->insert(tmpbuf); - delete []tmpbuf; - } // Fl_Int_Input* o - { Fl_Light_Button* o = new Fl_Light_Button(20, 80, 85, 20, "Swap Stereo "); - o->box(FL_THIN_UP_BOX); - o->labelsize(10); - o->callback((Fl_Callback*)cb_Swap); - o->value(config.cfg.SwapStereo); - } // Fl_Light_Button* o - { Fl_Choice* o = new Fl_Choice(175, 80, 75, 20, "OscilSize"); - o->tooltip("ADSynth Oscillator Size (samples)"); - o->down_box(FL_BORDER_BOX); - o->labelfont(1); - o->labelsize(11); - o->textsize(10); - o->callback((Fl_Callback*)cb_OscilSize); - o->menu(menu_OscilSize); - o->value( (int) (log(config.cfg.OscilSize/128.0-1.0)/log(2)) +1); - } // Fl_Choice* o - { Fl_Box* o = new Fl_Box(15, 275, 235, 30, "Most settings has effect only after ZynAddSubFX is restarted."); - o->labelfont(1); - o->labelsize(11); - o->align(Fl_Align(FL_ALIGN_WRAP)); - } // Fl_Box* o - { Fl_Box* o = new Fl_Box(10, 255, 240, 20, "Read the Readme.txt for other settings"); - o->labelfont(1); - o->labelsize(11); - o->align(Fl_Align(FL_ALIGN_WRAP)); - } // Fl_Box* o - { Fl_Group* o = new Fl_Group(15, 125, 230, 85); - o->box(FL_ENGRAVED_BOX); - { Fl_File_Input* o = new Fl_File_Input(20, 170, 220, 35, "Dump File"); - o->callback((Fl_Callback*)cb_Dump); - o->align(Fl_Align(FL_ALIGN_TOP_LEFT)); - o->insert(config.cfg.DumpFile); - } // Fl_File_Input* o - { Fl_Check_Button* o = new Fl_Check_Button(20, 130, 100, 20, "Dump notes"); - o->down_box(FL_DOWN_BOX); - o->callback((Fl_Callback*)cb_Dump1); - o->value(config.cfg.DumpNotesToFile); - } // Fl_Check_Button* o - { Fl_Check_Button* o = new Fl_Check_Button(160, 130, 80, 20, "Append"); - o->down_box(FL_DOWN_BOX); - o->callback((Fl_Callback*)cb_Append); - o->value(config.cfg.DumpAppend); - } // Fl_Check_Button* o - o->end(); - } // Fl_Group* o - { Fl_Group* o = new Fl_Group(255, 45, 245, 260); - o->box(FL_ENGRAVED_FRAME); - { Fl_Box* o = new Fl_Box(260, 50, 235, 45, "Note: Not all the following settings are used (this depends on the operating \ -system, etc..)"); - o->labelfont(1); - o->labelsize(11); - o->align(Fl_Align(FL_ALIGN_WRAP)); - } // Fl_Box* o - { Fl_Group* o = new Fl_Group(260, 110, 235, 115, "Linux"); - o->box(FL_ENGRAVED_BOX); - o->labelfont(1); - o->labelsize(13); - o->align(Fl_Align(FL_ALIGN_TOP_LEFT)); - { Fl_File_Input* o = new Fl_File_Input(265, 180, 225, 35, "OSS Sequencer Device (/dev/...)"); - o->callback((Fl_Callback*)cb_OSS); - o->align(Fl_Align(FL_ALIGN_TOP_LEFT)); - o->insert(config.cfg.LinuxOSSSeqInDev); - } // Fl_File_Input* o - { Fl_File_Input* o = new Fl_File_Input(265, 130, 225, 35, "OSS Wave Out Device (/dev/...)"); - o->callback((Fl_Callback*)cb_OSS1); - o->align(Fl_Align(FL_ALIGN_TOP_LEFT)); - o->insert(config.cfg.LinuxOSSWaveOutDev); - } // Fl_File_Input* o - o->end(); - } // Fl_Group* o - { Fl_Group* o = new Fl_Group(260, 250, 235, 50, "Windows"); - o->box(FL_ENGRAVED_BOX); - o->labelfont(1); - o->labelsize(13); - o->align(Fl_Align(FL_ALIGN_TOP_LEFT)); - { Fl_Counter* o = new Fl_Counter(270, 270, 65, 20, "Midi In Dev"); - o->type(1); - o->labelsize(11); - o->minimum(0); - o->maximum(100); - o->step(1); - o->callback((Fl_Callback*)cb_Midi); - o->align(Fl_Align(FL_ALIGN_TOP)); - o->maximum(config.winmidimax-1); - o->value(config.cfg.WindowsMidiInId); - } // Fl_Counter* o - { Fl_Box* o = midiinputnamebox = new Fl_Box(340, 260, 150, 35, "Midi input device name"); - midiinputnamebox->labelfont(1); - midiinputnamebox->labelsize(11); - midiinputnamebox->align(Fl_Align(196|FL_ALIGN_INSIDE)); - o->label(config.winmididevices[config.cfg.WindowsMidiInId].name); - } // Fl_Box* midiinputnamebox - o->end(); - } // Fl_Group* o - o->end(); - } // Fl_Group* o - { Fl_Counter* o = new Fl_Counter(20, 215, 65, 15, "XML compression level"); - o->tooltip("gzip compression level (0 - uncompressed)"); - o->type(1); - o->labelsize(11); - o->minimum(0); - o->maximum(9); - o->step(1); - o->callback((Fl_Callback*)cb_XML); - o->align(Fl_Align(FL_ALIGN_RIGHT)); - o->value(config.cfg.GzipCompression); - } // Fl_Counter* o - { Fl_Choice* o = new Fl_Choice(175, 105, 75, 15, "PADsynth Interpolation"); - o->down_box(FL_BORDER_BOX); - o->labelsize(10); - o->textsize(11); - o->callback((Fl_Callback*)cb_PADsynth); - o->menu(menu_PADsynth); - o->value(config.cfg.Interpolation); - } // Fl_Choice* o - { Fl_Choice* o = new Fl_Choice(155, 235, 85, 20, "Virtual Keyboard Layout"); - o->down_box(FL_BORDER_BOX); - o->labelsize(12); - o->textfont(1); - o->textsize(11); - o->callback((Fl_Callback*)cb_Virtual); - o->menu(menu_Virtual); - o->value(config.cfg.VirKeybLayout); - } // Fl_Choice* o - o->end(); - } // Fl_Group* o - { Fl_Group* o = new Fl_Group(5, 25, 500, 285, "Bank root dirs"); - o->hide(); - { rootsbrowse = new Fl_Browser(15, 35, 485, 220); - rootsbrowse->type(2); - rootsbrowse->callback((Fl_Callback*)cb_rootsbrowse); - } // Fl_Browser* rootsbrowse - { Fl_Button* o = new Fl_Button(15, 265, 80, 35, "Add root directory..."); - o->box(FL_THIN_UP_BOX); - o->callback((Fl_Callback*)cb_Add); - o->align(Fl_Align(FL_ALIGN_WRAP)); - } // Fl_Button* o - { Fl_Button* o = removerootdirbutton = new Fl_Button(105, 265, 80, 35, "Remove root dir..."); - removerootdirbutton->box(FL_THIN_UP_BOX); - removerootdirbutton->callback((Fl_Callback*)cb_removerootdirbutton); - removerootdirbutton->align(Fl_Align(FL_ALIGN_WRAP)); - o->deactivate(); - } // Fl_Button* removerootdirbutton - { Fl_Button* o = makedefaultrootdirbutton = new Fl_Button(190, 265, 80, 35, "Make default"); - makedefaultrootdirbutton->box(FL_THIN_UP_BOX); - makedefaultrootdirbutton->callback((Fl_Callback*)cb_makedefaultrootdirbutton); - makedefaultrootdirbutton->align(Fl_Align(FL_ALIGN_WRAP)); - o->deactivate(); - } // Fl_Button* makedefaultrootdirbutton - o->end(); - } // Fl_Group* o - { Fl_Group* o = new Fl_Group(5, 25, 500, 285, "Presets dirs"); - o->hide(); - { presetbrowse = new Fl_Browser(15, 35, 485, 220); - presetbrowse->type(2); - presetbrowse->callback((Fl_Callback*)cb_presetbrowse); - } // Fl_Browser* presetbrowse - { Fl_Button* o = new Fl_Button(15, 265, 80, 35, "Add preset directory..."); - o->box(FL_THIN_UP_BOX); - o->callback((Fl_Callback*)cb_Add1); - o->align(Fl_Align(FL_ALIGN_WRAP)); - } // Fl_Button* o - { Fl_Button* o = removepresetbutton = new Fl_Button(105, 265, 80, 35, "Remove preset dir..."); - removepresetbutton->box(FL_THIN_UP_BOX); - removepresetbutton->callback((Fl_Callback*)cb_removepresetbutton); - removepresetbutton->align(Fl_Align(FL_ALIGN_WRAP)); - o->deactivate(); - } // Fl_Button* removepresetbutton - { Fl_Button* o = makedefaultpresetbutton = new Fl_Button(190, 265, 80, 35, "Make default"); - makedefaultpresetbutton->box(FL_THIN_UP_BOX); - makedefaultpresetbutton->callback((Fl_Callback*)cb_makedefaultpresetbutton); - makedefaultpresetbutton->align(Fl_Align(FL_ALIGN_WRAP)); - o->deactivate(); - } // Fl_Button* makedefaultpresetbutton - o->end(); - } // Fl_Group* o - o->end(); - } // Fl_Tabs* o - { Fl_Button* o = new Fl_Button(200, 315, 105, 20, "Close"); - o->box(FL_THIN_UP_BOX); - o->callback((Fl_Callback*)cb_Close); - } // Fl_Button* o - configwindow->end(); - } // Fl_Double_Window* configwindow - return configwindow; -} - -ConfigUI::ConfigUI() { - make_window(); - readbankcfg(); - readpresetcfg(); -} - -void ConfigUI::activatebutton_rootdir(bool active) { - if (active) { - removerootdirbutton->activate(); - makedefaultrootdirbutton->activate(); - }else{ - removerootdirbutton->deactivate(); - makedefaultrootdirbutton->deactivate(); - }; -} - -void ConfigUI::activatebutton_presetdir(bool active) { - if (active) { - removepresetbutton->activate(); - makedefaultpresetbutton->activate(); - }else{ - removepresetbutton->deactivate(); - makedefaultpresetbutton->deactivate(); - }; -} - -void ConfigUI::readbankcfg() { - rootsbrowse->clear(); - - for (int i=0;iadd(config.cfg.bankRootDirList[i]); - }; -} - -void ConfigUI::writebankcfg() { - config.clearbankrootdirlist(); - - for (int n=0;nsize();n++){ - config.cfg.bankRootDirList[n]=new char [MAX_STRING_SIZE]; - strncpy(config.cfg.bankRootDirList[n],rootsbrowse->text(n+1),MAX_STRING_SIZE); - }; -} - -void ConfigUI::readpresetcfg() { - presetbrowse->clear(); - - for (int i=0;iadd(config.cfg.presetsDirList[i]); - }; -} - -void ConfigUI::writepresetcfg() { - config.clearpresetsdirlist(); - - for (int n=0;nsize();n++){ - config.cfg.presetsDirList[n]=new char [MAX_STRING_SIZE]; - strncpy(config.cfg.presetsDirList[n],presetbrowse->text(n+1),MAX_STRING_SIZE); - }; -} - -int ConfigUI::getsamplerateorder() { - int smpr=config.cfg.SampleRate; - int order=0; - switch(smpr){ - case 16000:order=1;break; - case 22050:order=2;break; - case 32000:order=3;break; - case 44100:order=4;break; - case 48000:order=5;break; - case 88200:order=6;break; - case 96000:order=7;break; - default:order=0;break; - }; - return(order); -} - -void ConfigUI::setsamplerateinput() { - char *tmpbuf=new char[100]; - samplerateinput->cut(0,samplerateinput->maximum_size()); - snprintf(tmpbuf,100,"%d",config.cfg.SampleRate); - samplerateinput->insert(tmpbuf); - delete []tmpbuf; -} - -void ConfigUI::show() { - configwindow->show(); -} diff --git a/plugins/zynaddsubfx/src/UI/ConfigUI.fl b/plugins/zynaddsubfx/src/UI/ConfigUI.fl deleted file mode 100644 index ddb8e1bd6..000000000 --- a/plugins/zynaddsubfx/src/UI/ConfigUI.fl +++ /dev/null @@ -1,451 +0,0 @@ -# data file for the Fltk User Interface Designer (fluid) -version 1.0106 -header_name {.h} -code_name {.cc} -decl {//Copyright (c) 2002-2005 Nasca Octavian Paul} {} - -decl {//License: GNU GPL version 2 or later} {} - -decl {\#include } {public -} - -decl {\#include } {public -} - -decl {\#include } {public -} - -decl {\#include } {public -} - -decl {\#include "../globals.h"} {public -} - -decl {\#include "../Misc/Util.h"} {public -} - -decl {\#include "../Misc/Dump.h"} {public -} - -decl {extern Dump dump;} {public -} - -class ConfigUI {} { - Function {make_window()} {} { - Fl_Window configwindow { - label {ZynAddSubFX Settings} - callback {writebankcfg(); -o->hide();} - xywh {88 313 510 340} type Double hide - } { - Fl_Tabs {} { - xywh {5 5 500 305} - } { - Fl_Group {} { - label {Main settings} - xywh {5 25 500 285} - } { - Fl_Group {} { - label {Sample Rate} - xywh {15 45 165 30} box ENGRAVED_FRAME - } { - Fl_Choice {} { - callback {if ((int)o->value()==0) samplerateinput->activate(); - else samplerateinput->deactivate(); - -int samplerates[8]={44100,16000,22050,32000,44100,48000,88200,96000}; -config.cfg.SampleRate=samplerates[(int)o->value()]; - -setsamplerateinput();} - xywh {20 50 85 20} down_box BORDER_BOX textsize 10 - code0 {o->value(getsamplerateorder());} - } { - menuitem {} { - label Custom - xywh {10 10 100 20} labelfont 1 - } - menuitem {} { - label 16000Hz - xywh {30 30 100 20} labelfont 1 - } - menuitem {} { - label 22050Hz - xywh {20 20 100 20} labelfont 1 - } - menuitem {} { - label 32000Hz - xywh {30 30 100 20} labelfont 1 - } - menuitem {} { - label 44100Hz - xywh {40 40 100 20} labelfont 1 - } - menuitem {} { - label 48000Hz - xywh {50 50 100 20} labelfont 1 - } - menuitem {} { - label 88200Hz - xywh {60 60 100 20} labelfont 1 - } - menuitem {} { - label 96000Hz - xywh {70 70 100 20} labelfont 1 - } - } - Fl_Input samplerateinput { - callback {char *tmp; -config.cfg.SampleRate=strtoul(o->value(),&tmp,10);} - xywh {115 50 60 20} type Int textfont 1 - code0 {setsamplerateinput();} - code1 {if (getsamplerateorder()!=0) o->deactivate();} - } - } - Fl_Input {} { - label {Buffer Size} - callback {char *tmp; -config.cfg.SoundBufferSize=strtoul(o->value(),&tmp,10);} - tooltip {Internal Sound Buffer Size (samples)} xywh {190 45 60 20} type Int labelsize 11 align 129 textfont 1 - code0 {char *tmpbuf=new char[100];o->cut(0,o->maximum_size());} - code1 {snprintf(tmpbuf,100,"%d",config.cfg.SoundBufferSize);o->insert(tmpbuf);} - code2 {delete []tmpbuf;} - } - Fl_Light_Button {} { - label {Swap Stereo } - callback {config.cfg.SwapStereo=(int) o->value();} - xywh {20 80 85 20} box THIN_UP_BOX labelsize 10 - code0 {o->value(config.cfg.SwapStereo);} - } - Fl_Choice {} { - label OscilSize - callback {config.cfg.OscilSize=128<value();} - tooltip {ADSynth Oscillator Size (samples)} xywh {175 80 75 20} down_box BORDER_BOX labelfont 1 labelsize 11 textsize 10 - code0 {o->value( (int) (log(config.cfg.OscilSize/128.0-1.0)/log(2)) +1);} - } { - menuitem {} { - label 128 - xywh {25 25 100 20} labelfont 1 - } - menuitem {} { - label 256 - xywh {35 35 100 20} labelfont 1 - } - menuitem {} { - label 512 - xywh {45 45 100 20} labelfont 1 - } - menuitem {} { - label 1024 - xywh {45 45 100 20} labelfont 1 - } - menuitem {} { - label 2048 - xywh {55 55 100 20} labelfont 1 - } - menuitem {} { - label 4096 - xywh {55 55 100 20} labelfont 1 - } - menuitem {} { - label 8192 - xywh {65 65 100 20} labelfont 1 - } - menuitem {} { - label 16384 - xywh {75 75 100 20} labelfont 1 - } - } - Fl_Box {} { - label {Most settings has effect only after ZynAddSubFX is restarted.} - xywh {15 275 235 30} labelfont 1 labelsize 11 align 128 - } - Fl_Box {} { - label {Read the Readme.txt for other settings} - xywh {10 255 240 20} labelfont 1 labelsize 11 align 128 - } - Fl_Group {} { - xywh {15 125 230 85} box ENGRAVED_BOX - } { - Fl_File_Input {} { - label {Dump File} - callback {snprintf(config.cfg.DumpFile,config.maxstringsize,"%s",o->value());} - xywh {20 170 220 35} align 5 - code0 {o->insert(config.cfg.DumpFile);} - } - Fl_Check_Button {} { - label {Dump notes} - callback {config.cfg.DumpNotesToFile=(int) o->value(); -dump.startnow();//this has effect only if this option was disabled} - xywh {20 130 100 20} down_box DOWN_BOX - code0 {o->value(config.cfg.DumpNotesToFile);} - } - Fl_Check_Button {} { - label Append - callback {config.cfg.DumpAppend=(int) o->value();} - xywh {160 130 80 20} down_box DOWN_BOX - code0 {o->value(config.cfg.DumpAppend);} - } - } - Fl_Group {} { - xywh {255 45 245 260} box ENGRAVED_FRAME - } { - Fl_Box {} { - label {Note: Not all the following settings are used (this depends on the operating system, etc..)} - xywh {260 50 235 45} labelfont 1 labelsize 11 align 128 - } - Fl_Group {} { - label Linux - xywh {260 110 235 115} box ENGRAVED_BOX labelfont 1 labelsize 13 align 5 - } { - Fl_File_Input {} { - label {OSS Sequencer Device (/dev/...)} - callback {snprintf(config.cfg.LinuxOSSSeqInDev,config.maxstringsize,"%s",o->value());} - xywh {265 180 225 35} align 5 - code0 {o->insert(config.cfg.LinuxOSSSeqInDev);} - } - Fl_File_Input {} { - label {OSS Wave Out Device (/dev/...)} - callback {snprintf(config.cfg.LinuxOSSWaveOutDev,config.maxstringsize,"%s",o->value());} - xywh {265 130 225 35} align 5 - code0 {o->insert(config.cfg.LinuxOSSWaveOutDev);} - } - } - Fl_Group {} { - label Windows - xywh {260 250 235 50} box ENGRAVED_BOX labelfont 1 labelsize 13 align 5 - } { - Fl_Counter {} { - label {Midi In Dev} - callback {config.cfg.WindowsMidiInId=(int) o->value(); -midiinputnamebox->label(config.winmididevices[config.cfg.WindowsMidiInId].name);} - xywh {270 270 65 20} type Simple labelsize 11 align 1 minimum 0 maximum 100 step 1 - code0 {o->maximum(config.winmidimax-1);} - code1 {o->value(config.cfg.WindowsMidiInId);} - } - Fl_Box midiinputnamebox { - label {Midi input device name} - xywh {340 260 150 35} labelfont 1 labelsize 11 align 212 - code0 {o->label(config.winmididevices[config.cfg.WindowsMidiInId].name);} - } - } - } - Fl_Counter {} { - label {XML compression level} - callback {config.cfg.GzipCompression=(int) o->value();} - tooltip {gzip compression level (0 - uncompressed)} xywh {20 215 65 15} type Simple labelsize 11 align 8 minimum 0 maximum 9 step 1 - code0 {o->value(config.cfg.GzipCompression);} - } - Fl_Choice {} { - label {PADsynth Interpolation} - callback {config.cfg.Interpolation=(int) o->value();} - xywh {175 105 75 15} down_box BORDER_BOX labelsize 10 textsize 11 - code0 {o->value(config.cfg.Interpolation);} - } { - menuitem {} { - label {Linear(fast)} - xywh {0 0 100 20} labelfont 1 labelsize 10 - } - menuitem {} { - label {Cubic(slow)} - xywh {10 10 100 20} labelfont 1 labelsize 10 - } - } - Fl_Choice {} { - label {Virtual Keyboard Layout} - callback {config.cfg.VirKeybLayout=(int) o->value();;} open selected - xywh {155 235 85 20} down_box BORDER_BOX labelsize 12 textfont 1 textsize 11 - code0 {o->value(config.cfg.VirKeybLayout);} - } { - menuitem {} { - label { } - xywh {5 5 100 20} labelfont 1 labelsize 11 deactivate - } - menuitem {} { - label QWERTY - xywh {15 15 100 20} labelfont 1 labelsize 11 - } - menuitem {} { - label Dvorak - xywh {25 25 100 20} labelfont 1 labelsize 11 - } - menuitem {} { - label QWERTZ - xywh {35 35 100 20} labelfont 1 labelsize 11 - } - menuitem {} { - label AZERTY - xywh {45 45 100 20} labelfont 1 labelsize 11 - } - } - } - Fl_Group {} { - label {Bank root dirs} - xywh {5 25 500 285} hide - } { - Fl_Browser rootsbrowse { - callback {activatebutton_rootdir(o->value()!=0);} - xywh {15 35 485 220} type Hold - } - Fl_Button {} { - label {Add root directory...} - callback {const char *dirname; -dirname=fl_dir_chooser("Add a root directory for banks:",NULL,0); -if (dirname==NULL) return; - -rootsbrowse->add(dirname);} - xywh {15 265 80 35} box THIN_UP_BOX align 128 - } - Fl_Button removerootdirbutton { - label {Remove root dir...} - callback {if (rootsbrowse->value()!=0) { - rootsbrowse->remove(rootsbrowse->value()); -}; -activatebutton_rootdir(false);} - xywh {105 265 80 35} box THIN_UP_BOX align 128 - code0 {o->deactivate();} - } - Fl_Button makedefaultrootdirbutton { - label {Make default} - callback {int n=rootsbrowse->value(); - -if (n!=0) { - rootsbrowse->move(1,n); - rootsbrowse->value(1); - rootsbrowse->redraw(); -}; -activatebutton_rootdir(true);} - xywh {190 265 80 35} box THIN_UP_BOX align 128 - code0 {o->deactivate();} - } - } - Fl_Group {} { - label {Presets dirs} - xywh {5 25 500 285} hide - } { - Fl_Browser presetbrowse { - callback {activatebutton_presetdir(o->value()!=0);} - xywh {15 35 485 220} type Hold - } - Fl_Button {} { - label {Add preset directory...} - callback {const char *dirname; -dirname=fl_dir_chooser("Add a preset directory :",NULL,0); -if (dirname==NULL) return; - -presetbrowse->add(dirname);} - xywh {15 265 80 35} box THIN_UP_BOX align 128 - } - Fl_Button removepresetbutton { - label {Remove preset dir...} - callback {if (presetbrowse->value()!=0) { - presetbrowse->remove(presetbrowse->value()); -}; -activatebutton_presetdir(false);} - xywh {105 265 80 35} box THIN_UP_BOX align 128 - code0 {o->deactivate();} - } - Fl_Button makedefaultpresetbutton { - label {Make default} - callback {int n=presetbrowse->value(); - -if (n!=0) { - presetbrowse->move(1,n); - presetbrowse->value(1); - presetbrowse->redraw(); -}; -activatebutton_presetdir(true);} - xywh {190 265 80 35} box THIN_UP_BOX align 128 - code0 {o->deactivate();} - } - } - } - Fl_Button {} { - label Close - callback {configwindow->hide(); -writebankcfg(); -writepresetcfg();} - xywh {200 315 105 20} box THIN_UP_BOX - } - } - } - Function {ConfigUI()} {} { - code {make_window(); -readbankcfg(); -readpresetcfg();} {} - } - Function {activatebutton_rootdir(bool active)} {} { - code {if (active) { - removerootdirbutton->activate(); - makedefaultrootdirbutton->activate(); -}else{ - removerootdirbutton->deactivate(); - makedefaultrootdirbutton->deactivate(); -};} {} - } - Function {activatebutton_presetdir(bool active)} {} { - code {if (active) { - removepresetbutton->activate(); - makedefaultpresetbutton->activate(); -}else{ - removepresetbutton->deactivate(); - makedefaultpresetbutton->deactivate(); -};} {} - } - Function {readbankcfg()} {} { - code {rootsbrowse->clear(); - -for (int i=0;iadd(config.cfg.bankRootDirList[i]); -};} {} - } - Function {writebankcfg()} {} { - code {config.clearbankrootdirlist(); - -for (int n=0;nsize();n++){ - config.cfg.bankRootDirList[n]=new char [MAX_STRING_SIZE]; - strncpy(config.cfg.bankRootDirList[n],rootsbrowse->text(n+1),MAX_STRING_SIZE); -};} {} - } - Function {readpresetcfg()} {} { - code {presetbrowse->clear(); - -for (int i=0;iadd(config.cfg.presetsDirList[i]); -};} {} - } - Function {writepresetcfg()} {} { - code {config.clearpresetsdirlist(); - -for (int n=0;nsize();n++){ - config.cfg.presetsDirList[n]=new char [MAX_STRING_SIZE]; - strncpy(config.cfg.presetsDirList[n],presetbrowse->text(n+1),MAX_STRING_SIZE); -};} {} - } - Function {getsamplerateorder()} {return_type int - } { - code {int smpr=config.cfg.SampleRate; -int order=0; -switch(smpr){ - case 16000:order=1;break; - case 22050:order=2;break; - case 32000:order=3;break; - case 44100:order=4;break; - case 48000:order=5;break; - case 88200:order=6;break; - case 96000:order=7;break; - default:order=0;break; -}; -return(order);} {} - } - Function {setsamplerateinput()} {return_type void - } { - code {char *tmpbuf=new char[100]; -samplerateinput->cut(0,samplerateinput->maximum_size()); -snprintf(tmpbuf,100,"%d",config.cfg.SampleRate); -samplerateinput->insert(tmpbuf); -delete []tmpbuf;} {} - } - Function {show()} {} { - code {configwindow->show();} {} - } -} diff --git a/plugins/zynaddsubfx/src/UI/ConfigUI.h b/plugins/zynaddsubfx/src/UI/ConfigUI.h deleted file mode 100644 index bc0cda5c6..000000000 --- a/plugins/zynaddsubfx/src/UI/ConfigUI.h +++ /dev/null @@ -1,120 +0,0 @@ -// generated by Fast Light User Interface Designer (fluid) version 1.0300 - -#ifndef ConfigUI_h -#define ConfigUI_h -#include -#include -#include -#include -#include -#include "../globals.h" -#include "../Misc/Util.h" -#include "../Misc/Dump.h" -extern Dump dump; -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -class ConfigUI { -public: - Fl_Double_Window* make_window(); - Fl_Double_Window *configwindow; -private: - void cb_configwindow_i(Fl_Double_Window*, void*); - static void cb_configwindow(Fl_Double_Window*, void*); - void cb__i(Fl_Choice*, void*); - static void cb_(Fl_Choice*, void*); - static Fl_Menu_Item menu_[]; -public: - Fl_Int_Input *samplerateinput; -private: - void cb_samplerateinput_i(Fl_Int_Input*, void*); - static void cb_samplerateinput(Fl_Int_Input*, void*); - void cb_Buffer_i(Fl_Int_Input*, void*); - static void cb_Buffer(Fl_Int_Input*, void*); - void cb_Swap_i(Fl_Light_Button*, void*); - static void cb_Swap(Fl_Light_Button*, void*); - void cb_OscilSize_i(Fl_Choice*, void*); - static void cb_OscilSize(Fl_Choice*, void*); - static Fl_Menu_Item menu_OscilSize[]; - void cb_Dump_i(Fl_File_Input*, void*); - static void cb_Dump(Fl_File_Input*, void*); - void cb_Dump1_i(Fl_Check_Button*, void*); - static void cb_Dump1(Fl_Check_Button*, void*); - void cb_Append_i(Fl_Check_Button*, void*); - static void cb_Append(Fl_Check_Button*, void*); - void cb_OSS_i(Fl_File_Input*, void*); - static void cb_OSS(Fl_File_Input*, void*); - void cb_OSS1_i(Fl_File_Input*, void*); - static void cb_OSS1(Fl_File_Input*, void*); - void cb_Midi_i(Fl_Counter*, void*); - static void cb_Midi(Fl_Counter*, void*); -public: - Fl_Box *midiinputnamebox; -private: - void cb_XML_i(Fl_Counter*, void*); - static void cb_XML(Fl_Counter*, void*); - void cb_PADsynth_i(Fl_Choice*, void*); - static void cb_PADsynth(Fl_Choice*, void*); - static Fl_Menu_Item menu_PADsynth[]; - void cb_Virtual_i(Fl_Choice*, void*); - static void cb_Virtual(Fl_Choice*, void*); - static Fl_Menu_Item menu_Virtual[]; -public: - Fl_Browser *rootsbrowse; -private: - void cb_rootsbrowse_i(Fl_Browser*, void*); - static void cb_rootsbrowse(Fl_Browser*, void*); - void cb_Add_i(Fl_Button*, void*); - static void cb_Add(Fl_Button*, void*); -public: - Fl_Button *removerootdirbutton; -private: - void cb_removerootdirbutton_i(Fl_Button*, void*); - static void cb_removerootdirbutton(Fl_Button*, void*); -public: - Fl_Button *makedefaultrootdirbutton; -private: - void cb_makedefaultrootdirbutton_i(Fl_Button*, void*); - static void cb_makedefaultrootdirbutton(Fl_Button*, void*); -public: - Fl_Browser *presetbrowse; -private: - void cb_presetbrowse_i(Fl_Browser*, void*); - static void cb_presetbrowse(Fl_Browser*, void*); - void cb_Add1_i(Fl_Button*, void*); - static void cb_Add1(Fl_Button*, void*); -public: - Fl_Button *removepresetbutton; -private: - void cb_removepresetbutton_i(Fl_Button*, void*); - static void cb_removepresetbutton(Fl_Button*, void*); -public: - Fl_Button *makedefaultpresetbutton; -private: - void cb_makedefaultpresetbutton_i(Fl_Button*, void*); - static void cb_makedefaultpresetbutton(Fl_Button*, void*); - void cb_Close_i(Fl_Button*, void*); - static void cb_Close(Fl_Button*, void*); -public: - ConfigUI(); - void activatebutton_rootdir(bool active); - void activatebutton_presetdir(bool active); - void readbankcfg(); - void writebankcfg(); - void readpresetcfg(); - void writepresetcfg(); - int getsamplerateorder(); - void setsamplerateinput(); - void show(); -}; -#endif diff --git a/plugins/zynaddsubfx/src/UI/EffUI.cc b/plugins/zynaddsubfx/src/UI/EffUI.cc deleted file mode 100644 index aae61d9c7..000000000 --- a/plugins/zynaddsubfx/src/UI/EffUI.cc +++ /dev/null @@ -1,4113 +0,0 @@ -// generated by Fast Light User Interface Designer (fluid) version 1.0300 - -#include "EffUI.h" -//Copyright (c) 2002-2005 Nasca Octavian Paul -//License: GNU GPL version 2 or later - -EQGraph::EQGraph(int x,int y, int w, int h, const char *label):Fl_Box(x,y,w,h,label) { - eff=NULL; - maxdB=30; -} - -void EQGraph::init(EffectMgr *eff_) { - eff=eff_; - oldx=-1; - khzval=-1; -} - -void EQGraph::draw_freq_line(REALTYPE freq,int type) { - fl_color(FL_GRAY); - REALTYPE freqx=getfreqpos(freq); - switch(type){ - case 0:if (active_r()) fl_color(FL_WHITE); - else fl_color(205,205,205); - fl_line_style(FL_SOLID); - break; - case 1:fl_line_style(FL_DOT);break; - case 2:fl_line_style(FL_DASH);break; - }; - - - if ((freqx>0.0)&&(freqx<1.0)) - fl_line(x()+(int) (freqx*w()),y(), - x()+(int) (freqx*w()),y()+h()); -} - -void EQGraph::draw() { - int ox=x(),oy=y(),lx=w(),ly=h(),i,iy,oiy; - REALTYPE freqx; - - if (active_r()) fl_color(0,70,150); - else fl_color(80,120,160); - fl_rectf(ox,oy,lx,ly); - - - //draw the lines - fl_color(FL_GRAY); - - fl_line_style(FL_SOLID); - fl_line(ox+2,oy+ly/2,ox+lx-2,oy+ly/2); - - freqx=getfreqpos(1000.0); - if ((freqx>0.0)&&(freqx<1.0)) - fl_line(ox+(int) (freqx*lx),oy, - ox+(int) (freqx*lx),oy+ly); - - for (i=1;i<10;i++){ - if(i==1){ - draw_freq_line(i*100.0,0); - draw_freq_line(i*1000.0,0); - }else - if (i==5){ - draw_freq_line(i*10.0,2); - draw_freq_line(i*100.0,2); - draw_freq_line(i*1000.0,2); - }else{ - draw_freq_line(i*10.0,1); - draw_freq_line(i*100.0,1); - draw_freq_line(i*1000.0,1); - }; - }; - - draw_freq_line(10000.0,0); - draw_freq_line(20000.0,1); - - - fl_line_style(FL_DOT); - int GY=6;if (lySAMPLE_RATE/2) break; - iy=getresponse(ly,frq); - if ((oiy>=0) && (oiy=0) && (iygetEQfreqresponse(freq); - int idbresp=(int) ((dbresp/maxdB+1.0)*maxy/2.0); - - - //fprintf(stderr,"%.5f\n",(dbresp/maxdB+1.0)*maxy/2.0); - - - return(idbresp); -} - -REALTYPE EQGraph::getfreqx(REALTYPE x) { - if (x>1.0) x=1.0; - return(20.0*pow((REALTYPE)1000.0,x)); -} - -REALTYPE EQGraph::getfreqpos(REALTYPE freq) { - if (freq<0.00001) freq=0.00001; - return(log(freq/20.0)/log(1000.0)); -} - -void EffUI::cb_revp_i(Fl_Choice* o, void*) { - eff->changepreset((int)o->value()); - -refresh(eff); -} -void EffUI::cb_revp(Fl_Choice* o, void* v) { - ((EffUI*)(o->parent()->user_data()))->cb_revp_i(o,v); -} - -Fl_Menu_Item EffUI::menu_revp[] = { - {"Cathedral 1", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 7}, - {"Cathedral 2", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 7}, - {"Cathedral 3", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 7}, - {"Hall 1", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 7}, - {"Hall 2", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 7}, - {"Room 1", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 7}, - {"Room 2", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 7}, - {"Basement", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 7}, - {"Tunnel", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 7}, - {"Echoed 1", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 7}, - {"Echoed 2", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 7}, - {"Very Long 1", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 7}, - {"Very Long 2", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 7}, - {0,0,0,0,0,0,0,0,0} -}; - -void EffUI::cb_revp10_i(Fl_Choice* o, void*) { - eff->seteffectpar(10,(int) o->value()); -if (eff->geteffectpar(10)==2) revp12->activate(); - else revp12->deactivate(); -} -void EffUI::cb_revp10(Fl_Choice* o, void* v) { - ((EffUI*)(o->parent()->user_data()))->cb_revp10_i(o,v); -} - -Fl_Menu_Item EffUI::menu_revp10[] = { - {"Random", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 7}, - {"Freeverb", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 7}, - {"Bandwidth", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 7}, - {0,0,0,0,0,0,0,0,0} -}; - -void EffUI::cb_revp0_i(WidgetPDial* o, void*) { - eff->seteffectpar(0,(int) o->value()); -} -void EffUI::cb_revp0(WidgetPDial* o, void* v) { - ((EffUI*)(o->parent()->user_data()))->cb_revp0_i(o,v); -} - -void EffUI::cb_revp1_i(WidgetPDial* o, void*) { - eff->seteffectpar(1,(int) o->value()); -} -void EffUI::cb_revp1(WidgetPDial* o, void* v) { - ((EffUI*)(o->parent()->user_data()))->cb_revp1_i(o,v); -} - -void EffUI::cb_revp2_i(WidgetPDial* o, void*) { - eff->seteffectpar(2,(int) o->value()); -} -void EffUI::cb_revp2(WidgetPDial* o, void* v) { - ((EffUI*)(o->parent()->user_data()))->cb_revp2_i(o,v); -} - -void EffUI::cb_revp3_i(WidgetPDial* o, void*) { - eff->seteffectpar(3,(int) o->value()); -} -void EffUI::cb_revp3(WidgetPDial* o, void* v) { - ((EffUI*)(o->parent()->user_data()))->cb_revp3_i(o,v); -} - -void EffUI::cb_revp4_i(WidgetPDial* o, void*) { - eff->seteffectpar(4,(int) o->value()); -} -void EffUI::cb_revp4(WidgetPDial* o, void* v) { - ((EffUI*)(o->parent()->user_data()))->cb_revp4_i(o,v); -} - -void EffUI::cb_revp12_i(WidgetPDial* o, void*) { - eff->seteffectpar(12,(int) o->value()); -} -void EffUI::cb_revp12(WidgetPDial* o, void* v) { - ((EffUI*)(o->parent()->user_data()))->cb_revp12_i(o,v); -} - -void EffUI::cb_revp6_i(WidgetPDial* o, void*) { - eff->seteffectpar(6,(int) o->value()); -} -void EffUI::cb_revp6(WidgetPDial* o, void* v) { - ((EffUI*)(o->parent()->user_data()))->cb_revp6_i(o,v); -} - -void EffUI::cb_revp7_i(WidgetPDial* o, void*) { - eff->seteffectpar(7,(int) o->value()); -} -void EffUI::cb_revp7(WidgetPDial* o, void* v) { - ((EffUI*)(o->parent()->user_data()))->cb_revp7_i(o,v); -} - -void EffUI::cb_revp8_i(WidgetPDial* o, void*) { - eff->seteffectpar(8,(int) o->value()); -} -void EffUI::cb_revp8(WidgetPDial* o, void* v) { - ((EffUI*)(o->parent()->user_data()))->cb_revp8_i(o,v); -} - -void EffUI::cb_revp9_i(WidgetPDial* o, void*) { - eff->seteffectpar(9,(int) o->value()); -} -void EffUI::cb_revp9(WidgetPDial* o, void* v) { - ((EffUI*)(o->parent()->user_data()))->cb_revp9_i(o,v); -} - -void EffUI::cb_revp11_i(WidgetPDial* o, void*) { - int x=64; -if (Fl::event_button1()) x=(int)o->value(); - else o->value(x); -eff->seteffectpar(11,x); -} -void EffUI::cb_revp11(WidgetPDial* o, void* v) { - ((EffUI*)(o->parent()->user_data()))->cb_revp11_i(o,v); -} - -void EffUI::cb_echop_i(Fl_Choice* o, void*) { - eff->changepreset((int)o->value()); -refresh(eff); -} -void EffUI::cb_echop(Fl_Choice* o, void* v) { - ((EffUI*)(o->parent()->user_data()))->cb_echop_i(o,v); -} - -Fl_Menu_Item EffUI::menu_echop[] = { - {"Echo 1", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 7}, - {"Echo 2", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 7}, - {"Echo 3", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 7}, - {"Simple Echo", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 7}, - {"Canyon", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 7}, - {"Panning Echo 1", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 7}, - {"Panning Echo 2", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 7}, - {"Panning Echo 3", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 7}, - {"Feedback Echo", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 7}, - {0,0,0,0,0,0,0,0,0} -}; - -void EffUI::cb_echop0_i(WidgetPDial* o, void*) { - eff->seteffectpar(0,(int) o->value()); -} -void EffUI::cb_echop0(WidgetPDial* o, void* v) { - ((EffUI*)(o->parent()->user_data()))->cb_echop0_i(o,v); -} - -void EffUI::cb_echop1_i(WidgetPDial* o, void*) { - eff->seteffectpar(1,(int) o->value()); -} -void EffUI::cb_echop1(WidgetPDial* o, void* v) { - ((EffUI*)(o->parent()->user_data()))->cb_echop1_i(o,v); -} - -void EffUI::cb_echop2_i(WidgetPDial* o, void*) { - eff->seteffectpar(2,(int) o->value()); -} -void EffUI::cb_echop2(WidgetPDial* o, void* v) { - ((EffUI*)(o->parent()->user_data()))->cb_echop2_i(o,v); -} - -void EffUI::cb_echop3_i(WidgetPDial* o, void*) { - eff->seteffectpar(3,(int) o->value()); -} -void EffUI::cb_echop3(WidgetPDial* o, void* v) { - ((EffUI*)(o->parent()->user_data()))->cb_echop3_i(o,v); -} - -void EffUI::cb_echop4_i(WidgetPDial* o, void*) { - eff->seteffectpar(4,(int) o->value()); -} -void EffUI::cb_echop4(WidgetPDial* o, void* v) { - ((EffUI*)(o->parent()->user_data()))->cb_echop4_i(o,v); -} - -void EffUI::cb_echop5_i(WidgetPDial* o, void*) { - eff->seteffectpar(5,(int) o->value()); -} -void EffUI::cb_echop5(WidgetPDial* o, void* v) { - ((EffUI*)(o->parent()->user_data()))->cb_echop5_i(o,v); -} - -void EffUI::cb_echop6_i(WidgetPDial* o, void*) { - eff->seteffectpar(6,(int) o->value()); -} -void EffUI::cb_echop6(WidgetPDial* o, void* v) { - ((EffUI*)(o->parent()->user_data()))->cb_echop6_i(o,v); -} - -void EffUI::cb_chorusp_i(Fl_Choice* o, void*) { - eff->changepreset((int)o->value()); -refresh(eff); -} -void EffUI::cb_chorusp(Fl_Choice* o, void* v) { - ((EffUI*)(o->parent()->user_data()))->cb_chorusp_i(o,v); -} - -Fl_Menu_Item EffUI::menu_chorusp[] = { - {"Chorus 1", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 7}, - {"Chorus 2", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 7}, - {"Chorus 3", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 7}, - {"Celeste 1", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 7}, - {"Celeste 2", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 7}, - {"Flange 1", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 7}, - {"Flange 2", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 7}, - {"Flange 3", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 7}, - {"Flange 4", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 7}, - {"Flange 5", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 7}, - {0,0,0,0,0,0,0,0,0} -}; - -void EffUI::cb_chorusp0_i(WidgetPDial* o, void*) { - eff->seteffectpar(0,(int) o->value()); -} -void EffUI::cb_chorusp0(WidgetPDial* o, void* v) { - ((EffUI*)(o->parent()->user_data()))->cb_chorusp0_i(o,v); -} - -void EffUI::cb_chorusp1_i(WidgetPDial* o, void*) { - eff->seteffectpar(1,(int) o->value()); -} -void EffUI::cb_chorusp1(WidgetPDial* o, void* v) { - ((EffUI*)(o->parent()->user_data()))->cb_chorusp1_i(o,v); -} - -void EffUI::cb_chorusp2_i(WidgetPDial* o, void*) { - eff->seteffectpar(2,(int) o->value()); -} -void EffUI::cb_chorusp2(WidgetPDial* o, void* v) { - ((EffUI*)(o->parent()->user_data()))->cb_chorusp2_i(o,v); -} - -void EffUI::cb_chorusp3_i(WidgetPDial* o, void*) { - eff->seteffectpar(3,(int) o->value()); -} -void EffUI::cb_chorusp3(WidgetPDial* o, void* v) { - ((EffUI*)(o->parent()->user_data()))->cb_chorusp3_i(o,v); -} - -void EffUI::cb_chorusp5_i(WidgetPDial* o, void*) { - eff->seteffectpar(5,(int) o->value()); -} -void EffUI::cb_chorusp5(WidgetPDial* o, void* v) { - ((EffUI*)(o->parent()->user_data()))->cb_chorusp5_i(o,v); -} - -void EffUI::cb_chorusp6_i(WidgetPDial* o, void*) { - eff->seteffectpar(6,(int) o->value()); -} -void EffUI::cb_chorusp6(WidgetPDial* o, void* v) { - ((EffUI*)(o->parent()->user_data()))->cb_chorusp6_i(o,v); -} - -void EffUI::cb_chorusp7_i(WidgetPDial* o, void*) { - eff->seteffectpar(7,(int) o->value()); -} -void EffUI::cb_chorusp7(WidgetPDial* o, void* v) { - ((EffUI*)(o->parent()->user_data()))->cb_chorusp7_i(o,v); -} - -void EffUI::cb_chorusp8_i(WidgetPDial* o, void*) { - eff->seteffectpar(8,(int) o->value()); -} -void EffUI::cb_chorusp8(WidgetPDial* o, void* v) { - ((EffUI*)(o->parent()->user_data()))->cb_chorusp8_i(o,v); -} - -void EffUI::cb_chorusp9_i(WidgetPDial* o, void*) { - eff->seteffectpar(9,(int) o->value()); -} -void EffUI::cb_chorusp9(WidgetPDial* o, void* v) { - ((EffUI*)(o->parent()->user_data()))->cb_chorusp9_i(o,v); -} - -void EffUI::cb_Flange_i(Fl_Check_Button* o, void*) { - eff->seteffectpar(10,(int) o->value()); -} -void EffUI::cb_Flange(Fl_Check_Button* o, void* v) { - ((EffUI*)(o->parent()->user_data()))->cb_Flange_i(o,v); -} - -void EffUI::cb_chorusp11_i(Fl_Check_Button* o, void*) { - eff->seteffectpar(11,(int) o->value()); -} -void EffUI::cb_chorusp11(Fl_Check_Button* o, void* v) { - ((EffUI*)(o->parent()->user_data()))->cb_chorusp11_i(o,v); -} - -void EffUI::cb_chorusp4_i(Fl_Choice* o, void*) { - eff->seteffectpar(4,(int) o->value()); -} -void EffUI::cb_chorusp4(Fl_Choice* o, void* v) { - ((EffUI*)(o->parent()->user_data()))->cb_chorusp4_i(o,v); -} - -Fl_Menu_Item EffUI::menu_chorusp4[] = { - {"SINE", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {"TRI", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {0,0,0,0,0,0,0,0,0} -}; - -void EffUI::cb_phaserp_i(Fl_Choice* o, void*) { - eff->changepreset((int)o->value()); -refresh(eff); -} -void EffUI::cb_phaserp(Fl_Choice* o, void* v) { - ((EffUI*)(o->parent()->user_data()))->cb_phaserp_i(o,v); -} - -Fl_Menu_Item EffUI::menu_phaserp[] = { - {"Phaser 1", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 7}, - {"Phaser 2", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 7}, - {"Phaser 3", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 7}, - {"Phaser 4", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 7}, - {"Phaser 5", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 7}, - {"Phaser 6", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 7}, - {"APhaser 1", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 7}, - {"APhaser 2", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 7}, - {"APhaser 3", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 7}, - {"APhaser 4", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 7}, - {"APhaser 5", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 7}, - {"APhaser 6", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 7}, - {0,0,0,0,0,0,0,0,0} -}; - -void EffUI::cb_phaserp0_i(WidgetPDial* o, void*) { - eff->seteffectpar(0,(int) o->value()); -} -void EffUI::cb_phaserp0(WidgetPDial* o, void* v) { - ((EffUI*)(o->parent()->user_data()))->cb_phaserp0_i(o,v); -} - -void EffUI::cb_phaserp1_i(WidgetPDial* o, void*) { - eff->seteffectpar(1,(int) o->value()); -} -void EffUI::cb_phaserp1(WidgetPDial* o, void* v) { - ((EffUI*)(o->parent()->user_data()))->cb_phaserp1_i(o,v); -} - -void EffUI::cb_phaserp2_i(WidgetPDial* o, void*) { - eff->seteffectpar(2,(int) o->value()); -} -void EffUI::cb_phaserp2(WidgetPDial* o, void* v) { - ((EffUI*)(o->parent()->user_data()))->cb_phaserp2_i(o,v); -} - -void EffUI::cb_phaserp3_i(WidgetPDial* o, void*) { - eff->seteffectpar(3,(int) o->value()); -} -void EffUI::cb_phaserp3(WidgetPDial* o, void* v) { - ((EffUI*)(o->parent()->user_data()))->cb_phaserp3_i(o,v); -} - -void EffUI::cb_phaserp4_i(Fl_Choice* o, void*) { - eff->seteffectpar(4,(int) o->value()); -} -void EffUI::cb_phaserp4(Fl_Choice* o, void* v) { - ((EffUI*)(o->parent()->user_data()))->cb_phaserp4_i(o,v); -} - -Fl_Menu_Item EffUI::menu_phaserp4[] = { - {"SIN", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {"TRI", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {0,0,0,0,0,0,0,0,0} -}; - -void EffUI::cb_phaserp5_i(WidgetPDial* o, void*) { - eff->seteffectpar(5,(int) o->value()); -} -void EffUI::cb_phaserp5(WidgetPDial* o, void* v) { - ((EffUI*)(o->parent()->user_data()))->cb_phaserp5_i(o,v); -} - -void EffUI::cb_phaserp6_i(WidgetPDial* o, void*) { - eff->seteffectpar(6,(int) o->value()); -} -void EffUI::cb_phaserp6(WidgetPDial* o, void* v) { - ((EffUI*)(o->parent()->user_data()))->cb_phaserp6_i(o,v); -} - -void EffUI::cb_phaserp7_i(WidgetPDial* o, void*) { - eff->seteffectpar(7,(int) o->value()); -} -void EffUI::cb_phaserp7(WidgetPDial* o, void* v) { - ((EffUI*)(o->parent()->user_data()))->cb_phaserp7_i(o,v); -} - -void EffUI::cb_phaserp8_i(Fl_Counter* o, void*) { - eff->seteffectpar(8,(int) o->value()); -} -void EffUI::cb_phaserp8(Fl_Counter* o, void* v) { - ((EffUI*)(o->parent()->user_data()))->cb_phaserp8_i(o,v); -} - -void EffUI::cb_phaserp9_i(WidgetPDial* o, void*) { - eff->seteffectpar(9,(int) o->value()); -} -void EffUI::cb_phaserp9(WidgetPDial* o, void* v) { - ((EffUI*)(o->parent()->user_data()))->cb_phaserp9_i(o,v); -} - -void EffUI::cb_phaserp10_i(Fl_Check_Button* o, void*) { - eff->seteffectpar(10,(int) o->value()); -} -void EffUI::cb_phaserp10(Fl_Check_Button* o, void* v) { - ((EffUI*)(o->parent()->user_data()))->cb_phaserp10_i(o,v); -} - -void EffUI::cb_phaserp11_i(WidgetPDial* o, void*) { - eff->seteffectpar(11,(int) o->value()); -} -void EffUI::cb_phaserp11(WidgetPDial* o, void* v) { - ((EffUI*)(o->parent()->user_data()))->cb_phaserp11_i(o,v); -} - -void EffUI::cb_phaserp12_i(Fl_Check_Button* o, void*) { - eff->seteffectpar(12,(int) o->value()); -} -void EffUI::cb_phaserp12(Fl_Check_Button* o, void* v) { - ((EffUI*)(o->parent()->user_data()))->cb_phaserp12_i(o,v); -} - -void EffUI::cb_phaserp13_i(WidgetPDial* o, void*) { - eff->seteffectpar(13,(int) o->value()); -} -void EffUI::cb_phaserp13(WidgetPDial* o, void* v) { - ((EffUI*)(o->parent()->user_data()))->cb_phaserp13_i(o,v); -} - -void EffUI::cb_phaserp14_i(Fl_Check_Button* o, void*) { - eff->seteffectpar(14,(int) o->value()); -} -void EffUI::cb_phaserp14(Fl_Check_Button* o, void* v) { - ((EffUI*)(o->parent()->user_data()))->cb_phaserp14_i(o,v); -} - -void EffUI::cb_awp_i(Fl_Choice* o, void*) { - eff->changepreset((int)o->value()); -refresh(eff); -} -void EffUI::cb_awp(Fl_Choice* o, void* v) { - ((EffUI*)(o->parent()->user_data()))->cb_awp_i(o,v); -} - -Fl_Menu_Item EffUI::menu_awp[] = { - {"Alienwah 1", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 7}, - {"Alienwah 2", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 7}, - {"Alienwah 3", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 7}, - {"Alienwah 4", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 7}, - {0,0,0,0,0,0,0,0,0} -}; - -void EffUI::cb_awp0_i(WidgetPDial* o, void*) { - eff->seteffectpar(0,(int) o->value()); -} -void EffUI::cb_awp0(WidgetPDial* o, void* v) { - ((EffUI*)(o->parent()->user_data()))->cb_awp0_i(o,v); -} - -void EffUI::cb_awp1_i(WidgetPDial* o, void*) { - eff->seteffectpar(1,(int) o->value()); -} -void EffUI::cb_awp1(WidgetPDial* o, void* v) { - ((EffUI*)(o->parent()->user_data()))->cb_awp1_i(o,v); -} - -void EffUI::cb_awp2_i(WidgetPDial* o, void*) { - eff->seteffectpar(2,(int) o->value()); -} -void EffUI::cb_awp2(WidgetPDial* o, void* v) { - ((EffUI*)(o->parent()->user_data()))->cb_awp2_i(o,v); -} - -void EffUI::cb_awp3_i(WidgetPDial* o, void*) { - eff->seteffectpar(3,(int) o->value()); -} -void EffUI::cb_awp3(WidgetPDial* o, void* v) { - ((EffUI*)(o->parent()->user_data()))->cb_awp3_i(o,v); -} - -void EffUI::cb_awp5_i(WidgetPDial* o, void*) { - eff->seteffectpar(5,(int) o->value()); -} -void EffUI::cb_awp5(WidgetPDial* o, void* v) { - ((EffUI*)(o->parent()->user_data()))->cb_awp5_i(o,v); -} - -void EffUI::cb_awp6_i(WidgetPDial* o, void*) { - eff->seteffectpar(6,(int) o->value()); -} -void EffUI::cb_awp6(WidgetPDial* o, void* v) { - ((EffUI*)(o->parent()->user_data()))->cb_awp6_i(o,v); -} - -void EffUI::cb_awp7_i(WidgetPDial* o, void*) { - eff->seteffectpar(7,(int) o->value()); -} -void EffUI::cb_awp7(WidgetPDial* o, void* v) { - ((EffUI*)(o->parent()->user_data()))->cb_awp7_i(o,v); -} - -void EffUI::cb_awp9_i(WidgetPDial* o, void*) { - eff->seteffectpar(9,(int) o->value()); -} -void EffUI::cb_awp9(WidgetPDial* o, void* v) { - ((EffUI*)(o->parent()->user_data()))->cb_awp9_i(o,v); -} - -void EffUI::cb_awp4_i(Fl_Choice* o, void*) { - eff->seteffectpar(4,(int) o->value()); -} -void EffUI::cb_awp4(Fl_Choice* o, void* v) { - ((EffUI*)(o->parent()->user_data()))->cb_awp4_i(o,v); -} - -Fl_Menu_Item EffUI::menu_awp4[] = { - {"SINE", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {"TRI", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {0,0,0,0,0,0,0,0,0} -}; - -void EffUI::cb_awp10_i(WidgetPDial* o, void*) { - eff->seteffectpar(10,(int) o->value()); -} -void EffUI::cb_awp10(WidgetPDial* o, void* v) { - ((EffUI*)(o->parent()->user_data()))->cb_awp10_i(o,v); -} - -void EffUI::cb_awp8_i(Fl_Counter* o, void*) { - eff->seteffectpar(8,(int) o->value()); -} -void EffUI::cb_awp8(Fl_Counter* o, void* v) { - ((EffUI*)(o->parent()->user_data()))->cb_awp8_i(o,v); -} - -void EffUI::cb_distp_i(Fl_Choice* o, void*) { - eff->changepreset((int)o->value()); -refresh(eff); -} -void EffUI::cb_distp(Fl_Choice* o, void* v) { - ((EffUI*)(o->parent()->user_data()))->cb_distp_i(o,v); -} - -Fl_Menu_Item EffUI::menu_distp[] = { - {"Overdrive 1", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 7}, - {"Overdrive 2", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 7}, - {"A. Exciter 1", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 7}, - {"A. Exciter 2", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 7}, - {"Guitar Amp", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 7}, - {"Quantisize", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 7}, - {0,0,0,0,0,0,0,0,0} -}; - -void EffUI::cb_distp0_i(WidgetPDial* o, void*) { - eff->seteffectpar(0,(int) o->value()); -} -void EffUI::cb_distp0(WidgetPDial* o, void* v) { - ((EffUI*)(o->parent()->user_data()))->cb_distp0_i(o,v); -} - -void EffUI::cb_distp1_i(WidgetPDial* o, void*) { - eff->seteffectpar(1,(int) o->value()); -} -void EffUI::cb_distp1(WidgetPDial* o, void* v) { - ((EffUI*)(o->parent()->user_data()))->cb_distp1_i(o,v); -} - -void EffUI::cb_distp2_i(WidgetPDial* o, void*) { - eff->seteffectpar(2,(int) o->value()); -} -void EffUI::cb_distp2(WidgetPDial* o, void* v) { - ((EffUI*)(o->parent()->user_data()))->cb_distp2_i(o,v); -} - -void EffUI::cb_distp3_i(WidgetPDial* o, void*) { - eff->seteffectpar(3,(int) o->value()); -} -void EffUI::cb_distp3(WidgetPDial* o, void* v) { - ((EffUI*)(o->parent()->user_data()))->cb_distp3_i(o,v); -} - -void EffUI::cb_distp4_i(WidgetPDial* o, void*) { - eff->seteffectpar(4,(int) o->value()); -} -void EffUI::cb_distp4(WidgetPDial* o, void* v) { - ((EffUI*)(o->parent()->user_data()))->cb_distp4_i(o,v); -} - -void EffUI::cb_distp7_i(WidgetPDial* o, void*) { - eff->seteffectpar(7,(int) o->value()); -} -void EffUI::cb_distp7(WidgetPDial* o, void* v) { - ((EffUI*)(o->parent()->user_data()))->cb_distp7_i(o,v); -} - -void EffUI::cb_distp8_i(WidgetPDial* o, void*) { - eff->seteffectpar(8,(int) o->value()); -} -void EffUI::cb_distp8(WidgetPDial* o, void* v) { - ((EffUI*)(o->parent()->user_data()))->cb_distp8_i(o,v); -} - -void EffUI::cb_distp5_i(Fl_Choice* o, void*) { - eff->seteffectpar(5,(int) o->value()); -} -void EffUI::cb_distp5(Fl_Choice* o, void* v) { - ((EffUI*)(o->parent()->user_data()))->cb_distp5_i(o,v); -} - -Fl_Menu_Item EffUI::menu_distp5[] = { - {"Atan", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {"Asym1", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {"Pow", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {"Sine", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {"Qnts", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {"Zigzg", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {"Lmt", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {"LmtU", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {"LmtL", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {"ILmt", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {"Clip", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {"Asym2", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {"Pow2", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {"Sgm", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {0,0,0,0,0,0,0,0,0} -}; - -void EffUI::cb_distp6_i(Fl_Check_Button* o, void*) { - eff->seteffectpar(6,(int) o->value()); -} -void EffUI::cb_distp6(Fl_Check_Button* o, void* v) { - ((EffUI*)(o->parent()->user_data()))->cb_distp6_i(o,v); -} - -void EffUI::cb_distp9_i(Fl_Check_Button* o, void*) { - eff->seteffectpar(9,(int) o->value()); -} -void EffUI::cb_distp9(Fl_Check_Button* o, void* v) { - ((EffUI*)(o->parent()->user_data()))->cb_distp9_i(o,v); -} - -void EffUI::cb_distp10_i(Fl_Check_Button* o, void*) { - eff->seteffectpar(10,(int) o->value()); -} -void EffUI::cb_distp10(Fl_Check_Button* o, void* v) { - ((EffUI*)(o->parent()->user_data()))->cb_distp10_i(o,v); -} - -void EffUI::cb_eqp0_i(WidgetPDial* o, void*) { - eff->seteffectpar(0,(int) o->value()); -eqgraph->redraw(); -} -void EffUI::cb_eqp0(WidgetPDial* o, void* v) { - ((EffUI*)(o->parent()->user_data()))->cb_eqp0_i(o,v); -} - -void EffUI::cb_bandcounter_i(Fl_Counter* o, void*) { - eqband=(int) o->value(); -int npb=eqband*5+10; - -int type=eff->geteffectpar(npb); -typechoice->value(type); - -if (type>6) gaindial->activate(); - else gaindial->deactivate(); - -if (type==0) bandgroup->deactivate(); -else bandgroup->activate(); - -int freq=eff->geteffectpar(npb+1); -freqdial->value(freq); - -int gain=eff->geteffectpar(npb+2); -gaindial->value(gain); - -int q=eff->geteffectpar(npb+3); -qdial->value(q); - -int dbl=eff->geteffectpar(npb+4); -stagescounter->value(dbl); -} -void EffUI::cb_bandcounter(Fl_Counter* o, void* v) { - ((EffUI*)(o->parent()->user_data()))->cb_bandcounter_i(o,v); -} - -void EffUI::cb_freqdial_i(WidgetPDial* o, void*) { - int np=eqband*5+11; -eff->seteffectpar(np,(int) o->value()); -eqgraph->redraw(); -} -void EffUI::cb_freqdial(WidgetPDial* o, void* v) { - ((EffUI*)(o->parent()->parent()->user_data()))->cb_freqdial_i(o,v); -} - -void EffUI::cb_gaindial_i(WidgetPDial* o, void*) { - int np=eqband*5+12; -eff->seteffectpar(np,(int) o->value()); -eqgraph->redraw(); -} -void EffUI::cb_gaindial(WidgetPDial* o, void* v) { - ((EffUI*)(o->parent()->parent()->user_data()))->cb_gaindial_i(o,v); -} - -void EffUI::cb_qdial_i(WidgetPDial* o, void*) { - int np=eqband*5+13; -eff->seteffectpar(np,(int) o->value()); -eqgraph->redraw(); -} -void EffUI::cb_qdial(WidgetPDial* o, void* v) { - ((EffUI*)(o->parent()->parent()->user_data()))->cb_qdial_i(o,v); -} - -void EffUI::cb_stagescounter_i(Fl_Counter* o, void*) { - int np=eqband*5+14; -eff->seteffectpar(np,(int) o->value()); -eqgraph->redraw(); -} -void EffUI::cb_stagescounter(Fl_Counter* o, void* v) { - ((EffUI*)(o->parent()->parent()->user_data()))->cb_stagescounter_i(o,v); -} - -void EffUI::cb_typechoice_i(Fl_Choice* o, void*) { - int np=eqband*5+10; -eff->seteffectpar(np,(int) o->value()); -bandcounter->do_callback(); -eqgraph->redraw(); -} -void EffUI::cb_typechoice(Fl_Choice* o, void* v) { - ((EffUI*)(o->parent()->user_data()))->cb_typechoice_i(o,v); -} - -Fl_Menu_Item EffUI::menu_typechoice[] = { - {"OFF", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {"Lp1", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {"Hp1", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {"Lp2", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {"Hp2", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {"Bp2", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {"N2", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {"Pk", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {"LSh", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {"HSh", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {0,0,0,0,0,0,0,0,0} -}; - -void EffUI::cb_dfp_i(Fl_Choice* o, void*) { - eff->changepreset((int)o->value()); -refresh(eff); -} -void EffUI::cb_dfp(Fl_Choice* o, void* v) { - ((EffUI*)(o->parent()->user_data()))->cb_dfp_i(o,v); -} - -Fl_Menu_Item EffUI::menu_dfp[] = { - {"WahWah", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 7}, - {"AutoWah", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 7}, - {"Sweep", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 7}, - {"VocalMorph1", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 7}, - {"VocalMorph2", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 7}, - {0,0,0,0,0,0,0,0,0} -}; - -void EffUI::cb_dfp0_i(WidgetPDial* o, void*) { - eff->seteffectpar(0,(int) o->value()); -} -void EffUI::cb_dfp0(WidgetPDial* o, void* v) { - ((EffUI*)(o->parent()->user_data()))->cb_dfp0_i(o,v); -} - -void EffUI::cb_dfp1_i(WidgetPDial* o, void*) { - eff->seteffectpar(1,(int) o->value()); -} -void EffUI::cb_dfp1(WidgetPDial* o, void* v) { - ((EffUI*)(o->parent()->user_data()))->cb_dfp1_i(o,v); -} - -void EffUI::cb_dfp2_i(WidgetPDial* o, void*) { - eff->seteffectpar(2,(int) o->value()); -} -void EffUI::cb_dfp2(WidgetPDial* o, void* v) { - ((EffUI*)(o->parent()->user_data()))->cb_dfp2_i(o,v); -} - -void EffUI::cb_dfp3_i(WidgetPDial* o, void*) { - eff->seteffectpar(3,(int) o->value()); -} -void EffUI::cb_dfp3(WidgetPDial* o, void* v) { - ((EffUI*)(o->parent()->user_data()))->cb_dfp3_i(o,v); -} - -void EffUI::cb_dfp5_i(WidgetPDial* o, void*) { - eff->seteffectpar(5,(int) o->value()); -} -void EffUI::cb_dfp5(WidgetPDial* o, void* v) { - ((EffUI*)(o->parent()->user_data()))->cb_dfp5_i(o,v); -} - -void EffUI::cb_dfp6_i(WidgetPDial* o, void*) { - eff->seteffectpar(6,(int) o->value()); -} -void EffUI::cb_dfp6(WidgetPDial* o, void* v) { - ((EffUI*)(o->parent()->user_data()))->cb_dfp6_i(o,v); -} - -void EffUI::cb_dfp4_i(Fl_Choice* o, void*) { - eff->seteffectpar(4,(int) o->value()); -} -void EffUI::cb_dfp4(Fl_Choice* o, void* v) { - ((EffUI*)(o->parent()->user_data()))->cb_dfp4_i(o,v); -} - -Fl_Menu_Item EffUI::menu_dfp4[] = { - {"SINE", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {"TRI", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {0,0,0,0,0,0,0,0,0} -}; - -void EffUI::cb_Filter_i(Fl_Button*, void*) { - filterwindow->show(); -} -void EffUI::cb_Filter(Fl_Button* o, void* v) { - ((EffUI*)(o->parent()->user_data()))->cb_Filter_i(o,v); -} - -void EffUI::cb_dfp7_i(WidgetPDial* o, void*) { - eff->seteffectpar(7,(int) o->value()); -} -void EffUI::cb_dfp7(WidgetPDial* o, void* v) { - ((EffUI*)(o->parent()->parent()->user_data()))->cb_dfp7_i(o,v); -} - -void EffUI::cb_dfp9_i(WidgetPDial* o, void*) { - eff->seteffectpar(9,(int) o->value()); -} -void EffUI::cb_dfp9(WidgetPDial* o, void* v) { - ((EffUI*)(o->parent()->parent()->user_data()))->cb_dfp9_i(o,v); -} - -void EffUI::cb_dfp8_i(Fl_Check_Button* o, void*) { - eff->seteffectpar(8,(int) o->value()); -} -void EffUI::cb_dfp8(Fl_Check_Button* o, void* v) { - ((EffUI*)(o->parent()->parent()->user_data()))->cb_dfp8_i(o,v); -} - -void EffUI::cb_Close_i(Fl_Button*, void*) { - filterwindow->hide(); -} -void EffUI::cb_Close(Fl_Button* o, void* v) { - ((EffUI*)(o->parent()->user_data()))->cb_Close_i(o,v); -} - -EffUI::EffUI(int x,int y, int w, int h, const char *label):Fl_Group(x,y,w,h,label) { - eff=NULL; - filterwindow=NULL; -} - -EffUI::~EffUI() { - effnullwindow->hide();//delete (effnullwindow); - effreverbwindow->hide();//delete (effreverbwindow); - effechowindow->hide();//delete (effechowindow); - effchoruswindow->hide();//delete (effchoruswindow); - effphaserwindow->hide();//delete (effphaserwindow); - effalienwahwindow->hide();//delete (effalienwahwindow); - effdistorsionwindow->hide();//delete (effdistorsionwindow); - effeqwindow->hide();//delete (effeqwindow); - effdynamicfilterwindow->hide();//delete (effdynamicfilterwindow); - - if (filterwindow!=NULL){ - filterwindow->hide(); - delete(filterwindow); - }; -} - -Fl_Group* EffUI::make_null_window() { - { effnullwindow = new Fl_Group(0, 0, 380, 95); - effnullwindow->box(FL_PLASTIC_UP_BOX); - effnullwindow->color((Fl_Color)221); - effnullwindow->selection_color(FL_BACKGROUND_COLOR); - effnullwindow->labeltype(FL_NO_LABEL); - effnullwindow->labelfont(1); - effnullwindow->labelsize(14); - effnullwindow->labelcolor(FL_FOREGROUND_COLOR); - effnullwindow->user_data((void*)(this)); - effnullwindow->align(Fl_Align(FL_ALIGN_TOP)); - effnullwindow->when(FL_WHEN_RELEASE); - { Fl_Text_Display* o = new Fl_Text_Display(120, 35, 10, 20, "No Effect"); - o->box(FL_NO_BOX); - o->labeltype(FL_EMBOSSED_LABEL); - o->labelfont(1); - o->labelsize(22); - o->labelcolor((Fl_Color)43); - o->align(Fl_Align(FL_ALIGN_RIGHT)); - } // Fl_Text_Display* o - effnullwindow->end(); - } // Fl_Group* effnullwindow - return effnullwindow; -} - -Fl_Group* EffUI::make_reverb_window() { - { effreverbwindow = new Fl_Group(0, 0, 380, 95); - effreverbwindow->box(FL_PLASTIC_UP_BOX); - effreverbwindow->color((Fl_Color)221); - effreverbwindow->selection_color(FL_BACKGROUND_COLOR); - effreverbwindow->labeltype(FL_NO_LABEL); - effreverbwindow->labelfont(1); - effreverbwindow->labelsize(14); - effreverbwindow->labelcolor(FL_FOREGROUND_COLOR); - effreverbwindow->user_data((void*)(this)); - effreverbwindow->align(Fl_Align(FL_ALIGN_TOP)); - effreverbwindow->when(FL_WHEN_RELEASE); - { Fl_Text_Display* o = new Fl_Text_Display(275, 10, 10, 20, "Reverb "); - o->box(FL_NO_BOX); - o->labeltype(FL_EMBOSSED_LABEL); - o->labelfont(1); - o->labelsize(22); - o->align(Fl_Align(FL_ALIGN_RIGHT)); - } // Fl_Text_Display* o - { revp = new Fl_Choice(10, 15, 90, 15, "Preset"); - revp->down_box(FL_BORDER_BOX); - revp->color((Fl_Color)14); - revp->selection_color(FL_FOREGROUND_COLOR); - revp->labelfont(1); - revp->labelsize(10); - revp->textfont(1); - revp->textsize(10); - revp->textcolor(FL_BACKGROUND2_COLOR); - revp->callback((Fl_Callback*)cb_revp); - revp->align(Fl_Align(FL_ALIGN_TOP_LEFT)); - revp->menu(menu_revp); - } // Fl_Choice* revp - { revp10 = new Fl_Choice(110, 15, 85, 15, "Type"); - revp10->down_box(FL_BORDER_BOX); - revp10->color((Fl_Color)14); - revp10->labelfont(1); - revp10->labelsize(10); - revp10->textfont(1); - revp10->textsize(10); - revp10->textcolor(FL_BACKGROUND2_COLOR); - revp10->callback((Fl_Callback*)cb_revp10); - revp10->align(Fl_Align(FL_ALIGN_TOP_LEFT)); - revp10->menu(menu_revp10); - } // Fl_Choice* revp10 - { revp0 = new WidgetPDial(10, 40, 30, 30, "Vol"); - revp0->tooltip("Effect Volume"); - revp0->box(FL_ROUND_UP_BOX); - revp0->color(FL_BACKGROUND_COLOR); - revp0->selection_color(FL_INACTIVE_COLOR); - revp0->labeltype(FL_NORMAL_LABEL); - revp0->labelfont(1); - revp0->labelsize(11); - revp0->labelcolor(FL_FOREGROUND_COLOR); - revp0->maximum(127); - revp0->callback((Fl_Callback*)cb_revp0); - revp0->align(Fl_Align(FL_ALIGN_BOTTOM)); - revp0->when(FL_WHEN_CHANGED); - } // WidgetPDial* revp0 - { revp1 = new WidgetPDial(45, 40, 30, 30, "Pan"); - revp1->box(FL_ROUND_UP_BOX); - revp1->color(FL_BACKGROUND_COLOR); - revp1->selection_color(FL_INACTIVE_COLOR); - revp1->labeltype(FL_NORMAL_LABEL); - revp1->labelfont(1); - revp1->labelsize(11); - revp1->labelcolor(FL_FOREGROUND_COLOR); - revp1->maximum(127); - revp1->callback((Fl_Callback*)cb_revp1); - revp1->align(Fl_Align(FL_ALIGN_BOTTOM)); - revp1->when(FL_WHEN_CHANGED); - } // WidgetPDial* revp1 - { revp2 = new WidgetPDial(80, 40, 30, 30, "Time"); - revp2->tooltip("Duration of Effect"); - revp2->box(FL_ROUND_UP_BOX); - revp2->color(FL_BACKGROUND_COLOR); - revp2->selection_color(FL_INACTIVE_COLOR); - revp2->labeltype(FL_NORMAL_LABEL); - revp2->labelfont(1); - revp2->labelsize(11); - revp2->labelcolor(FL_FOREGROUND_COLOR); - revp2->maximum(127); - revp2->callback((Fl_Callback*)cb_revp2); - revp2->align(Fl_Align(FL_ALIGN_BOTTOM)); - revp2->when(FL_WHEN_CHANGED); - } // WidgetPDial* revp2 - { revp3 = new WidgetPDial(120, 40, 30, 30, "I.del"); - revp3->tooltip("Initial Delay"); - revp3->box(FL_ROUND_UP_BOX); - revp3->color(FL_BACKGROUND_COLOR); - revp3->selection_color(FL_INACTIVE_COLOR); - revp3->labeltype(FL_NORMAL_LABEL); - revp3->labelfont(1); - revp3->labelsize(11); - revp3->labelcolor(FL_FOREGROUND_COLOR); - revp3->maximum(127); - revp3->callback((Fl_Callback*)cb_revp3); - revp3->align(Fl_Align(FL_ALIGN_BOTTOM)); - revp3->when(FL_WHEN_RELEASE); - } // WidgetPDial* revp3 - { revp4 = new WidgetPDial(155, 40, 30, 30, "I.delfb"); - revp4->tooltip("Initial Delay Feedback"); - revp4->box(FL_ROUND_UP_BOX); - revp4->color(FL_BACKGROUND_COLOR); - revp4->selection_color(FL_INACTIVE_COLOR); - revp4->labeltype(FL_NORMAL_LABEL); - revp4->labelfont(1); - revp4->labelsize(11); - revp4->labelcolor(FL_FOREGROUND_COLOR); - revp4->maximum(127); - revp4->callback((Fl_Callback*)cb_revp4); - revp4->align(Fl_Align(FL_ALIGN_BOTTOM)); - revp4->when(FL_WHEN_CHANGED); - } // WidgetPDial* revp4 - { WidgetPDial* o = revp12 = new WidgetPDial(200, 40, 30, 30, "bw"); - revp12->box(FL_ROUND_UP_BOX); - revp12->color(FL_BACKGROUND_COLOR); - revp12->selection_color(FL_INACTIVE_COLOR); - revp12->labeltype(FL_NORMAL_LABEL); - revp12->labelfont(1); - revp12->labelsize(11); - revp12->labelcolor(FL_FOREGROUND_COLOR); - revp12->maximum(127); - revp12->callback((Fl_Callback*)cb_revp12); - revp12->align(Fl_Align(FL_ALIGN_BOTTOM)); - revp12->when(FL_WHEN_RELEASE); - revp12->deactivate(); - if (eff->geteffectpar(10)==2) o->activate(); - } // WidgetPDial* revp12 - { revp6 = new WidgetPDial(235, 40, 30, 30, "E/R"); - revp6->box(FL_ROUND_UP_BOX); - revp6->color(FL_BACKGROUND_COLOR); - revp6->selection_color(FL_INACTIVE_COLOR); - revp6->labeltype(FL_NORMAL_LABEL); - revp6->labelfont(1); - revp6->labelsize(11); - revp6->labelcolor(FL_FOREGROUND_COLOR); - revp6->maximum(127); - revp6->callback((Fl_Callback*)cb_revp6); - revp6->align(Fl_Align(FL_ALIGN_BOTTOM)); - revp6->when(FL_WHEN_CHANGED); - revp6->deactivate(); - } // WidgetPDial* revp6 - { revp7 = new WidgetPDial(270, 40, 30, 30, "LPF"); - revp7->tooltip("Low Pass Filter"); - revp7->box(FL_ROUND_UP_BOX); - revp7->color(FL_BACKGROUND_COLOR); - revp7->selection_color(FL_INACTIVE_COLOR); - revp7->labeltype(FL_NORMAL_LABEL); - revp7->labelfont(1); - revp7->labelsize(11); - revp7->labelcolor(FL_FOREGROUND_COLOR); - revp7->maximum(127); - revp7->callback((Fl_Callback*)cb_revp7); - revp7->align(Fl_Align(FL_ALIGN_BOTTOM)); - revp7->when(FL_WHEN_CHANGED); - } // WidgetPDial* revp7 - { revp8 = new WidgetPDial(305, 40, 30, 30, "HPF"); - revp8->tooltip("High Pass Filter"); - revp8->box(FL_ROUND_UP_BOX); - revp8->color(FL_BACKGROUND_COLOR); - revp8->selection_color(FL_INACTIVE_COLOR); - revp8->labeltype(FL_NORMAL_LABEL); - revp8->labelfont(1); - revp8->labelsize(11); - revp8->labelcolor(FL_FOREGROUND_COLOR); - revp8->maximum(127); - revp8->callback((Fl_Callback*)cb_revp8); - revp8->align(Fl_Align(FL_ALIGN_BOTTOM)); - revp8->when(FL_WHEN_CHANGED); - } // WidgetPDial* revp8 - { revp9 = new WidgetPDial(340, 40, 30, 30, "Damp"); - revp9->tooltip("Dampening"); - revp9->box(FL_ROUND_UP_BOX); - revp9->color(FL_BACKGROUND_COLOR); - revp9->selection_color(FL_INACTIVE_COLOR); - revp9->labeltype(FL_NORMAL_LABEL); - revp9->labelfont(1); - revp9->labelsize(11); - revp9->labelcolor(FL_FOREGROUND_COLOR); - revp9->minimum(64); - revp9->maximum(127); - revp9->step(1); - revp9->callback((Fl_Callback*)cb_revp9); - revp9->align(Fl_Align(FL_ALIGN_BOTTOM)); - revp9->when(FL_WHEN_CHANGED); - } // WidgetPDial* revp9 - { revp11 = new WidgetPDial(200, 10, 25, 25, "R.S."); - revp11->tooltip("RoomSize"); - revp11->box(FL_ROUND_UP_BOX); - revp11->color(FL_BACKGROUND_COLOR); - revp11->selection_color(FL_INACTIVE_COLOR); - revp11->labeltype(FL_NORMAL_LABEL); - revp11->labelfont(1); - revp11->labelsize(8); - revp11->labelcolor(FL_FOREGROUND_COLOR); - revp11->minimum(1); - revp11->maximum(127); - revp11->step(1); - revp11->callback((Fl_Callback*)cb_revp11); - revp11->align(Fl_Align(FL_ALIGN_RIGHT)); - revp11->when(FL_WHEN_CHANGED); - } // WidgetPDial* revp11 - effreverbwindow->end(); - } // Fl_Group* effreverbwindow - return effreverbwindow; -} - -Fl_Group* EffUI::make_echo_window() { - { effechowindow = new Fl_Group(0, 0, 380, 95); - effechowindow->box(FL_PLASTIC_UP_BOX); - effechowindow->color((Fl_Color)221); - effechowindow->selection_color(FL_BACKGROUND_COLOR); - effechowindow->labeltype(FL_NO_LABEL); - effechowindow->labelfont(1); - effechowindow->labelsize(14); - effechowindow->labelcolor(FL_FOREGROUND_COLOR); - effechowindow->user_data((void*)(this)); - effechowindow->align(Fl_Align(FL_ALIGN_TOP)); - effechowindow->when(FL_WHEN_RELEASE); - { echop = new Fl_Choice(11, 15, 95, 15, "Preset"); - echop->down_box(FL_BORDER_BOX); - echop->color((Fl_Color)14); - echop->selection_color(FL_FOREGROUND_COLOR); - echop->labelfont(1); - echop->labelsize(10); - echop->textfont(1); - echop->textsize(10); - echop->textcolor(FL_BACKGROUND2_COLOR); - echop->callback((Fl_Callback*)cb_echop); - echop->align(Fl_Align(FL_ALIGN_TOP_LEFT)); - echop->menu(menu_echop); - } // Fl_Choice* echop - { Fl_Text_Display* o = new Fl_Text_Display(295, 10, 10, 20, "Echo"); - o->box(FL_NO_BOX); - o->labeltype(FL_EMBOSSED_LABEL); - o->labelfont(1); - o->labelsize(22); - o->align(Fl_Align(FL_ALIGN_RIGHT)); - } // Fl_Text_Display* o - { echop0 = new WidgetPDial(10, 40, 30, 30, "Vol"); - echop0->tooltip("Effect Volume"); - echop0->box(FL_ROUND_UP_BOX); - echop0->color(FL_BACKGROUND_COLOR); - echop0->selection_color(FL_INACTIVE_COLOR); - echop0->labeltype(FL_NORMAL_LABEL); - echop0->labelfont(1); - echop0->labelsize(11); - echop0->labelcolor(FL_FOREGROUND_COLOR); - echop0->maximum(127); - echop0->callback((Fl_Callback*)cb_echop0); - echop0->align(Fl_Align(FL_ALIGN_BOTTOM)); - echop0->when(FL_WHEN_CHANGED); - } // WidgetPDial* echop0 - { echop1 = new WidgetPDial(45, 40, 30, 30, "Pan"); - echop1->box(FL_ROUND_UP_BOX); - echop1->color(FL_BACKGROUND_COLOR); - echop1->selection_color(FL_INACTIVE_COLOR); - echop1->labeltype(FL_NORMAL_LABEL); - echop1->labelfont(1); - echop1->labelsize(11); - echop1->labelcolor(FL_FOREGROUND_COLOR); - echop1->maximum(127); - echop1->callback((Fl_Callback*)cb_echop1); - echop1->align(Fl_Align(FL_ALIGN_BOTTOM)); - echop1->when(FL_WHEN_CHANGED); - } // WidgetPDial* echop1 - { echop2 = new WidgetPDial(80, 40, 30, 30, "Delay"); - echop2->box(FL_ROUND_UP_BOX); - echop2->color(FL_BACKGROUND_COLOR); - echop2->selection_color(FL_INACTIVE_COLOR); - echop2->labeltype(FL_NORMAL_LABEL); - echop2->labelfont(1); - echop2->labelsize(11); - echop2->labelcolor(FL_FOREGROUND_COLOR); - echop2->maximum(127); - echop2->callback((Fl_Callback*)cb_echop2); - echop2->align(Fl_Align(FL_ALIGN_BOTTOM)); - echop2->when(FL_WHEN_RELEASE); - } // WidgetPDial* echop2 - { echop3 = new WidgetPDial(120, 40, 30, 30, "LRdl."); - echop3->tooltip("Delay Between L/R"); - echop3->box(FL_ROUND_UP_BOX); - echop3->color(FL_BACKGROUND_COLOR); - echop3->selection_color(FL_INACTIVE_COLOR); - echop3->labeltype(FL_NORMAL_LABEL); - echop3->labelfont(1); - echop3->labelsize(11); - echop3->labelcolor(FL_FOREGROUND_COLOR); - echop3->maximum(127); - echop3->callback((Fl_Callback*)cb_echop3); - echop3->align(Fl_Align(FL_ALIGN_BOTTOM)); - echop3->when(FL_WHEN_RELEASE); - } // WidgetPDial* echop3 - { echop4 = new WidgetPDial(155, 40, 30, 30, "LRc."); - echop4->tooltip("L/R Crossover"); - echop4->box(FL_ROUND_UP_BOX); - echop4->color(FL_BACKGROUND_COLOR); - echop4->selection_color(FL_INACTIVE_COLOR); - echop4->labeltype(FL_NORMAL_LABEL); - echop4->labelfont(1); - echop4->labelsize(11); - echop4->labelcolor(FL_FOREGROUND_COLOR); - echop4->maximum(127); - echop4->callback((Fl_Callback*)cb_echop4); - echop4->align(Fl_Align(FL_ALIGN_BOTTOM)); - echop4->when(FL_WHEN_CHANGED); - } // WidgetPDial* echop4 - { echop5 = new WidgetPDial(195, 40, 30, 30, "Fb."); - echop5->tooltip("Feedback"); - echop5->box(FL_ROUND_UP_BOX); - echop5->color(FL_BACKGROUND_COLOR); - echop5->selection_color(FL_INACTIVE_COLOR); - echop5->labeltype(FL_NORMAL_LABEL); - echop5->labelfont(1); - echop5->labelsize(11); - echop5->labelcolor(FL_FOREGROUND_COLOR); - echop5->maximum(127); - echop5->callback((Fl_Callback*)cb_echop5); - echop5->align(Fl_Align(FL_ALIGN_BOTTOM)); - echop5->when(FL_WHEN_CHANGED); - } // WidgetPDial* echop5 - { echop6 = new WidgetPDial(235, 40, 30, 30, "Damp"); - echop6->tooltip("Dampening"); - echop6->box(FL_ROUND_UP_BOX); - echop6->color(FL_BACKGROUND_COLOR); - echop6->selection_color(FL_INACTIVE_COLOR); - echop6->labeltype(FL_NORMAL_LABEL); - echop6->labelfont(1); - echop6->labelsize(11); - echop6->labelcolor(FL_FOREGROUND_COLOR); - echop6->maximum(127); - echop6->callback((Fl_Callback*)cb_echop6); - echop6->align(Fl_Align(FL_ALIGN_BOTTOM)); - echop6->when(FL_WHEN_CHANGED); - } // WidgetPDial* echop6 - effechowindow->end(); - } // Fl_Group* effechowindow - return effechowindow; -} - -Fl_Group* EffUI::make_chorus_window() { - { effchoruswindow = new Fl_Group(0, 0, 380, 95); - effchoruswindow->box(FL_PLASTIC_UP_BOX); - effchoruswindow->color((Fl_Color)221); - effchoruswindow->selection_color(FL_BACKGROUND_COLOR); - effchoruswindow->labeltype(FL_NO_LABEL); - effchoruswindow->labelfont(1); - effchoruswindow->labelsize(14); - effchoruswindow->labelcolor(FL_FOREGROUND_COLOR); - effchoruswindow->user_data((void*)(this)); - effchoruswindow->align(Fl_Align(FL_ALIGN_TOP)); - effchoruswindow->when(FL_WHEN_RELEASE); - { chorusp = new Fl_Choice(10, 15, 90, 15, "Preset"); - chorusp->down_box(FL_BORDER_BOX); - chorusp->color((Fl_Color)14); - chorusp->selection_color(FL_FOREGROUND_COLOR); - chorusp->labelfont(1); - chorusp->labelsize(10); - chorusp->textfont(1); - chorusp->textsize(10); - chorusp->textcolor(FL_BACKGROUND2_COLOR); - chorusp->callback((Fl_Callback*)cb_chorusp); - chorusp->align(Fl_Align(FL_ALIGN_TOP_LEFT)); - chorusp->menu(menu_chorusp); - } // Fl_Choice* chorusp - { Fl_Text_Display* o = new Fl_Text_Display(265, 10, 10, 20, "Chorus"); - o->box(FL_NO_BOX); - o->labeltype(FL_EMBOSSED_LABEL); - o->labelfont(1); - o->labelsize(22); - o->align(Fl_Align(FL_ALIGN_RIGHT)); - } // Fl_Text_Display* o - { chorusp0 = new WidgetPDial(10, 40, 30, 30, "Vol"); - chorusp0->box(FL_ROUND_UP_BOX); - chorusp0->color(FL_BACKGROUND_COLOR); - chorusp0->selection_color(FL_INACTIVE_COLOR); - chorusp0->labeltype(FL_NORMAL_LABEL); - chorusp0->labelfont(1); - chorusp0->labelsize(11); - chorusp0->labelcolor(FL_FOREGROUND_COLOR); - chorusp0->maximum(127); - chorusp0->callback((Fl_Callback*)cb_chorusp0); - chorusp0->align(Fl_Align(FL_ALIGN_BOTTOM)); - chorusp0->when(FL_WHEN_CHANGED); - } // WidgetPDial* chorusp0 - { chorusp1 = new WidgetPDial(45, 40, 30, 30, "Pan"); - chorusp1->box(FL_ROUND_UP_BOX); - chorusp1->color(FL_BACKGROUND_COLOR); - chorusp1->selection_color(FL_INACTIVE_COLOR); - chorusp1->labeltype(FL_NORMAL_LABEL); - chorusp1->labelfont(1); - chorusp1->labelsize(11); - chorusp1->labelcolor(FL_FOREGROUND_COLOR); - chorusp1->maximum(127); - chorusp1->callback((Fl_Callback*)cb_chorusp1); - chorusp1->align(Fl_Align(FL_ALIGN_BOTTOM)); - chorusp1->when(FL_WHEN_CHANGED); - } // WidgetPDial* chorusp1 - { chorusp2 = new WidgetPDial(85, 40, 30, 30, "Freq"); - chorusp2->tooltip("LFO Frequency"); - chorusp2->box(FL_ROUND_UP_BOX); - chorusp2->color(FL_BACKGROUND_COLOR); - chorusp2->selection_color(FL_INACTIVE_COLOR); - chorusp2->labeltype(FL_NORMAL_LABEL); - chorusp2->labelfont(1); - chorusp2->labelsize(11); - chorusp2->labelcolor(FL_FOREGROUND_COLOR); - chorusp2->maximum(127); - chorusp2->callback((Fl_Callback*)cb_chorusp2); - chorusp2->align(Fl_Align(FL_ALIGN_BOTTOM)); - chorusp2->when(FL_WHEN_CHANGED); - } // WidgetPDial* chorusp2 - { chorusp3 = new WidgetPDial(120, 40, 30, 30, "Rnd"); - chorusp3->tooltip("LFO Randomness"); - chorusp3->box(FL_ROUND_UP_BOX); - chorusp3->color(FL_BACKGROUND_COLOR); - chorusp3->selection_color(FL_INACTIVE_COLOR); - chorusp3->labeltype(FL_NORMAL_LABEL); - chorusp3->labelfont(1); - chorusp3->labelsize(11); - chorusp3->labelcolor(FL_FOREGROUND_COLOR); - chorusp3->maximum(127); - chorusp3->callback((Fl_Callback*)cb_chorusp3); - chorusp3->align(Fl_Align(FL_ALIGN_BOTTOM)); - chorusp3->when(FL_WHEN_RELEASE); - } // WidgetPDial* chorusp3 - { chorusp5 = new WidgetPDial(200, 40, 30, 30, "St.df"); - chorusp5->tooltip("L/R Phase Shift"); - chorusp5->box(FL_ROUND_UP_BOX); - chorusp5->color(FL_BACKGROUND_COLOR); - chorusp5->selection_color(FL_INACTIVE_COLOR); - chorusp5->labeltype(FL_NORMAL_LABEL); - chorusp5->labelfont(1); - chorusp5->labelsize(11); - chorusp5->labelcolor(FL_FOREGROUND_COLOR); - chorusp5->maximum(127); - chorusp5->callback((Fl_Callback*)cb_chorusp5); - chorusp5->align(Fl_Align(FL_ALIGN_BOTTOM)); - chorusp5->when(FL_WHEN_CHANGED); - } // WidgetPDial* chorusp5 - { chorusp6 = new WidgetPDial(235, 40, 30, 30, "Dpth"); - chorusp6->tooltip("LFO Depth"); - chorusp6->box(FL_ROUND_UP_BOX); - chorusp6->color(FL_BACKGROUND_COLOR); - chorusp6->selection_color(FL_INACTIVE_COLOR); - chorusp6->labeltype(FL_NORMAL_LABEL); - chorusp6->labelfont(1); - chorusp6->labelsize(11); - chorusp6->labelcolor(FL_FOREGROUND_COLOR); - chorusp6->maximum(127); - chorusp6->callback((Fl_Callback*)cb_chorusp6); - chorusp6->align(Fl_Align(FL_ALIGN_BOTTOM)); - chorusp6->when(FL_WHEN_CHANGED); - } // WidgetPDial* chorusp6 - { chorusp7 = new WidgetPDial(270, 40, 30, 30, "Delay"); - chorusp7->box(FL_ROUND_UP_BOX); - chorusp7->color(FL_BACKGROUND_COLOR); - chorusp7->selection_color(FL_INACTIVE_COLOR); - chorusp7->labeltype(FL_NORMAL_LABEL); - chorusp7->labelfont(1); - chorusp7->labelsize(11); - chorusp7->labelcolor(FL_FOREGROUND_COLOR); - chorusp7->maximum(127); - chorusp7->callback((Fl_Callback*)cb_chorusp7); - chorusp7->align(Fl_Align(FL_ALIGN_BOTTOM)); - chorusp7->when(FL_WHEN_CHANGED); - } // WidgetPDial* chorusp7 - { chorusp8 = new WidgetPDial(305, 40, 30, 30, "Fb"); - chorusp8->tooltip("Feedback"); - chorusp8->box(FL_ROUND_UP_BOX); - chorusp8->color(FL_BACKGROUND_COLOR); - chorusp8->selection_color(FL_INACTIVE_COLOR); - chorusp8->labeltype(FL_NORMAL_LABEL); - chorusp8->labelfont(1); - chorusp8->labelsize(11); - chorusp8->labelcolor(FL_FOREGROUND_COLOR); - chorusp8->maximum(127); - chorusp8->callback((Fl_Callback*)cb_chorusp8); - chorusp8->align(Fl_Align(FL_ALIGN_BOTTOM)); - chorusp8->when(FL_WHEN_CHANGED); - } // WidgetPDial* chorusp8 - { chorusp9 = new WidgetPDial(340, 40, 30, 30, "L/R"); - chorusp9->tooltip("Channel Routing"); - chorusp9->box(FL_ROUND_UP_BOX); - chorusp9->color(FL_BACKGROUND_COLOR); - chorusp9->selection_color(FL_INACTIVE_COLOR); - chorusp9->labeltype(FL_NORMAL_LABEL); - chorusp9->labelfont(1); - chorusp9->labelsize(11); - chorusp9->labelcolor(FL_FOREGROUND_COLOR); - chorusp9->maximum(127); - chorusp9->callback((Fl_Callback*)cb_chorusp9); - chorusp9->align(Fl_Align(FL_ALIGN_BOTTOM)); - chorusp9->when(FL_WHEN_CHANGED); - } // WidgetPDial* chorusp9 - { Fl_Check_Button* o = new Fl_Check_Button(120, 10, 55, 20, "Flange"); - o->box(FL_THIN_UP_BOX); - o->down_box(FL_DOWN_BOX); - o->color((Fl_Color)230); - o->labelfont(1); - o->labelsize(10); - o->callback((Fl_Callback*)cb_Flange); - o->hide(); - o->deactivate(); - o->value(eff->geteffectpar(10)); - } // Fl_Check_Button* o - { chorusp11 = new Fl_Check_Button(185, 10, 70, 20, "Substract"); - chorusp11->tooltip("inverts the output"); - chorusp11->box(FL_THIN_UP_BOX); - chorusp11->down_box(FL_DOWN_BOX); - chorusp11->color((Fl_Color)230); - chorusp11->labelfont(1); - chorusp11->labelsize(10); - chorusp11->callback((Fl_Callback*)cb_chorusp11); - } // Fl_Check_Button* chorusp11 - { chorusp4 = new Fl_Choice(155, 50, 40, 15, "LFO type"); - chorusp4->tooltip("LFO function"); - chorusp4->down_box(FL_BORDER_BOX); - chorusp4->labelfont(1); - chorusp4->labelsize(10); - chorusp4->textsize(8); - chorusp4->callback((Fl_Callback*)cb_chorusp4); - chorusp4->align(Fl_Align(130)); - chorusp4->menu(menu_chorusp4); - } // Fl_Choice* chorusp4 - effchoruswindow->end(); - } // Fl_Group* effchoruswindow - return effchoruswindow; -} - -Fl_Group* EffUI::make_phaser_window() { - { effphaserwindow = new Fl_Group(0, 0, 380, 95); - effphaserwindow->box(FL_PLASTIC_UP_BOX); - effphaserwindow->color((Fl_Color)221); - effphaserwindow->selection_color(FL_BACKGROUND_COLOR); - effphaserwindow->labeltype(FL_NO_LABEL); - effphaserwindow->labelfont(1); - effphaserwindow->labelsize(14); - effphaserwindow->labelcolor(FL_FOREGROUND_COLOR); - effphaserwindow->user_data((void*)(this)); - effphaserwindow->align(Fl_Align(FL_ALIGN_TOP)); - effphaserwindow->when(FL_WHEN_RELEASE); - { phaserp = new Fl_Choice(10, 15, 100, 15, "Preset"); - phaserp->down_box(FL_BORDER_BOX); - phaserp->color((Fl_Color)14); - phaserp->selection_color(FL_FOREGROUND_COLOR); - phaserp->labelfont(1); - phaserp->labelsize(10); - phaserp->textfont(1); - phaserp->textsize(10); - phaserp->textcolor(FL_BACKGROUND2_COLOR); - phaserp->callback((Fl_Callback*)cb_phaserp); - phaserp->align(Fl_Align(FL_ALIGN_TOP_LEFT)); - phaserp->menu(menu_phaserp); - } // Fl_Choice* phaserp - { Fl_Text_Display* o = new Fl_Text_Display(275, 10, 10, 20, "Phaser"); - o->box(FL_NO_BOX); - o->labeltype(FL_EMBOSSED_LABEL); - o->labelfont(1); - o->labelsize(22); - o->align(Fl_Align(FL_ALIGN_RIGHT)); - } // Fl_Text_Display* o - { phaserp0 = new WidgetPDial(10, 40, 30, 30, "Vol"); - phaserp0->tooltip("Effect Volume"); - phaserp0->box(FL_ROUND_UP_BOX); - phaserp0->color(FL_BACKGROUND_COLOR); - phaserp0->selection_color(FL_INACTIVE_COLOR); - phaserp0->labeltype(FL_NORMAL_LABEL); - phaserp0->labelfont(1); - phaserp0->labelsize(11); - phaserp0->labelcolor(FL_FOREGROUND_COLOR); - phaserp0->maximum(127); - phaserp0->callback((Fl_Callback*)cb_phaserp0); - phaserp0->align(Fl_Align(FL_ALIGN_BOTTOM)); - phaserp0->when(FL_WHEN_CHANGED); - } // WidgetPDial* phaserp0 - { phaserp1 = new WidgetPDial(45, 40, 30, 30, "Pan"); - phaserp1->box(FL_ROUND_UP_BOX); - phaserp1->color(FL_BACKGROUND_COLOR); - phaserp1->selection_color(FL_INACTIVE_COLOR); - phaserp1->labeltype(FL_NORMAL_LABEL); - phaserp1->labelfont(1); - phaserp1->labelsize(11); - phaserp1->labelcolor(FL_FOREGROUND_COLOR); - phaserp1->maximum(127); - phaserp1->callback((Fl_Callback*)cb_phaserp1); - phaserp1->align(Fl_Align(FL_ALIGN_BOTTOM)); - phaserp1->when(FL_WHEN_CHANGED); - } // WidgetPDial* phaserp1 - { phaserp2 = new WidgetPDial(85, 45, 25, 25, "Freq"); - phaserp2->tooltip("LFO frequency"); - phaserp2->box(FL_ROUND_UP_BOX); - phaserp2->color(FL_BACKGROUND_COLOR); - phaserp2->selection_color(FL_INACTIVE_COLOR); - phaserp2->labeltype(FL_NORMAL_LABEL); - phaserp2->labelfont(1); - phaserp2->labelsize(11); - phaserp2->labelcolor(FL_FOREGROUND_COLOR); - phaserp2->maximum(127); - phaserp2->callback((Fl_Callback*)cb_phaserp2); - phaserp2->align(Fl_Align(FL_ALIGN_BOTTOM)); - phaserp2->when(FL_WHEN_CHANGED); - } // WidgetPDial* phaserp2 - { phaserp3 = new WidgetPDial(120, 45, 25, 25, "Rnd"); - phaserp3->tooltip("LFO randomness"); - phaserp3->box(FL_ROUND_UP_BOX); - phaserp3->color(FL_BACKGROUND_COLOR); - phaserp3->selection_color(FL_INACTIVE_COLOR); - phaserp3->labeltype(FL_NORMAL_LABEL); - phaserp3->labelfont(1); - phaserp3->labelsize(11); - phaserp3->labelcolor(FL_FOREGROUND_COLOR); - phaserp3->maximum(127); - phaserp3->callback((Fl_Callback*)cb_phaserp3); - phaserp3->align(Fl_Align(FL_ALIGN_BOTTOM)); - phaserp3->when(FL_WHEN_RELEASE); - } // WidgetPDial* phaserp3 - { phaserp4 = new Fl_Choice(245, 55, 40, 15, "LFO"); - phaserp4->tooltip("LFO function"); - phaserp4->down_box(FL_BORDER_BOX); - phaserp4->labelfont(1); - phaserp4->labelsize(10); - phaserp4->textsize(8); - phaserp4->callback((Fl_Callback*)cb_phaserp4); - phaserp4->align(Fl_Align(130)); - phaserp4->menu(menu_phaserp4); - } // Fl_Choice* phaserp4 - { phaserp5 = new WidgetPDial(155, 45, 25, 25, "St.df"); - phaserp5->tooltip("Left/Right Channel Phase Shift"); - phaserp5->box(FL_ROUND_UP_BOX); - phaserp5->color(FL_BACKGROUND_COLOR); - phaserp5->selection_color(FL_INACTIVE_COLOR); - phaserp5->labeltype(FL_NORMAL_LABEL); - phaserp5->labelfont(1); - phaserp5->labelsize(11); - phaserp5->labelcolor(FL_FOREGROUND_COLOR); - phaserp5->maximum(127); - phaserp5->callback((Fl_Callback*)cb_phaserp5); - phaserp5->align(Fl_Align(FL_ALIGN_BOTTOM)); - phaserp5->when(FL_WHEN_CHANGED); - } // WidgetPDial* phaserp5 - { phaserp6 = new WidgetPDial(120, 5, 25, 25, "Dpth"); - phaserp6->tooltip("LFO Depth"); - phaserp6->box(FL_ROUND_UP_BOX); - phaserp6->color(FL_BACKGROUND_COLOR); - phaserp6->selection_color(FL_INACTIVE_COLOR); - phaserp6->labeltype(FL_NORMAL_LABEL); - phaserp6->labelfont(1); - phaserp6->labelsize(10); - phaserp6->labelcolor(FL_FOREGROUND_COLOR); - phaserp6->maximum(127); - phaserp6->callback((Fl_Callback*)cb_phaserp6); - phaserp6->align(Fl_Align(FL_ALIGN_BOTTOM)); - phaserp6->when(FL_WHEN_CHANGED); - } // WidgetPDial* phaserp6 - { phaserp7 = new WidgetPDial(185, 45, 25, 25, "Fb"); - phaserp7->tooltip("Feedback"); - phaserp7->box(FL_ROUND_UP_BOX); - phaserp7->color(FL_BACKGROUND_COLOR); - phaserp7->selection_color(FL_INACTIVE_COLOR); - phaserp7->labeltype(FL_NORMAL_LABEL); - phaserp7->labelfont(1); - phaserp7->labelsize(11); - phaserp7->labelcolor(FL_FOREGROUND_COLOR); - phaserp7->maximum(127); - phaserp7->callback((Fl_Callback*)cb_phaserp7); - phaserp7->align(Fl_Align(FL_ALIGN_BOTTOM)); - phaserp7->when(FL_WHEN_CHANGED); - } // WidgetPDial* phaserp7 - { Fl_Counter* o = phaserp8 = new Fl_Counter(290, 55, 35, 15, "Stages"); - phaserp8->type(1); - phaserp8->labelfont(1); - phaserp8->labelsize(11); - phaserp8->minimum(0); - phaserp8->maximum(127); - phaserp8->step(1); - phaserp8->callback((Fl_Callback*)cb_phaserp8); - o->range(1,MAX_PHASER_STAGES); - } // Fl_Counter* phaserp8 - { phaserp9 = new WidgetPDial(215, 45, 25, 25, "L/R"); - phaserp9->tooltip("Channel Routing"); - phaserp9->box(FL_ROUND_UP_BOX); - phaserp9->color(FL_BACKGROUND_COLOR); - phaserp9->selection_color(FL_INACTIVE_COLOR); - phaserp9->labeltype(FL_NORMAL_LABEL); - phaserp9->labelfont(1); - phaserp9->labelsize(11); - phaserp9->labelcolor(FL_FOREGROUND_COLOR); - phaserp9->maximum(127); - phaserp9->callback((Fl_Callback*)cb_phaserp9); - phaserp9->align(Fl_Align(FL_ALIGN_BOTTOM)); - phaserp9->when(FL_WHEN_CHANGED); - } // WidgetPDial* phaserp9 - { phaserp10 = new Fl_Check_Button(200, 10, 74, 20, "Substract"); - phaserp10->tooltip("inverts output"); - phaserp10->box(FL_THIN_UP_BOX); - phaserp10->down_box(FL_DOWN_BOX); - phaserp10->color((Fl_Color)230); - phaserp10->labelfont(1); - phaserp10->labelsize(10); - phaserp10->callback((Fl_Callback*)cb_phaserp10); - } // Fl_Check_Button* phaserp10 - { phaserp11 = new WidgetPDial(155, 5, 25, 25, "Phase"); - phaserp11->box(FL_ROUND_UP_BOX); - phaserp11->color(FL_BACKGROUND_COLOR); - phaserp11->selection_color(FL_INACTIVE_COLOR); - phaserp11->labeltype(FL_NORMAL_LABEL); - phaserp11->labelfont(1); - phaserp11->labelsize(10); - phaserp11->labelcolor(FL_FOREGROUND_COLOR); - phaserp11->maximum(127); - phaserp11->callback((Fl_Callback*)cb_phaserp11); - phaserp11->align(Fl_Align(FL_ALIGN_BOTTOM)); - phaserp11->when(FL_WHEN_CHANGED); - } // WidgetPDial* phaserp11 - { phaserp12 = new Fl_Check_Button(245, 35, 55, 15, "hyp."); - phaserp12->tooltip("hyper"); - phaserp12->down_box(FL_DOWN_BOX); - phaserp12->callback((Fl_Callback*)cb_phaserp12); - } // Fl_Check_Button* phaserp12 - { phaserp13 = new WidgetPDial(340, 50, 25, 25, "dist"); - phaserp13->tooltip("Distortion"); - phaserp13->box(FL_ROUND_UP_BOX); - phaserp13->color(FL_BACKGROUND_COLOR); - phaserp13->selection_color(FL_INACTIVE_COLOR); - phaserp13->labeltype(FL_NORMAL_LABEL); - phaserp13->labelfont(1); - phaserp13->labelsize(11); - phaserp13->labelcolor(FL_FOREGROUND_COLOR); - phaserp13->maximum(127); - phaserp13->callback((Fl_Callback*)cb_phaserp13); - phaserp13->align(Fl_Align(FL_ALIGN_BOTTOM)); - phaserp13->when(FL_WHEN_CHANGED); - } // WidgetPDial* phaserp13 - { phaserp14 = new Fl_Check_Button(305, 35, 70, 15, "Analog"); - phaserp14->down_box(FL_DOWN_BOX); - phaserp14->callback((Fl_Callback*)cb_phaserp14); - } // Fl_Check_Button* phaserp14 - effphaserwindow->end(); - } // Fl_Group* effphaserwindow - return effphaserwindow; -} - -Fl_Group* EffUI::make_alienwah_window() { - { effalienwahwindow = new Fl_Group(0, 0, 380, 95); - effalienwahwindow->box(FL_PLASTIC_UP_BOX); - effalienwahwindow->color((Fl_Color)221); - effalienwahwindow->selection_color(FL_BACKGROUND_COLOR); - effalienwahwindow->labeltype(FL_NO_LABEL); - effalienwahwindow->labelfont(1); - effalienwahwindow->labelsize(14); - effalienwahwindow->labelcolor(FL_FOREGROUND_COLOR); - effalienwahwindow->user_data((void*)(this)); - effalienwahwindow->align(Fl_Align(FL_ALIGN_TOP)); - effalienwahwindow->when(FL_WHEN_RELEASE); - { awp = new Fl_Choice(10, 15, 90, 15, "Preset"); - awp->down_box(FL_BORDER_BOX); - awp->color((Fl_Color)14); - awp->selection_color(FL_FOREGROUND_COLOR); - awp->labelfont(1); - awp->labelsize(10); - awp->textfont(1); - awp->textsize(10); - awp->textcolor(FL_BACKGROUND2_COLOR); - awp->callback((Fl_Callback*)cb_awp); - awp->align(Fl_Align(FL_ALIGN_TOP_LEFT)); - awp->menu(menu_awp); - } // Fl_Choice* awp - { Fl_Text_Display* o = new Fl_Text_Display(245, 10, 10, 20, "AlienWah"); - o->box(FL_NO_BOX); - o->labeltype(FL_EMBOSSED_LABEL); - o->labelfont(1); - o->labelsize(22); - o->align(Fl_Align(FL_ALIGN_RIGHT)); - } // Fl_Text_Display* o - { awp0 = new WidgetPDial(10, 40, 30, 30, "Vol"); - awp0->tooltip("Effect Volume"); - awp0->box(FL_ROUND_UP_BOX); - awp0->color(FL_BACKGROUND_COLOR); - awp0->selection_color(FL_INACTIVE_COLOR); - awp0->labeltype(FL_NORMAL_LABEL); - awp0->labelfont(1); - awp0->labelsize(11); - awp0->labelcolor(FL_FOREGROUND_COLOR); - awp0->maximum(127); - awp0->callback((Fl_Callback*)cb_awp0); - awp0->align(Fl_Align(FL_ALIGN_BOTTOM)); - awp0->when(FL_WHEN_CHANGED); - } // WidgetPDial* awp0 - { awp1 = new WidgetPDial(45, 40, 30, 30, "Pan"); - awp1->box(FL_ROUND_UP_BOX); - awp1->color(FL_BACKGROUND_COLOR); - awp1->selection_color(FL_INACTIVE_COLOR); - awp1->labeltype(FL_NORMAL_LABEL); - awp1->labelfont(1); - awp1->labelsize(11); - awp1->labelcolor(FL_FOREGROUND_COLOR); - awp1->maximum(127); - awp1->callback((Fl_Callback*)cb_awp1); - awp1->align(Fl_Align(FL_ALIGN_BOTTOM)); - awp1->when(FL_WHEN_CHANGED); - } // WidgetPDial* awp1 - { awp2 = new WidgetPDial(85, 40, 30, 30, "Freq"); - awp2->tooltip("LFO Frequency"); - awp2->box(FL_ROUND_UP_BOX); - awp2->color(FL_BACKGROUND_COLOR); - awp2->selection_color(FL_INACTIVE_COLOR); - awp2->labeltype(FL_NORMAL_LABEL); - awp2->labelfont(1); - awp2->labelsize(11); - awp2->labelcolor(FL_FOREGROUND_COLOR); - awp2->maximum(127); - awp2->callback((Fl_Callback*)cb_awp2); - awp2->align(Fl_Align(FL_ALIGN_BOTTOM)); - awp2->when(FL_WHEN_CHANGED); - } // WidgetPDial* awp2 - { awp3 = new WidgetPDial(120, 40, 30, 30, "Rnd"); - awp3->tooltip("LFO Randomness"); - awp3->box(FL_ROUND_UP_BOX); - awp3->color(FL_BACKGROUND_COLOR); - awp3->selection_color(FL_INACTIVE_COLOR); - awp3->labeltype(FL_NORMAL_LABEL); - awp3->labelfont(1); - awp3->labelsize(11); - awp3->labelcolor(FL_FOREGROUND_COLOR); - awp3->maximum(127); - awp3->callback((Fl_Callback*)cb_awp3); - awp3->align(Fl_Align(FL_ALIGN_BOTTOM)); - awp3->when(FL_WHEN_RELEASE); - } // WidgetPDial* awp3 - { awp5 = new WidgetPDial(200, 40, 30, 30, "St.df"); - awp5->tooltip("Left/Right Channel Phase Shift"); - awp5->box(FL_ROUND_UP_BOX); - awp5->color(FL_BACKGROUND_COLOR); - awp5->selection_color(FL_INACTIVE_COLOR); - awp5->labeltype(FL_NORMAL_LABEL); - awp5->labelfont(1); - awp5->labelsize(11); - awp5->labelcolor(FL_FOREGROUND_COLOR); - awp5->maximum(127); - awp5->callback((Fl_Callback*)cb_awp5); - awp5->align(Fl_Align(FL_ALIGN_BOTTOM)); - awp5->when(FL_WHEN_CHANGED); - } // WidgetPDial* awp5 - { awp6 = new WidgetPDial(235, 40, 30, 30, "Dpth"); - awp6->tooltip("Depth"); - awp6->box(FL_ROUND_UP_BOX); - awp6->color(FL_BACKGROUND_COLOR); - awp6->selection_color(FL_INACTIVE_COLOR); - awp6->labeltype(FL_NORMAL_LABEL); - awp6->labelfont(1); - awp6->labelsize(11); - awp6->labelcolor(FL_FOREGROUND_COLOR); - awp6->maximum(127); - awp6->callback((Fl_Callback*)cb_awp6); - awp6->align(Fl_Align(FL_ALIGN_BOTTOM)); - awp6->when(FL_WHEN_CHANGED); - } // WidgetPDial* awp6 - { awp7 = new WidgetPDial(270, 40, 30, 30, "Fb"); - awp7->tooltip("Feedback"); - awp7->box(FL_ROUND_UP_BOX); - awp7->color(FL_BACKGROUND_COLOR); - awp7->selection_color(FL_INACTIVE_COLOR); - awp7->labeltype(FL_NORMAL_LABEL); - awp7->labelfont(1); - awp7->labelsize(11); - awp7->labelcolor(FL_FOREGROUND_COLOR); - awp7->maximum(127); - awp7->callback((Fl_Callback*)cb_awp7); - awp7->align(Fl_Align(FL_ALIGN_BOTTOM)); - awp7->when(FL_WHEN_CHANGED); - } // WidgetPDial* awp7 - { awp9 = new WidgetPDial(345, 40, 30, 30, "L/R"); - awp9->box(FL_ROUND_UP_BOX); - awp9->color(FL_BACKGROUND_COLOR); - awp9->selection_color(FL_INACTIVE_COLOR); - awp9->labeltype(FL_NORMAL_LABEL); - awp9->labelfont(1); - awp9->labelsize(11); - awp9->labelcolor(FL_FOREGROUND_COLOR); - awp9->maximum(127); - awp9->callback((Fl_Callback*)cb_awp9); - awp9->align(Fl_Align(FL_ALIGN_BOTTOM)); - awp9->when(FL_WHEN_CHANGED); - } // WidgetPDial* awp9 - { awp4 = new Fl_Choice(155, 50, 40, 15, "LFO type"); - awp4->tooltip("LFO function"); - awp4->down_box(FL_BORDER_BOX); - awp4->labelfont(1); - awp4->labelsize(10); - awp4->textsize(8); - awp4->callback((Fl_Callback*)cb_awp4); - awp4->align(Fl_Align(130)); - awp4->menu(menu_awp4); - } // Fl_Choice* awp4 - { awp10 = new WidgetPDial(160, 5, 30, 30, "Phase"); - awp10->box(FL_ROUND_UP_BOX); - awp10->color(FL_BACKGROUND_COLOR); - awp10->selection_color(FL_INACTIVE_COLOR); - awp10->labeltype(FL_NORMAL_LABEL); - awp10->labelfont(1); - awp10->labelsize(11); - awp10->labelcolor(FL_FOREGROUND_COLOR); - awp10->maximum(127); - awp10->callback((Fl_Callback*)cb_awp10); - awp10->align(Fl_Align(FL_ALIGN_BOTTOM)); - awp10->when(FL_WHEN_CHANGED); - } // WidgetPDial* awp10 - { Fl_Counter* o = awp8 = new Fl_Counter(305, 55, 35, 15, "Delay"); - awp8->type(1); - awp8->labelfont(1); - awp8->labelsize(11); - awp8->minimum(0); - awp8->maximum(127); - awp8->step(1); - awp8->callback((Fl_Callback*)cb_awp8); - o->range(1,MAX_ALIENWAH_DELAY); - } // Fl_Counter* awp8 - effalienwahwindow->end(); - } // Fl_Group* effalienwahwindow - return effalienwahwindow; -} - -Fl_Group* EffUI::make_distorsion_window() { - { effdistorsionwindow = new Fl_Group(0, 0, 380, 95); - effdistorsionwindow->box(FL_PLASTIC_UP_BOX); - effdistorsionwindow->color((Fl_Color)221); - effdistorsionwindow->selection_color(FL_BACKGROUND_COLOR); - effdistorsionwindow->labeltype(FL_NO_LABEL); - effdistorsionwindow->labelfont(1); - effdistorsionwindow->labelsize(14); - effdistorsionwindow->labelcolor(FL_FOREGROUND_COLOR); - effdistorsionwindow->user_data((void*)(this)); - effdistorsionwindow->align(Fl_Align(FL_ALIGN_TOP)); - effdistorsionwindow->when(FL_WHEN_RELEASE); - { distp = new Fl_Choice(11, 15, 95, 15, "Preset"); - distp->down_box(FL_BORDER_BOX); - distp->color((Fl_Color)14); - distp->selection_color(FL_FOREGROUND_COLOR); - distp->labelfont(1); - distp->labelsize(10); - distp->textfont(1); - distp->textsize(10); - distp->textcolor(FL_BACKGROUND2_COLOR); - distp->callback((Fl_Callback*)cb_distp); - distp->align(Fl_Align(FL_ALIGN_TOP_LEFT)); - distp->menu(menu_distp); - } // Fl_Choice* distp - { Fl_Text_Display* o = new Fl_Text_Display(230, 10, 10, 20, "Distortion"); - o->box(FL_NO_BOX); - o->labeltype(FL_EMBOSSED_LABEL); - o->labelfont(1); - o->labelsize(22); - o->align(Fl_Align(FL_ALIGN_RIGHT)); - } // Fl_Text_Display* o - { distp0 = new WidgetPDial(10, 40, 30, 30, "Vol"); - distp0->tooltip("Effect Volume"); - distp0->box(FL_ROUND_UP_BOX); - distp0->color(FL_BACKGROUND_COLOR); - distp0->selection_color(FL_INACTIVE_COLOR); - distp0->labeltype(FL_NORMAL_LABEL); - distp0->labelfont(1); - distp0->labelsize(11); - distp0->labelcolor(FL_FOREGROUND_COLOR); - distp0->maximum(127); - distp0->callback((Fl_Callback*)cb_distp0); - distp0->align(Fl_Align(FL_ALIGN_BOTTOM)); - distp0->when(FL_WHEN_CHANGED); - } // WidgetPDial* distp0 - { distp1 = new WidgetPDial(45, 40, 30, 30, "Pan"); - distp1->box(FL_ROUND_UP_BOX); - distp1->color(FL_BACKGROUND_COLOR); - distp1->selection_color(FL_INACTIVE_COLOR); - distp1->labeltype(FL_NORMAL_LABEL); - distp1->labelfont(1); - distp1->labelsize(11); - distp1->labelcolor(FL_FOREGROUND_COLOR); - distp1->maximum(127); - distp1->callback((Fl_Callback*)cb_distp1); - distp1->align(Fl_Align(FL_ALIGN_BOTTOM)); - distp1->when(FL_WHEN_CHANGED); - } // WidgetPDial* distp1 - { distp2 = new WidgetPDial(80, 40, 30, 30, "LRc."); - distp2->tooltip("L/R Mix"); - distp2->box(FL_ROUND_UP_BOX); - distp2->color(FL_BACKGROUND_COLOR); - distp2->selection_color(FL_INACTIVE_COLOR); - distp2->labeltype(FL_NORMAL_LABEL); - distp2->labelfont(1); - distp2->labelsize(11); - distp2->labelcolor(FL_FOREGROUND_COLOR); - distp2->maximum(127); - distp2->callback((Fl_Callback*)cb_distp2); - distp2->align(Fl_Align(FL_ALIGN_BOTTOM)); - distp2->when(FL_WHEN_RELEASE); - } // WidgetPDial* distp2 - { distp3 = new WidgetPDial(120, 40, 30, 30, "Drive"); - distp3->tooltip("Input Amplification"); - distp3->box(FL_ROUND_UP_BOX); - distp3->color(FL_BACKGROUND_COLOR); - distp3->selection_color(FL_INACTIVE_COLOR); - distp3->labeltype(FL_NORMAL_LABEL); - distp3->labelfont(1); - distp3->labelsize(11); - distp3->labelcolor(FL_FOREGROUND_COLOR); - distp3->maximum(127); - distp3->callback((Fl_Callback*)cb_distp3); - distp3->align(Fl_Align(FL_ALIGN_BOTTOM)); - distp3->when(FL_WHEN_RELEASE); - } // WidgetPDial* distp3 - { distp4 = new WidgetPDial(155, 40, 30, 30, "Level"); - distp4->tooltip("Output Amplification"); - distp4->box(FL_ROUND_UP_BOX); - distp4->color(FL_BACKGROUND_COLOR); - distp4->selection_color(FL_INACTIVE_COLOR); - distp4->labeltype(FL_NORMAL_LABEL); - distp4->labelfont(1); - distp4->labelsize(11); - distp4->labelcolor(FL_FOREGROUND_COLOR); - distp4->maximum(127); - distp4->callback((Fl_Callback*)cb_distp4); - distp4->align(Fl_Align(FL_ALIGN_BOTTOM)); - distp4->when(FL_WHEN_CHANGED); - } // WidgetPDial* distp4 - { distp7 = new WidgetPDial(285, 40, 30, 30, "LPF"); - distp7->tooltip("Low Pass Filter"); - distp7->box(FL_ROUND_UP_BOX); - distp7->color(FL_BACKGROUND_COLOR); - distp7->selection_color(FL_INACTIVE_COLOR); - distp7->labeltype(FL_NORMAL_LABEL); - distp7->labelfont(1); - distp7->labelsize(11); - distp7->labelcolor(FL_FOREGROUND_COLOR); - distp7->maximum(127); - distp7->callback((Fl_Callback*)cb_distp7); - distp7->align(Fl_Align(FL_ALIGN_BOTTOM)); - distp7->when(FL_WHEN_CHANGED); - } // WidgetPDial* distp7 - { distp8 = new WidgetPDial(320, 40, 30, 30, "HPF"); - distp8->tooltip("High Pass Filter"); - distp8->box(FL_ROUND_UP_BOX); - distp8->color(FL_BACKGROUND_COLOR); - distp8->selection_color(FL_INACTIVE_COLOR); - distp8->labeltype(FL_NORMAL_LABEL); - distp8->labelfont(1); - distp8->labelsize(11); - distp8->labelcolor(FL_FOREGROUND_COLOR); - distp8->maximum(127); - distp8->callback((Fl_Callback*)cb_distp8); - distp8->align(Fl_Align(FL_ALIGN_BOTTOM)); - distp8->when(FL_WHEN_CHANGED); - } // WidgetPDial* distp8 - { distp5 = new Fl_Choice(190, 50, 60, 20, "Type"); - distp5->box(FL_UP_BOX); - distp5->down_box(FL_BORDER_BOX); - distp5->labelfont(1); - distp5->labelsize(11); - distp5->textsize(10); - distp5->callback((Fl_Callback*)cb_distp5); - distp5->align(Fl_Align(FL_ALIGN_BOTTOM)); - distp5->menu(menu_distp5); - } // Fl_Choice* distp5 - { distp6 = new Fl_Check_Button(260, 55, 15, 15, "Neg."); - distp6->down_box(FL_DOWN_BOX); - distp6->labelfont(1); - distp6->labelsize(11); - distp6->callback((Fl_Callback*)cb_distp6); - distp6->align(Fl_Align(FL_ALIGN_BOTTOM)); - } // Fl_Check_Button* distp6 - { distp9 = new Fl_Check_Button(355, 60, 15, 15, "St."); - distp9->tooltip("Stereo"); - distp9->down_box(FL_DOWN_BOX); - distp9->labelfont(1); - distp9->labelsize(11); - distp9->callback((Fl_Callback*)cb_distp9); - distp9->align(Fl_Align(FL_ALIGN_BOTTOM)); - } // Fl_Check_Button* distp9 - { distp10 = new Fl_Check_Button(355, 44, 15, 15, "PF"); - distp10->tooltip("Applies the filters(before or after) the distorsion"); - distp10->down_box(FL_DOWN_BOX); - distp10->labelfont(1); - distp10->labelsize(11); - distp10->callback((Fl_Callback*)cb_distp10); - distp10->align(Fl_Align(FL_ALIGN_TOP)); - } // Fl_Check_Button* distp10 - effdistorsionwindow->end(); - } // Fl_Group* effdistorsionwindow - return effdistorsionwindow; -} - -Fl_Group* EffUI::make_eq_window() { - { effeqwindow = new Fl_Group(0, 0, 380, 95); - effeqwindow->box(FL_PLASTIC_UP_BOX); - effeqwindow->color((Fl_Color)221); - effeqwindow->selection_color(FL_BACKGROUND_COLOR); - effeqwindow->labeltype(FL_NO_LABEL); - effeqwindow->labelfont(1); - effeqwindow->labelsize(14); - effeqwindow->labelcolor(FL_FOREGROUND_COLOR); - effeqwindow->user_data((void*)(this)); - effeqwindow->align(Fl_Align(FL_ALIGN_TOP)); - effeqwindow->when(FL_WHEN_RELEASE); - { Fl_Text_Display* o = new Fl_Text_Display(320, 10, 15, 20, "EQ"); - o->box(FL_NO_BOX); - o->labeltype(FL_EMBOSSED_LABEL); - o->labelfont(1); - o->labelsize(22); - o->align(Fl_Align(FL_ALIGN_RIGHT)); - } // Fl_Text_Display* o - { eqp0 = new WidgetPDial(10, 35, 30, 30, "Gain"); - eqp0->box(FL_ROUND_UP_BOX); - eqp0->color(FL_BACKGROUND_COLOR); - eqp0->selection_color(FL_INACTIVE_COLOR); - eqp0->labeltype(FL_NORMAL_LABEL); - eqp0->labelfont(1); - eqp0->labelsize(11); - eqp0->labelcolor(FL_FOREGROUND_COLOR); - eqp0->maximum(127); - eqp0->callback((Fl_Callback*)cb_eqp0); - eqp0->align(Fl_Align(FL_ALIGN_BOTTOM)); - eqp0->when(FL_WHEN_CHANGED); - } // WidgetPDial* eqp0 - { Fl_Counter* o = bandcounter = new Fl_Counter(240, 20, 45, 15, "B."); - bandcounter->tooltip("Band no."); - bandcounter->type(1); - bandcounter->labelfont(1); - bandcounter->labelsize(11); - bandcounter->minimum(0); - bandcounter->maximum(1); - bandcounter->step(1); - bandcounter->textfont(1); - bandcounter->textsize(11); - bandcounter->callback((Fl_Callback*)cb_bandcounter); - bandcounter->align(Fl_Align(FL_ALIGN_TOP)); - o->bounds(0,MAX_EQ_BANDS-1); - } // Fl_Counter* bandcounter - { Fl_Group* o = bandgroup = new Fl_Group(245, 40, 130, 50); - bandgroup->box(FL_ENGRAVED_FRAME); - { freqdial = new WidgetPDial(250, 50, 25, 25, "Freq"); - freqdial->box(FL_ROUND_UP_BOX); - freqdial->color(FL_BACKGROUND_COLOR); - freqdial->selection_color(FL_INACTIVE_COLOR); - freqdial->labeltype(FL_NORMAL_LABEL); - freqdial->labelfont(1); - freqdial->labelsize(10); - freqdial->labelcolor(FL_FOREGROUND_COLOR); - freqdial->maximum(127); - freqdial->callback((Fl_Callback*)cb_freqdial); - freqdial->align(Fl_Align(FL_ALIGN_BOTTOM)); - freqdial->when(3); - } // WidgetPDial* freqdial - { gaindial = new WidgetPDial(280, 50, 25, 25, "Gain"); - gaindial->box(FL_ROUND_UP_BOX); - gaindial->color(FL_BACKGROUND_COLOR); - gaindial->selection_color(FL_INACTIVE_COLOR); - gaindial->labeltype(FL_NORMAL_LABEL); - gaindial->labelfont(1); - gaindial->labelsize(10); - gaindial->labelcolor(FL_FOREGROUND_COLOR); - gaindial->maximum(127); - gaindial->step(1); - gaindial->callback((Fl_Callback*)cb_gaindial); - gaindial->align(Fl_Align(FL_ALIGN_BOTTOM)); - gaindial->when(3); - } // WidgetPDial* gaindial - { qdial = new WidgetPDial(310, 50, 25, 25, "Q"); - qdial->tooltip("Resonance/Bandwidth"); - qdial->box(FL_ROUND_UP_BOX); - qdial->color(FL_BACKGROUND_COLOR); - qdial->selection_color(FL_INACTIVE_COLOR); - qdial->labeltype(FL_NORMAL_LABEL); - qdial->labelfont(1); - qdial->labelsize(10); - qdial->labelcolor(FL_FOREGROUND_COLOR); - qdial->maximum(127); - qdial->callback((Fl_Callback*)cb_qdial); - qdial->align(Fl_Align(FL_ALIGN_BOTTOM)); - qdial->when(3); - } // WidgetPDial* qdial - { Fl_Counter* o = stagescounter = new Fl_Counter(340, 60, 30, 15, "St."); - stagescounter->tooltip("Additional filter stages"); - stagescounter->type(1); - stagescounter->labelfont(1); - stagescounter->labelsize(10); - stagescounter->minimum(1); - stagescounter->maximum(127); - stagescounter->step(1); - stagescounter->textfont(1); - stagescounter->textsize(11); - stagescounter->callback((Fl_Callback*)cb_stagescounter); - o->bounds(0,MAX_FILTER_STAGES-1); - } // Fl_Counter* stagescounter - if (eff->geteffectpar(10)==0) o->deactivate(); - bandgroup->end(); - } // Fl_Group* bandgroup - { typechoice = new Fl_Choice(290, 20, 40, 15, "T."); - typechoice->tooltip("Type"); - typechoice->down_box(FL_BORDER_BOX); - typechoice->labelfont(1); - typechoice->labelsize(10); - typechoice->textsize(10); - typechoice->callback((Fl_Callback*)cb_typechoice); - typechoice->align(Fl_Align(FL_ALIGN_TOP)); - typechoice->when(FL_WHEN_RELEASE_ALWAYS); - typechoice->menu(menu_typechoice); - } // Fl_Choice* typechoice - { EQGraph* o = eqgraph = new EQGraph(45, 10, 190, 75); - eqgraph->box(FL_BORDER_BOX); - eqgraph->color((Fl_Color)178); - eqgraph->selection_color(FL_BACKGROUND_COLOR); - eqgraph->labeltype(FL_NORMAL_LABEL); - eqgraph->labelfont(0); - eqgraph->labelsize(14); - eqgraph->labelcolor(FL_FOREGROUND_COLOR); - eqgraph->align(Fl_Align(FL_ALIGN_CENTER)); - eqgraph->when(FL_WHEN_RELEASE); - o->init(eff); - } // EQGraph* eqgraph - effeqwindow->end(); - } // Fl_Group* effeqwindow - return effeqwindow; -} - -Fl_Group* EffUI::make_dynamicfilter_window() { - { effdynamicfilterwindow = new Fl_Group(0, 0, 380, 95); - effdynamicfilterwindow->box(FL_PLASTIC_UP_BOX); - effdynamicfilterwindow->color((Fl_Color)221); - effdynamicfilterwindow->selection_color(FL_BACKGROUND_COLOR); - effdynamicfilterwindow->labeltype(FL_NO_LABEL); - effdynamicfilterwindow->labelfont(1); - effdynamicfilterwindow->labelsize(14); - effdynamicfilterwindow->labelcolor(FL_FOREGROUND_COLOR); - effdynamicfilterwindow->user_data((void*)(this)); - effdynamicfilterwindow->align(Fl_Align(FL_ALIGN_TOP)); - effdynamicfilterwindow->when(FL_WHEN_RELEASE); - { dfp = new Fl_Choice(10, 15, 90, 15, "Preset"); - dfp->down_box(FL_BORDER_BOX); - dfp->color((Fl_Color)14); - dfp->selection_color(FL_FOREGROUND_COLOR); - dfp->labelfont(1); - dfp->labelsize(10); - dfp->textfont(1); - dfp->textsize(10); - dfp->textcolor(FL_BACKGROUND2_COLOR); - dfp->callback((Fl_Callback*)cb_dfp); - dfp->align(Fl_Align(FL_ALIGN_TOP_LEFT)); - dfp->menu(menu_dfp); - } // Fl_Choice* dfp - { Fl_Text_Display* o = new Fl_Text_Display(245, 10, 10, 20, "DynFilter"); - o->box(FL_NO_BOX); - o->labeltype(FL_EMBOSSED_LABEL); - o->labelfont(1); - o->labelsize(22); - o->align(Fl_Align(FL_ALIGN_RIGHT)); - } // Fl_Text_Display* o - { dfp0 = new WidgetPDial(10, 40, 30, 30, "Vol"); - dfp0->tooltip("Effect Volume"); - dfp0->box(FL_ROUND_UP_BOX); - dfp0->color(FL_BACKGROUND_COLOR); - dfp0->selection_color(FL_INACTIVE_COLOR); - dfp0->labeltype(FL_NORMAL_LABEL); - dfp0->labelfont(1); - dfp0->labelsize(11); - dfp0->labelcolor(FL_FOREGROUND_COLOR); - dfp0->maximum(127); - dfp0->callback((Fl_Callback*)cb_dfp0); - dfp0->align(Fl_Align(FL_ALIGN_BOTTOM)); - dfp0->when(FL_WHEN_CHANGED); - } // WidgetPDial* dfp0 - { dfp1 = new WidgetPDial(45, 40, 30, 30, "Pan"); - dfp1->box(FL_ROUND_UP_BOX); - dfp1->color(FL_BACKGROUND_COLOR); - dfp1->selection_color(FL_INACTIVE_COLOR); - dfp1->labeltype(FL_NORMAL_LABEL); - dfp1->labelfont(1); - dfp1->labelsize(11); - dfp1->labelcolor(FL_FOREGROUND_COLOR); - dfp1->maximum(127); - dfp1->callback((Fl_Callback*)cb_dfp1); - dfp1->align(Fl_Align(FL_ALIGN_BOTTOM)); - dfp1->when(FL_WHEN_CHANGED); - } // WidgetPDial* dfp1 - { dfp2 = new WidgetPDial(85, 40, 30, 30, "Freq"); - dfp2->tooltip("LFO Frequency"); - dfp2->box(FL_ROUND_UP_BOX); - dfp2->color(FL_BACKGROUND_COLOR); - dfp2->selection_color(FL_INACTIVE_COLOR); - dfp2->labeltype(FL_NORMAL_LABEL); - dfp2->labelfont(1); - dfp2->labelsize(11); - dfp2->labelcolor(FL_FOREGROUND_COLOR); - dfp2->maximum(127); - dfp2->callback((Fl_Callback*)cb_dfp2); - dfp2->align(Fl_Align(FL_ALIGN_BOTTOM)); - dfp2->when(FL_WHEN_CHANGED); - } // WidgetPDial* dfp2 - { dfp3 = new WidgetPDial(120, 40, 30, 30, "Rnd"); - dfp3->tooltip("LFO Randomness"); - dfp3->box(FL_ROUND_UP_BOX); - dfp3->color(FL_BACKGROUND_COLOR); - dfp3->selection_color(FL_INACTIVE_COLOR); - dfp3->labeltype(FL_NORMAL_LABEL); - dfp3->labelfont(1); - dfp3->labelsize(11); - dfp3->labelcolor(FL_FOREGROUND_COLOR); - dfp3->maximum(127); - dfp3->callback((Fl_Callback*)cb_dfp3); - dfp3->align(Fl_Align(FL_ALIGN_BOTTOM)); - dfp3->when(FL_WHEN_RELEASE); - } // WidgetPDial* dfp3 - { dfp5 = new WidgetPDial(200, 40, 30, 30, "St.df"); - dfp5->tooltip("Left/Right Channel Phase Shift"); - dfp5->box(FL_ROUND_UP_BOX); - dfp5->color(FL_BACKGROUND_COLOR); - dfp5->selection_color(FL_INACTIVE_COLOR); - dfp5->labeltype(FL_NORMAL_LABEL); - dfp5->labelfont(1); - dfp5->labelsize(11); - dfp5->labelcolor(FL_FOREGROUND_COLOR); - dfp5->maximum(127); - dfp5->callback((Fl_Callback*)cb_dfp5); - dfp5->align(Fl_Align(FL_ALIGN_BOTTOM)); - dfp5->when(FL_WHEN_CHANGED); - } // WidgetPDial* dfp5 - { dfp6 = new WidgetPDial(235, 40, 30, 30, "LfoD"); - dfp6->tooltip("LFO Depth"); - dfp6->box(FL_ROUND_UP_BOX); - dfp6->color(FL_BACKGROUND_COLOR); - dfp6->selection_color(FL_INACTIVE_COLOR); - dfp6->labeltype(FL_NORMAL_LABEL); - dfp6->labelfont(1); - dfp6->labelsize(11); - dfp6->labelcolor(FL_FOREGROUND_COLOR); - dfp6->maximum(127); - dfp6->callback((Fl_Callback*)cb_dfp6); - dfp6->align(Fl_Align(FL_ALIGN_BOTTOM)); - dfp6->when(FL_WHEN_CHANGED); - } // WidgetPDial* dfp6 - { dfp4 = new Fl_Choice(155, 50, 40, 15, "LFO type"); - dfp4->tooltip("LFO function"); - dfp4->down_box(FL_BORDER_BOX); - dfp4->labelfont(1); - dfp4->labelsize(10); - dfp4->textsize(8); - dfp4->callback((Fl_Callback*)cb_dfp4); - dfp4->align(Fl_Align(130)); - dfp4->menu(menu_dfp4); - } // Fl_Choice* dfp4 - { Fl_Button* o = new Fl_Button(115, 10, 55, 25, "Filter"); - o->box(FL_PLASTIC_THIN_UP_BOX); - o->callback((Fl_Callback*)cb_Filter); - } // Fl_Button* o - { Fl_Group* o = new Fl_Group(270, 40, 105, 45); - o->box(FL_BORDER_BOX); - o->color((Fl_Color)181); - { dfp7 = new WidgetPDial(275, 45, 25, 25, "A.S."); - dfp7->tooltip("Filter vs Amplitude"); - dfp7->box(FL_ROUND_UP_BOX); - dfp7->color(FL_BACKGROUND_COLOR); - dfp7->selection_color(FL_INACTIVE_COLOR); - dfp7->labeltype(FL_NORMAL_LABEL); - dfp7->labelfont(1); - dfp7->labelsize(11); - dfp7->labelcolor(FL_FOREGROUND_COLOR); - dfp7->maximum(127); - dfp7->callback((Fl_Callback*)cb_dfp7); - dfp7->align(Fl_Align(FL_ALIGN_BOTTOM)); - dfp7->when(FL_WHEN_CHANGED); - } // WidgetPDial* dfp7 - { dfp9 = new WidgetPDial(305, 45, 25, 25, "A.M"); - dfp9->tooltip("rate that amplitude changes the filter"); - dfp9->box(FL_ROUND_UP_BOX); - dfp9->color(FL_BACKGROUND_COLOR); - dfp9->selection_color(FL_INACTIVE_COLOR); - dfp9->labeltype(FL_NORMAL_LABEL); - dfp9->labelfont(1); - dfp9->labelsize(11); - dfp9->labelcolor(FL_FOREGROUND_COLOR); - dfp9->maximum(127); - dfp9->callback((Fl_Callback*)cb_dfp9); - dfp9->align(Fl_Align(FL_ALIGN_BOTTOM)); - dfp9->when(FL_WHEN_CHANGED); - } // WidgetPDial* dfp9 - { dfp8 = new Fl_Check_Button(345, 55, 15, 15, "A.Inv."); - dfp8->tooltip("enable for filter frequency to lower with higher input amplitude"); - dfp8->down_box(FL_DOWN_BOX); - dfp8->labelfont(1); - dfp8->labelsize(11); - dfp8->callback((Fl_Callback*)cb_dfp8); - dfp8->align(Fl_Align(FL_ALIGN_BOTTOM)); - } // Fl_Check_Button* dfp8 - o->end(); - } // Fl_Group* o - effdynamicfilterwindow->end(); - } // Fl_Group* effdynamicfilterwindow - return effdynamicfilterwindow; -} - -Fl_Double_Window* EffUI::make_filter_window() { - { filterwindow = new Fl_Double_Window(290, 110, "Filter Parameters for DynFilter Eff."); - filterwindow->user_data((void*)(this)); - { FilterUI* o = new FilterUI(5, 5, 275, 75, "DynFilter effect - Filter"); - o->box(FL_FLAT_BOX); - o->color(FL_LIGHT1); - o->selection_color(FL_BACKGROUND_COLOR); - o->labeltype(FL_NORMAL_LABEL); - o->labelfont(0); - o->labelsize(14); - o->labelcolor(FL_FOREGROUND_COLOR); - o->align(Fl_Align(FL_ALIGN_WRAP|FL_ALIGN_INSIDE)); - o->when(FL_WHEN_RELEASE); - o->init(eff->filterpars,NULL,NULL); - o->use_for_dynamic_filter(); - o->end(); - } // FilterUI* o - { Fl_Button* o = new Fl_Button(105, 85, 70, 20, "Close"); - o->box(FL_THIN_UP_BOX); - o->callback((Fl_Callback*)cb_Close); - } // Fl_Button* o - filterwindow->end(); - } // Fl_Double_Window* filterwindow - return filterwindow; -} - -void EffUI::init(EffectMgr *eff_) { - eff=eff_; - - make_null_window(); - make_reverb_window(); - make_echo_window(); - make_chorus_window(); - make_phaser_window(); - make_alienwah_window(); - make_distorsion_window(); - make_eq_window(); - make_dynamicfilter_window(); - - int px=this->parent()->x(); - int py=this->parent()->y(); - - effnullwindow->position(px,py); - effreverbwindow->position(px,py); - effechowindow->position(px,py); - effchoruswindow->position(px,py); - effphaserwindow->position(px,py); - effalienwahwindow->position(px,py); - effdistorsionwindow->position(px,py); - effeqwindow->position(px,py); - effdynamicfilterwindow->position(px,py); - - refresh(eff); -} - -void EffUI::refresh(EffectMgr *eff_) { - eff=eff_; - this->hide(); - - effnullwindow->hide(); - effreverbwindow->hide(); - effechowindow->hide(); - effchoruswindow->hide(); - effphaserwindow->hide(); - effalienwahwindow->hide(); - effdistorsionwindow->hide(); - effeqwindow->hide(); - effdynamicfilterwindow->hide(); - - eqband=0; - - if (filterwindow!=NULL){ - filterwindow->hide(); - delete(filterwindow); - filterwindow=NULL; - }; - - switch(eff->geteffect()){ - case 1: - revp->value(eff->getpreset()); - revp0->value(eff->geteffectpar(0));if (eff->insertion!=0) revp0->label("D/W"); - revp1->value(eff->geteffectpar(1)); - revp2->value(eff->geteffectpar(2)); - revp3->value(eff->geteffectpar(3)); - revp4->value(eff->geteffectpar(4)); - //revp5->value(eff->geteffectpar(5)); - revp6->value(eff->geteffectpar(6)); - revp7->value(eff->geteffectpar(7)); - revp8->value(eff->geteffectpar(8)); - revp9->value(eff->geteffectpar(9)); - revp10->value(eff->geteffectpar(10)); - revp11->value(eff->geteffectpar(11)); - revp12->value(eff->geteffectpar(12)); - - effreverbwindow->show(); - break; - case 2: - echop->value(eff->getpreset()); - echop0->value(eff->geteffectpar(0));if (eff->insertion!=0) echop0->label("D/W"); - echop1->value(eff->geteffectpar(1)); - echop2->value(eff->geteffectpar(2)); - echop3->value(eff->geteffectpar(3)); - echop4->value(eff->geteffectpar(4)); - echop5->value(eff->geteffectpar(5)); - echop6->value(eff->geteffectpar(6)); - effechowindow->show(); - break; - case 3: - chorusp->value(eff->getpreset()); - chorusp0->value(eff->geteffectpar(0));if (eff->insertion!=0) chorusp0->label("D/W"); - chorusp1->value(eff->geteffectpar(1)); - chorusp2->value(eff->geteffectpar(2)); - chorusp3->value(eff->geteffectpar(3)); - chorusp4->value(eff->geteffectpar(4)); - chorusp5->value(eff->geteffectpar(5)); - chorusp6->value(eff->geteffectpar(6)); - chorusp7->value(eff->geteffectpar(7)); - chorusp8->value(eff->geteffectpar(8)); - chorusp9->value(eff->geteffectpar(9)); - chorusp11->value(eff->geteffectpar(11)); - effchoruswindow->show(); - break; - case 4: - phaserp->value(eff->getpreset()); - phaserp0->value(eff->geteffectpar(0));if (eff->insertion!=0) phaserp0->label("D/W"); - phaserp1->value(eff->geteffectpar(1)); - phaserp2->value(eff->geteffectpar(2)); - phaserp3->value(eff->geteffectpar(3)); - phaserp4->value(eff->geteffectpar(4)); - phaserp5->value(eff->geteffectpar(5)); - phaserp6->value(eff->geteffectpar(6)); - phaserp7->value(eff->geteffectpar(7)); - phaserp8->value(eff->geteffectpar(8)); - phaserp9->value(eff->geteffectpar(9)); - phaserp10->value(eff->geteffectpar(10)); - phaserp11->value(eff->geteffectpar(11)); - phaserp12->value(eff->geteffectpar(12)); - phaserp13->value(eff->geteffectpar(13)); - phaserp14->value(eff->geteffectpar(14)); - effphaserwindow->show(); - break; - case 5: - awp->value(eff->getpreset()); - awp0->value(eff->geteffectpar(0));if (eff->insertion!=0) awp0->label("D/W"); - awp1->value(eff->geteffectpar(1)); - awp2->value(eff->geteffectpar(2)); - awp3->value(eff->geteffectpar(3)); - awp4->value(eff->geteffectpar(4)); - awp5->value(eff->geteffectpar(5)); - awp6->value(eff->geteffectpar(6)); - awp7->value(eff->geteffectpar(7)); - awp8->value(eff->geteffectpar(8)); - awp9->value(eff->geteffectpar(9)); - awp10->value(eff->geteffectpar(10)); - - effalienwahwindow->show(); - break; - case 6: - distp->value(eff->getpreset()); - distp0->value(eff->geteffectpar(0));if (eff->insertion!=0) distp0->label("D/W"); - distp1->value(eff->geteffectpar(1)); - distp2->value(eff->geteffectpar(2)); - distp3->value(eff->geteffectpar(3)); - distp4->value(eff->geteffectpar(4)); - distp5->value(eff->geteffectpar(5)); - distp6->value(eff->geteffectpar(6)); - distp7->value(eff->geteffectpar(7)); - distp8->value(eff->geteffectpar(8)); - distp9->value(eff->geteffectpar(9)); - distp10->value(eff->geteffectpar(10)); - effdistorsionwindow->show(); - break; - case 7:eqband=0; - eqp0->value(eff->geteffectpar(0)); - bandcounter->value(eqband); - bandcounter->do_callback(); - typechoice->value(eff->geteffectpar(10)); - eqgraph->redraw(); - freqdial->value(eff->geteffectpar(11)); - gaindial->value(eff->geteffectpar(12)); - if (eff->geteffectpar(10)<6) gaindial->deactivate(); - qdial->value(eff->geteffectpar(13)); - stagescounter->value(eff->geteffectpar(14)); - eqgraph->init(eff); - effeqwindow->show(); - break; - case 8:make_filter_window(); - dfp->value(eff->getpreset()); - dfp0->value(eff->geteffectpar(0));if (eff->insertion!=0) dfp0->label("D/W"); - dfp1->value(eff->geteffectpar(1)); - dfp2->value(eff->geteffectpar(2)); - dfp3->value(eff->geteffectpar(3)); - dfp4->value(eff->geteffectpar(4)); - dfp5->value(eff->geteffectpar(5)); - dfp6->value(eff->geteffectpar(6)); - dfp7->value(eff->geteffectpar(7)); - dfp8->value(eff->geteffectpar(8)); - dfp9->value(eff->geteffectpar(9)); - - - effdynamicfilterwindow->show(); - break; - default:effnullwindow->show(); - break; - }; - - this->show(); -} - -void EffUI::refresh() { - refresh(eff); -} - -void SimpleEffUI::cb_revp5_i(Fl_Choice* o, void*) { - eff->changepreset((int)o->value()); - -refresh(eff); -} -void SimpleEffUI::cb_revp5(Fl_Choice* o, void* v) { - ((SimpleEffUI*)(o->parent()->user_data()))->cb_revp5_i(o,v); -} - -Fl_Menu_Item SimpleEffUI::menu_revp1[] = { - {"Cathedral 1", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 7}, - {"Cathedral 2", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 7}, - {"Cathedral 3", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 7}, - {"Hall 1", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 7}, - {"Hall 2", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 7}, - {"Room 1", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 7}, - {"Room 2", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 7}, - {"Basement", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 7}, - {"Tunnel", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 7}, - {"Echoed 1", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 7}, - {"Echoed 2", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 7}, - {"Very Long 1", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 7}, - {"Very Long 2", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 7}, - {0,0,0,0,0,0,0,0,0} -}; - -void SimpleEffUI::cb_revp01_i(WidgetPDial* o, void*) { - eff->seteffectpar(0,(int) o->value()); -} -void SimpleEffUI::cb_revp01(WidgetPDial* o, void* v) { - ((SimpleEffUI*)(o->parent()->user_data()))->cb_revp01_i(o,v); -} - -void SimpleEffUI::cb_revp21_i(WidgetPDial* o, void*) { - eff->seteffectpar(2,(int) o->value()); -} -void SimpleEffUI::cb_revp21(WidgetPDial* o, void* v) { - ((SimpleEffUI*)(o->parent()->user_data()))->cb_revp21_i(o,v); -} - -void SimpleEffUI::cb_revp31_i(WidgetPDial* o, void*) { - eff->seteffectpar(3,(int) o->value()); -} -void SimpleEffUI::cb_revp31(WidgetPDial* o, void* v) { - ((SimpleEffUI*)(o->parent()->user_data()))->cb_revp31_i(o,v); -} - -void SimpleEffUI::cb_revp91_i(WidgetPDial* o, void*) { - eff->seteffectpar(9,(int) o->value()); -} -void SimpleEffUI::cb_revp91(WidgetPDial* o, void* v) { - ((SimpleEffUI*)(o->parent()->user_data()))->cb_revp91_i(o,v); -} - -void SimpleEffUI::cb_echop7_i(Fl_Choice* o, void*) { - eff->changepreset((int)o->value()); -refresh(eff); -} -void SimpleEffUI::cb_echop7(Fl_Choice* o, void* v) { - ((SimpleEffUI*)(o->parent()->user_data()))->cb_echop7_i(o,v); -} - -Fl_Menu_Item SimpleEffUI::menu_echop1[] = { - {"Echo 1", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 7}, - {"Echo 2", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 7}, - {"Echo 3", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 7}, - {"Simple Echo", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 7}, - {"Canyon", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 7}, - {"Panning Echo 1", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 7}, - {"Panning Echo 2", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 7}, - {"Panning Echo 3", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 7}, - {"Feedback Echo", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 7}, - {0,0,0,0,0,0,0,0,0} -}; - -void SimpleEffUI::cb_echop01_i(WidgetPDial* o, void*) { - eff->seteffectpar(0,(int) o->value()); -} -void SimpleEffUI::cb_echop01(WidgetPDial* o, void* v) { - ((SimpleEffUI*)(o->parent()->user_data()))->cb_echop01_i(o,v); -} - -void SimpleEffUI::cb_echop21_i(WidgetPDial* o, void*) { - eff->seteffectpar(2,(int) o->value()); -} -void SimpleEffUI::cb_echop21(WidgetPDial* o, void* v) { - ((SimpleEffUI*)(o->parent()->user_data()))->cb_echop21_i(o,v); -} - -void SimpleEffUI::cb_echop51_i(WidgetPDial* o, void*) { - eff->seteffectpar(5,(int) o->value()); -} -void SimpleEffUI::cb_echop51(WidgetPDial* o, void* v) { - ((SimpleEffUI*)(o->parent()->user_data()))->cb_echop51_i(o,v); -} - -void SimpleEffUI::cb_choruspa_i(Fl_Choice* o, void*) { - eff->changepreset((int)o->value()); -refresh(eff); -} -void SimpleEffUI::cb_choruspa(Fl_Choice* o, void* v) { - ((SimpleEffUI*)(o->parent()->user_data()))->cb_choruspa_i(o,v); -} - -Fl_Menu_Item SimpleEffUI::menu_chorusp1[] = { - {"Chorus 1", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 7}, - {"Chorus 2", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 7}, - {"Chorus 3", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 7}, - {"Celeste 1", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 7}, - {"Celeste 2", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 7}, - {"Flange 1", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 7}, - {"Flange 2", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 7}, - {"Flange 3", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 7}, - {"Flange 4", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 7}, - {"Flange 5", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 7}, - {0,0,0,0,0,0,0,0,0} -}; - -void SimpleEffUI::cb_chorusp01_i(WidgetPDial* o, void*) { - eff->seteffectpar(0,(int) o->value()); -} -void SimpleEffUI::cb_chorusp01(WidgetPDial* o, void* v) { - ((SimpleEffUI*)(o->parent()->user_data()))->cb_chorusp01_i(o,v); -} - -void SimpleEffUI::cb_chorusp21_i(WidgetPDial* o, void*) { - eff->seteffectpar(2,(int) o->value()); -} -void SimpleEffUI::cb_chorusp21(WidgetPDial* o, void* v) { - ((SimpleEffUI*)(o->parent()->user_data()))->cb_chorusp21_i(o,v); -} - -void SimpleEffUI::cb_chorusp61_i(WidgetPDial* o, void*) { - eff->seteffectpar(6,(int) o->value()); -} -void SimpleEffUI::cb_chorusp61(WidgetPDial* o, void* v) { - ((SimpleEffUI*)(o->parent()->user_data()))->cb_chorusp61_i(o,v); -} - -void SimpleEffUI::cb_chorusp71_i(WidgetPDial* o, void*) { - eff->seteffectpar(7,(int) o->value()); -} -void SimpleEffUI::cb_chorusp71(WidgetPDial* o, void* v) { - ((SimpleEffUI*)(o->parent()->user_data()))->cb_chorusp71_i(o,v); -} - -void SimpleEffUI::cb_chorusp81_i(WidgetPDial* o, void*) { - eff->seteffectpar(8,(int) o->value()); -} -void SimpleEffUI::cb_chorusp81(WidgetPDial* o, void* v) { - ((SimpleEffUI*)(o->parent()->user_data()))->cb_chorusp81_i(o,v); -} - -void SimpleEffUI::cb_Flange1_i(Fl_Check_Button* o, void*) { - eff->seteffectpar(10,(int) o->value()); -} -void SimpleEffUI::cb_Flange1(Fl_Check_Button* o, void* v) { - ((SimpleEffUI*)(o->parent()->user_data()))->cb_Flange1_i(o,v); -} - -void SimpleEffUI::cb_phaserpa_i(Fl_Choice* o, void*) { - eff->changepreset((int)o->value()); -refresh(eff); -} -void SimpleEffUI::cb_phaserpa(Fl_Choice* o, void* v) { - ((SimpleEffUI*)(o->parent()->user_data()))->cb_phaserpa_i(o,v); -} - -Fl_Menu_Item SimpleEffUI::menu_phaserp1[] = { - {"Phaser 1", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 7}, - {"Phaser 2", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 7}, - {"Phaser 3", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 7}, - {"Phaser 4", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 7}, - {"Phaser 5", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 7}, - {"Phaser 6", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 7}, - {0,0,0,0,0,0,0,0,0} -}; - -void SimpleEffUI::cb_phaserp01_i(WidgetPDial* o, void*) { - eff->seteffectpar(0,(int) o->value()); -} -void SimpleEffUI::cb_phaserp01(WidgetPDial* o, void* v) { - ((SimpleEffUI*)(o->parent()->user_data()))->cb_phaserp01_i(o,v); -} - -void SimpleEffUI::cb_phaserp21_i(WidgetPDial* o, void*) { - eff->seteffectpar(2,(int) o->value()); -} -void SimpleEffUI::cb_phaserp21(WidgetPDial* o, void* v) { - ((SimpleEffUI*)(o->parent()->user_data()))->cb_phaserp21_i(o,v); -} - -void SimpleEffUI::cb_phaserp51_i(WidgetPDial* o, void*) { - eff->seteffectpar(5,(int) o->value()); -} -void SimpleEffUI::cb_phaserp51(WidgetPDial* o, void* v) { - ((SimpleEffUI*)(o->parent()->user_data()))->cb_phaserp51_i(o,v); -} - -void SimpleEffUI::cb_phaserp61_i(WidgetPDial* o, void*) { - eff->seteffectpar(6,(int) o->value()); -} -void SimpleEffUI::cb_phaserp61(WidgetPDial* o, void* v) { - ((SimpleEffUI*)(o->parent()->user_data()))->cb_phaserp61_i(o,v); -} - -void SimpleEffUI::cb_phaserp71_i(WidgetPDial* o, void*) { - eff->seteffectpar(7,(int) o->value()); -} -void SimpleEffUI::cb_phaserp71(WidgetPDial* o, void* v) { - ((SimpleEffUI*)(o->parent()->user_data()))->cb_phaserp71_i(o,v); -} - -void SimpleEffUI::cb_phaserp81_i(Fl_Counter* o, void*) { - eff->seteffectpar(8,(int) o->value()); -} -void SimpleEffUI::cb_phaserp81(Fl_Counter* o, void* v) { - ((SimpleEffUI*)(o->parent()->user_data()))->cb_phaserp81_i(o,v); -} - -void SimpleEffUI::cb_awpa_i(Fl_Choice* o, void*) { - eff->changepreset((int)o->value()); -refresh(eff); -} -void SimpleEffUI::cb_awpa(Fl_Choice* o, void* v) { - ((SimpleEffUI*)(o->parent()->user_data()))->cb_awpa_i(o,v); -} - -Fl_Menu_Item SimpleEffUI::menu_awp1[] = { - {"Alienwah 1", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 7}, - {"Alienwah 2", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 7}, - {"Alienwah 3", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 7}, - {"Alienwah 4", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 7}, - {0,0,0,0,0,0,0,0,0} -}; - -void SimpleEffUI::cb_awp01_i(WidgetPDial* o, void*) { - eff->seteffectpar(0,(int) o->value()); -} -void SimpleEffUI::cb_awp01(WidgetPDial* o, void* v) { - ((SimpleEffUI*)(o->parent()->user_data()))->cb_awp01_i(o,v); -} - -void SimpleEffUI::cb_awp21_i(WidgetPDial* o, void*) { - eff->seteffectpar(2,(int) o->value()); -} -void SimpleEffUI::cb_awp21(WidgetPDial* o, void* v) { - ((SimpleEffUI*)(o->parent()->user_data()))->cb_awp21_i(o,v); -} - -void SimpleEffUI::cb_awp61_i(WidgetPDial* o, void*) { - eff->seteffectpar(6,(int) o->value()); -} -void SimpleEffUI::cb_awp61(WidgetPDial* o, void* v) { - ((SimpleEffUI*)(o->parent()->user_data()))->cb_awp61_i(o,v); -} - -void SimpleEffUI::cb_awp81_i(Fl_Counter* o, void*) { - eff->seteffectpar(8,(int) o->value()); -} -void SimpleEffUI::cb_awp81(Fl_Counter* o, void* v) { - ((SimpleEffUI*)(o->parent()->user_data()))->cb_awp81_i(o,v); -} - -void SimpleEffUI::cb_distpa_i(Fl_Choice* o, void*) { - eff->changepreset((int)o->value()); -refresh(eff); -} -void SimpleEffUI::cb_distpa(Fl_Choice* o, void* v) { - ((SimpleEffUI*)(o->parent()->user_data()))->cb_distpa_i(o,v); -} - -Fl_Menu_Item SimpleEffUI::menu_distp1[] = { - {"Overdrive 1", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 7}, - {"Overdrive 2", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 7}, - {"A. Exciter 1", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 7}, - {"A. Exciter 2", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 7}, - {"Guitar Amp", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 7}, - {"Quantisize", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 7}, - {0,0,0,0,0,0,0,0,0} -}; - -void SimpleEffUI::cb_distp01_i(WidgetPDial* o, void*) { - eff->seteffectpar(0,(int) o->value()); -} -void SimpleEffUI::cb_distp01(WidgetPDial* o, void* v) { - ((SimpleEffUI*)(o->parent()->user_data()))->cb_distp01_i(o,v); -} - -void SimpleEffUI::cb_distp31_i(WidgetPDial* o, void*) { - eff->seteffectpar(3,(int) o->value()); -} -void SimpleEffUI::cb_distp31(WidgetPDial* o, void* v) { - ((SimpleEffUI*)(o->parent()->user_data()))->cb_distp31_i(o,v); -} - -void SimpleEffUI::cb_distp41_i(WidgetPDial* o, void*) { - eff->seteffectpar(4,(int) o->value()); -} -void SimpleEffUI::cb_distp41(WidgetPDial* o, void* v) { - ((SimpleEffUI*)(o->parent()->user_data()))->cb_distp41_i(o,v); -} - -void SimpleEffUI::cb_distp71_i(WidgetPDial* o, void*) { - eff->seteffectpar(7,(int) o->value()); -} -void SimpleEffUI::cb_distp71(WidgetPDial* o, void* v) { - ((SimpleEffUI*)(o->parent()->user_data()))->cb_distp71_i(o,v); -} - -void SimpleEffUI::cb_distp51_i(Fl_Choice* o, void*) { - eff->seteffectpar(5,(int) o->value()); -} -void SimpleEffUI::cb_distp51(Fl_Choice* o, void* v) { - ((SimpleEffUI*)(o->parent()->user_data()))->cb_distp51_i(o,v); -} - -Fl_Menu_Item SimpleEffUI::menu_distp51[] = { - {"Atan", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {"Asym1", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {"Pow", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {"Sine", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {"Qnts", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {"Zigzg", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {"Lmt", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {"LmtU", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {"LmtL", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {"ILmt", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {"Clip", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {"Asym2", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {"Pow2", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {"Sgm", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {0,0,0,0,0,0,0,0,0} -}; - -void SimpleEffUI::cb_bandcounter1_i(Fl_Counter* o, void*) { - eqband=(int) o->value(); -int npb=eqband*5+10; - -int type=eff->geteffectpar(npb); -typechoice->value(type); - -if (type>6) gaindial->activate(); - else gaindial->deactivate(); - -if (type==0) bandgroup->deactivate(); -else bandgroup->activate(); - -int freq=eff->geteffectpar(npb+1); -freqdial->value(freq); - -int gain=eff->geteffectpar(npb+2); -gaindial->value(gain); - -int q=eff->geteffectpar(npb+3); -qdial->value(q); - -int dbl=eff->geteffectpar(npb+4); -stagescounter->value(dbl); -} -void SimpleEffUI::cb_bandcounter1(Fl_Counter* o, void* v) { - ((SimpleEffUI*)(o->parent()->user_data()))->cb_bandcounter1_i(o,v); -} - -void SimpleEffUI::cb_freqdial1_i(WidgetPDial* o, void*) { - int np=eqband*5+11; -eff->seteffectpar(np,(int) o->value()); -eqgraph->redraw(); -} -void SimpleEffUI::cb_freqdial1(WidgetPDial* o, void* v) { - ((SimpleEffUI*)(o->parent()->parent()->user_data()))->cb_freqdial1_i(o,v); -} - -void SimpleEffUI::cb_gaindial1_i(WidgetPDial* o, void*) { - int np=eqband*5+12; -eff->seteffectpar(np,(int) o->value()); -eqgraph->redraw(); -} -void SimpleEffUI::cb_gaindial1(WidgetPDial* o, void* v) { - ((SimpleEffUI*)(o->parent()->parent()->user_data()))->cb_gaindial1_i(o,v); -} - -void SimpleEffUI::cb_qdial1_i(WidgetPDial* o, void*) { - int np=eqband*5+13; -eff->seteffectpar(np,(int) o->value()); -eqgraph->redraw(); -} -void SimpleEffUI::cb_qdial1(WidgetPDial* o, void* v) { - ((SimpleEffUI*)(o->parent()->parent()->user_data()))->cb_qdial1_i(o,v); -} - -void SimpleEffUI::cb_stagescounter1_i(Fl_Counter* o, void*) { - int np=eqband*5+14; -eff->seteffectpar(np,(int) o->value()); -eqgraph->redraw(); -} -void SimpleEffUI::cb_stagescounter1(Fl_Counter* o, void* v) { - ((SimpleEffUI*)(o->parent()->parent()->user_data()))->cb_stagescounter1_i(o,v); -} - -void SimpleEffUI::cb_typechoice1_i(Fl_Choice* o, void*) { - int np=eqband*5+10; -eff->seteffectpar(np,(int) o->value()); -bandcounter->do_callback(); -eqgraph->redraw(); -} -void SimpleEffUI::cb_typechoice1(Fl_Choice* o, void* v) { - ((SimpleEffUI*)(o->parent()->user_data()))->cb_typechoice1_i(o,v); -} - -Fl_Menu_Item SimpleEffUI::menu_typechoice1[] = { - {"OFF", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {"Lp1", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {"Hp1", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {"Lp2", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {"Hp2", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {"Bp2", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {"N2", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {"Pk", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {"LSh", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {"HSh", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {0,0,0,0,0,0,0,0,0} -}; - -void SimpleEffUI::cb_dfpa_i(Fl_Choice* o, void*) { - eff->changepreset((int)o->value()); -refresh(eff); -} -void SimpleEffUI::cb_dfpa(Fl_Choice* o, void* v) { - ((SimpleEffUI*)(o->parent()->user_data()))->cb_dfpa_i(o,v); -} - -Fl_Menu_Item SimpleEffUI::menu_dfp1[] = { - {"WahWah", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 7}, - {"AutoWah", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 7}, - {"Sweep", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 7}, - {"VocalMorph1", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 7}, - {"VocalMorph2", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 7}, - {0,0,0,0,0,0,0,0,0} -}; - -void SimpleEffUI::cb_dfp01_i(WidgetPDial* o, void*) { - eff->seteffectpar(0,(int) o->value()); -} -void SimpleEffUI::cb_dfp01(WidgetPDial* o, void* v) { - ((SimpleEffUI*)(o->parent()->user_data()))->cb_dfp01_i(o,v); -} - -void SimpleEffUI::cb_dfp21_i(WidgetPDial* o, void*) { - eff->seteffectpar(2,(int) o->value()); -} -void SimpleEffUI::cb_dfp21(WidgetPDial* o, void* v) { - ((SimpleEffUI*)(o->parent()->user_data()))->cb_dfp21_i(o,v); -} - -void SimpleEffUI::cb_dfp61_i(WidgetPDial* o, void*) { - eff->seteffectpar(6,(int) o->value()); -} -void SimpleEffUI::cb_dfp61(WidgetPDial* o, void* v) { - ((SimpleEffUI*)(o->parent()->user_data()))->cb_dfp61_i(o,v); -} - -void SimpleEffUI::cb_dfp71_i(WidgetPDial* o, void*) { - eff->seteffectpar(7,(int) o->value()); -} -void SimpleEffUI::cb_dfp71(WidgetPDial* o, void* v) { - ((SimpleEffUI*)(o->parent()->parent()->user_data()))->cb_dfp71_i(o,v); -} - -void SimpleEffUI::cb_dfp91_i(WidgetPDial* o, void*) { - eff->seteffectpar(9,(int) o->value()); -} -void SimpleEffUI::cb_dfp91(WidgetPDial* o, void* v) { - ((SimpleEffUI*)(o->parent()->parent()->user_data()))->cb_dfp91_i(o,v); -} - -SimpleEffUI::SimpleEffUI(int x,int y, int w, int h, const char *label):Fl_Group(x,y,w,h,label) { - eff=NULL; -} - -SimpleEffUI::~SimpleEffUI() { - effnullwindow->hide();//delete (effnullwindow); - effreverbwindow->hide();//delete (effreverbwindow); - effechowindow->hide();//delete (effechowindow); - effchoruswindow->hide();//delete (effchoruswindow); - effphaserwindow->hide();//delete (effphaserwindow); - effalienwahwindow->hide();//delete (effalienwahwindow); - effdistorsionwindow->hide();//delete (effdistorsionwindow); - effeqwindow->hide();//delete (effeqwindow); - effdynamicfilterwindow->hide();//delete (effdynamicfilterwindow); -} - -Fl_Group* SimpleEffUI::make_null_window() { - { effnullwindow = new Fl_Group(0, 0, 230, 95); - effnullwindow->box(FL_PLASTIC_UP_BOX); - effnullwindow->color((Fl_Color)221); - effnullwindow->selection_color(FL_BACKGROUND_COLOR); - effnullwindow->labeltype(FL_NO_LABEL); - effnullwindow->labelfont(1); - effnullwindow->labelsize(14); - effnullwindow->labelcolor(FL_FOREGROUND_COLOR); - effnullwindow->user_data((void*)(this)); - effnullwindow->align(Fl_Align(FL_ALIGN_TOP)); - effnullwindow->when(FL_WHEN_RELEASE); - { Fl_Text_Display* o = new Fl_Text_Display(25, 35, 35, 20, "No Effect"); - o->box(FL_NO_BOX); - o->labeltype(FL_EMBOSSED_LABEL); - o->labelfont(1); - o->labelsize(22); - o->labelcolor((Fl_Color)43); - o->align(Fl_Align(FL_ALIGN_RIGHT)); - } // Fl_Text_Display* o - effnullwindow->end(); - } // Fl_Group* effnullwindow - return effnullwindow; -} - -Fl_Group* SimpleEffUI::make_reverb_window() { - { effreverbwindow = new Fl_Group(0, 0, 230, 95); - effreverbwindow->box(FL_PLASTIC_UP_BOX); - effreverbwindow->color((Fl_Color)221); - effreverbwindow->selection_color(FL_BACKGROUND_COLOR); - effreverbwindow->labeltype(FL_NO_LABEL); - effreverbwindow->labelfont(1); - effreverbwindow->labelsize(14); - effreverbwindow->labelcolor(FL_FOREGROUND_COLOR); - effreverbwindow->user_data((void*)(this)); - effreverbwindow->align(Fl_Align(FL_ALIGN_TOP)); - effreverbwindow->when(FL_WHEN_RELEASE); - { Fl_Text_Display* o = new Fl_Text_Display(115, 10, 20, 20, "Reverb "); - o->box(FL_NO_BOX); - o->labeltype(FL_EMBOSSED_LABEL); - o->labelfont(1); - o->labelsize(22); - o->align(Fl_Align(FL_ALIGN_RIGHT)); - } // Fl_Text_Display* o - { revp = new Fl_Choice(10, 15, 90, 15, "Preset"); - revp->down_box(FL_BORDER_BOX); - revp->color((Fl_Color)14); - revp->selection_color(FL_FOREGROUND_COLOR); - revp->labelfont(1); - revp->labelsize(10); - revp->textfont(1); - revp->textsize(10); - revp->textcolor(FL_BACKGROUND2_COLOR); - revp->callback((Fl_Callback*)cb_revp5); - revp->align(Fl_Align(FL_ALIGN_TOP_LEFT)); - revp->menu(menu_revp1); - } // Fl_Choice* revp - { revp0 = new WidgetPDial(10, 40, 30, 30, "Vol"); - revp0->tooltip("Effect Volume"); - revp0->box(FL_ROUND_UP_BOX); - revp0->color(FL_BACKGROUND_COLOR); - revp0->selection_color(FL_INACTIVE_COLOR); - revp0->labeltype(FL_NORMAL_LABEL); - revp0->labelfont(1); - revp0->labelsize(11); - revp0->labelcolor(FL_FOREGROUND_COLOR); - revp0->maximum(127); - revp0->callback((Fl_Callback*)cb_revp01); - revp0->align(Fl_Align(FL_ALIGN_BOTTOM)); - revp0->when(FL_WHEN_CHANGED); - } // WidgetPDial* revp0 - { revp2 = new WidgetPDial(45, 40, 30, 30, "Time"); - revp2->tooltip("Duration of Reverb"); - revp2->box(FL_ROUND_UP_BOX); - revp2->color(FL_BACKGROUND_COLOR); - revp2->selection_color(FL_INACTIVE_COLOR); - revp2->labeltype(FL_NORMAL_LABEL); - revp2->labelfont(1); - revp2->labelsize(11); - revp2->labelcolor(FL_FOREGROUND_COLOR); - revp2->maximum(127); - revp2->callback((Fl_Callback*)cb_revp21); - revp2->align(Fl_Align(FL_ALIGN_BOTTOM)); - revp2->when(FL_WHEN_CHANGED); - } // WidgetPDial* revp2 - { revp3 = new WidgetPDial(85, 40, 30, 30, "I.del"); - revp3->tooltip("Initial Delay"); - revp3->box(FL_ROUND_UP_BOX); - revp3->color(FL_BACKGROUND_COLOR); - revp3->selection_color(FL_INACTIVE_COLOR); - revp3->labeltype(FL_NORMAL_LABEL); - revp3->labelfont(1); - revp3->labelsize(11); - revp3->labelcolor(FL_FOREGROUND_COLOR); - revp3->maximum(127); - revp3->callback((Fl_Callback*)cb_revp31); - revp3->align(Fl_Align(FL_ALIGN_BOTTOM)); - revp3->when(FL_WHEN_RELEASE); - } // WidgetPDial* revp3 - { revp9 = new WidgetPDial(120, 40, 30, 30, "Damp"); - revp9->tooltip("Dampening"); - revp9->box(FL_ROUND_UP_BOX); - revp9->color(FL_BACKGROUND_COLOR); - revp9->selection_color(FL_INACTIVE_COLOR); - revp9->labeltype(FL_NORMAL_LABEL); - revp9->labelfont(1); - revp9->labelsize(11); - revp9->labelcolor(FL_FOREGROUND_COLOR); - revp9->minimum(64); - revp9->maximum(127); - revp9->step(1); - revp9->callback((Fl_Callback*)cb_revp91); - revp9->align(Fl_Align(FL_ALIGN_BOTTOM)); - revp9->when(FL_WHEN_CHANGED); - } // WidgetPDial* revp9 - effreverbwindow->end(); - } // Fl_Group* effreverbwindow - return effreverbwindow; -} - -Fl_Group* SimpleEffUI::make_echo_window() { - { effechowindow = new Fl_Group(0, 0, 230, 95); - effechowindow->box(FL_PLASTIC_UP_BOX); - effechowindow->color((Fl_Color)221); - effechowindow->selection_color(FL_BACKGROUND_COLOR); - effechowindow->labeltype(FL_NO_LABEL); - effechowindow->labelfont(1); - effechowindow->labelsize(14); - effechowindow->labelcolor(FL_FOREGROUND_COLOR); - effechowindow->user_data((void*)(this)); - effechowindow->align(Fl_Align(FL_ALIGN_TOP)); - effechowindow->when(FL_WHEN_RELEASE); - { echop = new Fl_Choice(11, 15, 95, 15, "Preset"); - echop->down_box(FL_BORDER_BOX); - echop->color((Fl_Color)14); - echop->selection_color(FL_FOREGROUND_COLOR); - echop->labelfont(1); - echop->labelsize(10); - echop->textfont(1); - echop->textsize(10); - echop->textcolor(FL_BACKGROUND2_COLOR); - echop->callback((Fl_Callback*)cb_echop7); - echop->align(Fl_Align(FL_ALIGN_TOP_LEFT)); - echop->menu(menu_echop1); - } // Fl_Choice* echop - { Fl_Text_Display* o = new Fl_Text_Display(145, 10, 10, 20, "Echo"); - o->box(FL_NO_BOX); - o->labeltype(FL_EMBOSSED_LABEL); - o->labelfont(1); - o->labelsize(22); - o->align(Fl_Align(FL_ALIGN_RIGHT)); - } // Fl_Text_Display* o - { echop0 = new WidgetPDial(10, 40, 30, 30, "Vol"); - echop0->tooltip("Effect Volume"); - echop0->box(FL_ROUND_UP_BOX); - echop0->color(FL_BACKGROUND_COLOR); - echop0->selection_color(FL_INACTIVE_COLOR); - echop0->labeltype(FL_NORMAL_LABEL); - echop0->labelfont(1); - echop0->labelsize(11); - echop0->labelcolor(FL_FOREGROUND_COLOR); - echop0->maximum(127); - echop0->callback((Fl_Callback*)cb_echop01); - echop0->align(Fl_Align(FL_ALIGN_BOTTOM)); - echop0->when(FL_WHEN_CHANGED); - } // WidgetPDial* echop0 - { echop2 = new WidgetPDial(45, 40, 30, 30, "Delay"); - echop2->box(FL_ROUND_UP_BOX); - echop2->color(FL_BACKGROUND_COLOR); - echop2->selection_color(FL_INACTIVE_COLOR); - echop2->labeltype(FL_NORMAL_LABEL); - echop2->labelfont(1); - echop2->labelsize(11); - echop2->labelcolor(FL_FOREGROUND_COLOR); - echop2->maximum(127); - echop2->callback((Fl_Callback*)cb_echop21); - echop2->align(Fl_Align(FL_ALIGN_BOTTOM)); - echop2->when(FL_WHEN_RELEASE); - } // WidgetPDial* echop2 - { echop5 = new WidgetPDial(80, 40, 30, 30, "Fb."); - echop5->tooltip("Feedback"); - echop5->box(FL_ROUND_UP_BOX); - echop5->color(FL_BACKGROUND_COLOR); - echop5->selection_color(FL_INACTIVE_COLOR); - echop5->labeltype(FL_NORMAL_LABEL); - echop5->labelfont(1); - echop5->labelsize(11); - echop5->labelcolor(FL_FOREGROUND_COLOR); - echop5->maximum(127); - echop5->callback((Fl_Callback*)cb_echop51); - echop5->align(Fl_Align(FL_ALIGN_BOTTOM)); - echop5->when(FL_WHEN_CHANGED); - } // WidgetPDial* echop5 - effechowindow->end(); - } // Fl_Group* effechowindow - return effechowindow; -} - -Fl_Group* SimpleEffUI::make_chorus_window() { - { effchoruswindow = new Fl_Group(0, 0, 230, 95); - effchoruswindow->box(FL_PLASTIC_UP_BOX); - effchoruswindow->color((Fl_Color)221); - effchoruswindow->selection_color(FL_BACKGROUND_COLOR); - effchoruswindow->labeltype(FL_NO_LABEL); - effchoruswindow->labelfont(1); - effchoruswindow->labelsize(14); - effchoruswindow->labelcolor(FL_FOREGROUND_COLOR); - effchoruswindow->user_data((void*)(this)); - effchoruswindow->align(Fl_Align(FL_ALIGN_TOP)); - effchoruswindow->when(FL_WHEN_RELEASE); - { chorusp = new Fl_Choice(10, 15, 90, 15, "Preset"); - chorusp->down_box(FL_BORDER_BOX); - chorusp->color((Fl_Color)14); - chorusp->selection_color(FL_FOREGROUND_COLOR); - chorusp->labelfont(1); - chorusp->labelsize(10); - chorusp->textfont(1); - chorusp->textsize(10); - chorusp->textcolor(FL_BACKGROUND2_COLOR); - chorusp->callback((Fl_Callback*)cb_choruspa); - chorusp->align(Fl_Align(FL_ALIGN_TOP_LEFT)); - chorusp->menu(menu_chorusp1); - } // Fl_Choice* chorusp - { Fl_Text_Display* o = new Fl_Text_Display(120, 10, 10, 20, "Chorus"); - o->box(FL_NO_BOX); - o->labeltype(FL_EMBOSSED_LABEL); - o->labelfont(1); - o->labelsize(22); - o->align(Fl_Align(FL_ALIGN_RIGHT)); - } // Fl_Text_Display* o - { chorusp0 = new WidgetPDial(10, 40, 30, 30, "Vol"); - chorusp0->tooltip("Effect Volume"); - chorusp0->box(FL_ROUND_UP_BOX); - chorusp0->color(FL_BACKGROUND_COLOR); - chorusp0->selection_color(FL_INACTIVE_COLOR); - chorusp0->labeltype(FL_NORMAL_LABEL); - chorusp0->labelfont(1); - chorusp0->labelsize(11); - chorusp0->labelcolor(FL_FOREGROUND_COLOR); - chorusp0->maximum(127); - chorusp0->callback((Fl_Callback*)cb_chorusp01); - chorusp0->align(Fl_Align(FL_ALIGN_BOTTOM)); - chorusp0->when(FL_WHEN_CHANGED); - } // WidgetPDial* chorusp0 - { chorusp2 = new WidgetPDial(45, 40, 30, 30, "Freq"); - chorusp2->tooltip("LFO Frequency"); - chorusp2->box(FL_ROUND_UP_BOX); - chorusp2->color(FL_BACKGROUND_COLOR); - chorusp2->selection_color(FL_INACTIVE_COLOR); - chorusp2->labeltype(FL_NORMAL_LABEL); - chorusp2->labelfont(1); - chorusp2->labelsize(11); - chorusp2->labelcolor(FL_FOREGROUND_COLOR); - chorusp2->maximum(127); - chorusp2->callback((Fl_Callback*)cb_chorusp21); - chorusp2->align(Fl_Align(FL_ALIGN_BOTTOM)); - chorusp2->when(FL_WHEN_CHANGED); - } // WidgetPDial* chorusp2 - { chorusp6 = new WidgetPDial(80, 40, 30, 30, "Dpth"); - chorusp6->tooltip("Depth"); - chorusp6->box(FL_ROUND_UP_BOX); - chorusp6->color(FL_BACKGROUND_COLOR); - chorusp6->selection_color(FL_INACTIVE_COLOR); - chorusp6->labeltype(FL_NORMAL_LABEL); - chorusp6->labelfont(1); - chorusp6->labelsize(11); - chorusp6->labelcolor(FL_FOREGROUND_COLOR); - chorusp6->maximum(127); - chorusp6->callback((Fl_Callback*)cb_chorusp61); - chorusp6->align(Fl_Align(FL_ALIGN_BOTTOM)); - chorusp6->when(FL_WHEN_CHANGED); - } // WidgetPDial* chorusp6 - { chorusp7 = new WidgetPDial(115, 40, 30, 30, "Delay"); - chorusp7->box(FL_ROUND_UP_BOX); - chorusp7->color(FL_BACKGROUND_COLOR); - chorusp7->selection_color(FL_INACTIVE_COLOR); - chorusp7->labeltype(FL_NORMAL_LABEL); - chorusp7->labelfont(1); - chorusp7->labelsize(11); - chorusp7->labelcolor(FL_FOREGROUND_COLOR); - chorusp7->maximum(127); - chorusp7->callback((Fl_Callback*)cb_chorusp71); - chorusp7->align(Fl_Align(FL_ALIGN_BOTTOM)); - chorusp7->when(FL_WHEN_CHANGED); - } // WidgetPDial* chorusp7 - { chorusp8 = new WidgetPDial(150, 40, 30, 30, "Fb"); - chorusp8->tooltip("Feedback"); - chorusp8->box(FL_ROUND_UP_BOX); - chorusp8->color(FL_BACKGROUND_COLOR); - chorusp8->selection_color(FL_INACTIVE_COLOR); - chorusp8->labeltype(FL_NORMAL_LABEL); - chorusp8->labelfont(1); - chorusp8->labelsize(11); - chorusp8->labelcolor(FL_FOREGROUND_COLOR); - chorusp8->maximum(127); - chorusp8->callback((Fl_Callback*)cb_chorusp81); - chorusp8->align(Fl_Align(FL_ALIGN_BOTTOM)); - chorusp8->when(FL_WHEN_CHANGED); - } // WidgetPDial* chorusp8 - { Fl_Check_Button* o = new Fl_Check_Button(120, 10, 55, 20, "Flange"); - o->box(FL_THIN_UP_BOX); - o->down_box(FL_DOWN_BOX); - o->color((Fl_Color)230); - o->labelfont(1); - o->labelsize(10); - o->callback((Fl_Callback*)cb_Flange1); - o->hide(); - o->deactivate(); - o->value(eff->geteffectpar(10)); - } // Fl_Check_Button* o - effchoruswindow->end(); - } // Fl_Group* effchoruswindow - return effchoruswindow; -} - -Fl_Group* SimpleEffUI::make_phaser_window() { - { effphaserwindow = new Fl_Group(0, 0, 230, 95); - effphaserwindow->box(FL_PLASTIC_UP_BOX); - effphaserwindow->color((Fl_Color)221); - effphaserwindow->selection_color(FL_BACKGROUND_COLOR); - effphaserwindow->labeltype(FL_NO_LABEL); - effphaserwindow->labelfont(1); - effphaserwindow->labelsize(14); - effphaserwindow->labelcolor(FL_FOREGROUND_COLOR); - effphaserwindow->user_data((void*)(this)); - effphaserwindow->align(Fl_Align(FL_ALIGN_TOP)); - effphaserwindow->when(FL_WHEN_RELEASE); - { phaserp = new Fl_Choice(10, 15, 90, 15, "Preset"); - phaserp->down_box(FL_BORDER_BOX); - phaserp->color((Fl_Color)14); - phaserp->selection_color(FL_FOREGROUND_COLOR); - phaserp->labelfont(1); - phaserp->labelsize(10); - phaserp->textfont(1); - phaserp->textsize(10); - phaserp->textcolor(FL_BACKGROUND2_COLOR); - phaserp->callback((Fl_Callback*)cb_phaserpa); - phaserp->align(Fl_Align(FL_ALIGN_TOP_LEFT)); - phaserp->menu(menu_phaserp1); - } // Fl_Choice* phaserp - { Fl_Text_Display* o = new Fl_Text_Display(125, 10, 10, 20, "Phaser"); - o->box(FL_NO_BOX); - o->labeltype(FL_EMBOSSED_LABEL); - o->labelfont(1); - o->labelsize(22); - o->align(Fl_Align(FL_ALIGN_RIGHT)); - } // Fl_Text_Display* o - { phaserp0 = new WidgetPDial(10, 40, 30, 30, "Vol"); - phaserp0->tooltip("Effect Volume"); - phaserp0->box(FL_ROUND_UP_BOX); - phaserp0->color(FL_BACKGROUND_COLOR); - phaserp0->selection_color(FL_INACTIVE_COLOR); - phaserp0->labeltype(FL_NORMAL_LABEL); - phaserp0->labelfont(1); - phaserp0->labelsize(11); - phaserp0->labelcolor(FL_FOREGROUND_COLOR); - phaserp0->maximum(127); - phaserp0->callback((Fl_Callback*)cb_phaserp01); - phaserp0->align(Fl_Align(FL_ALIGN_BOTTOM)); - phaserp0->when(FL_WHEN_CHANGED); - } // WidgetPDial* phaserp0 - { phaserp2 = new WidgetPDial(45, 40, 30, 30, "Freq"); - phaserp2->tooltip("LFO frequency"); - phaserp2->box(FL_ROUND_UP_BOX); - phaserp2->color(FL_BACKGROUND_COLOR); - phaserp2->selection_color(FL_INACTIVE_COLOR); - phaserp2->labeltype(FL_NORMAL_LABEL); - phaserp2->labelfont(1); - phaserp2->labelsize(11); - phaserp2->labelcolor(FL_FOREGROUND_COLOR); - phaserp2->maximum(127); - phaserp2->callback((Fl_Callback*)cb_phaserp21); - phaserp2->align(Fl_Align(FL_ALIGN_BOTTOM)); - phaserp2->when(FL_WHEN_CHANGED); - } // WidgetPDial* phaserp2 - { phaserp5 = new WidgetPDial(80, 40, 30, 30, "St.df"); - phaserp5->tooltip("Left/Right Channel Phase Shift"); - phaserp5->box(FL_ROUND_UP_BOX); - phaserp5->color(FL_BACKGROUND_COLOR); - phaserp5->selection_color(FL_INACTIVE_COLOR); - phaserp5->labeltype(FL_NORMAL_LABEL); - phaserp5->labelfont(1); - phaserp5->labelsize(11); - phaserp5->labelcolor(FL_FOREGROUND_COLOR); - phaserp5->maximum(127); - phaserp5->callback((Fl_Callback*)cb_phaserp51); - phaserp5->align(Fl_Align(FL_ALIGN_BOTTOM)); - phaserp5->when(FL_WHEN_CHANGED); - } // WidgetPDial* phaserp5 - { phaserp6 = new WidgetPDial(115, 40, 30, 30, "Dpth"); - phaserp6->tooltip("Depth"); - phaserp6->box(FL_ROUND_UP_BOX); - phaserp6->color(FL_BACKGROUND_COLOR); - phaserp6->selection_color(FL_INACTIVE_COLOR); - phaserp6->labeltype(FL_NORMAL_LABEL); - phaserp6->labelfont(1); - phaserp6->labelsize(11); - phaserp6->labelcolor(FL_FOREGROUND_COLOR); - phaserp6->maximum(127); - phaserp6->callback((Fl_Callback*)cb_phaserp61); - phaserp6->align(Fl_Align(FL_ALIGN_BOTTOM)); - phaserp6->when(FL_WHEN_CHANGED); - } // WidgetPDial* phaserp6 - { phaserp7 = new WidgetPDial(150, 40, 30, 30, "Fb"); - phaserp7->tooltip("Feedback"); - phaserp7->box(FL_ROUND_UP_BOX); - phaserp7->color(FL_BACKGROUND_COLOR); - phaserp7->selection_color(FL_INACTIVE_COLOR); - phaserp7->labeltype(FL_NORMAL_LABEL); - phaserp7->labelfont(1); - phaserp7->labelsize(11); - phaserp7->labelcolor(FL_FOREGROUND_COLOR); - phaserp7->maximum(127); - phaserp7->callback((Fl_Callback*)cb_phaserp71); - phaserp7->align(Fl_Align(FL_ALIGN_BOTTOM)); - phaserp7->when(FL_WHEN_CHANGED); - } // WidgetPDial* phaserp7 - { Fl_Counter* o = phaserp8 = new Fl_Counter(185, 55, 35, 15, "Stages"); - phaserp8->type(1); - phaserp8->labelfont(1); - phaserp8->labelsize(11); - phaserp8->minimum(0); - phaserp8->maximum(127); - phaserp8->step(1); - phaserp8->callback((Fl_Callback*)cb_phaserp81); - o->range(1,MAX_PHASER_STAGES); - } // Fl_Counter* phaserp8 - effphaserwindow->end(); - } // Fl_Group* effphaserwindow - return effphaserwindow; -} - -Fl_Group* SimpleEffUI::make_alienwah_window() { - { effalienwahwindow = new Fl_Group(0, 0, 230, 95); - effalienwahwindow->box(FL_PLASTIC_UP_BOX); - effalienwahwindow->color((Fl_Color)221); - effalienwahwindow->selection_color(FL_BACKGROUND_COLOR); - effalienwahwindow->labeltype(FL_NO_LABEL); - effalienwahwindow->labelfont(1); - effalienwahwindow->labelsize(14); - effalienwahwindow->labelcolor(FL_FOREGROUND_COLOR); - effalienwahwindow->user_data((void*)(this)); - effalienwahwindow->align(Fl_Align(FL_ALIGN_TOP)); - effalienwahwindow->when(FL_WHEN_RELEASE); - { awp = new Fl_Choice(10, 15, 90, 15, "Preset"); - awp->down_box(FL_BORDER_BOX); - awp->color((Fl_Color)14); - awp->selection_color(FL_FOREGROUND_COLOR); - awp->labelfont(1); - awp->labelsize(10); - awp->textfont(1); - awp->textsize(10); - awp->textcolor(FL_BACKGROUND2_COLOR); - awp->callback((Fl_Callback*)cb_awpa); - awp->align(Fl_Align(FL_ALIGN_TOP_LEFT)); - awp->menu(menu_awp1); - } // Fl_Choice* awp - { Fl_Text_Display* o = new Fl_Text_Display(100, 10, 10, 20, "AlienWah"); - o->box(FL_NO_BOX); - o->labeltype(FL_EMBOSSED_LABEL); - o->labelfont(1); - o->labelsize(22); - o->align(Fl_Align(FL_ALIGN_RIGHT)); - } // Fl_Text_Display* o - { awp0 = new WidgetPDial(10, 40, 30, 30, "Vol"); - awp0->tooltip("Effect Volume"); - awp0->box(FL_ROUND_UP_BOX); - awp0->color(FL_BACKGROUND_COLOR); - awp0->selection_color(FL_INACTIVE_COLOR); - awp0->labeltype(FL_NORMAL_LABEL); - awp0->labelfont(1); - awp0->labelsize(11); - awp0->labelcolor(FL_FOREGROUND_COLOR); - awp0->maximum(127); - awp0->callback((Fl_Callback*)cb_awp01); - awp0->align(Fl_Align(FL_ALIGN_BOTTOM)); - awp0->when(FL_WHEN_CHANGED); - } // WidgetPDial* awp0 - { awp2 = new WidgetPDial(45, 40, 30, 30, "Freq"); - awp2->tooltip("LFO frequency"); - awp2->box(FL_ROUND_UP_BOX); - awp2->color(FL_BACKGROUND_COLOR); - awp2->selection_color(FL_INACTIVE_COLOR); - awp2->labeltype(FL_NORMAL_LABEL); - awp2->labelfont(1); - awp2->labelsize(11); - awp2->labelcolor(FL_FOREGROUND_COLOR); - awp2->maximum(127); - awp2->callback((Fl_Callback*)cb_awp21); - awp2->align(Fl_Align(FL_ALIGN_BOTTOM)); - awp2->when(FL_WHEN_CHANGED); - } // WidgetPDial* awp2 - { awp6 = new WidgetPDial(85, 40, 30, 30, "Dpth"); - awp6->tooltip("Depth"); - awp6->box(FL_ROUND_UP_BOX); - awp6->color(FL_BACKGROUND_COLOR); - awp6->selection_color(FL_INACTIVE_COLOR); - awp6->labeltype(FL_NORMAL_LABEL); - awp6->labelfont(1); - awp6->labelsize(11); - awp6->labelcolor(FL_FOREGROUND_COLOR); - awp6->maximum(127); - awp6->callback((Fl_Callback*)cb_awp61); - awp6->align(Fl_Align(FL_ALIGN_BOTTOM)); - awp6->when(FL_WHEN_CHANGED); - } // WidgetPDial* awp6 - { Fl_Counter* o = awp8 = new Fl_Counter(125, 55, 35, 15, "Delay"); - awp8->type(1); - awp8->labelfont(1); - awp8->labelsize(11); - awp8->minimum(0); - awp8->maximum(127); - awp8->step(1); - awp8->callback((Fl_Callback*)cb_awp81); - o->range(1,MAX_ALIENWAH_DELAY); - } // Fl_Counter* awp8 - effalienwahwindow->end(); - } // Fl_Group* effalienwahwindow - return effalienwahwindow; -} - -Fl_Group* SimpleEffUI::make_distorsion_window() { - { effdistorsionwindow = new Fl_Group(0, 0, 230, 95); - effdistorsionwindow->box(FL_PLASTIC_UP_BOX); - effdistorsionwindow->color((Fl_Color)221); - effdistorsionwindow->selection_color(FL_BACKGROUND_COLOR); - effdistorsionwindow->labeltype(FL_NO_LABEL); - effdistorsionwindow->labelfont(1); - effdistorsionwindow->labelsize(14); - effdistorsionwindow->labelcolor(FL_FOREGROUND_COLOR); - effdistorsionwindow->user_data((void*)(this)); - effdistorsionwindow->align(Fl_Align(FL_ALIGN_TOP)); - effdistorsionwindow->when(FL_WHEN_RELEASE); - { distp = new Fl_Choice(11, 15, 95, 15, "Preset"); - distp->down_box(FL_BORDER_BOX); - distp->color((Fl_Color)14); - distp->selection_color(FL_FOREGROUND_COLOR); - distp->labelfont(1); - distp->labelsize(10); - distp->textfont(1); - distp->textsize(10); - distp->textcolor(FL_BACKGROUND2_COLOR); - distp->callback((Fl_Callback*)cb_distpa); - distp->align(Fl_Align(FL_ALIGN_TOP_LEFT)); - distp->menu(menu_distp1); - } // Fl_Choice* distp - { Fl_Text_Display* o = new Fl_Text_Display(110, 10, 10, 20, "Distortion"); - o->box(FL_NO_BOX); - o->labeltype(FL_EMBOSSED_LABEL); - o->labelfont(1); - o->labelsize(16); - o->align(Fl_Align(FL_ALIGN_RIGHT)); - } // Fl_Text_Display* o - { distp0 = new WidgetPDial(10, 40, 30, 30, "Vol"); - distp0->tooltip("Effect Volume"); - distp0->box(FL_ROUND_UP_BOX); - distp0->color(FL_BACKGROUND_COLOR); - distp0->selection_color(FL_INACTIVE_COLOR); - distp0->labeltype(FL_NORMAL_LABEL); - distp0->labelfont(1); - distp0->labelsize(11); - distp0->labelcolor(FL_FOREGROUND_COLOR); - distp0->maximum(127); - distp0->callback((Fl_Callback*)cb_distp01); - distp0->align(Fl_Align(FL_ALIGN_BOTTOM)); - distp0->when(FL_WHEN_CHANGED); - } // WidgetPDial* distp0 - { distp3 = new WidgetPDial(45, 40, 30, 30, "Drive"); - distp3->tooltip("Input amplification"); - distp3->box(FL_ROUND_UP_BOX); - distp3->color(FL_BACKGROUND_COLOR); - distp3->selection_color(FL_INACTIVE_COLOR); - distp3->labeltype(FL_NORMAL_LABEL); - distp3->labelfont(1); - distp3->labelsize(11); - distp3->labelcolor(FL_FOREGROUND_COLOR); - distp3->maximum(127); - distp3->callback((Fl_Callback*)cb_distp31); - distp3->align(Fl_Align(FL_ALIGN_BOTTOM)); - distp3->when(FL_WHEN_RELEASE); - } // WidgetPDial* distp3 - { distp4 = new WidgetPDial(80, 40, 30, 30, "Level"); - distp4->tooltip("Output Amplification"); - distp4->box(FL_ROUND_UP_BOX); - distp4->color(FL_BACKGROUND_COLOR); - distp4->selection_color(FL_INACTIVE_COLOR); - distp4->labeltype(FL_NORMAL_LABEL); - distp4->labelfont(1); - distp4->labelsize(11); - distp4->labelcolor(FL_FOREGROUND_COLOR); - distp4->maximum(127); - distp4->callback((Fl_Callback*)cb_distp41); - distp4->align(Fl_Align(FL_ALIGN_BOTTOM)); - distp4->when(FL_WHEN_CHANGED); - } // WidgetPDial* distp4 - { distp7 = new WidgetPDial(190, 40, 30, 30, "LPF"); - distp7->tooltip("Low Pass Filter"); - distp7->box(FL_ROUND_UP_BOX); - distp7->color(FL_BACKGROUND_COLOR); - distp7->selection_color(FL_INACTIVE_COLOR); - distp7->labeltype(FL_NORMAL_LABEL); - distp7->labelfont(1); - distp7->labelsize(11); - distp7->labelcolor(FL_FOREGROUND_COLOR); - distp7->maximum(127); - distp7->callback((Fl_Callback*)cb_distp71); - distp7->align(Fl_Align(FL_ALIGN_BOTTOM)); - distp7->when(FL_WHEN_CHANGED); - } // WidgetPDial* distp7 - { distp5 = new Fl_Choice(120, 50, 60, 20, "Type"); - distp5->box(FL_UP_BOX); - distp5->down_box(FL_BORDER_BOX); - distp5->labelfont(1); - distp5->labelsize(11); - distp5->textsize(10); - distp5->callback((Fl_Callback*)cb_distp51); - distp5->align(Fl_Align(FL_ALIGN_BOTTOM)); - distp5->menu(menu_distp51); - } // Fl_Choice* distp5 - effdistorsionwindow->end(); - } // Fl_Group* effdistorsionwindow - return effdistorsionwindow; -} - -Fl_Group* SimpleEffUI::make_eq_window() { - { effeqwindow = new Fl_Group(0, 0, 230, 95); - effeqwindow->box(FL_PLASTIC_UP_BOX); - effeqwindow->color((Fl_Color)221); - effeqwindow->selection_color(FL_BACKGROUND_COLOR); - effeqwindow->labeltype(FL_NO_LABEL); - effeqwindow->labelfont(1); - effeqwindow->labelsize(14); - effeqwindow->labelcolor(FL_FOREGROUND_COLOR); - effeqwindow->user_data((void*)(this)); - effeqwindow->align(Fl_Align(FL_ALIGN_TOP)); - effeqwindow->when(FL_WHEN_RELEASE); - { Fl_Text_Display* o = new Fl_Text_Display(170, 5, 15, 25, "EQ"); - o->box(FL_NO_BOX); - o->labeltype(FL_EMBOSSED_LABEL); - o->labelfont(1); - o->labelsize(22); - o->align(Fl_Align(FL_ALIGN_RIGHT)); - } // Fl_Text_Display* o - { Fl_Counter* o = bandcounter = new Fl_Counter(85, 15, 45, 15, "Band"); - bandcounter->tooltip("Band no."); - bandcounter->type(1); - bandcounter->labelfont(1); - bandcounter->labelsize(11); - bandcounter->minimum(0); - bandcounter->maximum(1); - bandcounter->step(1); - bandcounter->textfont(1); - bandcounter->textsize(11); - bandcounter->callback((Fl_Callback*)cb_bandcounter1); - bandcounter->align(Fl_Align(FL_ALIGN_TOP)); - o->bounds(0,MAX_EQ_BANDS-1); - } // Fl_Counter* bandcounter - { Fl_Group* o = bandgroup = new Fl_Group(5, 5, 75, 85); - bandgroup->box(FL_ENGRAVED_FRAME); - { freqdial = new WidgetPDial(10, 10, 25, 25, "Freq"); - freqdial->box(FL_ROUND_UP_BOX); - freqdial->color(FL_BACKGROUND_COLOR); - freqdial->selection_color(FL_INACTIVE_COLOR); - freqdial->labeltype(FL_NORMAL_LABEL); - freqdial->labelfont(1); - freqdial->labelsize(10); - freqdial->labelcolor(FL_FOREGROUND_COLOR); - freqdial->maximum(127); - freqdial->callback((Fl_Callback*)cb_freqdial1); - freqdial->align(Fl_Align(FL_ALIGN_BOTTOM)); - freqdial->when(3); - } // WidgetPDial* freqdial - { gaindial = new WidgetPDial(45, 10, 25, 25, "Gain"); - gaindial->box(FL_ROUND_UP_BOX); - gaindial->color(FL_BACKGROUND_COLOR); - gaindial->selection_color(FL_INACTIVE_COLOR); - gaindial->labeltype(FL_NORMAL_LABEL); - gaindial->labelfont(1); - gaindial->labelsize(10); - gaindial->labelcolor(FL_FOREGROUND_COLOR); - gaindial->maximum(127); - gaindial->step(1); - gaindial->callback((Fl_Callback*)cb_gaindial1); - gaindial->align(Fl_Align(FL_ALIGN_BOTTOM)); - gaindial->when(3); - } // WidgetPDial* gaindial - { qdial = new WidgetPDial(10, 50, 25, 25, "Q"); - qdial->tooltip("Bandwidth/Resonance"); - qdial->box(FL_ROUND_UP_BOX); - qdial->color(FL_BACKGROUND_COLOR); - qdial->selection_color(FL_INACTIVE_COLOR); - qdial->labeltype(FL_NORMAL_LABEL); - qdial->labelfont(1); - qdial->labelsize(10); - qdial->labelcolor(FL_FOREGROUND_COLOR); - qdial->maximum(127); - qdial->callback((Fl_Callback*)cb_qdial1); - qdial->align(Fl_Align(FL_ALIGN_BOTTOM)); - qdial->when(3); - } // WidgetPDial* qdial - { Fl_Counter* o = stagescounter = new Fl_Counter(40, 55, 30, 15, "Stages"); - stagescounter->tooltip("Additional filter stages"); - stagescounter->type(1); - stagescounter->labelfont(1); - stagescounter->labelsize(10); - stagescounter->minimum(1); - stagescounter->maximum(127); - stagescounter->step(1); - stagescounter->textfont(1); - stagescounter->textsize(11); - stagescounter->callback((Fl_Callback*)cb_stagescounter1); - o->bounds(0,MAX_FILTER_STAGES-1); - } // Fl_Counter* stagescounter - if (eff->geteffectpar(10)==0) o->deactivate(); - bandgroup->end(); - } // Fl_Group* bandgroup - { typechoice = new Fl_Choice(135, 15, 40, 15, "Type"); - typechoice->tooltip("Type"); - typechoice->down_box(FL_BORDER_BOX); - typechoice->labelfont(1); - typechoice->labelsize(10); - typechoice->textsize(10); - typechoice->callback((Fl_Callback*)cb_typechoice1); - typechoice->align(Fl_Align(FL_ALIGN_TOP)); - typechoice->when(FL_WHEN_RELEASE_ALWAYS); - typechoice->menu(menu_typechoice1); - } // Fl_Choice* typechoice - { EQGraph* o = eqgraph = new EQGraph(85, 35, 140, 55); - eqgraph->box(FL_BORDER_BOX); - eqgraph->color((Fl_Color)178); - eqgraph->selection_color(FL_BACKGROUND_COLOR); - eqgraph->labeltype(FL_NORMAL_LABEL); - eqgraph->labelfont(0); - eqgraph->labelsize(14); - eqgraph->labelcolor(FL_FOREGROUND_COLOR); - eqgraph->align(Fl_Align(FL_ALIGN_CENTER)); - eqgraph->when(FL_WHEN_RELEASE); - o->init(eff); - } // EQGraph* eqgraph - effeqwindow->end(); - } // Fl_Group* effeqwindow - return effeqwindow; -} - -Fl_Group* SimpleEffUI::make_dynamicfilter_window() { - { effdynamicfilterwindow = new Fl_Group(0, 0, 230, 95); - effdynamicfilterwindow->box(FL_PLASTIC_UP_BOX); - effdynamicfilterwindow->color((Fl_Color)221); - effdynamicfilterwindow->selection_color(FL_BACKGROUND_COLOR); - effdynamicfilterwindow->labeltype(FL_NO_LABEL); - effdynamicfilterwindow->labelfont(1); - effdynamicfilterwindow->labelsize(14); - effdynamicfilterwindow->labelcolor(FL_FOREGROUND_COLOR); - effdynamicfilterwindow->user_data((void*)(this)); - effdynamicfilterwindow->align(Fl_Align(FL_ALIGN_TOP)); - effdynamicfilterwindow->when(FL_WHEN_RELEASE); - { dfp = new Fl_Choice(10, 15, 90, 15, "Preset"); - dfp->down_box(FL_BORDER_BOX); - dfp->color((Fl_Color)14); - dfp->selection_color(FL_FOREGROUND_COLOR); - dfp->labelfont(1); - dfp->labelsize(10); - dfp->textfont(1); - dfp->textsize(10); - dfp->textcolor(FL_BACKGROUND2_COLOR); - dfp->callback((Fl_Callback*)cb_dfpa); - dfp->align(Fl_Align(FL_ALIGN_TOP_LEFT)); - dfp->menu(menu_dfp1); - } // Fl_Choice* dfp - { Fl_Text_Display* o = new Fl_Text_Display(100, 10, 10, 20, "DynFilter"); - o->box(FL_NO_BOX); - o->labeltype(FL_EMBOSSED_LABEL); - o->labelfont(1); - o->labelsize(22); - o->align(Fl_Align(FL_ALIGN_RIGHT)); - } // Fl_Text_Display* o - { dfp0 = new WidgetPDial(10, 40, 30, 30, "Vol"); - dfp0->tooltip("Effect Volume"); - dfp0->box(FL_ROUND_UP_BOX); - dfp0->color(FL_BACKGROUND_COLOR); - dfp0->selection_color(FL_INACTIVE_COLOR); - dfp0->labeltype(FL_NORMAL_LABEL); - dfp0->labelfont(1); - dfp0->labelsize(11); - dfp0->labelcolor(FL_FOREGROUND_COLOR); - dfp0->maximum(127); - dfp0->callback((Fl_Callback*)cb_dfp01); - dfp0->align(Fl_Align(FL_ALIGN_BOTTOM)); - dfp0->when(FL_WHEN_CHANGED); - } // WidgetPDial* dfp0 - { dfp2 = new WidgetPDial(45, 40, 30, 30, "Freq"); - dfp2->tooltip("LFO frequency"); - dfp2->box(FL_ROUND_UP_BOX); - dfp2->color(FL_BACKGROUND_COLOR); - dfp2->selection_color(FL_INACTIVE_COLOR); - dfp2->labeltype(FL_NORMAL_LABEL); - dfp2->labelfont(1); - dfp2->labelsize(11); - dfp2->labelcolor(FL_FOREGROUND_COLOR); - dfp2->maximum(127); - dfp2->callback((Fl_Callback*)cb_dfp21); - dfp2->align(Fl_Align(FL_ALIGN_BOTTOM)); - dfp2->when(FL_WHEN_CHANGED); - } // WidgetPDial* dfp2 - { dfp6 = new WidgetPDial(80, 40, 30, 30, "LfoD"); - dfp6->tooltip("LFO depth"); - dfp6->box(FL_ROUND_UP_BOX); - dfp6->color(FL_BACKGROUND_COLOR); - dfp6->selection_color(FL_INACTIVE_COLOR); - dfp6->labeltype(FL_NORMAL_LABEL); - dfp6->labelfont(1); - dfp6->labelsize(11); - dfp6->labelcolor(FL_FOREGROUND_COLOR); - dfp6->maximum(127); - dfp6->callback((Fl_Callback*)cb_dfp61); - dfp6->align(Fl_Align(FL_ALIGN_BOTTOM)); - dfp6->when(FL_WHEN_CHANGED); - } // WidgetPDial* dfp6 - { Fl_Group* o = new Fl_Group(115, 40, 65, 45); - o->box(FL_BORDER_BOX); - o->color((Fl_Color)181); - { dfp7 = new WidgetPDial(120, 45, 25, 25, "A.S."); - dfp7->tooltip("how filter varies with amplitude"); - dfp7->box(FL_ROUND_UP_BOX); - dfp7->color(FL_BACKGROUND_COLOR); - dfp7->selection_color(FL_INACTIVE_COLOR); - dfp7->labeltype(FL_NORMAL_LABEL); - dfp7->labelfont(1); - dfp7->labelsize(11); - dfp7->labelcolor(FL_FOREGROUND_COLOR); - dfp7->maximum(127); - dfp7->callback((Fl_Callback*)cb_dfp71); - dfp7->align(Fl_Align(FL_ALIGN_BOTTOM)); - dfp7->when(FL_WHEN_CHANGED); - } // WidgetPDial* dfp7 - { dfp9 = new WidgetPDial(150, 45, 25, 25, "A.M"); - dfp9->tooltip("how quickly the filter varies with amplitude"); - dfp9->box(FL_ROUND_UP_BOX); - dfp9->color(FL_BACKGROUND_COLOR); - dfp9->selection_color(FL_INACTIVE_COLOR); - dfp9->labeltype(FL_NORMAL_LABEL); - dfp9->labelfont(1); - dfp9->labelsize(11); - dfp9->labelcolor(FL_FOREGROUND_COLOR); - dfp9->maximum(127); - dfp9->callback((Fl_Callback*)cb_dfp91); - dfp9->align(Fl_Align(FL_ALIGN_BOTTOM)); - dfp9->when(FL_WHEN_CHANGED); - } // WidgetPDial* dfp9 - o->end(); - } // Fl_Group* o - effdynamicfilterwindow->end(); - } // Fl_Group* effdynamicfilterwindow - return effdynamicfilterwindow; -} - -void SimpleEffUI::init(EffectMgr *eff_) { - eff=eff_; - - make_null_window(); - make_reverb_window(); - make_echo_window(); - make_chorus_window(); - make_phaser_window(); - make_alienwah_window(); - make_distorsion_window(); - make_eq_window(); - make_dynamicfilter_window(); - - int px=this->parent()->x(); - int py=this->parent()->y(); - - effnullwindow->position(px,py); - effreverbwindow->position(px,py); - effechowindow->position(px,py); - effchoruswindow->position(px,py); - effphaserwindow->position(px,py); - effalienwahwindow->position(px,py); - effdistorsionwindow->position(px,py); - effeqwindow->position(px,py); - effdynamicfilterwindow->position(px,py); - - refresh(eff); -} - -void SimpleEffUI::refresh(EffectMgr *eff_) { - eff=eff_; - this->hide(); - - effnullwindow->hide(); - effreverbwindow->hide(); - effechowindow->hide(); - effchoruswindow->hide(); - effphaserwindow->hide(); - effalienwahwindow->hide(); - effdistorsionwindow->hide(); - effeqwindow->hide(); - effdynamicfilterwindow->hide(); - - eqband=0; - - - switch(eff->geteffect()){ - case 1: - revp->value(eff->getpreset()); - revp0->value(eff->geteffectpar(0));if (eff->insertion!=0) revp0->label("D/W"); - revp2->value(eff->geteffectpar(2)); - revp3->value(eff->geteffectpar(3)); - revp9->value(eff->geteffectpar(9)); - effreverbwindow->show(); - break; - case 2: - echop->value(eff->getpreset()); - echop0->value(eff->geteffectpar(0));if (eff->insertion!=0) echop0->label("D/W"); - echop2->value(eff->geteffectpar(2)); - echop5->value(eff->geteffectpar(5)); - effechowindow->show(); - break; - case 3: - chorusp->value(eff->getpreset()); - chorusp0->value(eff->geteffectpar(0));if (eff->insertion!=0) chorusp0->label("D/W"); - chorusp2->value(eff->geteffectpar(2)); - chorusp6->value(eff->geteffectpar(6)); - chorusp7->value(eff->geteffectpar(7)); - chorusp8->value(eff->geteffectpar(8)); - effchoruswindow->show(); - break; - case 4: - phaserp->value(eff->getpreset()); - phaserp0->value(eff->geteffectpar(0));if (eff->insertion!=0) phaserp0->label("D/W"); - phaserp2->value(eff->geteffectpar(2)); - phaserp5->value(eff->geteffectpar(5)); - phaserp6->value(eff->geteffectpar(6)); - phaserp7->value(eff->geteffectpar(7)); - phaserp8->value(eff->geteffectpar(8)); - effphaserwindow->show(); - break; - case 5: - awp->value(eff->getpreset()); - awp0->value(eff->geteffectpar(0));if (eff->insertion!=0) awp0->label("D/W"); - awp2->value(eff->geteffectpar(2)); - awp6->value(eff->geteffectpar(6)); - awp8->value(eff->geteffectpar(8)); - effalienwahwindow->show(); - break; - case 6: - distp->value(eff->getpreset()); - distp0->value(eff->geteffectpar(0));if (eff->insertion!=0) distp0->label("D/W"); - distp3->value(eff->geteffectpar(3)); - distp4->value(eff->geteffectpar(4)); - distp5->value(eff->geteffectpar(5)); - distp7->value(eff->geteffectpar(7)); - effdistorsionwindow->show(); - break; - case 7: - bandcounter->value(eqband); - bandcounter->do_callback(); - typechoice->value(eff->geteffectpar(10)); - eqgraph->redraw(); - freqdial->value(eff->geteffectpar(11)); - gaindial->value(eff->geteffectpar(12)); - if (eff->geteffectpar(10)<6) gaindial->deactivate(); - qdial->value(eff->geteffectpar(13)); - stagescounter->value(eff->geteffectpar(14)); - eqgraph->init(eff); - effeqwindow->show(); - break; - case 8: - dfp->value(eff->getpreset()); - dfp0->value(eff->geteffectpar(0));if (eff->insertion!=0) dfp0->label("D/W"); - dfp2->value(eff->geteffectpar(2)); - dfp6->value(eff->geteffectpar(6)); - dfp7->value(eff->geteffectpar(7)); - dfp9->value(eff->geteffectpar(9)); - - - effdynamicfilterwindow->show(); - break; - default:effnullwindow->show(); - break; - }; - - this->show(); -} - -void SimpleEffUI::refresh() { - refresh(eff); -} diff --git a/plugins/zynaddsubfx/src/UI/EffUI.fl b/plugins/zynaddsubfx/src/UI/EffUI.fl deleted file mode 100644 index 69ebac180..000000000 --- a/plugins/zynaddsubfx/src/UI/EffUI.fl +++ /dev/null @@ -1,2361 +0,0 @@ -# data file for the Fltk User Interface Designer (fluid) -version 1.0107 -header_name {.h} -code_name {.cc} -decl {//Copyright (c) 2002-2005 Nasca Octavian Paul} {} - -decl {//License: GNU GPL version 2 or later} {} - -decl {\#include } {public -} - -decl {\#include } {public -} - -decl {\#include } {public -} - -decl {\#include "../globals.h"} {public -} - -decl {\#include "WidgetPDial.h"} {public -} - -decl {\#include "EnvelopeUI.h"} {public -} - -decl {\#include "FilterUI.h"} {public -} - -decl {\#include "../Misc/Util.h"} {public -} - -decl {\#include "../Effects/EffectMgr.h"} {public -} - -decl {\#include "PresetsUI.h"} {public -} - -class EQGraph {: {public Fl_Box} -} { - Function {EQGraph(int x,int y, int w, int h, const char *label=0):Fl_Box(x,y,w,h,label)} {} { - code {eff=NULL; -maxdB=30;} {} - } - Function {init(EffectMgr *eff_)} {} { - code {eff=eff_; -oldx=-1; -khzval=-1;} {} - } - Function {draw_freq_line(REALTYPE freq,int type)} {} { - code {fl_color(FL_GRAY); -REALTYPE freqx=getfreqpos(freq); -switch(type){ - case 0:if (active_r()) fl_color(FL_WHITE); - else fl_color(205,205,205); - fl_line_style(FL_SOLID); - break; - case 1:fl_line_style(FL_DOT);break; - case 2:fl_line_style(FL_DASH);break; -}; - - -if ((freqx>0.0)&&(freqx<1.0)) - fl_line(x()+(int) (freqx*w()),y(), - x()+(int) (freqx*w()),y()+h());} {} - } - Function {draw()} {} { - code {int ox=x(),oy=y(),lx=w(),ly=h(),i,iy,oiy; -REALTYPE freqx; - -if (active_r()) fl_color(0,70,150); - else fl_color(80,120,160); -fl_rectf(ox,oy,lx,ly); - - -//draw the lines -fl_color(FL_GRAY); - -fl_line_style(FL_SOLID); -fl_line(ox+2,oy+ly/2,ox+lx-2,oy+ly/2); - -freqx=getfreqpos(1000.0); -if ((freqx>0.0)&&(freqx<1.0)) - fl_line(ox+(int) (freqx*lx),oy, - ox+(int) (freqx*lx),oy+ly); - -for (i=1;i<10;i++){ - if(i==1){ - draw_freq_line(i*100.0,0); - draw_freq_line(i*1000.0,0); - }else - if (i==5){ - draw_freq_line(i*10.0,2); - draw_freq_line(i*100.0,2); - draw_freq_line(i*1000.0,2); - }else{ - draw_freq_line(i*10.0,1); - draw_freq_line(i*100.0,1); - draw_freq_line(i*1000.0,1); - }; -}; - -draw_freq_line(10000.0,0); -draw_freq_line(20000.0,1); - - -fl_line_style(FL_DOT); -int GY=6;if (lySAMPLE_RATE/2) break; - iy=getresponse(ly,frq); - if ((oiy>=0) && (oiy=0) && (iygetEQfreqresponse(freq); -int idbresp=(int) ((dbresp/maxdB+1.0)*maxy/2.0); - - -//fprintf(stderr,"%.5f\\n",(dbresp/maxdB+1.0)*maxy/2.0); - - -return(idbresp);} {} - } - Function {getfreqx(REALTYPE x)} {return_type REALTYPE - } { - code {if (x>1.0) x=1.0; -return(20.0*pow((REALTYPE)1000.0,x));} {} - } - Function {getfreqpos(REALTYPE freq)} {return_type REALTYPE - } { - code {if (freq<0.00001) freq=0.00001; -return(log(freq/20.0)/log(1000.0));} {} - } - decl {int oldx,oldy;} {} - decl {REALTYPE khzval;} {public - } - decl {EffectMgr *eff;} {} - decl {int maxdB;} {} -} - -class EffUI {: {public Fl_Group,public PresetsUI_} -} { - Function {EffUI(int x,int y, int w, int h, const char *label=0):Fl_Group(x,y,w,h,label)} {} { - code {eff=NULL; -filterwindow=NULL;} {} - } - Function {~EffUI()} {} { - code {effnullwindow->hide();//delete (effnullwindow); -effreverbwindow->hide();//delete (effreverbwindow); -effechowindow->hide();//delete (effechowindow); -effchoruswindow->hide();//delete (effchoruswindow); -effphaserwindow->hide();//delete (effphaserwindow); -effalienwahwindow->hide();//delete (effalienwahwindow); -effdistorsionwindow->hide();//delete (effdistorsionwindow); -effeqwindow->hide();//delete (effeqwindow); -effdynamicfilterwindow->hide();//delete (effdynamicfilterwindow); - -if (filterwindow!=NULL){ - filterwindow->hide(); - delete(filterwindow); -};} {} - } - Function {make_null_window()} {} { - Fl_Window effnullwindow { - xywh {216 539 380 95} type Double box PLASTIC_UP_BOX color 221 labelfont 1 hide - class Fl_Group - } { - Fl_Text_Display {} { - label {No Effect} - xywh {120 35 10 20} box NO_BOX labeltype EMBOSSED_LABEL labelfont 1 labelsize 22 labelcolor 43 align 8 - } - } - } - Function {make_reverb_window()} {} { - Fl_Window effreverbwindow { - xywh {343 337 380 95} type Double box PLASTIC_UP_BOX color 221 labelfont 1 hide - class Fl_Group - } { - Fl_Text_Display {} { - label {Reverb } - xywh {275 10 10 20} box NO_BOX labeltype EMBOSSED_LABEL labelfont 1 labelsize 22 align 8 - } - Fl_Choice revp { - label Preset - callback {eff->changepreset((int)o->value()); - -refresh(eff);} - xywh {10 15 90 15} down_box BORDER_BOX color 14 selection_color 0 labelfont 1 labelsize 10 align 5 textfont 1 textsize 10 textcolor 7 - } { - MenuItem {} { - label {Cathedral 1} - xywh {10 10 100 20} labelfont 1 labelsize 10 labelcolor 7 - } - MenuItem {} { - label {Cathedral 2} - xywh {20 20 100 20} labelfont 1 labelsize 10 labelcolor 7 - } - MenuItem {} { - label {Cathedral 3} - xywh {30 30 100 20} labelfont 1 labelsize 10 labelcolor 7 - } - MenuItem {} { - label {Hall 1} - xywh {40 40 100 20} labelfont 1 labelsize 10 labelcolor 7 - } - MenuItem {} { - label {Hall 2} - xywh {50 50 100 20} labelfont 1 labelsize 10 labelcolor 7 - } - MenuItem {} { - label {Room 1} - xywh {60 60 100 20} labelfont 1 labelsize 10 labelcolor 7 - } - MenuItem {} { - label {Room 2} - xywh {70 70 100 20} labelfont 1 labelsize 10 labelcolor 7 - } - MenuItem {} { - label Basement - xywh {80 80 100 20} labelfont 1 labelsize 10 labelcolor 7 - } - MenuItem {} { - label Tunnel - xywh {90 90 100 20} labelfont 1 labelsize 10 labelcolor 7 - } - MenuItem {} { - label {Echoed 1} - xywh {100 100 100 20} labelfont 1 labelsize 10 labelcolor 7 - } - MenuItem {} { - label {Echoed 2} - xywh {110 110 100 20} labelfont 1 labelsize 10 labelcolor 7 - } - MenuItem {} { - label {Very Long 1} - xywh {120 120 100 20} labelfont 1 labelsize 10 labelcolor 7 - } - MenuItem {} { - label {Very Long 2} - xywh {130 130 100 20} labelfont 1 labelsize 10 labelcolor 7 - } - } - Fl_Choice revp10 { - label Type - callback {eff->seteffectpar(10,(int) o->value()); -if (eff->geteffectpar(10)==2) revp12->activate(); - else revp12->deactivate();} - xywh {110 15 85 15} down_box BORDER_BOX color 14 labelfont 1 labelsize 10 align 5 textfont 1 textsize 10 textcolor 7 - } { - MenuItem {} { - label Random - xywh {20 20 100 20} labelfont 1 labelsize 10 labelcolor 7 - } - MenuItem {} { - label Freeverb - xywh {30 30 100 20} labelfont 1 labelsize 10 labelcolor 7 - } - MenuItem {} { - label Bandwidth - xywh {40 40 100 20} labelfont 1 labelsize 10 labelcolor 7 - } - } - Fl_Dial revp0 { - label Vol - callback {eff->seteffectpar(0,(int) o->value());} - tooltip {Effect Volume} xywh {10 40 30 30} box ROUND_UP_BOX labelfont 1 labelsize 11 maximum 127 - class WidgetPDial - } - Fl_Dial revp1 { - label Pan - callback {eff->seteffectpar(1,(int) o->value());} - xywh {45 40 30 30} box ROUND_UP_BOX labelfont 1 labelsize 11 maximum 127 - class WidgetPDial - } - Fl_Dial revp2 { - label Time - callback {eff->seteffectpar(2,(int) o->value());} - tooltip {Duration of Effect} xywh {80 40 30 30} box ROUND_UP_BOX labelfont 1 labelsize 11 maximum 127 - class WidgetPDial - } - Fl_Dial revp3 { - label {I.del} - callback {eff->seteffectpar(3,(int) o->value());} - tooltip {Initial Delay} xywh {120 40 30 30} box ROUND_UP_BOX labelfont 1 labelsize 11 when 4 maximum 127 - class WidgetPDial - } - Fl_Dial revp4 { - label {I.delfb} - callback {eff->seteffectpar(4,(int) o->value());} - tooltip {Initial Delay Feedback} xywh {155 40 30 30} box ROUND_UP_BOX labelfont 1 labelsize 11 maximum 127 - class WidgetPDial - } - Fl_Dial revp12 { - label bw - callback {eff->seteffectpar(12,(int) o->value());} - xywh {200 40 30 30} box ROUND_UP_BOX labelfont 1 labelsize 11 when 4 maximum 127 deactivate - code0 {if (eff->geteffectpar(10)==2) o->activate();} - class WidgetPDial - } - Fl_Dial revp6 { - label {E/R} - callback {eff->seteffectpar(6,(int) o->value());} - xywh {235 40 30 30} box ROUND_UP_BOX labelfont 1 labelsize 11 maximum 127 deactivate - class WidgetPDial - } - Fl_Dial revp7 { - label LPF - callback {eff->seteffectpar(7,(int) o->value());} - tooltip {Low Pass Filter} xywh {270 40 30 30} box ROUND_UP_BOX labelfont 1 labelsize 11 maximum 127 - class WidgetPDial - } - Fl_Dial revp8 { - label HPF - callback {eff->seteffectpar(8,(int) o->value());} - tooltip {High Pass Filter} xywh {305 40 30 30} box ROUND_UP_BOX labelfont 1 labelsize 11 maximum 127 - class WidgetPDial - } - Fl_Dial revp9 { - label Damp - callback {eff->seteffectpar(9,(int) o->value());} - tooltip Dampening xywh {340 40 30 30} box ROUND_UP_BOX labelfont 1 labelsize 11 minimum 64 maximum 127 step 1 - class WidgetPDial - } - Fl_Dial revp11 { - label {R.S.} - callback {int x=64; -if (Fl::event_button1()) x=(int)o->value(); - else o->value(x); -eff->seteffectpar(11,x);} - tooltip RoomSize xywh {200 10 25 25} box ROUND_UP_BOX labelfont 1 labelsize 8 align 8 minimum 1 maximum 127 step 1 - class WidgetPDial - } - } - } - Function {make_echo_window()} {} { - Fl_Window effechowindow { - xywh {318 364 380 95} type Double box PLASTIC_UP_BOX color 221 labelfont 1 hide - class Fl_Group - } { - Fl_Choice echop { - label Preset - callback {eff->changepreset((int)o->value()); -refresh(eff);} - xywh {11 15 95 15} down_box BORDER_BOX color 14 selection_color 0 labelfont 1 labelsize 10 align 5 textfont 1 textsize 10 textcolor 7 - } { - MenuItem {} { - label {Echo 1} - xywh {20 20 100 20} labelfont 1 labelsize 10 labelcolor 7 - } - MenuItem {} { - label {Echo 2} - xywh {30 30 100 20} labelfont 1 labelsize 10 labelcolor 7 - } - MenuItem {} { - label {Echo 3} - xywh {40 40 100 20} labelfont 1 labelsize 10 labelcolor 7 - } - MenuItem {} { - label {Simple Echo} - xywh {50 50 100 20} labelfont 1 labelsize 10 labelcolor 7 - } - MenuItem {} { - label Canyon - xywh {60 60 100 20} labelfont 1 labelsize 10 labelcolor 7 - } - MenuItem {} { - label {Panning Echo 1} - xywh {70 70 100 20} labelfont 1 labelsize 10 labelcolor 7 - } - MenuItem {} { - label {Panning Echo 2} - xywh {80 80 100 20} labelfont 1 labelsize 10 labelcolor 7 - } - MenuItem {} { - label {Panning Echo 3} - xywh {90 90 100 20} labelfont 1 labelsize 10 labelcolor 7 - } - MenuItem {} { - label {Feedback Echo} - xywh {100 100 100 20} labelfont 1 labelsize 10 labelcolor 7 - } - } - Fl_Text_Display {} { - label Echo - xywh {295 10 10 20} box NO_BOX labeltype EMBOSSED_LABEL labelfont 1 labelsize 22 align 8 - } - Fl_Dial echop0 { - label Vol - callback {eff->seteffectpar(0,(int) o->value());} - tooltip {Effect Volume} xywh {10 40 30 30} box ROUND_UP_BOX labelfont 1 labelsize 11 maximum 127 - class WidgetPDial - } - Fl_Dial echop1 { - label Pan - callback {eff->seteffectpar(1,(int) o->value());} - xywh {45 40 30 30} box ROUND_UP_BOX labelfont 1 labelsize 11 maximum 127 - class WidgetPDial - } - Fl_Dial echop2 { - label Delay - callback {eff->seteffectpar(2,(int) o->value());} - xywh {80 40 30 30} box ROUND_UP_BOX labelfont 1 labelsize 11 when 4 maximum 127 - class WidgetPDial - } - Fl_Dial echop3 { - label {LRdl.} - callback {eff->seteffectpar(3,(int) o->value());} - tooltip {Delay Between L/R} xywh {120 40 30 30} box ROUND_UP_BOX labelfont 1 labelsize 11 when 4 maximum 127 - class WidgetPDial - } - Fl_Dial echop4 { - label {LRc.} - callback {eff->seteffectpar(4,(int) o->value());} - tooltip {L/R Crossover} xywh {155 40 30 30} box ROUND_UP_BOX labelfont 1 labelsize 11 maximum 127 - class WidgetPDial - } - Fl_Dial echop5 { - label {Fb.} - callback {eff->seteffectpar(5,(int) o->value());} - tooltip Feedback xywh {195 40 30 30} box ROUND_UP_BOX labelfont 1 labelsize 11 maximum 127 - class WidgetPDial - } - Fl_Dial echop6 { - label Damp - callback {eff->seteffectpar(6,(int) o->value());} - tooltip Dampening xywh {235 40 30 30} box ROUND_UP_BOX labelfont 1 labelsize 11 maximum 127 - class WidgetPDial - } - } - } - Function {make_chorus_window()} {} { - Fl_Window effchoruswindow { - xywh {372 287 380 95} type Double box PLASTIC_UP_BOX color 221 labelfont 1 hide - class Fl_Group - } { - Fl_Choice chorusp { - label Preset - callback {eff->changepreset((int)o->value()); -refresh(eff);} - xywh {10 15 90 15} down_box BORDER_BOX color 14 selection_color 0 labelfont 1 labelsize 10 align 5 textfont 1 textsize 10 textcolor 7 - } { - MenuItem {} { - label {Chorus 1} - xywh {20 20 100 20} labelfont 1 labelsize 10 labelcolor 7 - } - MenuItem {} { - label {Chorus 2} - xywh {30 30 100 20} labelfont 1 labelsize 10 labelcolor 7 - } - MenuItem {} { - label {Chorus 3} - xywh {40 40 100 20} labelfont 1 labelsize 10 labelcolor 7 - } - MenuItem {} { - label {Celeste 1} - xywh {50 50 100 20} labelfont 1 labelsize 10 labelcolor 7 - } - MenuItem {} { - label {Celeste 2} - xywh {60 60 100 20} labelfont 1 labelsize 10 labelcolor 7 - } - MenuItem {} { - label {Flange 1} - xywh {70 70 100 20} labelfont 1 labelsize 10 labelcolor 7 - } - MenuItem {} { - label {Flange 2} - xywh {80 80 100 20} labelfont 1 labelsize 10 labelcolor 7 - } - MenuItem {} { - label {Flange 3} - xywh {90 90 100 20} labelfont 1 labelsize 10 labelcolor 7 - } - MenuItem {} { - label {Flange 4} - xywh {100 100 100 20} labelfont 1 labelsize 10 labelcolor 7 - } - MenuItem {} { - label {Flange 5} - xywh {110 110 100 20} labelfont 1 labelsize 10 labelcolor 7 - } - } - Fl_Text_Display {} { - label Chorus - xywh {265 10 10 20} box NO_BOX labeltype EMBOSSED_LABEL labelfont 1 labelsize 22 align 8 - } - Fl_Dial chorusp0 { - label Vol - callback {eff->seteffectpar(0,(int) o->value());} - xywh {10 40 30 30} box ROUND_UP_BOX labelfont 1 labelsize 11 maximum 127 - class WidgetPDial - } - Fl_Dial chorusp1 { - label Pan - callback {eff->seteffectpar(1,(int) o->value());} - xywh {45 40 30 30} box ROUND_UP_BOX labelfont 1 labelsize 11 maximum 127 - class WidgetPDial - } - Fl_Dial chorusp2 { - label Freq - callback {eff->seteffectpar(2,(int) o->value());} - tooltip {LFO Frequency} xywh {85 40 30 30} box ROUND_UP_BOX labelfont 1 labelsize 11 maximum 127 - class WidgetPDial - } - Fl_Dial chorusp3 { - label Rnd - callback {eff->seteffectpar(3,(int) o->value());} - tooltip {LFO Randomness} xywh {120 40 30 30} box ROUND_UP_BOX labelfont 1 labelsize 11 when 4 maximum 127 - class WidgetPDial - } - Fl_Dial chorusp5 { - label {St.df} - callback {eff->seteffectpar(5,(int) o->value());} - tooltip {L/R Phase Shift} xywh {200 40 30 30} box ROUND_UP_BOX labelfont 1 labelsize 11 maximum 127 - class WidgetPDial - } - Fl_Dial chorusp6 { - label Dpth - callback {eff->seteffectpar(6,(int) o->value());} - tooltip {LFO Depth} xywh {235 40 30 30} box ROUND_UP_BOX labelfont 1 labelsize 11 maximum 127 - class WidgetPDial - } - Fl_Dial chorusp7 { - label Delay - callback {eff->seteffectpar(7,(int) o->value());} - xywh {270 40 30 30} box ROUND_UP_BOX labelfont 1 labelsize 11 maximum 127 - class WidgetPDial - } - Fl_Dial chorusp8 { - label Fb - callback {eff->seteffectpar(8,(int) o->value());} - tooltip Feedback xywh {305 40 30 30} box ROUND_UP_BOX labelfont 1 labelsize 11 maximum 127 - class WidgetPDial - } - Fl_Dial chorusp9 { - label {L/R} - callback {eff->seteffectpar(9,(int) o->value());} - tooltip {Channel Routing} xywh {340 40 30 30} box ROUND_UP_BOX labelfont 1 labelsize 11 maximum 127 - class WidgetPDial - } - Fl_Check_Button {} { - label Flange - callback {eff->seteffectpar(10,(int) o->value());} - xywh {120 10 55 20} box THIN_UP_BOX down_box DOWN_BOX color 230 labelfont 1 labelsize 10 hide deactivate - code0 {o->value(eff->geteffectpar(10));} - } - Fl_Check_Button chorusp11 { - label Substract - callback {eff->seteffectpar(11,(int) o->value());} - tooltip {inverts the output} xywh {185 10 70 20} box THIN_UP_BOX down_box DOWN_BOX color 230 labelfont 1 labelsize 10 - } - Fl_Choice chorusp4 { - label {LFO type} - callback {eff->seteffectpar(4,(int) o->value());} - tooltip {LFO function} xywh {155 50 40 15} down_box BORDER_BOX labelfont 1 labelsize 10 align 130 textsize 8 - } { - MenuItem {} { - label SINE - xywh {15 15 100 20} labelfont 1 labelsize 10 - } - MenuItem {} { - label TRI - xywh {25 25 100 20} labelfont 1 labelsize 10 - } - } - } - } - Function {make_phaser_window()} {} { - Fl_Window effphaserwindow { - xywh {75 25 380 95} type Double box PLASTIC_UP_BOX color 221 labelfont 1 hide - class Fl_Group - } { - Fl_Choice phaserp { - label Preset - callback {eff->changepreset((int)o->value()); -refresh(eff);} - xywh {10 15 100 15} down_box BORDER_BOX color 14 selection_color 0 labelfont 1 labelsize 10 align 5 textfont 1 textsize 10 textcolor 7 - } { - MenuItem {} { - label {Phaser 1} - xywh {30 30 100 20} labelfont 1 labelsize 10 labelcolor 7 - } - MenuItem {} { - label {Phaser 2} - xywh {40 40 100 20} labelfont 1 labelsize 10 labelcolor 7 - } - MenuItem {} { - label {Phaser 3} - xywh {50 50 100 20} labelfont 1 labelsize 10 labelcolor 7 - } - MenuItem {} { - label {Phaser 4} - xywh {60 60 100 20} labelfont 1 labelsize 10 labelcolor 7 - } - MenuItem {} { - label {Phaser 5} - xywh {70 70 100 20} labelfont 1 labelsize 10 labelcolor 7 - } - MenuItem {} { - label {Phaser 6} - xywh {80 80 100 20} labelfont 1 labelsize 10 labelcolor 7 - } - MenuItem {} { - label {APhaser 1} - xywh {40 40 100 20} labelfont 1 labelsize 10 labelcolor 7 - } - MenuItem {} { - label {APhaser 2} - xywh {50 50 100 20} labelfont 1 labelsize 10 labelcolor 7 - } - MenuItem {} { - label {APhaser 3} - xywh {60 60 100 20} labelfont 1 labelsize 10 labelcolor 7 - } - MenuItem {} { - label {APhaser 4} - xywh {70 70 100 20} labelfont 1 labelsize 10 labelcolor 7 - } - MenuItem {} { - label {APhaser 5} - xywh {80 80 100 20} labelfont 1 labelsize 10 labelcolor 7 - } - MenuItem {} { - label {APhaser 6} selected - xywh {90 90 100 20} labelfont 1 labelsize 10 labelcolor 7 - } - } - Fl_Text_Display {} { - label Phaser - xywh {275 10 10 20} box NO_BOX labeltype EMBOSSED_LABEL labelfont 1 labelsize 22 align 8 - } - Fl_Dial phaserp0 { - label Vol - callback {eff->seteffectpar(0,(int) o->value());} - tooltip {Effect Volume} xywh {10 40 30 30} box ROUND_UP_BOX labelfont 1 labelsize 11 maximum 127 - class WidgetPDial - } - Fl_Dial phaserp1 { - label Pan - callback {eff->seteffectpar(1,(int) o->value());} - xywh {45 40 30 30} box ROUND_UP_BOX labelfont 1 labelsize 11 maximum 127 - class WidgetPDial - } - Fl_Dial phaserp2 { - label Freq - callback {eff->seteffectpar(2,(int) o->value());} - tooltip {LFO frequency} xywh {85 45 25 25} box ROUND_UP_BOX labelfont 1 labelsize 11 maximum 127 - class WidgetPDial - } - Fl_Dial phaserp3 { - label Rnd - callback {eff->seteffectpar(3,(int) o->value());} - tooltip {LFO randomness} xywh {120 45 25 25} box ROUND_UP_BOX labelfont 1 labelsize 11 when 4 maximum 127 - class WidgetPDial - } - Fl_Choice phaserp4 { - label LFO - callback {eff->seteffectpar(4,(int) o->value());} - tooltip {LFO function} xywh {245 55 40 15} down_box BORDER_BOX labelfont 1 labelsize 10 align 130 textsize 8 - } { - MenuItem {} { - label SIN - xywh {15 15 100 20} labelfont 1 labelsize 10 - } - MenuItem {} { - label TRI - xywh {25 25 100 20} labelfont 1 labelsize 10 - } - } - Fl_Dial phaserp5 { - label {St.df} - callback {eff->seteffectpar(5,(int) o->value());} - tooltip {Left/Right Channel Phase Shift} xywh {155 45 25 25} box ROUND_UP_BOX labelfont 1 labelsize 11 maximum 127 - class WidgetPDial - } - Fl_Dial phaserp6 { - label Dpth - callback {eff->seteffectpar(6,(int) o->value());} - tooltip {LFO Depth} xywh {120 5 25 25} box ROUND_UP_BOX labelfont 1 labelsize 10 maximum 127 - class WidgetPDial - } - Fl_Dial phaserp7 { - label Fb - callback {eff->seteffectpar(7,(int) o->value());} - tooltip Feedback xywh {185 45 25 25} box ROUND_UP_BOX labelfont 1 labelsize 11 maximum 127 - class WidgetPDial - } - Fl_Counter phaserp8 { - label Stages - callback {eff->seteffectpar(8,(int) o->value());} - xywh {290 55 35 15} type Simple labelfont 1 labelsize 11 minimum 0 maximum 127 step 1 - code0 {o->range(1,MAX_PHASER_STAGES);} - } - Fl_Dial phaserp9 { - label {L/R} - callback {eff->seteffectpar(9,(int) o->value());} - tooltip {Channel Routing} xywh {215 45 25 25} box ROUND_UP_BOX labelfont 1 labelsize 11 maximum 127 - class WidgetPDial - } - Fl_Check_Button phaserp10 { - label Substract - callback {eff->seteffectpar(10,(int) o->value());} - tooltip {inverts output} xywh {200 10 74 20} box THIN_UP_BOX down_box DOWN_BOX color 230 labelfont 1 labelsize 10 - } - Fl_Dial phaserp11 { - label Phase - callback {eff->seteffectpar(11,(int) o->value());} - xywh {155 5 25 25} box ROUND_UP_BOX labelfont 1 labelsize 10 maximum 127 - class WidgetPDial - } - Fl_Check_Button phaserp12 { - label {hyp.} - callback {eff->seteffectpar(12,(int) o->value());} - tooltip hyper xywh {245 35 55 15} down_box DOWN_BOX - } - Fl_Dial phaserp13 { - label dist - callback {eff->seteffectpar(13,(int) o->value());} - tooltip Distortion xywh {340 50 25 25} box ROUND_UP_BOX labelfont 1 labelsize 11 maximum 127 - class WidgetPDial - } - Fl_Check_Button phaserp14 { - label Analog - callback {eff->seteffectpar(14,(int) o->value());} - xywh {305 35 70 15} down_box DOWN_BOX - } - } - } - Function {make_alienwah_window()} {} { - Fl_Window effalienwahwindow { - xywh {538 250 380 95} type Double box PLASTIC_UP_BOX color 221 labelfont 1 hide - class Fl_Group - } { - Fl_Choice awp { - label Preset - callback {eff->changepreset((int)o->value()); -refresh(eff);} - xywh {10 15 90 15} down_box BORDER_BOX color 14 selection_color 0 labelfont 1 labelsize 10 align 5 textfont 1 textsize 10 textcolor 7 - } { - MenuItem {} { - label {Alienwah 1} - xywh {40 40 100 20} labelfont 1 labelsize 10 labelcolor 7 - } - MenuItem {} { - label {Alienwah 2} - xywh {50 50 100 20} labelfont 1 labelsize 10 labelcolor 7 - } - MenuItem {} { - label {Alienwah 3} - xywh {60 60 100 20} labelfont 1 labelsize 10 labelcolor 7 - } - MenuItem {} { - label {Alienwah 4} - xywh {70 70 100 20} labelfont 1 labelsize 10 labelcolor 7 - } - } - Fl_Text_Display {} { - label AlienWah - xywh {245 10 10 20} box NO_BOX labeltype EMBOSSED_LABEL labelfont 1 labelsize 22 align 8 - } - Fl_Dial awp0 { - label Vol - callback {eff->seteffectpar(0,(int) o->value());} - tooltip {Effect Volume} xywh {10 40 30 30} box ROUND_UP_BOX labelfont 1 labelsize 11 maximum 127 - class WidgetPDial - } - Fl_Dial awp1 { - label Pan - callback {eff->seteffectpar(1,(int) o->value());} - xywh {45 40 30 30} box ROUND_UP_BOX labelfont 1 labelsize 11 maximum 127 - class WidgetPDial - } - Fl_Dial awp2 { - label Freq - callback {eff->seteffectpar(2,(int) o->value());} - tooltip {LFO Frequency} xywh {85 40 30 30} box ROUND_UP_BOX labelfont 1 labelsize 11 maximum 127 - class WidgetPDial - } - Fl_Dial awp3 { - label Rnd - callback {eff->seteffectpar(3,(int) o->value());} - tooltip {LFO Randomness} xywh {120 40 30 30} box ROUND_UP_BOX labelfont 1 labelsize 11 when 4 maximum 127 - class WidgetPDial - } - Fl_Dial awp5 { - label {St.df} - callback {eff->seteffectpar(5,(int) o->value());} - tooltip {Left/Right Channel Phase Shift} xywh {200 40 30 30} box ROUND_UP_BOX labelfont 1 labelsize 11 maximum 127 - class WidgetPDial - } - Fl_Dial awp6 { - label Dpth - callback {eff->seteffectpar(6,(int) o->value());} - tooltip Depth xywh {235 40 30 30} box ROUND_UP_BOX labelfont 1 labelsize 11 maximum 127 - class WidgetPDial - } - Fl_Dial awp7 { - label Fb - callback {eff->seteffectpar(7,(int) o->value());} - tooltip Feedback xywh {270 40 30 30} box ROUND_UP_BOX labelfont 1 labelsize 11 maximum 127 - class WidgetPDial - } - Fl_Dial awp9 { - label {L/R} - callback {eff->seteffectpar(9,(int) o->value());} - xywh {345 40 30 30} box ROUND_UP_BOX labelfont 1 labelsize 11 maximum 127 - class WidgetPDial - } - Fl_Choice awp4 { - label {LFO type} - callback {eff->seteffectpar(4,(int) o->value());} - tooltip {LFO function} xywh {155 50 40 15} down_box BORDER_BOX labelfont 1 labelsize 10 align 130 textsize 8 - } { - MenuItem {} { - label SINE - xywh {15 15 100 20} labelfont 1 labelsize 10 - } - MenuItem {} { - label TRI - xywh {25 25 100 20} labelfont 1 labelsize 10 - } - } - Fl_Dial awp10 { - label Phase - callback {eff->seteffectpar(10,(int) o->value());} - xywh {160 5 30 30} box ROUND_UP_BOX labelfont 1 labelsize 11 maximum 127 - class WidgetPDial - } - Fl_Counter awp8 { - label Delay - callback {eff->seteffectpar(8,(int) o->value());} - xywh {305 55 35 15} type Simple labelfont 1 labelsize 11 minimum 0 maximum 127 step 1 - code0 {o->range(1,MAX_ALIENWAH_DELAY);} - } - } - } - Function {make_distorsion_window()} {} { - Fl_Window effdistorsionwindow { - xywh {409 143 380 95} type Double box PLASTIC_UP_BOX color 221 labelfont 1 hide - class Fl_Group - } { - Fl_Choice distp { - label Preset - callback {eff->changepreset((int)o->value()); -refresh(eff);} - xywh {11 15 95 15} down_box BORDER_BOX color 14 selection_color 0 labelfont 1 labelsize 10 align 5 textfont 1 textsize 10 textcolor 7 - } { - MenuItem {} { - label {Overdrive 1} - xywh {20 20 100 20} labelfont 1 labelsize 10 labelcolor 7 - } - MenuItem {} { - label {Overdrive 2} - xywh {30 30 100 20} labelfont 1 labelsize 10 labelcolor 7 - } - MenuItem {} { - label {A. Exciter 1} - xywh {40 40 100 20} labelfont 1 labelsize 10 labelcolor 7 - } - MenuItem {} { - label {A. Exciter 2} - xywh {50 50 100 20} labelfont 1 labelsize 10 labelcolor 7 - } - MenuItem {} { - label {Guitar Amp} - xywh {50 50 100 20} labelfont 1 labelsize 10 labelcolor 7 - } - MenuItem {} { - label Quantisize - xywh {60 60 100 20} labelfont 1 labelsize 10 labelcolor 7 - } - } - Fl_Text_Display {} { - label Distortion - xywh {230 10 10 20} box NO_BOX labeltype EMBOSSED_LABEL labelfont 1 labelsize 22 align 8 - } - Fl_Dial distp0 { - label Vol - callback {eff->seteffectpar(0,(int) o->value());} - tooltip {Effect Volume} xywh {10 40 30 30} box ROUND_UP_BOX labelfont 1 labelsize 11 maximum 127 - class WidgetPDial - } - Fl_Dial distp1 { - label Pan - callback {eff->seteffectpar(1,(int) o->value());} - xywh {45 40 30 30} box ROUND_UP_BOX labelfont 1 labelsize 11 maximum 127 - class WidgetPDial - } - Fl_Dial distp2 { - label {LRc.} - callback {eff->seteffectpar(2,(int) o->value());} - tooltip {L/R Mix} xywh {80 40 30 30} box ROUND_UP_BOX labelfont 1 labelsize 11 when 4 maximum 127 - class WidgetPDial - } - Fl_Dial distp3 { - label Drive - callback {eff->seteffectpar(3,(int) o->value());} - tooltip {Input Amplification} xywh {120 40 30 30} box ROUND_UP_BOX labelfont 1 labelsize 11 when 4 maximum 127 - class WidgetPDial - } - Fl_Dial distp4 { - label Level - callback {eff->seteffectpar(4,(int) o->value());} - tooltip {Output Amplification} xywh {155 40 30 30} box ROUND_UP_BOX labelfont 1 labelsize 11 maximum 127 - class WidgetPDial - } - Fl_Dial distp7 { - label LPF - callback {eff->seteffectpar(7,(int) o->value());} - tooltip {Low Pass Filter} xywh {285 40 30 30} box ROUND_UP_BOX labelfont 1 labelsize 11 maximum 127 - class WidgetPDial - } - Fl_Dial distp8 { - label HPF - callback {eff->seteffectpar(8,(int) o->value());} - tooltip {High Pass Filter} xywh {320 40 30 30} box ROUND_UP_BOX labelfont 1 labelsize 11 maximum 127 - class WidgetPDial - } - Fl_Choice distp5 { - label Type - callback {eff->seteffectpar(5,(int) o->value());} - xywh {190 50 60 20} box UP_BOX down_box BORDER_BOX labelfont 1 labelsize 11 align 2 textsize 10 - } { - MenuItem {} { - label Atan - xywh {55 55 100 20} labelfont 1 labelsize 10 - } - MenuItem {} { - label Asym1 - xywh {65 65 100 20} labelfont 1 labelsize 10 - } - MenuItem {} { - label Pow - xywh {75 75 100 20} labelfont 1 labelsize 10 - } - MenuItem {} { - label Sine - xywh {85 85 100 20} labelfont 1 labelsize 10 - } - MenuItem {} { - label Qnts - xywh {95 95 100 20} labelfont 1 labelsize 10 - } - MenuItem {} { - label Zigzg - xywh {105 105 100 20} labelfont 1 labelsize 10 - } - MenuItem {} { - label Lmt - xywh {115 115 100 20} labelfont 1 labelsize 10 - } - MenuItem {} { - label LmtU - xywh {125 125 100 20} labelfont 1 labelsize 10 - } - MenuItem {} { - label LmtL - xywh {135 135 100 20} labelfont 1 labelsize 10 - } - MenuItem {} { - label ILmt - xywh {147 147 100 20} labelfont 1 labelsize 10 - } - MenuItem {} { - label Clip - xywh {157 157 100 20} labelfont 1 labelsize 10 - } - MenuItem {} { - label Asym2 - xywh {75 75 100 20} labelfont 1 labelsize 10 - } - MenuItem {} { - label Pow2 - xywh {85 85 100 20} labelfont 1 labelsize 10 - } - MenuItem {} { - label Sgm - xywh {95 95 100 20} labelfont 1 labelsize 10 - } - } - Fl_Check_Button distp6 { - label {Neg.} - callback {eff->seteffectpar(6,(int) o->value());} - xywh {260 55 15 15} down_box DOWN_BOX labelfont 1 labelsize 11 align 2 - } - Fl_Check_Button distp9 { - label {St.} - callback {eff->seteffectpar(9,(int) o->value());} - tooltip Stereo xywh {355 60 15 15} down_box DOWN_BOX labelfont 1 labelsize 11 align 2 - } - Fl_Check_Button distp10 { - label PF - callback {eff->seteffectpar(10,(int) o->value());} - tooltip {Applies the filters(before or after) the distorsion} xywh {355 44 15 15} down_box DOWN_BOX labelfont 1 labelsize 11 align 1 - } - } - } - Function {make_eq_window()} {} { - Fl_Window effeqwindow { - xywh {258 307 380 95} type Double box PLASTIC_UP_BOX color 221 labelfont 1 hide - class Fl_Group - } { - Fl_Text_Display {} { - label EQ - xywh {320 10 15 20} box NO_BOX labeltype EMBOSSED_LABEL labelfont 1 labelsize 22 align 8 - } - Fl_Dial eqp0 { - label Gain - callback {eff->seteffectpar(0,(int) o->value()); -eqgraph->redraw();} - xywh {10 35 30 30} box ROUND_UP_BOX labelfont 1 labelsize 11 maximum 127 - class WidgetPDial - } - Fl_Counter bandcounter { - label {B.} - callback {eqband=(int) o->value(); -int npb=eqband*5+10; - -int type=eff->geteffectpar(npb); -typechoice->value(type); - -if (type>6) gaindial->activate(); - else gaindial->deactivate(); - -if (type==0) bandgroup->deactivate(); -else bandgroup->activate(); - -int freq=eff->geteffectpar(npb+1); -freqdial->value(freq); - -int gain=eff->geteffectpar(npb+2); -gaindial->value(gain); - -int q=eff->geteffectpar(npb+3); -qdial->value(q); - -int dbl=eff->geteffectpar(npb+4); -stagescounter->value(dbl);} - tooltip {Band no.} xywh {240 20 45 15} type Simple labelfont 1 labelsize 11 align 1 minimum 0 maximum 1 step 1 textfont 1 textsize 11 - code0 {o->bounds(0,MAX_EQ_BANDS-1);} - } - Fl_Group bandgroup { - xywh {245 40 130 50} box ENGRAVED_FRAME - code0 {if (eff->geteffectpar(10)==0) o->deactivate();} - } { - Fl_Dial freqdial { - label Freq - callback {int np=eqband*5+11; -eff->seteffectpar(np,(int) o->value()); -eqgraph->redraw();} - xywh {250 50 25 25} box ROUND_UP_BOX labelfont 1 labelsize 10 when 3 maximum 127 - class WidgetPDial - } - Fl_Dial gaindial { - label Gain - callback {int np=eqband*5+12; -eff->seteffectpar(np,(int) o->value()); -eqgraph->redraw();} - xywh {280 50 25 25} box ROUND_UP_BOX labelfont 1 labelsize 10 when 3 maximum 127 step 1 - class WidgetPDial - } - Fl_Dial qdial { - label Q - callback {int np=eqband*5+13; -eff->seteffectpar(np,(int) o->value()); -eqgraph->redraw();} - tooltip {Resonance/Bandwidth} xywh {310 50 25 25} box ROUND_UP_BOX labelfont 1 labelsize 10 when 3 maximum 127 - class WidgetPDial - } - Fl_Counter stagescounter { - label {St.} - callback {int np=eqband*5+14; -eff->seteffectpar(np,(int) o->value()); -eqgraph->redraw();} - tooltip {Additional filter stages} xywh {340 60 30 15} type Simple labelfont 1 labelsize 10 minimum 1 maximum 127 step 1 textfont 1 textsize 11 - code0 {o->bounds(0,MAX_FILTER_STAGES-1);} - } - } - Fl_Choice typechoice { - label {T.} - callback {int np=eqband*5+10; -eff->seteffectpar(np,(int) o->value()); -bandcounter->do_callback(); -eqgraph->redraw();} - tooltip Type xywh {290 20 40 15} down_box BORDER_BOX labelfont 1 labelsize 10 align 1 when 6 textsize 10 - } { - MenuItem {} { - label OFF - xywh {0 0 100 20} labelfont 1 labelsize 10 - } - MenuItem {} { - label Lp1 - xywh {10 10 100 20} labelfont 1 labelsize 10 - } - MenuItem {} { - label Hp1 - xywh {20 20 100 20} labelfont 1 labelsize 10 - } - MenuItem {} { - label Lp2 - xywh {30 30 100 20} labelfont 1 labelsize 10 - } - MenuItem {} { - label Hp2 - xywh {40 40 100 20} labelfont 1 labelsize 10 - } - MenuItem {} { - label Bp2 - xywh {50 50 100 20} labelfont 1 labelsize 10 - } - MenuItem {} { - label N2 - xywh {60 60 100 20} labelfont 1 labelsize 10 - } - MenuItem {} { - label Pk - xywh {80 80 100 20} labelfont 1 labelsize 10 - } - MenuItem {} { - label LSh - xywh {70 70 100 20} labelfont 1 labelsize 10 - } - MenuItem {} { - label HSh - xywh {80 80 100 20} labelfont 1 labelsize 10 - } - } - Fl_Box eqgraph { - xywh {45 10 190 75} box BORDER_BOX color 178 - code0 {o->init(eff);} - class EQGraph - } - } - } - Function {make_dynamicfilter_window()} {} { - Fl_Window effdynamicfilterwindow { - xywh {570 56 380 95} type Double box PLASTIC_UP_BOX color 221 labelfont 1 hide - class Fl_Group - } { - Fl_Choice dfp { - label Preset - callback {eff->changepreset((int)o->value()); -refresh(eff);} - xywh {10 15 90 15} down_box BORDER_BOX color 14 selection_color 0 labelfont 1 labelsize 10 align 5 textfont 1 textsize 10 textcolor 7 - } { - MenuItem {} { - label WahWah - xywh {30 30 100 20} labelfont 1 labelsize 10 labelcolor 7 - } - MenuItem {} { - label AutoWah - xywh {40 40 100 20} labelfont 1 labelsize 10 labelcolor 7 - } - MenuItem {} { - label Sweep - xywh {50 50 100 20} labelfont 1 labelsize 10 labelcolor 7 - } - MenuItem {} { - label VocalMorph1 - xywh {50 50 100 20} labelfont 1 labelsize 10 labelcolor 7 - } - MenuItem {} { - label VocalMorph2 - xywh {60 60 100 20} labelfont 1 labelsize 10 labelcolor 7 - } - } - Fl_Text_Display {} { - label DynFilter - xywh {245 10 10 20} box NO_BOX labeltype EMBOSSED_LABEL labelfont 1 labelsize 22 align 8 - } - Fl_Dial dfp0 { - label Vol - callback {eff->seteffectpar(0,(int) o->value());} - tooltip {Effect Volume} xywh {10 40 30 30} box ROUND_UP_BOX labelfont 1 labelsize 11 maximum 127 - class WidgetPDial - } - Fl_Dial dfp1 { - label Pan - callback {eff->seteffectpar(1,(int) o->value());} - xywh {45 40 30 30} box ROUND_UP_BOX labelfont 1 labelsize 11 maximum 127 - class WidgetPDial - } - Fl_Dial dfp2 { - label Freq - callback {eff->seteffectpar(2,(int) o->value());} - tooltip {LFO Frequency} xywh {85 40 30 30} box ROUND_UP_BOX labelfont 1 labelsize 11 maximum 127 - class WidgetPDial - } - Fl_Dial dfp3 { - label Rnd - callback {eff->seteffectpar(3,(int) o->value());} - tooltip {LFO Randomness} xywh {120 40 30 30} box ROUND_UP_BOX labelfont 1 labelsize 11 when 4 maximum 127 - class WidgetPDial - } - Fl_Dial dfp5 { - label {St.df} - callback {eff->seteffectpar(5,(int) o->value());} - tooltip {Left/Right Channel Phase Shift} xywh {200 40 30 30} box ROUND_UP_BOX labelfont 1 labelsize 11 maximum 127 - class WidgetPDial - } - Fl_Dial dfp6 { - label LfoD - callback {eff->seteffectpar(6,(int) o->value());} - tooltip {LFO Depth} xywh {235 40 30 30} box ROUND_UP_BOX labelfont 1 labelsize 11 maximum 127 - class WidgetPDial - } - Fl_Choice dfp4 { - label {LFO type} - callback {eff->seteffectpar(4,(int) o->value());} - tooltip {LFO function} xywh {155 50 40 15} down_box BORDER_BOX labelfont 1 labelsize 10 align 130 textsize 8 - } { - MenuItem {} { - label SINE - xywh {15 15 100 20} labelfont 1 labelsize 10 - } - MenuItem {} { - label TRI - xywh {25 25 100 20} labelfont 1 labelsize 10 - } - } - Fl_Button {} { - label Filter - callback {filterwindow->show();} - xywh {115 10 55 25} box PLASTIC_THIN_UP_BOX - } - Fl_Group {} { - xywh {270 40 105 45} box BORDER_BOX color 181 - } { - Fl_Dial dfp7 { - label {A.S.} - callback {eff->seteffectpar(7,(int) o->value());} - tooltip {Filter vs Amplitude} xywh {275 45 25 25} box ROUND_UP_BOX labelfont 1 labelsize 11 maximum 127 - class WidgetPDial - } - Fl_Dial dfp9 { - label {A.M} - callback {eff->seteffectpar(9,(int) o->value());} - tooltip {rate that amplitude changes the filter} xywh {305 45 25 25} box ROUND_UP_BOX labelfont 1 labelsize 11 maximum 127 - class WidgetPDial - } - Fl_Check_Button dfp8 { - label {A.Inv.} - callback {eff->seteffectpar(8,(int) o->value());} - tooltip {enable for filter frequency to lower with higher input amplitude} xywh {345 55 15 15} down_box DOWN_BOX labelfont 1 labelsize 11 align 2 - } - } - } - } - Function {make_filter_window()} {} { - Fl_Window filterwindow { - label {Filter Parameters for DynFilter Eff.} - xywh {212 170 290 110} type Double hide - } { - Fl_Group {} { - label {DynFilter effect - Filter} - xywh {5 5 275 75} box FLAT_BOX color 50 align 144 - code0 {o->init(eff->filterpars,NULL,NULL);} - code1 {o->use_for_dynamic_filter();} - class FilterUI - } {} - Fl_Button {} { - label Close - callback {filterwindow->hide();} - xywh {105 85 70 20} box THIN_UP_BOX - } - } - } - Function {init(EffectMgr *eff_)} {} { - code {eff=eff_; - -make_null_window(); -make_reverb_window(); -make_echo_window(); -make_chorus_window(); -make_phaser_window(); -make_alienwah_window(); -make_distorsion_window(); -make_eq_window(); -make_dynamicfilter_window(); - -int px=this->parent()->x(); -int py=this->parent()->y(); - -effnullwindow->position(px,py); -effreverbwindow->position(px,py); -effechowindow->position(px,py); -effchoruswindow->position(px,py); -effphaserwindow->position(px,py); -effalienwahwindow->position(px,py); -effdistorsionwindow->position(px,py); -effeqwindow->position(px,py); -effdynamicfilterwindow->position(px,py); - -refresh(eff);} {} - } - Function {refresh(EffectMgr *eff_)} {open - } { - code {eff=eff_; -this->hide(); - -effnullwindow->hide(); -effreverbwindow->hide(); -effechowindow->hide(); -effchoruswindow->hide(); -effphaserwindow->hide(); -effalienwahwindow->hide(); -effdistorsionwindow->hide(); -effeqwindow->hide(); -effdynamicfilterwindow->hide(); - -eqband=0; - -if (filterwindow!=NULL){ - filterwindow->hide(); - delete(filterwindow); - filterwindow=NULL; -}; - -switch(eff->geteffect()){ - case 1: - revp->value(eff->getpreset()); - revp0->value(eff->geteffectpar(0));if (eff->insertion!=0) revp0->label("D/W"); - revp1->value(eff->geteffectpar(1)); - revp2->value(eff->geteffectpar(2)); - revp3->value(eff->geteffectpar(3)); - revp4->value(eff->geteffectpar(4)); - //revp5->value(eff->geteffectpar(5)); - revp6->value(eff->geteffectpar(6)); - revp7->value(eff->geteffectpar(7)); - revp8->value(eff->geteffectpar(8)); - revp9->value(eff->geteffectpar(9)); - revp10->value(eff->geteffectpar(10)); - revp11->value(eff->geteffectpar(11)); - revp12->value(eff->geteffectpar(12)); - - effreverbwindow->show(); - break; - case 2: - echop->value(eff->getpreset()); - echop0->value(eff->geteffectpar(0));if (eff->insertion!=0) echop0->label("D/W"); - echop1->value(eff->geteffectpar(1)); - echop2->value(eff->geteffectpar(2)); - echop3->value(eff->geteffectpar(3)); - echop4->value(eff->geteffectpar(4)); - echop5->value(eff->geteffectpar(5)); - echop6->value(eff->geteffectpar(6)); - effechowindow->show(); - break; - case 3: - chorusp->value(eff->getpreset()); - chorusp0->value(eff->geteffectpar(0));if (eff->insertion!=0) chorusp0->label("D/W"); - chorusp1->value(eff->geteffectpar(1)); - chorusp2->value(eff->geteffectpar(2)); - chorusp3->value(eff->geteffectpar(3)); - chorusp4->value(eff->geteffectpar(4)); - chorusp5->value(eff->geteffectpar(5)); - chorusp6->value(eff->geteffectpar(6)); - chorusp7->value(eff->geteffectpar(7)); - chorusp8->value(eff->geteffectpar(8)); - chorusp9->value(eff->geteffectpar(9)); - chorusp11->value(eff->geteffectpar(11)); - effchoruswindow->show(); - break; - case 4: - phaserp->value(eff->getpreset()); - phaserp0->value(eff->geteffectpar(0));if (eff->insertion!=0) phaserp0->label("D/W"); - phaserp1->value(eff->geteffectpar(1)); - phaserp2->value(eff->geteffectpar(2)); - phaserp3->value(eff->geteffectpar(3)); - phaserp4->value(eff->geteffectpar(4)); - phaserp5->value(eff->geteffectpar(5)); - phaserp6->value(eff->geteffectpar(6)); - phaserp7->value(eff->geteffectpar(7)); - phaserp8->value(eff->geteffectpar(8)); - phaserp9->value(eff->geteffectpar(9)); - phaserp10->value(eff->geteffectpar(10)); - phaserp11->value(eff->geteffectpar(11)); - phaserp12->value(eff->geteffectpar(12)); - phaserp13->value(eff->geteffectpar(13)); - phaserp14->value(eff->geteffectpar(14)); - effphaserwindow->show(); - break; - case 5: - awp->value(eff->getpreset()); - awp0->value(eff->geteffectpar(0));if (eff->insertion!=0) awp0->label("D/W"); - awp1->value(eff->geteffectpar(1)); - awp2->value(eff->geteffectpar(2)); - awp3->value(eff->geteffectpar(3)); - awp4->value(eff->geteffectpar(4)); - awp5->value(eff->geteffectpar(5)); - awp6->value(eff->geteffectpar(6)); - awp7->value(eff->geteffectpar(7)); - awp8->value(eff->geteffectpar(8)); - awp9->value(eff->geteffectpar(9)); - awp10->value(eff->geteffectpar(10)); - - effalienwahwindow->show(); - break; - case 6: - distp->value(eff->getpreset()); - distp0->value(eff->geteffectpar(0));if (eff->insertion!=0) distp0->label("D/W"); - distp1->value(eff->geteffectpar(1)); - distp2->value(eff->geteffectpar(2)); - distp3->value(eff->geteffectpar(3)); - distp4->value(eff->geteffectpar(4)); - distp5->value(eff->geteffectpar(5)); - distp6->value(eff->geteffectpar(6)); - distp7->value(eff->geteffectpar(7)); - distp8->value(eff->geteffectpar(8)); - distp9->value(eff->geteffectpar(9)); - distp10->value(eff->geteffectpar(10)); - effdistorsionwindow->show(); - break; - case 7:eqband=0; - eqp0->value(eff->geteffectpar(0)); - bandcounter->value(eqband); - bandcounter->do_callback(); - typechoice->value(eff->geteffectpar(10)); - eqgraph->redraw(); - freqdial->value(eff->geteffectpar(11)); - gaindial->value(eff->geteffectpar(12)); - if (eff->geteffectpar(10)<6) gaindial->deactivate(); - qdial->value(eff->geteffectpar(13)); - stagescounter->value(eff->geteffectpar(14)); - eqgraph->init(eff); - effeqwindow->show(); - break; - case 8:make_filter_window(); - dfp->value(eff->getpreset()); - dfp0->value(eff->geteffectpar(0));if (eff->insertion!=0) dfp0->label("D/W"); - dfp1->value(eff->geteffectpar(1)); - dfp2->value(eff->geteffectpar(2)); - dfp3->value(eff->geteffectpar(3)); - dfp4->value(eff->geteffectpar(4)); - dfp5->value(eff->geteffectpar(5)); - dfp6->value(eff->geteffectpar(6)); - dfp7->value(eff->geteffectpar(7)); - dfp8->value(eff->geteffectpar(8)); - dfp9->value(eff->geteffectpar(9)); - - - effdynamicfilterwindow->show(); - break; - default:effnullwindow->show(); - break; -}; - -this->show();} {} - } - Function {refresh()} {open - } { - code {refresh(eff);} {} - } - decl {EffectMgr *eff;} {} - decl {int eqband;} {} -} - -class SimpleEffUI {: {public Fl_Group,public PresetsUI_} -} { - Function {SimpleEffUI(int x,int y, int w, int h, const char *label=0):Fl_Group(x,y,w,h,label)} {} { - code {eff=NULL;} {} - } - Function {~SimpleEffUI()} {} { - code {effnullwindow->hide();//delete (effnullwindow); -effreverbwindow->hide();//delete (effreverbwindow); -effechowindow->hide();//delete (effechowindow); -effchoruswindow->hide();//delete (effchoruswindow); -effphaserwindow->hide();//delete (effphaserwindow); -effalienwahwindow->hide();//delete (effalienwahwindow); -effdistorsionwindow->hide();//delete (effdistorsionwindow); -effeqwindow->hide();//delete (effeqwindow); -effdynamicfilterwindow->hide();//delete (effdynamicfilterwindow);} {} - } - Function {make_null_window()} {} { - Fl_Window effnullwindow { - xywh {539 150 230 95} type Double box PLASTIC_UP_BOX color 221 labelfont 1 hide - class Fl_Group - } { - Fl_Text_Display {} { - label {No Effect} - xywh {25 35 35 20} box NO_BOX labeltype EMBOSSED_LABEL labelfont 1 labelsize 22 labelcolor 43 align 8 - } - } - } - Function {make_reverb_window()} {} { - Fl_Window effreverbwindow { - xywh {398 298 230 95} type Double box PLASTIC_UP_BOX color 221 labelfont 1 hide - class Fl_Group - } { - Fl_Text_Display {} { - label {Reverb } - xywh {115 10 20 20} box NO_BOX labeltype EMBOSSED_LABEL labelfont 1 labelsize 22 align 8 - } - Fl_Choice revp { - label Preset - callback {eff->changepreset((int)o->value()); - -refresh(eff);} - xywh {10 15 90 15} down_box BORDER_BOX color 14 selection_color 0 labelfont 1 labelsize 10 align 5 textfont 1 textsize 10 textcolor 7 - } { - MenuItem {} { - label {Cathedral 1} - xywh {10 10 100 20} labelfont 1 labelsize 10 labelcolor 7 - } - MenuItem {} { - label {Cathedral 2} - xywh {20 20 100 20} labelfont 1 labelsize 10 labelcolor 7 - } - MenuItem {} { - label {Cathedral 3} - xywh {30 30 100 20} labelfont 1 labelsize 10 labelcolor 7 - } - MenuItem {} { - label {Hall 1} - xywh {40 40 100 20} labelfont 1 labelsize 10 labelcolor 7 - } - MenuItem {} { - label {Hall 2} - xywh {50 50 100 20} labelfont 1 labelsize 10 labelcolor 7 - } - MenuItem {} { - label {Room 1} - xywh {60 60 100 20} labelfont 1 labelsize 10 labelcolor 7 - } - MenuItem {} { - label {Room 2} - xywh {70 70 100 20} labelfont 1 labelsize 10 labelcolor 7 - } - MenuItem {} { - label Basement - xywh {80 80 100 20} labelfont 1 labelsize 10 labelcolor 7 - } - MenuItem {} { - label Tunnel - xywh {90 90 100 20} labelfont 1 labelsize 10 labelcolor 7 - } - MenuItem {} { - label {Echoed 1} - xywh {100 100 100 20} labelfont 1 labelsize 10 labelcolor 7 - } - MenuItem {} { - label {Echoed 2} - xywh {110 110 100 20} labelfont 1 labelsize 10 labelcolor 7 - } - MenuItem {} { - label {Very Long 1} - xywh {120 120 100 20} labelfont 1 labelsize 10 labelcolor 7 - } - MenuItem {} { - label {Very Long 2} - xywh {130 130 100 20} labelfont 1 labelsize 10 labelcolor 7 - } - } - Fl_Dial revp0 { - label Vol - callback {eff->seteffectpar(0,(int) o->value());} - tooltip {Effect Volume} xywh {10 40 30 30} box ROUND_UP_BOX labelfont 1 labelsize 11 maximum 127 - class WidgetPDial - } - Fl_Dial revp2 { - label Time - callback {eff->seteffectpar(2,(int) o->value());} - tooltip {Duration of Reverb} xywh {45 40 30 30} box ROUND_UP_BOX labelfont 1 labelsize 11 maximum 127 - class WidgetPDial - } - Fl_Dial revp3 { - label {I.del} - callback {eff->seteffectpar(3,(int) o->value());} - tooltip {Initial Delay} xywh {85 40 30 30} box ROUND_UP_BOX labelfont 1 labelsize 11 when 4 maximum 127 - class WidgetPDial - } - Fl_Dial revp9 { - label Damp - callback {eff->seteffectpar(9,(int) o->value());} - tooltip Dampening xywh {120 40 30 30} box ROUND_UP_BOX labelfont 1 labelsize 11 minimum 64 maximum 127 step 1 - class WidgetPDial - } - } - } - Function {make_echo_window()} {} { - Fl_Window effechowindow { - xywh {243 350 230 95} type Double box PLASTIC_UP_BOX color 221 labelfont 1 hide - class Fl_Group - } { - Fl_Choice echop { - label Preset - callback {eff->changepreset((int)o->value()); -refresh(eff);} - xywh {11 15 95 15} down_box BORDER_BOX color 14 selection_color 0 labelfont 1 labelsize 10 align 5 textfont 1 textsize 10 textcolor 7 - } { - MenuItem {} { - label {Echo 1} - xywh {20 20 100 20} labelfont 1 labelsize 10 labelcolor 7 - } - MenuItem {} { - label {Echo 2} - xywh {30 30 100 20} labelfont 1 labelsize 10 labelcolor 7 - } - MenuItem {} { - label {Echo 3} - xywh {40 40 100 20} labelfont 1 labelsize 10 labelcolor 7 - } - MenuItem {} { - label {Simple Echo} - xywh {50 50 100 20} labelfont 1 labelsize 10 labelcolor 7 - } - MenuItem {} { - label Canyon - xywh {60 60 100 20} labelfont 1 labelsize 10 labelcolor 7 - } - MenuItem {} { - label {Panning Echo 1} - xywh {70 70 100 20} labelfont 1 labelsize 10 labelcolor 7 - } - MenuItem {} { - label {Panning Echo 2} - xywh {80 80 100 20} labelfont 1 labelsize 10 labelcolor 7 - } - MenuItem {} { - label {Panning Echo 3} - xywh {90 90 100 20} labelfont 1 labelsize 10 labelcolor 7 - } - MenuItem {} { - label {Feedback Echo} - xywh {100 100 100 20} labelfont 1 labelsize 10 labelcolor 7 - } - } - Fl_Text_Display {} { - label Echo - xywh {145 10 10 20} box NO_BOX labeltype EMBOSSED_LABEL labelfont 1 labelsize 22 align 8 - } - Fl_Dial echop0 { - label Vol - callback {eff->seteffectpar(0,(int) o->value());} - tooltip {Effect Volume} xywh {10 40 30 30} box ROUND_UP_BOX labelfont 1 labelsize 11 maximum 127 - class WidgetPDial - } - Fl_Dial echop2 { - label Delay - callback {eff->seteffectpar(2,(int) o->value());} - xywh {45 40 30 30} box ROUND_UP_BOX labelfont 1 labelsize 11 when 4 maximum 127 - class WidgetPDial - } - Fl_Dial echop5 { - label {Fb.} - callback {eff->seteffectpar(5,(int) o->value());} - tooltip Feedback xywh {80 40 30 30} box ROUND_UP_BOX labelfont 1 labelsize 11 maximum 127 - class WidgetPDial - } - } - } - Function {make_chorus_window()} {} { - Fl_Window effchoruswindow { - xywh {234 353 230 95} type Double box PLASTIC_UP_BOX color 221 labelfont 1 hide - class Fl_Group - } { - Fl_Choice chorusp { - label Preset - callback {eff->changepreset((int)o->value()); -refresh(eff);} - xywh {10 15 90 15} down_box BORDER_BOX color 14 selection_color 0 labelfont 1 labelsize 10 align 5 textfont 1 textsize 10 textcolor 7 - } { - MenuItem {} { - label {Chorus 1} - xywh {20 20 100 20} labelfont 1 labelsize 10 labelcolor 7 - } - MenuItem {} { - label {Chorus 2} - xywh {30 30 100 20} labelfont 1 labelsize 10 labelcolor 7 - } - MenuItem {} { - label {Chorus 3} - xywh {40 40 100 20} labelfont 1 labelsize 10 labelcolor 7 - } - MenuItem {} { - label {Celeste 1} - xywh {50 50 100 20} labelfont 1 labelsize 10 labelcolor 7 - } - MenuItem {} { - label {Celeste 2} - xywh {60 60 100 20} labelfont 1 labelsize 10 labelcolor 7 - } - MenuItem {} { - label {Flange 1} - xywh {70 70 100 20} labelfont 1 labelsize 10 labelcolor 7 - } - MenuItem {} { - label {Flange 2} - xywh {80 80 100 20} labelfont 1 labelsize 10 labelcolor 7 - } - MenuItem {} { - label {Flange 3} - xywh {90 90 100 20} labelfont 1 labelsize 10 labelcolor 7 - } - MenuItem {} { - label {Flange 4} - xywh {100 100 100 20} labelfont 1 labelsize 10 labelcolor 7 - } - MenuItem {} { - label {Flange 5} - xywh {110 110 100 20} labelfont 1 labelsize 10 labelcolor 7 - } - } - Fl_Text_Display {} { - label Chorus - xywh {120 10 10 20} box NO_BOX labeltype EMBOSSED_LABEL labelfont 1 labelsize 22 align 8 - } - Fl_Dial chorusp0 { - label Vol - callback {eff->seteffectpar(0,(int) o->value());} - tooltip {Effect Volume} xywh {10 40 30 30} box ROUND_UP_BOX labelfont 1 labelsize 11 maximum 127 - class WidgetPDial - } - Fl_Dial chorusp2 { - label Freq - callback {eff->seteffectpar(2,(int) o->value());} - tooltip {LFO Frequency} xywh {45 40 30 30} box ROUND_UP_BOX labelfont 1 labelsize 11 maximum 127 - class WidgetPDial - } - Fl_Dial chorusp6 { - label Dpth - callback {eff->seteffectpar(6,(int) o->value());} - tooltip Depth xywh {80 40 30 30} box ROUND_UP_BOX labelfont 1 labelsize 11 maximum 127 - class WidgetPDial - } - Fl_Dial chorusp7 { - label Delay - callback {eff->seteffectpar(7,(int) o->value());} - xywh {115 40 30 30} box ROUND_UP_BOX labelfont 1 labelsize 11 maximum 127 - class WidgetPDial - } - Fl_Dial chorusp8 { - label Fb - callback {eff->seteffectpar(8,(int) o->value());} - tooltip Feedback xywh {150 40 30 30} box ROUND_UP_BOX labelfont 1 labelsize 11 maximum 127 - class WidgetPDial - } - Fl_Check_Button {} { - label Flange - callback {eff->seteffectpar(10,(int) o->value());} - xywh {120 10 55 20} box THIN_UP_BOX down_box DOWN_BOX color 230 labelfont 1 labelsize 10 hide deactivate - code0 {o->value(eff->geteffectpar(10));} - } - } - } - Function {make_phaser_window()} {} { - Fl_Window effphaserwindow { - xywh {661 430 230 95} type Double box PLASTIC_UP_BOX color 221 labelfont 1 hide - class Fl_Group - } { - Fl_Choice phaserp { - label Preset - callback {eff->changepreset((int)o->value()); -refresh(eff);} - xywh {10 15 90 15} down_box BORDER_BOX color 14 selection_color 0 labelfont 1 labelsize 10 align 5 textfont 1 textsize 10 textcolor 7 - } { - MenuItem {} { - label {Phaser 1} - xywh {30 30 100 20} labelfont 1 labelsize 10 labelcolor 7 - } - MenuItem {} { - label {Phaser 2} - xywh {40 40 100 20} labelfont 1 labelsize 10 labelcolor 7 - } - MenuItem {} { - label {Phaser 3} - xywh {50 50 100 20} labelfont 1 labelsize 10 labelcolor 7 - } - MenuItem {} { - label {Phaser 4} - xywh {60 60 100 20} labelfont 1 labelsize 10 labelcolor 7 - } - MenuItem {} { - label {Phaser 5} - xywh {70 70 100 20} labelfont 1 labelsize 10 labelcolor 7 - } - MenuItem {} { - label {Phaser 6} - xywh {80 80 100 20} labelfont 1 labelsize 10 labelcolor 7 - } - } - Fl_Text_Display {} { - label Phaser - xywh {125 10 10 20} box NO_BOX labeltype EMBOSSED_LABEL labelfont 1 labelsize 22 align 8 - } - Fl_Dial phaserp0 { - label Vol - callback {eff->seteffectpar(0,(int) o->value());} - tooltip {Effect Volume} xywh {10 40 30 30} box ROUND_UP_BOX labelfont 1 labelsize 11 maximum 127 - class WidgetPDial - } - Fl_Dial phaserp2 { - label Freq - callback {eff->seteffectpar(2,(int) o->value());} - tooltip {LFO frequency} xywh {45 40 30 30} box ROUND_UP_BOX labelfont 1 labelsize 11 maximum 127 - class WidgetPDial - } - Fl_Dial phaserp5 { - label {St.df} - callback {eff->seteffectpar(5,(int) o->value());} - tooltip {Left/Right Channel Phase Shift} xywh {80 40 30 30} box ROUND_UP_BOX labelfont 1 labelsize 11 maximum 127 - class WidgetPDial - } - Fl_Dial phaserp6 { - label Dpth - callback {eff->seteffectpar(6,(int) o->value());} - tooltip Depth xywh {115 40 30 30} box ROUND_UP_BOX labelfont 1 labelsize 11 maximum 127 - class WidgetPDial - } - Fl_Dial phaserp7 { - label Fb - callback {eff->seteffectpar(7,(int) o->value());} - tooltip Feedback xywh {150 40 30 30} box ROUND_UP_BOX labelfont 1 labelsize 11 maximum 127 - class WidgetPDial - } - Fl_Counter phaserp8 { - label Stages - callback {eff->seteffectpar(8,(int) o->value());} - xywh {185 55 35 15} type Simple labelfont 1 labelsize 11 minimum 0 maximum 127 step 1 - code0 {o->range(1,MAX_PHASER_STAGES);} - } - } - } - Function {make_alienwah_window()} {} { - Fl_Window effalienwahwindow { - xywh {367 170 230 95} type Double box PLASTIC_UP_BOX color 221 labelfont 1 hide - class Fl_Group - } { - Fl_Choice awp { - label Preset - callback {eff->changepreset((int)o->value()); -refresh(eff);} - xywh {10 15 90 15} down_box BORDER_BOX color 14 selection_color 0 labelfont 1 labelsize 10 align 5 textfont 1 textsize 10 textcolor 7 - } { - MenuItem {} { - label {Alienwah 1} - xywh {40 40 100 20} labelfont 1 labelsize 10 labelcolor 7 - } - MenuItem {} { - label {Alienwah 2} - xywh {50 50 100 20} labelfont 1 labelsize 10 labelcolor 7 - } - MenuItem {} { - label {Alienwah 3} - xywh {60 60 100 20} labelfont 1 labelsize 10 labelcolor 7 - } - MenuItem {} { - label {Alienwah 4} - xywh {70 70 100 20} labelfont 1 labelsize 10 labelcolor 7 - } - } - Fl_Text_Display {} { - label AlienWah - xywh {100 10 10 20} box NO_BOX labeltype EMBOSSED_LABEL labelfont 1 labelsize 22 align 8 - } - Fl_Dial awp0 { - label Vol - callback {eff->seteffectpar(0,(int) o->value());} - tooltip {Effect Volume} xywh {10 40 30 30} box ROUND_UP_BOX labelfont 1 labelsize 11 maximum 127 - class WidgetPDial - } - Fl_Dial awp2 { - label Freq - callback {eff->seteffectpar(2,(int) o->value());} - tooltip {LFO frequency} xywh {45 40 30 30} box ROUND_UP_BOX labelfont 1 labelsize 11 maximum 127 - class WidgetPDial - } - Fl_Dial awp6 { - label Dpth - callback {eff->seteffectpar(6,(int) o->value());} - tooltip Depth xywh {85 40 30 30} box ROUND_UP_BOX labelfont 1 labelsize 11 maximum 127 - class WidgetPDial - } - Fl_Counter awp8 { - label Delay - callback {eff->seteffectpar(8,(int) o->value());} - xywh {125 55 35 15} type Simple labelfont 1 labelsize 11 minimum 0 maximum 127 step 1 - code0 {o->range(1,MAX_ALIENWAH_DELAY);} - } - } - } - Function {make_distorsion_window()} {} { - Fl_Window effdistorsionwindow { - xywh {353 412 230 95} type Double box PLASTIC_UP_BOX color 221 labelfont 1 hide - class Fl_Group - } { - Fl_Choice distp { - label Preset - callback {eff->changepreset((int)o->value()); -refresh(eff);} - xywh {11 15 95 15} down_box BORDER_BOX color 14 selection_color 0 labelfont 1 labelsize 10 align 5 textfont 1 textsize 10 textcolor 7 - } { - MenuItem {} { - label {Overdrive 1} - xywh {20 20 100 20} labelfont 1 labelsize 10 labelcolor 7 - } - MenuItem {} { - label {Overdrive 2} - xywh {30 30 100 20} labelfont 1 labelsize 10 labelcolor 7 - } - MenuItem {} { - label {A. Exciter 1} - xywh {40 40 100 20} labelfont 1 labelsize 10 labelcolor 7 - } - MenuItem {} { - label {A. Exciter 2} - xywh {50 50 100 20} labelfont 1 labelsize 10 labelcolor 7 - } - MenuItem {} { - label {Guitar Amp} - xywh {50 50 100 20} labelfont 1 labelsize 10 labelcolor 7 - } - MenuItem {} { - label Quantisize - xywh {60 60 100 20} labelfont 1 labelsize 10 labelcolor 7 - } - } - Fl_Text_Display {} { - label Distortion - xywh {110 10 10 20} box NO_BOX labeltype EMBOSSED_LABEL labelfont 1 labelsize 16 align 8 - } - Fl_Dial distp0 { - label Vol - callback {eff->seteffectpar(0,(int) o->value());} - tooltip {Effect Volume} xywh {10 40 30 30} box ROUND_UP_BOX labelfont 1 labelsize 11 maximum 127 - class WidgetPDial - } - Fl_Dial distp3 { - label Drive - callback {eff->seteffectpar(3,(int) o->value());} - tooltip {Input amplification} xywh {45 40 30 30} box ROUND_UP_BOX labelfont 1 labelsize 11 when 4 maximum 127 - class WidgetPDial - } - Fl_Dial distp4 { - label Level - callback {eff->seteffectpar(4,(int) o->value());} - tooltip {Output Amplification} xywh {80 40 30 30} box ROUND_UP_BOX labelfont 1 labelsize 11 maximum 127 - class WidgetPDial - } - Fl_Dial distp7 { - label LPF - callback {eff->seteffectpar(7,(int) o->value());} - tooltip {Low Pass Filter} xywh {190 40 30 30} box ROUND_UP_BOX labelfont 1 labelsize 11 maximum 127 - class WidgetPDial - } - Fl_Choice distp5 { - label Type - callback {eff->seteffectpar(5,(int) o->value());} - xywh {120 50 60 20} box UP_BOX down_box BORDER_BOX labelfont 1 labelsize 11 align 2 textsize 10 - } { - MenuItem {} { - label Atan - xywh {55 55 100 20} labelfont 1 labelsize 10 - } - MenuItem {} { - label Asym1 - xywh {65 65 100 20} labelfont 1 labelsize 10 - } - MenuItem {} { - label Pow - xywh {75 75 100 20} labelfont 1 labelsize 10 - } - MenuItem {} { - label Sine - xywh {85 85 100 20} labelfont 1 labelsize 10 - } - MenuItem {} { - label Qnts - xywh {95 95 100 20} labelfont 1 labelsize 10 - } - MenuItem {} { - label Zigzg - xywh {105 105 100 20} labelfont 1 labelsize 10 - } - MenuItem {} { - label Lmt - xywh {115 115 100 20} labelfont 1 labelsize 10 - } - MenuItem {} { - label LmtU - xywh {125 125 100 20} labelfont 1 labelsize 10 - } - MenuItem {} { - label LmtL - xywh {135 135 100 20} labelfont 1 labelsize 10 - } - MenuItem {} { - label ILmt - xywh {147 147 100 20} labelfont 1 labelsize 10 - } - MenuItem {} { - label Clip - xywh {157 157 100 20} labelfont 1 labelsize 10 - } - MenuItem {} { - label Asym2 - xywh {75 75 100 20} labelfont 1 labelsize 10 - } - MenuItem {} { - label Pow2 - xywh {85 85 100 20} labelfont 1 labelsize 10 - } - MenuItem {} { - label Sgm - xywh {95 95 100 20} labelfont 1 labelsize 10 - } - } - } - } - Function {make_eq_window()} {} { - Fl_Window effeqwindow { - xywh {318 309 230 95} type Double box PLASTIC_UP_BOX color 221 labelfont 1 hide - class Fl_Group - } { - Fl_Text_Display {} { - label EQ - xywh {170 5 15 25} box NO_BOX labeltype EMBOSSED_LABEL labelfont 1 labelsize 22 align 8 - } - Fl_Counter bandcounter { - label Band - callback {eqband=(int) o->value(); -int npb=eqband*5+10; - -int type=eff->geteffectpar(npb); -typechoice->value(type); - -if (type>6) gaindial->activate(); - else gaindial->deactivate(); - -if (type==0) bandgroup->deactivate(); -else bandgroup->activate(); - -int freq=eff->geteffectpar(npb+1); -freqdial->value(freq); - -int gain=eff->geteffectpar(npb+2); -gaindial->value(gain); - -int q=eff->geteffectpar(npb+3); -qdial->value(q); - -int dbl=eff->geteffectpar(npb+4); -stagescounter->value(dbl);} - tooltip {Band no.} xywh {85 15 45 15} type Simple labelfont 1 labelsize 11 align 1 minimum 0 maximum 1 step 1 textfont 1 textsize 11 - code0 {o->bounds(0,MAX_EQ_BANDS-1);} - } - Fl_Group bandgroup { - xywh {5 5 75 85} box ENGRAVED_FRAME - code0 {if (eff->geteffectpar(10)==0) o->deactivate();} - } { - Fl_Dial freqdial { - label Freq - callback {int np=eqband*5+11; -eff->seteffectpar(np,(int) o->value()); -eqgraph->redraw();} - xywh {10 10 25 25} box ROUND_UP_BOX labelfont 1 labelsize 10 when 3 maximum 127 - class WidgetPDial - } - Fl_Dial gaindial { - label Gain - callback {int np=eqband*5+12; -eff->seteffectpar(np,(int) o->value()); -eqgraph->redraw();} - xywh {45 10 25 25} box ROUND_UP_BOX labelfont 1 labelsize 10 when 3 maximum 127 step 1 - class WidgetPDial - } - Fl_Dial qdial { - label Q - callback {int np=eqband*5+13; -eff->seteffectpar(np,(int) o->value()); -eqgraph->redraw();} - tooltip {Bandwidth/Resonance} xywh {10 50 25 25} box ROUND_UP_BOX labelfont 1 labelsize 10 when 3 maximum 127 - class WidgetPDial - } - Fl_Counter stagescounter { - label Stages - callback {int np=eqband*5+14; -eff->seteffectpar(np,(int) o->value()); -eqgraph->redraw();} - tooltip {Additional filter stages} xywh {40 55 30 15} type Simple labelfont 1 labelsize 10 minimum 1 maximum 127 step 1 textfont 1 textsize 11 - code0 {o->bounds(0,MAX_FILTER_STAGES-1);} - } - } - Fl_Choice typechoice { - label Type - callback {int np=eqband*5+10; -eff->seteffectpar(np,(int) o->value()); -bandcounter->do_callback(); -eqgraph->redraw();} - tooltip Type xywh {135 15 40 15} down_box BORDER_BOX labelfont 1 labelsize 10 align 1 when 6 textsize 10 - } { - MenuItem {} { - label OFF - xywh {10 10 100 20} labelfont 1 labelsize 10 - } - MenuItem {} { - label Lp1 - xywh {20 20 100 20} labelfont 1 labelsize 10 - } - MenuItem {} { - label Hp1 - xywh {30 30 100 20} labelfont 1 labelsize 10 - } - MenuItem {} { - label Lp2 - xywh {40 40 100 20} labelfont 1 labelsize 10 - } - MenuItem {} { - label Hp2 - xywh {50 50 100 20} labelfont 1 labelsize 10 - } - MenuItem {} { - label Bp2 - xywh {60 60 100 20} labelfont 1 labelsize 10 - } - MenuItem {} { - label N2 - xywh {70 70 100 20} labelfont 1 labelsize 10 - } - MenuItem {} { - label Pk - xywh {90 90 100 20} labelfont 1 labelsize 10 - } - MenuItem {} { - label LSh - xywh {80 80 100 20} labelfont 1 labelsize 10 - } - MenuItem {} { - label HSh - xywh {90 90 100 20} labelfont 1 labelsize 10 - } - } - Fl_Box eqgraph { - xywh {85 35 140 55} box BORDER_BOX color 178 - code0 {o->init(eff);} - class EQGraph - } - } - } - Function {make_dynamicfilter_window()} {} { - Fl_Window effdynamicfilterwindow { - xywh {475 471 230 95} type Double box PLASTIC_UP_BOX color 221 labelfont 1 hide - class Fl_Group - } { - Fl_Choice dfp { - label Preset - callback {eff->changepreset((int)o->value()); -refresh(eff);} - xywh {10 15 90 15} down_box BORDER_BOX color 14 selection_color 0 labelfont 1 labelsize 10 align 5 textfont 1 textsize 10 textcolor 7 - } { - MenuItem {} { - label WahWah - xywh {30 30 100 20} labelfont 1 labelsize 10 labelcolor 7 - } - MenuItem {} { - label AutoWah - xywh {40 40 100 20} labelfont 1 labelsize 10 labelcolor 7 - } - MenuItem {} { - label Sweep - xywh {50 50 100 20} labelfont 1 labelsize 10 labelcolor 7 - } - MenuItem {} { - label VocalMorph1 - xywh {50 50 100 20} labelfont 1 labelsize 10 labelcolor 7 - } - MenuItem {} { - label VocalMorph2 - xywh {60 60 100 20} labelfont 1 labelsize 10 labelcolor 7 - } - } - Fl_Text_Display {} { - label DynFilter - xywh {100 10 10 20} box NO_BOX labeltype EMBOSSED_LABEL labelfont 1 labelsize 22 align 8 - } - Fl_Dial dfp0 { - label Vol - callback {eff->seteffectpar(0,(int) o->value());} - tooltip {Effect Volume} xywh {10 40 30 30} box ROUND_UP_BOX labelfont 1 labelsize 11 maximum 127 - class WidgetPDial - } - Fl_Dial dfp2 { - label Freq - callback {eff->seteffectpar(2,(int) o->value());} - tooltip {LFO frequency} xywh {45 40 30 30} box ROUND_UP_BOX labelfont 1 labelsize 11 maximum 127 - class WidgetPDial - } - Fl_Dial dfp6 { - label LfoD - callback {eff->seteffectpar(6,(int) o->value());} - tooltip {LFO depth} xywh {80 40 30 30} box ROUND_UP_BOX labelfont 1 labelsize 11 maximum 127 - class WidgetPDial - } - Fl_Group {} { - xywh {115 40 65 45} box BORDER_BOX color 181 - } { - Fl_Dial dfp7 { - label {A.S.} - callback {eff->seteffectpar(7,(int) o->value());} - tooltip {how filter varies with amplitude} xywh {120 45 25 25} box ROUND_UP_BOX labelfont 1 labelsize 11 maximum 127 - class WidgetPDial - } - Fl_Dial dfp9 { - label {A.M} - callback {eff->seteffectpar(9,(int) o->value());} - tooltip {how quickly the filter varies with amplitude} xywh {150 45 25 25} box ROUND_UP_BOX labelfont 1 labelsize 11 maximum 127 - class WidgetPDial - } - } - } - } - Function {init(EffectMgr *eff_)} {} { - code {eff=eff_; - -make_null_window(); -make_reverb_window(); -make_echo_window(); -make_chorus_window(); -make_phaser_window(); -make_alienwah_window(); -make_distorsion_window(); -make_eq_window(); -make_dynamicfilter_window(); - -int px=this->parent()->x(); -int py=this->parent()->y(); - -effnullwindow->position(px,py); -effreverbwindow->position(px,py); -effechowindow->position(px,py); -effchoruswindow->position(px,py); -effphaserwindow->position(px,py); -effalienwahwindow->position(px,py); -effdistorsionwindow->position(px,py); -effeqwindow->position(px,py); -effdynamicfilterwindow->position(px,py); - -refresh(eff);} {} - } - Function {refresh(EffectMgr *eff_)} {} { - code {eff=eff_; -this->hide(); - -effnullwindow->hide(); -effreverbwindow->hide(); -effechowindow->hide(); -effchoruswindow->hide(); -effphaserwindow->hide(); -effalienwahwindow->hide(); -effdistorsionwindow->hide(); -effeqwindow->hide(); -effdynamicfilterwindow->hide(); - -eqband=0; - - -switch(eff->geteffect()){ - case 1: - revp->value(eff->getpreset()); - revp0->value(eff->geteffectpar(0));if (eff->insertion!=0) revp0->label("D/W"); - revp2->value(eff->geteffectpar(2)); - revp3->value(eff->geteffectpar(3)); - revp9->value(eff->geteffectpar(9)); - effreverbwindow->show(); - break; - case 2: - echop->value(eff->getpreset()); - echop0->value(eff->geteffectpar(0));if (eff->insertion!=0) echop0->label("D/W"); - echop2->value(eff->geteffectpar(2)); - echop5->value(eff->geteffectpar(5)); - effechowindow->show(); - break; - case 3: - chorusp->value(eff->getpreset()); - chorusp0->value(eff->geteffectpar(0));if (eff->insertion!=0) chorusp0->label("D/W"); - chorusp2->value(eff->geteffectpar(2)); - chorusp6->value(eff->geteffectpar(6)); - chorusp7->value(eff->geteffectpar(7)); - chorusp8->value(eff->geteffectpar(8)); - effchoruswindow->show(); - break; - case 4: - phaserp->value(eff->getpreset()); - phaserp0->value(eff->geteffectpar(0));if (eff->insertion!=0) phaserp0->label("D/W"); - phaserp2->value(eff->geteffectpar(2)); - phaserp5->value(eff->geteffectpar(5)); - phaserp6->value(eff->geteffectpar(6)); - phaserp7->value(eff->geteffectpar(7)); - phaserp8->value(eff->geteffectpar(8)); - effphaserwindow->show(); - break; - case 5: - awp->value(eff->getpreset()); - awp0->value(eff->geteffectpar(0));if (eff->insertion!=0) awp0->label("D/W"); - awp2->value(eff->geteffectpar(2)); - awp6->value(eff->geteffectpar(6)); - awp8->value(eff->geteffectpar(8)); - effalienwahwindow->show(); - break; - case 6: - distp->value(eff->getpreset()); - distp0->value(eff->geteffectpar(0));if (eff->insertion!=0) distp0->label("D/W"); - distp3->value(eff->geteffectpar(3)); - distp4->value(eff->geteffectpar(4)); - distp5->value(eff->geteffectpar(5)); - distp7->value(eff->geteffectpar(7)); - effdistorsionwindow->show(); - break; - case 7: - bandcounter->value(eqband); - bandcounter->do_callback(); - typechoice->value(eff->geteffectpar(10)); - eqgraph->redraw(); - freqdial->value(eff->geteffectpar(11)); - gaindial->value(eff->geteffectpar(12)); - if (eff->geteffectpar(10)<6) gaindial->deactivate(); - qdial->value(eff->geteffectpar(13)); - stagescounter->value(eff->geteffectpar(14)); - eqgraph->init(eff); - effeqwindow->show(); - break; - case 8: - dfp->value(eff->getpreset()); - dfp0->value(eff->geteffectpar(0));if (eff->insertion!=0) dfp0->label("D/W"); - dfp2->value(eff->geteffectpar(2)); - dfp6->value(eff->geteffectpar(6)); - dfp7->value(eff->geteffectpar(7)); - dfp9->value(eff->geteffectpar(9)); - - - effdynamicfilterwindow->show(); - break; - default:effnullwindow->show(); - break; -}; - -this->show();} {} - } - Function {refresh()} {} { - code {refresh(eff);} {} - } - decl {EffectMgr *eff;} {} - decl {int eqband;} {} -} diff --git a/plugins/zynaddsubfx/src/UI/EffUI.h b/plugins/zynaddsubfx/src/UI/EffUI.h deleted file mode 100644 index be2f5f4a8..000000000 --- a/plugins/zynaddsubfx/src/UI/EffUI.h +++ /dev/null @@ -1,820 +0,0 @@ -// generated by Fast Light User Interface Designer (fluid) version 1.0300 - -#ifndef EffUI_h -#define EffUI_h -#include -#include -#include -#include -#include "../globals.h" -#include "WidgetPDial.h" -#include "EnvelopeUI.h" -#include "FilterUI.h" -#include "../Misc/Util.h" -#include "../Effects/EffectMgr.h" -#include "PresetsUI.h" - -class EQGraph : public Fl_Box { -public: - EQGraph(int x,int y, int w, int h, const char *label=0); - void init(EffectMgr *eff_); - void draw_freq_line(REALTYPE freq,int type); - void draw(); - int getresponse(int maxy,REALTYPE freq); - REALTYPE getfreqx(REALTYPE x); - REALTYPE getfreqpos(REALTYPE freq); -private: - int oldx,oldy; -public: - REALTYPE khzval; -private: - EffectMgr *eff; - int maxdB; -}; -#include -#include -#include -#include -#include -#include -#include - -class EffUI : public Fl_Group,public PresetsUI_ { -public: - EffUI(int x,int y, int w, int h, const char *label=0); - ~EffUI(); - Fl_Group* make_null_window(); - Fl_Group *effnullwindow; - Fl_Group* make_reverb_window(); - Fl_Group *effreverbwindow; - Fl_Choice *revp; -private: - void cb_revp_i(Fl_Choice*, void*); - static void cb_revp(Fl_Choice*, void*); - static Fl_Menu_Item menu_revp[]; -public: - Fl_Choice *revp10; -private: - void cb_revp10_i(Fl_Choice*, void*); - static void cb_revp10(Fl_Choice*, void*); - static Fl_Menu_Item menu_revp10[]; -public: - WidgetPDial *revp0; -private: - void cb_revp0_i(WidgetPDial*, void*); - static void cb_revp0(WidgetPDial*, void*); -public: - WidgetPDial *revp1; -private: - void cb_revp1_i(WidgetPDial*, void*); - static void cb_revp1(WidgetPDial*, void*); -public: - WidgetPDial *revp2; -private: - void cb_revp2_i(WidgetPDial*, void*); - static void cb_revp2(WidgetPDial*, void*); -public: - WidgetPDial *revp3; -private: - void cb_revp3_i(WidgetPDial*, void*); - static void cb_revp3(WidgetPDial*, void*); -public: - WidgetPDial *revp4; -private: - void cb_revp4_i(WidgetPDial*, void*); - static void cb_revp4(WidgetPDial*, void*); -public: - WidgetPDial *revp12; -private: - void cb_revp12_i(WidgetPDial*, void*); - static void cb_revp12(WidgetPDial*, void*); -public: - WidgetPDial *revp6; -private: - void cb_revp6_i(WidgetPDial*, void*); - static void cb_revp6(WidgetPDial*, void*); -public: - WidgetPDial *revp7; -private: - void cb_revp7_i(WidgetPDial*, void*); - static void cb_revp7(WidgetPDial*, void*); -public: - WidgetPDial *revp8; -private: - void cb_revp8_i(WidgetPDial*, void*); - static void cb_revp8(WidgetPDial*, void*); -public: - WidgetPDial *revp9; -private: - void cb_revp9_i(WidgetPDial*, void*); - static void cb_revp9(WidgetPDial*, void*); -public: - WidgetPDial *revp11; -private: - void cb_revp11_i(WidgetPDial*, void*); - static void cb_revp11(WidgetPDial*, void*); -public: - Fl_Group* make_echo_window(); - Fl_Group *effechowindow; - Fl_Choice *echop; -private: - void cb_echop_i(Fl_Choice*, void*); - static void cb_echop(Fl_Choice*, void*); - static Fl_Menu_Item menu_echop[]; -public: - WidgetPDial *echop0; -private: - void cb_echop0_i(WidgetPDial*, void*); - static void cb_echop0(WidgetPDial*, void*); -public: - WidgetPDial *echop1; -private: - void cb_echop1_i(WidgetPDial*, void*); - static void cb_echop1(WidgetPDial*, void*); -public: - WidgetPDial *echop2; -private: - void cb_echop2_i(WidgetPDial*, void*); - static void cb_echop2(WidgetPDial*, void*); -public: - WidgetPDial *echop3; -private: - void cb_echop3_i(WidgetPDial*, void*); - static void cb_echop3(WidgetPDial*, void*); -public: - WidgetPDial *echop4; -private: - void cb_echop4_i(WidgetPDial*, void*); - static void cb_echop4(WidgetPDial*, void*); -public: - WidgetPDial *echop5; -private: - void cb_echop5_i(WidgetPDial*, void*); - static void cb_echop5(WidgetPDial*, void*); -public: - WidgetPDial *echop6; -private: - void cb_echop6_i(WidgetPDial*, void*); - static void cb_echop6(WidgetPDial*, void*); -public: - Fl_Group* make_chorus_window(); - Fl_Group *effchoruswindow; - Fl_Choice *chorusp; -private: - void cb_chorusp_i(Fl_Choice*, void*); - static void cb_chorusp(Fl_Choice*, void*); - static Fl_Menu_Item menu_chorusp[]; -public: - WidgetPDial *chorusp0; -private: - void cb_chorusp0_i(WidgetPDial*, void*); - static void cb_chorusp0(WidgetPDial*, void*); -public: - WidgetPDial *chorusp1; -private: - void cb_chorusp1_i(WidgetPDial*, void*); - static void cb_chorusp1(WidgetPDial*, void*); -public: - WidgetPDial *chorusp2; -private: - void cb_chorusp2_i(WidgetPDial*, void*); - static void cb_chorusp2(WidgetPDial*, void*); -public: - WidgetPDial *chorusp3; -private: - void cb_chorusp3_i(WidgetPDial*, void*); - static void cb_chorusp3(WidgetPDial*, void*); -public: - WidgetPDial *chorusp5; -private: - void cb_chorusp5_i(WidgetPDial*, void*); - static void cb_chorusp5(WidgetPDial*, void*); -public: - WidgetPDial *chorusp6; -private: - void cb_chorusp6_i(WidgetPDial*, void*); - static void cb_chorusp6(WidgetPDial*, void*); -public: - WidgetPDial *chorusp7; -private: - void cb_chorusp7_i(WidgetPDial*, void*); - static void cb_chorusp7(WidgetPDial*, void*); -public: - WidgetPDial *chorusp8; -private: - void cb_chorusp8_i(WidgetPDial*, void*); - static void cb_chorusp8(WidgetPDial*, void*); -public: - WidgetPDial *chorusp9; -private: - void cb_chorusp9_i(WidgetPDial*, void*); - static void cb_chorusp9(WidgetPDial*, void*); - void cb_Flange_i(Fl_Check_Button*, void*); - static void cb_Flange(Fl_Check_Button*, void*); -public: - Fl_Check_Button *chorusp11; -private: - void cb_chorusp11_i(Fl_Check_Button*, void*); - static void cb_chorusp11(Fl_Check_Button*, void*); -public: - Fl_Choice *chorusp4; -private: - void cb_chorusp4_i(Fl_Choice*, void*); - static void cb_chorusp4(Fl_Choice*, void*); - static Fl_Menu_Item menu_chorusp4[]; -public: - Fl_Group* make_phaser_window(); - Fl_Group *effphaserwindow; - Fl_Choice *phaserp; -private: - void cb_phaserp_i(Fl_Choice*, void*); - static void cb_phaserp(Fl_Choice*, void*); - static Fl_Menu_Item menu_phaserp[]; -public: - WidgetPDial *phaserp0; -private: - void cb_phaserp0_i(WidgetPDial*, void*); - static void cb_phaserp0(WidgetPDial*, void*); -public: - WidgetPDial *phaserp1; -private: - void cb_phaserp1_i(WidgetPDial*, void*); - static void cb_phaserp1(WidgetPDial*, void*); -public: - WidgetPDial *phaserp2; -private: - void cb_phaserp2_i(WidgetPDial*, void*); - static void cb_phaserp2(WidgetPDial*, void*); -public: - WidgetPDial *phaserp3; -private: - void cb_phaserp3_i(WidgetPDial*, void*); - static void cb_phaserp3(WidgetPDial*, void*); -public: - Fl_Choice *phaserp4; -private: - void cb_phaserp4_i(Fl_Choice*, void*); - static void cb_phaserp4(Fl_Choice*, void*); - static Fl_Menu_Item menu_phaserp4[]; -public: - WidgetPDial *phaserp5; -private: - void cb_phaserp5_i(WidgetPDial*, void*); - static void cb_phaserp5(WidgetPDial*, void*); -public: - WidgetPDial *phaserp6; -private: - void cb_phaserp6_i(WidgetPDial*, void*); - static void cb_phaserp6(WidgetPDial*, void*); -public: - WidgetPDial *phaserp7; -private: - void cb_phaserp7_i(WidgetPDial*, void*); - static void cb_phaserp7(WidgetPDial*, void*); -public: - Fl_Counter *phaserp8; -private: - void cb_phaserp8_i(Fl_Counter*, void*); - static void cb_phaserp8(Fl_Counter*, void*); -public: - WidgetPDial *phaserp9; -private: - void cb_phaserp9_i(WidgetPDial*, void*); - static void cb_phaserp9(WidgetPDial*, void*); -public: - Fl_Check_Button *phaserp10; -private: - void cb_phaserp10_i(Fl_Check_Button*, void*); - static void cb_phaserp10(Fl_Check_Button*, void*); -public: - WidgetPDial *phaserp11; -private: - void cb_phaserp11_i(WidgetPDial*, void*); - static void cb_phaserp11(WidgetPDial*, void*); -public: - Fl_Check_Button *phaserp12; -private: - void cb_phaserp12_i(Fl_Check_Button*, void*); - static void cb_phaserp12(Fl_Check_Button*, void*); -public: - WidgetPDial *phaserp13; -private: - void cb_phaserp13_i(WidgetPDial*, void*); - static void cb_phaserp13(WidgetPDial*, void*); -public: - Fl_Check_Button *phaserp14; -private: - void cb_phaserp14_i(Fl_Check_Button*, void*); - static void cb_phaserp14(Fl_Check_Button*, void*); -public: - Fl_Group* make_alienwah_window(); - Fl_Group *effalienwahwindow; - Fl_Choice *awp; -private: - void cb_awp_i(Fl_Choice*, void*); - static void cb_awp(Fl_Choice*, void*); - static Fl_Menu_Item menu_awp[]; -public: - WidgetPDial *awp0; -private: - void cb_awp0_i(WidgetPDial*, void*); - static void cb_awp0(WidgetPDial*, void*); -public: - WidgetPDial *awp1; -private: - void cb_awp1_i(WidgetPDial*, void*); - static void cb_awp1(WidgetPDial*, void*); -public: - WidgetPDial *awp2; -private: - void cb_awp2_i(WidgetPDial*, void*); - static void cb_awp2(WidgetPDial*, void*); -public: - WidgetPDial *awp3; -private: - void cb_awp3_i(WidgetPDial*, void*); - static void cb_awp3(WidgetPDial*, void*); -public: - WidgetPDial *awp5; -private: - void cb_awp5_i(WidgetPDial*, void*); - static void cb_awp5(WidgetPDial*, void*); -public: - WidgetPDial *awp6; -private: - void cb_awp6_i(WidgetPDial*, void*); - static void cb_awp6(WidgetPDial*, void*); -public: - WidgetPDial *awp7; -private: - void cb_awp7_i(WidgetPDial*, void*); - static void cb_awp7(WidgetPDial*, void*); -public: - WidgetPDial *awp9; -private: - void cb_awp9_i(WidgetPDial*, void*); - static void cb_awp9(WidgetPDial*, void*); -public: - Fl_Choice *awp4; -private: - void cb_awp4_i(Fl_Choice*, void*); - static void cb_awp4(Fl_Choice*, void*); - static Fl_Menu_Item menu_awp4[]; -public: - WidgetPDial *awp10; -private: - void cb_awp10_i(WidgetPDial*, void*); - static void cb_awp10(WidgetPDial*, void*); -public: - Fl_Counter *awp8; -private: - void cb_awp8_i(Fl_Counter*, void*); - static void cb_awp8(Fl_Counter*, void*); -public: - Fl_Group* make_distorsion_window(); - Fl_Group *effdistorsionwindow; - Fl_Choice *distp; -private: - void cb_distp_i(Fl_Choice*, void*); - static void cb_distp(Fl_Choice*, void*); - static Fl_Menu_Item menu_distp[]; -public: - WidgetPDial *distp0; -private: - void cb_distp0_i(WidgetPDial*, void*); - static void cb_distp0(WidgetPDial*, void*); -public: - WidgetPDial *distp1; -private: - void cb_distp1_i(WidgetPDial*, void*); - static void cb_distp1(WidgetPDial*, void*); -public: - WidgetPDial *distp2; -private: - void cb_distp2_i(WidgetPDial*, void*); - static void cb_distp2(WidgetPDial*, void*); -public: - WidgetPDial *distp3; -private: - void cb_distp3_i(WidgetPDial*, void*); - static void cb_distp3(WidgetPDial*, void*); -public: - WidgetPDial *distp4; -private: - void cb_distp4_i(WidgetPDial*, void*); - static void cb_distp4(WidgetPDial*, void*); -public: - WidgetPDial *distp7; -private: - void cb_distp7_i(WidgetPDial*, void*); - static void cb_distp7(WidgetPDial*, void*); -public: - WidgetPDial *distp8; -private: - void cb_distp8_i(WidgetPDial*, void*); - static void cb_distp8(WidgetPDial*, void*); -public: - Fl_Choice *distp5; -private: - void cb_distp5_i(Fl_Choice*, void*); - static void cb_distp5(Fl_Choice*, void*); - static Fl_Menu_Item menu_distp5[]; -public: - Fl_Check_Button *distp6; -private: - void cb_distp6_i(Fl_Check_Button*, void*); - static void cb_distp6(Fl_Check_Button*, void*); -public: - Fl_Check_Button *distp9; -private: - void cb_distp9_i(Fl_Check_Button*, void*); - static void cb_distp9(Fl_Check_Button*, void*); -public: - Fl_Check_Button *distp10; -private: - void cb_distp10_i(Fl_Check_Button*, void*); - static void cb_distp10(Fl_Check_Button*, void*); -public: - Fl_Group* make_eq_window(); - Fl_Group *effeqwindow; - WidgetPDial *eqp0; -private: - void cb_eqp0_i(WidgetPDial*, void*); - static void cb_eqp0(WidgetPDial*, void*); -public: - Fl_Counter *bandcounter; -private: - void cb_bandcounter_i(Fl_Counter*, void*); - static void cb_bandcounter(Fl_Counter*, void*); -public: - Fl_Group *bandgroup; - WidgetPDial *freqdial; -private: - void cb_freqdial_i(WidgetPDial*, void*); - static void cb_freqdial(WidgetPDial*, void*); -public: - WidgetPDial *gaindial; -private: - void cb_gaindial_i(WidgetPDial*, void*); - static void cb_gaindial(WidgetPDial*, void*); -public: - WidgetPDial *qdial; -private: - void cb_qdial_i(WidgetPDial*, void*); - static void cb_qdial(WidgetPDial*, void*); -public: - Fl_Counter *stagescounter; -private: - void cb_stagescounter_i(Fl_Counter*, void*); - static void cb_stagescounter(Fl_Counter*, void*); -public: - Fl_Choice *typechoice; -private: - void cb_typechoice_i(Fl_Choice*, void*); - static void cb_typechoice(Fl_Choice*, void*); - static Fl_Menu_Item menu_typechoice[]; -public: - EQGraph *eqgraph; - Fl_Group* make_dynamicfilter_window(); - Fl_Group *effdynamicfilterwindow; - Fl_Choice *dfp; -private: - void cb_dfp_i(Fl_Choice*, void*); - static void cb_dfp(Fl_Choice*, void*); - static Fl_Menu_Item menu_dfp[]; -public: - WidgetPDial *dfp0; -private: - void cb_dfp0_i(WidgetPDial*, void*); - static void cb_dfp0(WidgetPDial*, void*); -public: - WidgetPDial *dfp1; -private: - void cb_dfp1_i(WidgetPDial*, void*); - static void cb_dfp1(WidgetPDial*, void*); -public: - WidgetPDial *dfp2; -private: - void cb_dfp2_i(WidgetPDial*, void*); - static void cb_dfp2(WidgetPDial*, void*); -public: - WidgetPDial *dfp3; -private: - void cb_dfp3_i(WidgetPDial*, void*); - static void cb_dfp3(WidgetPDial*, void*); -public: - WidgetPDial *dfp5; -private: - void cb_dfp5_i(WidgetPDial*, void*); - static void cb_dfp5(WidgetPDial*, void*); -public: - WidgetPDial *dfp6; -private: - void cb_dfp6_i(WidgetPDial*, void*); - static void cb_dfp6(WidgetPDial*, void*); -public: - Fl_Choice *dfp4; -private: - void cb_dfp4_i(Fl_Choice*, void*); - static void cb_dfp4(Fl_Choice*, void*); - static Fl_Menu_Item menu_dfp4[]; - void cb_Filter_i(Fl_Button*, void*); - static void cb_Filter(Fl_Button*, void*); -public: - WidgetPDial *dfp7; -private: - void cb_dfp7_i(WidgetPDial*, void*); - static void cb_dfp7(WidgetPDial*, void*); -public: - WidgetPDial *dfp9; -private: - void cb_dfp9_i(WidgetPDial*, void*); - static void cb_dfp9(WidgetPDial*, void*); -public: - Fl_Check_Button *dfp8; -private: - void cb_dfp8_i(Fl_Check_Button*, void*); - static void cb_dfp8(Fl_Check_Button*, void*); -public: - Fl_Double_Window* make_filter_window(); - Fl_Double_Window *filterwindow; -private: - void cb_Close_i(Fl_Button*, void*); - static void cb_Close(Fl_Button*, void*); -public: - void init(EffectMgr *eff_); - void refresh(EffectMgr *eff_); - void refresh(); -private: - EffectMgr *eff; - int eqband; -}; - -class SimpleEffUI : public Fl_Group,public PresetsUI_ { -public: - SimpleEffUI(int x,int y, int w, int h, const char *label=0); - ~SimpleEffUI(); - Fl_Group* make_null_window(); - Fl_Group *effnullwindow; - Fl_Group* make_reverb_window(); - Fl_Group *effreverbwindow; - Fl_Choice *revp; -private: - void cb_revp5_i(Fl_Choice*, void*); - static void cb_revp5(Fl_Choice*, void*); - static Fl_Menu_Item menu_revp1[]; -public: - WidgetPDial *revp0; -private: - void cb_revp01_i(WidgetPDial*, void*); - static void cb_revp01(WidgetPDial*, void*); -public: - WidgetPDial *revp2; -private: - void cb_revp21_i(WidgetPDial*, void*); - static void cb_revp21(WidgetPDial*, void*); -public: - WidgetPDial *revp3; -private: - void cb_revp31_i(WidgetPDial*, void*); - static void cb_revp31(WidgetPDial*, void*); -public: - WidgetPDial *revp9; -private: - void cb_revp91_i(WidgetPDial*, void*); - static void cb_revp91(WidgetPDial*, void*); -public: - Fl_Group* make_echo_window(); - Fl_Group *effechowindow; - Fl_Choice *echop; -private: - void cb_echop7_i(Fl_Choice*, void*); - static void cb_echop7(Fl_Choice*, void*); - static Fl_Menu_Item menu_echop1[]; -public: - WidgetPDial *echop0; -private: - void cb_echop01_i(WidgetPDial*, void*); - static void cb_echop01(WidgetPDial*, void*); -public: - WidgetPDial *echop2; -private: - void cb_echop21_i(WidgetPDial*, void*); - static void cb_echop21(WidgetPDial*, void*); -public: - WidgetPDial *echop5; -private: - void cb_echop51_i(WidgetPDial*, void*); - static void cb_echop51(WidgetPDial*, void*); -public: - Fl_Group* make_chorus_window(); - Fl_Group *effchoruswindow; - Fl_Choice *chorusp; -private: - void cb_choruspa_i(Fl_Choice*, void*); - static void cb_choruspa(Fl_Choice*, void*); - static Fl_Menu_Item menu_chorusp1[]; -public: - WidgetPDial *chorusp0; -private: - void cb_chorusp01_i(WidgetPDial*, void*); - static void cb_chorusp01(WidgetPDial*, void*); -public: - WidgetPDial *chorusp2; -private: - void cb_chorusp21_i(WidgetPDial*, void*); - static void cb_chorusp21(WidgetPDial*, void*); -public: - WidgetPDial *chorusp6; -private: - void cb_chorusp61_i(WidgetPDial*, void*); - static void cb_chorusp61(WidgetPDial*, void*); -public: - WidgetPDial *chorusp7; -private: - void cb_chorusp71_i(WidgetPDial*, void*); - static void cb_chorusp71(WidgetPDial*, void*); -public: - WidgetPDial *chorusp8; -private: - void cb_chorusp81_i(WidgetPDial*, void*); - static void cb_chorusp81(WidgetPDial*, void*); - void cb_Flange1_i(Fl_Check_Button*, void*); - static void cb_Flange1(Fl_Check_Button*, void*); -public: - Fl_Group* make_phaser_window(); - Fl_Group *effphaserwindow; - Fl_Choice *phaserp; -private: - void cb_phaserpa_i(Fl_Choice*, void*); - static void cb_phaserpa(Fl_Choice*, void*); - static Fl_Menu_Item menu_phaserp1[]; -public: - WidgetPDial *phaserp0; -private: - void cb_phaserp01_i(WidgetPDial*, void*); - static void cb_phaserp01(WidgetPDial*, void*); -public: - WidgetPDial *phaserp2; -private: - void cb_phaserp21_i(WidgetPDial*, void*); - static void cb_phaserp21(WidgetPDial*, void*); -public: - WidgetPDial *phaserp5; -private: - void cb_phaserp51_i(WidgetPDial*, void*); - static void cb_phaserp51(WidgetPDial*, void*); -public: - WidgetPDial *phaserp6; -private: - void cb_phaserp61_i(WidgetPDial*, void*); - static void cb_phaserp61(WidgetPDial*, void*); -public: - WidgetPDial *phaserp7; -private: - void cb_phaserp71_i(WidgetPDial*, void*); - static void cb_phaserp71(WidgetPDial*, void*); -public: - Fl_Counter *phaserp8; -private: - void cb_phaserp81_i(Fl_Counter*, void*); - static void cb_phaserp81(Fl_Counter*, void*); -public: - Fl_Group* make_alienwah_window(); - Fl_Group *effalienwahwindow; - Fl_Choice *awp; -private: - void cb_awpa_i(Fl_Choice*, void*); - static void cb_awpa(Fl_Choice*, void*); - static Fl_Menu_Item menu_awp1[]; -public: - WidgetPDial *awp0; -private: - void cb_awp01_i(WidgetPDial*, void*); - static void cb_awp01(WidgetPDial*, void*); -public: - WidgetPDial *awp2; -private: - void cb_awp21_i(WidgetPDial*, void*); - static void cb_awp21(WidgetPDial*, void*); -public: - WidgetPDial *awp6; -private: - void cb_awp61_i(WidgetPDial*, void*); - static void cb_awp61(WidgetPDial*, void*); -public: - Fl_Counter *awp8; -private: - void cb_awp81_i(Fl_Counter*, void*); - static void cb_awp81(Fl_Counter*, void*); -public: - Fl_Group* make_distorsion_window(); - Fl_Group *effdistorsionwindow; - Fl_Choice *distp; -private: - void cb_distpa_i(Fl_Choice*, void*); - static void cb_distpa(Fl_Choice*, void*); - static Fl_Menu_Item menu_distp1[]; -public: - WidgetPDial *distp0; -private: - void cb_distp01_i(WidgetPDial*, void*); - static void cb_distp01(WidgetPDial*, void*); -public: - WidgetPDial *distp3; -private: - void cb_distp31_i(WidgetPDial*, void*); - static void cb_distp31(WidgetPDial*, void*); -public: - WidgetPDial *distp4; -private: - void cb_distp41_i(WidgetPDial*, void*); - static void cb_distp41(WidgetPDial*, void*); -public: - WidgetPDial *distp7; -private: - void cb_distp71_i(WidgetPDial*, void*); - static void cb_distp71(WidgetPDial*, void*); -public: - Fl_Choice *distp5; -private: - void cb_distp51_i(Fl_Choice*, void*); - static void cb_distp51(Fl_Choice*, void*); - static Fl_Menu_Item menu_distp51[]; -public: - Fl_Group* make_eq_window(); - Fl_Group *effeqwindow; - Fl_Counter *bandcounter; -private: - void cb_bandcounter1_i(Fl_Counter*, void*); - static void cb_bandcounter1(Fl_Counter*, void*); -public: - Fl_Group *bandgroup; - WidgetPDial *freqdial; -private: - void cb_freqdial1_i(WidgetPDial*, void*); - static void cb_freqdial1(WidgetPDial*, void*); -public: - WidgetPDial *gaindial; -private: - void cb_gaindial1_i(WidgetPDial*, void*); - static void cb_gaindial1(WidgetPDial*, void*); -public: - WidgetPDial *qdial; -private: - void cb_qdial1_i(WidgetPDial*, void*); - static void cb_qdial1(WidgetPDial*, void*); -public: - Fl_Counter *stagescounter; -private: - void cb_stagescounter1_i(Fl_Counter*, void*); - static void cb_stagescounter1(Fl_Counter*, void*); -public: - Fl_Choice *typechoice; -private: - void cb_typechoice1_i(Fl_Choice*, void*); - static void cb_typechoice1(Fl_Choice*, void*); - static Fl_Menu_Item menu_typechoice1[]; -public: - EQGraph *eqgraph; - Fl_Group* make_dynamicfilter_window(); - Fl_Group *effdynamicfilterwindow; - Fl_Choice *dfp; -private: - void cb_dfpa_i(Fl_Choice*, void*); - static void cb_dfpa(Fl_Choice*, void*); - static Fl_Menu_Item menu_dfp1[]; -public: - WidgetPDial *dfp0; -private: - void cb_dfp01_i(WidgetPDial*, void*); - static void cb_dfp01(WidgetPDial*, void*); -public: - WidgetPDial *dfp2; -private: - void cb_dfp21_i(WidgetPDial*, void*); - static void cb_dfp21(WidgetPDial*, void*); -public: - WidgetPDial *dfp6; -private: - void cb_dfp61_i(WidgetPDial*, void*); - static void cb_dfp61(WidgetPDial*, void*); -public: - WidgetPDial *dfp7; -private: - void cb_dfp71_i(WidgetPDial*, void*); - static void cb_dfp71(WidgetPDial*, void*); -public: - WidgetPDial *dfp9; -private: - void cb_dfp91_i(WidgetPDial*, void*); - static void cb_dfp91(WidgetPDial*, void*); -public: - void init(EffectMgr *eff_); - void refresh(EffectMgr *eff_); - void refresh(); -private: - EffectMgr *eff; - int eqband; -}; -#endif diff --git a/plugins/zynaddsubfx/src/UI/EnvelopeUI.cc b/plugins/zynaddsubfx/src/UI/EnvelopeUI.cc deleted file mode 100644 index 78d2b17cd..000000000 --- a/plugins/zynaddsubfx/src/UI/EnvelopeUI.cc +++ /dev/null @@ -1,1525 +0,0 @@ -// generated by Fast Light User Interface Designer (fluid) version 1.0300 - -#include "EnvelopeUI.h" -//Copyright (c) 2002-2005 Nasca Octavian Paul -//License: GNU GPL version 2 or later - -EnvelopeFreeEdit::EnvelopeFreeEdit(int x,int y, int w, int h, const char *label):Fl_Box(x,y,w,h,label) { - env=NULL; - pair=NULL; -} - -void EnvelopeFreeEdit::init(EnvelopeParams *env_) { - env=env_; - oldx=-1; - currentpoint=-1; - cpx=0; - lastpoint=-1; -} - -void EnvelopeFreeEdit::setpair(Fl_Box *pair_) { - pair=pair_; -} - -int EnvelopeFreeEdit::getpointx(int n) { - int lx=w()-10; - int npoints=env->Penvpoints; - - float sum=0; - for (int i=1;igetdt(i)+1; - - float sumbefore=0;//the sum of all points before the computed point - for (int i=1;i<=n;i++) sumbefore+=env->getdt(i)+1; - - return((int) (sumbefore/(REALTYPE) sum*lx)); -} - -int EnvelopeFreeEdit::getpointy(int n) { - int ly=h()-10; - - return((int) ((1.0-env->Penvval[n]/127.0)*ly)); -} - -int EnvelopeFreeEdit::getnearest(int x,int y) { - x-=5;y-=5; - - int nearestpoint=0; - int nearestval=1000000;//a big value - for (int i=0;iPenvpoints;i++){ - int distance=abs(x-getpointx(i))+abs(y-getpointy(i)); - if (distancePfreemode==0) env->converttofree(); - int npoints=env->Penvpoints; - - if (active_r()) fl_color(FL_BLACK); - else fl_color(90,90,90); - if (!active_r()) currentpoint=-1; - - fl_rectf(ox,oy,lx,ly); - - ox+=5;oy+=5;lx-=10;ly-=10; - - //draw the lines - fl_color(FL_GRAY); - - fl_line_style(FL_SOLID); - fl_line(ox+2,oy+ly/2,ox+lx-2,oy+ly/2); - - //draws the evelope points and lines - Fl_Color alb=FL_WHITE; - if (!active_r()) alb=fl_rgb_color(180,180,180); - fl_color(alb); - int oldxx=0,xx=0,oldyy=0,yy=getpointy(0); - fl_rectf(ox-3,oy+yy-3,6,6); - for (int i=1;i=0){ - fl_color(FL_CYAN); - fl_rectf(ox+getpointx(lastpoint)-5,oy+getpointy(lastpoint)-5,10,10); - }; - - //draw the sustain position - if (env->Penvsustain>0){ - fl_color(FL_YELLOW); - xx=getpointx(env->Penvsustain); - fl_line(ox+xx,oy+0,ox+xx,oy+ly); - }; - - //Show the envelope duration and the current line duration - fl_font(FL_HELVETICA|FL_BOLD,10); - float time=0.0; - if (currentpoint<=0){ - fl_color(alb); - for (int i=1;igetdt(i); - } else { - fl_color(255,0,0); - time=env->getdt(currentpoint); - }; - char tmpstr[20]; - if (time<1000.0) snprintf((char *)&tmpstr,20,"%.1fms",time); - else snprintf((char *)&tmpstr,20,"%.2fs",time/1000.0); - fl_draw(tmpstr,ox+lx-20,oy+ly-10,20,10,FL_ALIGN_RIGHT,NULL,0); -} - -int EnvelopeFreeEdit::handle(int event) { - int x_=Fl::event_x()-x(); - int y_=Fl::event_y()-y(); - - if (event==FL_PUSH) { - currentpoint=getnearest(x_,y_); - cpx=x_; - cpdt=env->Penvdt[currentpoint]; - lastpoint=currentpoint; - redraw(); - if (pair!=NULL) pair->redraw(); - }; - - if (event==FL_RELEASE){ - currentpoint=-1; - redraw(); - if (pair!=NULL) pair->redraw(); - }; - - if ((event==FL_DRAG)&&(currentpoint>=0)){ - int ny=127-(int) (y_*127.0/h()); - if (ny<0) ny=0;if (ny>127) ny=127; - env->Penvval[currentpoint]=ny; - - int dx=(int)((x_-cpx)*0.1); - int newdt=cpdt+dx; - if (newdt<0) newdt=0;if (newdt>127) newdt=127; - if (currentpoint!=0) env->Penvdt[currentpoint]=newdt; - else env->Penvdt[currentpoint]=0; - - redraw(); - if (pair!=NULL) pair->redraw(); - }; - - - return(1); -} - -void EnvelopeUI::cb_addpoint_i(Fl_Button*, void*) { - int curpoint=freeedit->lastpoint; -if (curpoint<0) return; -//if (curpoint>=env->Penvpoints-1) return; -if (env->Penvpoints>=MAX_ENVELOPE_POINTS) return; - -for (int i=env->Penvpoints;i>=curpoint+1;i--){ - env->Penvdt[i]=env->Penvdt[i-1]; - env->Penvval[i]=env->Penvval[i-1]; -}; - -if (curpoint==0) { - env->Penvdt[1]=64; -}; - -env->Penvpoints++; -if (curpoint<=env->Penvsustain) env->Penvsustain++; - -freeedit->lastpoint+=1; -freeedit->redraw(); -envfree->redraw(); - -sustaincounter->value(env->Penvsustain); -sustaincounter->maximum(env->Penvpoints-2); -} -void EnvelopeUI::cb_addpoint(Fl_Button* o, void* v) { - ((EnvelopeUI*)(o->parent()->user_data()))->cb_addpoint_i(o,v); -} - -void EnvelopeUI::cb_deletepoint_i(Fl_Button*, void*) { - int curpoint=freeedit->lastpoint; -if (curpoint<1) return; -if (curpoint>=env->Penvpoints-1) return; -if (env->Penvpoints<=3) return; - -for (int i=curpoint+1;iPenvpoints;i++){ - env->Penvdt[i-1]=env->Penvdt[i]; - env->Penvval[i-1]=env->Penvval[i]; -}; - -env->Penvpoints--; - -if (curpoint<=env->Penvsustain) env->Penvsustain--; - - -freeedit->lastpoint-=1; -freeedit->redraw(); -envfree->redraw(); - -sustaincounter->value(env->Penvsustain); -sustaincounter->maximum(env->Penvpoints-2); -} -void EnvelopeUI::cb_deletepoint(Fl_Button* o, void* v) { - ((EnvelopeUI*)(o->parent()->user_data()))->cb_deletepoint_i(o,v); -} - -void EnvelopeUI::cb_freemodebutton_i(Fl_Light_Button*, void*) { - reinit(); - -freeedit->lastpoint=-1; -freeedit->redraw(); -} -void EnvelopeUI::cb_freemodebutton(Fl_Light_Button* o, void* v) { - ((EnvelopeUI*)(o->parent()->user_data()))->cb_freemodebutton_i(o,v); -} - -void EnvelopeUI::cb_forcedreleasecheck_i(Fl_Check_Button* o, void*) { - env->Pforcedrelease=(int)o->value(); -} -void EnvelopeUI::cb_forcedreleasecheck(Fl_Check_Button* o, void* v) { - ((EnvelopeUI*)(o->parent()->user_data()))->cb_forcedreleasecheck_i(o,v); -} - -void EnvelopeUI::cb_envstretchdial_i(WidgetPDial* o, void*) { - env->Penvstretch=(int)o->value(); -} -void EnvelopeUI::cb_envstretchdial(WidgetPDial* o, void* v) { - ((EnvelopeUI*)(o->parent()->user_data()))->cb_envstretchdial_i(o,v); -} - -void EnvelopeUI::cb_Close_i(Fl_Button*, void*) { - freemodeeditwindow->hide(); -} -void EnvelopeUI::cb_Close(Fl_Button* o, void* v) { - ((EnvelopeUI*)(o->parent()->user_data()))->cb_Close_i(o,v); -} - -void EnvelopeUI::cb_linearenvelopecheck_i(Fl_Check_Button* o, void*) { - env->Plinearenvelope=(int)o->value(); -} -void EnvelopeUI::cb_linearenvelopecheck(Fl_Check_Button* o, void* v) { - ((EnvelopeUI*)(o->parent()->user_data()))->cb_linearenvelopecheck_i(o,v); -} - -void EnvelopeUI::cb_sustaincounter_i(Fl_Counter* o, void*) { - env->Penvsustain=(int) o->value(); -freeedit->redraw(); -envfree->redraw(); -} -void EnvelopeUI::cb_sustaincounter(Fl_Counter* o, void* v) { - ((EnvelopeUI*)(o->parent()->user_data()))->cb_sustaincounter_i(o,v); -} - -void EnvelopeUI::cb_C_i(Fl_Button*, void*) { - presetsui->copy(env); -} -void EnvelopeUI::cb_C(Fl_Button* o, void* v) { - ((EnvelopeUI*)(o->parent()->user_data()))->cb_C_i(o,v); -} - -void EnvelopeUI::cb_P_i(Fl_Button*, void*) { - presetsui->paste(env,this); -} -void EnvelopeUI::cb_P(Fl_Button* o, void* v) { - ((EnvelopeUI*)(o->parent()->user_data()))->cb_P_i(o,v); -} - -void EnvelopeUI::cb_e1adt_i(WidgetPDial* o, void*) { - env->PA_dt=(int)o->value(); -freeedit->redraw(); -} -void EnvelopeUI::cb_e1adt(WidgetPDial* o, void* v) { - ((EnvelopeUI*)(o->parent()->parent()->user_data()))->cb_e1adt_i(o,v); -} - -void EnvelopeUI::cb_e1ddt_i(WidgetPDial* o, void*) { - env->PD_dt=(int)o->value(); -freeedit->redraw(); -} -void EnvelopeUI::cb_e1ddt(WidgetPDial* o, void* v) { - ((EnvelopeUI*)(o->parent()->parent()->user_data()))->cb_e1ddt_i(o,v); -} - -void EnvelopeUI::cb_e1rdt_i(WidgetPDial* o, void*) { - env->PR_dt=(int)o->value(); -freeedit->redraw(); -} -void EnvelopeUI::cb_e1rdt(WidgetPDial* o, void* v) { - ((EnvelopeUI*)(o->parent()->parent()->user_data()))->cb_e1rdt_i(o,v); -} - -void EnvelopeUI::cb_e1sval_i(WidgetPDial* o, void*) { - env->PS_val=(int)o->value(); -freeedit->redraw(); -} -void EnvelopeUI::cb_e1sval(WidgetPDial* o, void* v) { - ((EnvelopeUI*)(o->parent()->parent()->user_data()))->cb_e1sval_i(o,v); -} - -void EnvelopeUI::cb_e1forcedrelease_i(Fl_Check_Button* o, void*) { - env->Pforcedrelease=(int)o->value(); -} -void EnvelopeUI::cb_e1forcedrelease(Fl_Check_Button* o, void* v) { - ((EnvelopeUI*)(o->parent()->parent()->user_data()))->cb_e1forcedrelease_i(o,v); -} - -void EnvelopeUI::cb_e1envstretch_i(WidgetPDial* o, void*) { - env->Penvstretch=(int)o->value(); -} -void EnvelopeUI::cb_e1envstretch(WidgetPDial* o, void* v) { - ((EnvelopeUI*)(o->parent()->parent()->user_data()))->cb_e1envstretch_i(o,v); -} - -void EnvelopeUI::cb_E_i(Fl_Button*, void*) { - freemodeeditwindow->show(); -} -void EnvelopeUI::cb_E(Fl_Button* o, void* v) { - ((EnvelopeUI*)(o->parent()->parent()->user_data()))->cb_E_i(o,v); -} - -void EnvelopeUI::cb_e1linearenvelope_i(Fl_Check_Button* o, void*) { - env->Plinearenvelope=(int)o->value(); -} -void EnvelopeUI::cb_e1linearenvelope(Fl_Check_Button* o, void* v) { - ((EnvelopeUI*)(o->parent()->parent()->user_data()))->cb_e1linearenvelope_i(o,v); -} - -void EnvelopeUI::cb_C1_i(Fl_Button*, void*) { - presetsui->copy(env); -} -void EnvelopeUI::cb_C1(Fl_Button* o, void* v) { - ((EnvelopeUI*)(o->parent()->parent()->user_data()))->cb_C1_i(o,v); -} - -void EnvelopeUI::cb_P1_i(Fl_Button*, void*) { - presetsui->paste(env,this); -} -void EnvelopeUI::cb_P1(Fl_Button* o, void* v) { - ((EnvelopeUI*)(o->parent()->parent()->user_data()))->cb_P1_i(o,v); -} - -void EnvelopeUI::cb_e2aval_i(WidgetPDial* o, void*) { - env->PA_val=(int)o->value(); -freeedit->redraw(); -} -void EnvelopeUI::cb_e2aval(WidgetPDial* o, void* v) { - ((EnvelopeUI*)(o->parent()->parent()->user_data()))->cb_e2aval_i(o,v); -} - -void EnvelopeUI::cb_e2adt_i(WidgetPDial* o, void*) { - env->PA_dt=(int)o->value(); -freeedit->redraw(); -} -void EnvelopeUI::cb_e2adt(WidgetPDial* o, void* v) { - ((EnvelopeUI*)(o->parent()->parent()->user_data()))->cb_e2adt_i(o,v); -} - -void EnvelopeUI::cb_e2rval_i(WidgetPDial* o, void*) { - env->PR_val=(int)o->value(); -freeedit->redraw(); -} -void EnvelopeUI::cb_e2rval(WidgetPDial* o, void* v) { - ((EnvelopeUI*)(o->parent()->parent()->user_data()))->cb_e2rval_i(o,v); -} - -void EnvelopeUI::cb_e2rdt_i(WidgetPDial* o, void*) { - env->PR_dt=(int)o->value(); -freeedit->redraw(); -} -void EnvelopeUI::cb_e2rdt(WidgetPDial* o, void* v) { - ((EnvelopeUI*)(o->parent()->parent()->user_data()))->cb_e2rdt_i(o,v); -} - -void EnvelopeUI::cb_e2envstretch_i(WidgetPDial* o, void*) { - env->Penvstretch=(int)o->value(); -} -void EnvelopeUI::cb_e2envstretch(WidgetPDial* o, void* v) { - ((EnvelopeUI*)(o->parent()->parent()->user_data()))->cb_e2envstretch_i(o,v); -} - -void EnvelopeUI::cb_e2forcedrelease_i(Fl_Check_Button* o, void*) { - env->Pforcedrelease=(int)o->value(); -} -void EnvelopeUI::cb_e2forcedrelease(Fl_Check_Button* o, void* v) { - ((EnvelopeUI*)(o->parent()->parent()->user_data()))->cb_e2forcedrelease_i(o,v); -} - -void EnvelopeUI::cb_C2_i(Fl_Button*, void*) { - presetsui->copy(env); -} -void EnvelopeUI::cb_C2(Fl_Button* o, void* v) { - ((EnvelopeUI*)(o->parent()->parent()->user_data()))->cb_C2_i(o,v); -} - -void EnvelopeUI::cb_P2_i(Fl_Button*, void*) { - presetsui->paste(env,this); -} -void EnvelopeUI::cb_P2(Fl_Button* o, void* v) { - ((EnvelopeUI*)(o->parent()->parent()->user_data()))->cb_P2_i(o,v); -} - -void EnvelopeUI::cb_E1_i(Fl_Button*, void*) { - freemodeeditwindow->show(); -} -void EnvelopeUI::cb_E1(Fl_Button* o, void* v) { - ((EnvelopeUI*)(o->parent()->user_data()))->cb_E1_i(o,v); -} - -void EnvelopeUI::cb_e3aval_i(WidgetPDial* o, void*) { - env->PA_val=(int)o->value(); -freeedit->redraw(); -} -void EnvelopeUI::cb_e3aval(WidgetPDial* o, void* v) { - ((EnvelopeUI*)(o->parent()->parent()->user_data()))->cb_e3aval_i(o,v); -} - -void EnvelopeUI::cb_e3adt_i(WidgetPDial* o, void*) { - env->PA_dt=(int)o->value(); -freeedit->redraw(); -} -void EnvelopeUI::cb_e3adt(WidgetPDial* o, void* v) { - ((EnvelopeUI*)(o->parent()->parent()->user_data()))->cb_e3adt_i(o,v); -} - -void EnvelopeUI::cb_e3dval_i(WidgetPDial* o, void*) { - env->PD_val=(int)o->value(); -freeedit->redraw(); -} -void EnvelopeUI::cb_e3dval(WidgetPDial* o, void* v) { - ((EnvelopeUI*)(o->parent()->parent()->user_data()))->cb_e3dval_i(o,v); -} - -void EnvelopeUI::cb_e3ddt_i(WidgetPDial* o, void*) { - env->PD_dt=(int)o->value(); -freeedit->redraw(); -} -void EnvelopeUI::cb_e3ddt(WidgetPDial* o, void* v) { - ((EnvelopeUI*)(o->parent()->parent()->user_data()))->cb_e3ddt_i(o,v); -} - -void EnvelopeUI::cb_e3rdt_i(WidgetPDial* o, void*) { - env->PR_dt=(int)o->value(); -freeedit->redraw(); -} -void EnvelopeUI::cb_e3rdt(WidgetPDial* o, void* v) { - ((EnvelopeUI*)(o->parent()->parent()->user_data()))->cb_e3rdt_i(o,v); -} - -void EnvelopeUI::cb_e3rval_i(WidgetPDial* o, void*) { - env->PR_val=(int)o->value(); -freeedit->redraw(); -} -void EnvelopeUI::cb_e3rval(WidgetPDial* o, void* v) { - ((EnvelopeUI*)(o->parent()->parent()->user_data()))->cb_e3rval_i(o,v); -} - -void EnvelopeUI::cb_e3envstretch_i(WidgetPDial* o, void*) { - env->Penvstretch=(int)o->value(); -} -void EnvelopeUI::cb_e3envstretch(WidgetPDial* o, void* v) { - ((EnvelopeUI*)(o->parent()->parent()->user_data()))->cb_e3envstretch_i(o,v); -} - -void EnvelopeUI::cb_e3forcedrelease_i(Fl_Check_Button* o, void*) { - env->Pforcedrelease=(int)o->value(); -} -void EnvelopeUI::cb_e3forcedrelease(Fl_Check_Button* o, void* v) { - ((EnvelopeUI*)(o->parent()->parent()->user_data()))->cb_e3forcedrelease_i(o,v); -} - -void EnvelopeUI::cb_E2_i(Fl_Button*, void*) { - freemodeeditwindow->show(); -} -void EnvelopeUI::cb_E2(Fl_Button* o, void* v) { - ((EnvelopeUI*)(o->parent()->parent()->user_data()))->cb_E2_i(o,v); -} - -void EnvelopeUI::cb_C3_i(Fl_Button*, void*) { - presetsui->copy(env); -} -void EnvelopeUI::cb_C3(Fl_Button* o, void* v) { - ((EnvelopeUI*)(o->parent()->parent()->user_data()))->cb_C3_i(o,v); -} - -void EnvelopeUI::cb_P3_i(Fl_Button*, void*) { - presetsui->paste(env,this); -} -void EnvelopeUI::cb_P3(Fl_Button* o, void* v) { - ((EnvelopeUI*)(o->parent()->parent()->user_data()))->cb_P3_i(o,v); -} - -void EnvelopeUI::cb_e4aval_i(WidgetPDial* o, void*) { - env->PA_val=(int)o->value(); -freeedit->redraw(); -} -void EnvelopeUI::cb_e4aval(WidgetPDial* o, void* v) { - ((EnvelopeUI*)(o->parent()->parent()->user_data()))->cb_e4aval_i(o,v); -} - -void EnvelopeUI::cb_e4adt_i(WidgetPDial* o, void*) { - env->PA_dt=(int)o->value(); -freeedit->redraw(); -} -void EnvelopeUI::cb_e4adt(WidgetPDial* o, void* v) { - ((EnvelopeUI*)(o->parent()->parent()->user_data()))->cb_e4adt_i(o,v); -} - -void EnvelopeUI::cb_e4rval_i(WidgetPDial* o, void*) { - env->PR_val=(int)o->value(); -freeedit->redraw(); -} -void EnvelopeUI::cb_e4rval(WidgetPDial* o, void* v) { - ((EnvelopeUI*)(o->parent()->parent()->user_data()))->cb_e4rval_i(o,v); -} - -void EnvelopeUI::cb_e4rdt_i(WidgetPDial* o, void*) { - env->PR_dt=(int)o->value(); -freeedit->redraw(); -} -void EnvelopeUI::cb_e4rdt(WidgetPDial* o, void* v) { - ((EnvelopeUI*)(o->parent()->parent()->user_data()))->cb_e4rdt_i(o,v); -} - -void EnvelopeUI::cb_e4envstretch_i(WidgetPDial* o, void*) { - env->Penvstretch=(int)o->value(); -} -void EnvelopeUI::cb_e4envstretch(WidgetPDial* o, void* v) { - ((EnvelopeUI*)(o->parent()->parent()->user_data()))->cb_e4envstretch_i(o,v); -} - -void EnvelopeUI::cb_e4forcedrelease_i(Fl_Check_Button* o, void*) { - env->Pforcedrelease=(int)o->value(); -} -void EnvelopeUI::cb_e4forcedrelease(Fl_Check_Button* o, void* v) { - ((EnvelopeUI*)(o->parent()->parent()->user_data()))->cb_e4forcedrelease_i(o,v); -} - -void EnvelopeUI::cb_C4_i(Fl_Button*, void*) { - presetsui->copy(env); -} -void EnvelopeUI::cb_C4(Fl_Button* o, void* v) { - ((EnvelopeUI*)(o->parent()->parent()->user_data()))->cb_C4_i(o,v); -} - -void EnvelopeUI::cb_P4_i(Fl_Button*, void*) { - presetsui->paste(env,this); -} -void EnvelopeUI::cb_P4(Fl_Button* o, void* v) { - ((EnvelopeUI*)(o->parent()->parent()->user_data()))->cb_P4_i(o,v); -} - -void EnvelopeUI::cb_E3_i(Fl_Button*, void*) { - freemodeeditwindow->show(); -} -void EnvelopeUI::cb_E3(Fl_Button* o, void* v) { - ((EnvelopeUI*)(o->parent()->user_data()))->cb_E3_i(o,v); -} - -void EnvelopeUI::cb_freeeditsmall_i(EnvelopeFreeEdit*, void*) { - envfree->redraw(); -} -void EnvelopeUI::cb_freeeditsmall(EnvelopeFreeEdit* o, void* v) { - ((EnvelopeUI*)(o->parent()->parent()->user_data()))->cb_freeeditsmall_i(o,v); -} - -void EnvelopeUI::cb_E4_i(Fl_Button*, void*) { - freemodeeditwindow->show(); -} -void EnvelopeUI::cb_E4(Fl_Button* o, void* v) { - ((EnvelopeUI*)(o->parent()->parent()->user_data()))->cb_E4_i(o,v); -} - -void EnvelopeUI::cb_C5_i(Fl_Button*, void*) { - presetsui->copy(env); -} -void EnvelopeUI::cb_C5(Fl_Button* o, void* v) { - ((EnvelopeUI*)(o->parent()->parent()->user_data()))->cb_C5_i(o,v); -} - -void EnvelopeUI::cb_P5_i(Fl_Button*, void*) { - presetsui->paste(env,this); -} -void EnvelopeUI::cb_P5(Fl_Button* o, void* v) { - ((EnvelopeUI*)(o->parent()->parent()->user_data()))->cb_P5_i(o,v); -} - -EnvelopeUI::EnvelopeUI(int x,int y, int w, int h, const char *label):Fl_Group(x,y,w,h,label) { - env=NULL; - freemodeeditwindow=NULL; - envADSR=NULL; - envASR=NULL; - envADSRfilter=NULL; - envASRbw=NULL; - envfree=NULL; -} - -EnvelopeUI::~EnvelopeUI() { - envwindow->hide(); - hide(); - freemodeeditwindow->hide(); - delete (freemodeeditwindow); -} - -Fl_Double_Window* EnvelopeUI::make_freemode_edit_window() { - { freemodeeditwindow = new Fl_Double_Window(575, 180, "Envelope"); - freemodeeditwindow->user_data((void*)(this)); - { EnvelopeFreeEdit* o = freeedit = new EnvelopeFreeEdit(5, 5, 565, 145, "Envelope"); - freeedit->box(FL_FLAT_BOX); - freeedit->color(FL_FOREGROUND_COLOR); - freeedit->selection_color(FL_BACKGROUND_COLOR); - freeedit->labeltype(FL_NORMAL_LABEL); - freeedit->labelfont(0); - freeedit->labelsize(14); - freeedit->labelcolor(FL_FOREGROUND_COLOR); - freeedit->align(Fl_Align(FL_ALIGN_CENTER)); - freeedit->when(FL_WHEN_RELEASE); - o->init(env); - } // EnvelopeFreeEdit* freeedit - { Fl_Button* o = addpoint = new Fl_Button(115, 155, 80, 20, "Add point"); - addpoint->box(FL_THIN_UP_BOX); - addpoint->callback((Fl_Callback*)cb_addpoint); - if (env->Pfreemode==0) o->hide(); - } // Fl_Button* addpoint - { Fl_Button* o = deletepoint = new Fl_Button(200, 155, 80, 20, "Delete point"); - deletepoint->box(FL_THIN_UP_BOX); - deletepoint->callback((Fl_Callback*)cb_deletepoint); - if (env->Pfreemode==0) o->hide(); - } // Fl_Button* deletepoint - { freemodebutton = new Fl_Light_Button(10, 155, 95, 25, "FreeMode"); - freemodebutton->tooltip("Enable or disable the freemode"); - freemodebutton->box(FL_PLASTIC_UP_BOX); - freemodebutton->callback((Fl_Callback*)cb_freemodebutton); - } // Fl_Light_Button* freemodebutton - { Fl_Check_Button* o = forcedreleasecheck = new Fl_Check_Button(410, 165, 40, 15, "frcR"); - forcedreleasecheck->tooltip("Forced Relase"); - forcedreleasecheck->down_box(FL_DOWN_BOX); - forcedreleasecheck->labelsize(10); - forcedreleasecheck->callback((Fl_Callback*)cb_forcedreleasecheck); - o->value(env->Pforcedrelease); - if (env->Pfreemode==0) o->hide(); - } // Fl_Check_Button* forcedreleasecheck - { WidgetPDial* o = envstretchdial = new WidgetPDial(380, 155, 25, 25, "Str."); - envstretchdial->tooltip("Envelope stretch (on lower notes make the envelope longer)"); - envstretchdial->box(FL_ROUND_UP_BOX); - envstretchdial->color(FL_BACKGROUND_COLOR); - envstretchdial->selection_color(FL_INACTIVE_COLOR); - envstretchdial->labeltype(FL_NORMAL_LABEL); - envstretchdial->labelfont(0); - envstretchdial->labelsize(10); - envstretchdial->labelcolor(FL_FOREGROUND_COLOR); - envstretchdial->maximum(127); - envstretchdial->step(1); - envstretchdial->callback((Fl_Callback*)cb_envstretchdial); - envstretchdial->align(Fl_Align(FL_ALIGN_LEFT)); - envstretchdial->when(FL_WHEN_CHANGED); - o->value(env->Penvstretch); - if (env->Pfreemode==0) o->hide(); - } // WidgetPDial* envstretchdial - { Fl_Button* o = new Fl_Button(510, 155, 60, 25, "Close"); - o->box(FL_THIN_UP_BOX); - o->callback((Fl_Callback*)cb_Close); - } // Fl_Button* o - { Fl_Check_Button* o = linearenvelopecheck = new Fl_Check_Button(410, 151, 30, 15, "L"); - linearenvelopecheck->tooltip("Linear Envelope"); - linearenvelopecheck->down_box(FL_DOWN_BOX); - linearenvelopecheck->labelsize(10); - linearenvelopecheck->callback((Fl_Callback*)cb_linearenvelopecheck); - o->value(env->Plinearenvelope); - if ((env->Pfreemode==0)||(env->Envmode>2)) o->hide(); - } // Fl_Check_Button* linearenvelopecheck - { Fl_Counter* o = sustaincounter = new Fl_Counter(315, 155, 40, 15, "Sust"); - sustaincounter->tooltip("Sustain (0 is disabled)"); - sustaincounter->type(1); - sustaincounter->labelsize(11); - sustaincounter->minimum(0); - sustaincounter->maximum(127); - sustaincounter->step(1); - sustaincounter->callback((Fl_Callback*)cb_sustaincounter); - sustaincounter->align(Fl_Align(FL_ALIGN_LEFT)); - o->value(env->Penvsustain); - if (env->Pfreemode==0) o->hide(); - o->maximum(env->Penvpoints-2); - } // Fl_Counter* sustaincounter - { Fl_Button* o = new Fl_Button(465, 160, 15, 15, "C"); - o->box(FL_THIN_UP_BOX); - o->color((Fl_Color)179); - o->labelfont(1); - o->labelsize(10); - o->labelcolor(FL_BACKGROUND2_COLOR); - o->callback((Fl_Callback*)cb_C); - } // Fl_Button* o - { Fl_Button* o = new Fl_Button(482, 160, 15, 15, "P"); - o->box(FL_THIN_UP_BOX); - o->color((Fl_Color)179); - o->labelfont(1); - o->labelsize(10); - o->labelcolor(FL_BACKGROUND2_COLOR); - o->callback((Fl_Callback*)cb_P); - } // Fl_Button* o - freemodeeditwindow->end(); - } // Fl_Double_Window* freemodeeditwindow - return freemodeeditwindow; -} - -Fl_Group* EnvelopeUI::make_ADSR_window() { - { envADSR = new Fl_Group(0, 0, 205, 70); - envADSR->box(FL_FLAT_BOX); - envADSR->color(FL_LIGHT1); - envADSR->selection_color(FL_BACKGROUND_COLOR); - envADSR->labeltype(FL_NO_LABEL); - envADSR->labelfont(1); - envADSR->labelsize(14); - envADSR->labelcolor(FL_FOREGROUND_COLOR); - envADSR->user_data((void*)(this)); - envADSR->align(Fl_Align(FL_ALIGN_TOP)); - envADSR->when(FL_WHEN_RELEASE); - { Fl_Group* o = new Fl_Group(0, 0, 205, 70, "Amplitude Envelope"); - o->box(FL_PLASTIC_UP_BOX); - o->color(FL_CYAN); - o->labeltype(FL_ENGRAVED_LABEL); - o->labelsize(10); - o->align(Fl_Align(FL_ALIGN_TOP|FL_ALIGN_INSIDE)); - { WidgetPDial* o = e1adt = new WidgetPDial(5, 20, 30, 30, "A.dt"); - e1adt->tooltip("Attack time"); - e1adt->box(FL_ROUND_UP_BOX); - e1adt->color(FL_BACKGROUND_COLOR); - e1adt->selection_color(FL_INACTIVE_COLOR); - e1adt->labeltype(FL_NORMAL_LABEL); - e1adt->labelfont(0); - e1adt->labelsize(10); - e1adt->labelcolor(FL_FOREGROUND_COLOR); - e1adt->maximum(127); - e1adt->step(1); - e1adt->callback((Fl_Callback*)cb_e1adt); - e1adt->align(Fl_Align(FL_ALIGN_BOTTOM)); - e1adt->when(FL_WHEN_CHANGED); - o->value(env->PA_dt); - } // WidgetPDial* e1adt - { WidgetPDial* o = e1ddt = new WidgetPDial(40, 20, 30, 30, "D.dt"); - e1ddt->tooltip("Decay time"); - e1ddt->box(FL_ROUND_UP_BOX); - e1ddt->color(FL_BACKGROUND_COLOR); - e1ddt->selection_color(FL_INACTIVE_COLOR); - e1ddt->labeltype(FL_NORMAL_LABEL); - e1ddt->labelfont(0); - e1ddt->labelsize(10); - e1ddt->labelcolor(FL_FOREGROUND_COLOR); - e1ddt->maximum(127); - e1ddt->step(1); - e1ddt->callback((Fl_Callback*)cb_e1ddt); - e1ddt->align(Fl_Align(FL_ALIGN_BOTTOM)); - e1ddt->when(FL_WHEN_CHANGED); - o->value(env->PD_dt); - } // WidgetPDial* e1ddt - { WidgetPDial* o = e1rdt = new WidgetPDial(110, 20, 30, 30, "R.dt"); - e1rdt->tooltip("Release time"); - e1rdt->box(FL_ROUND_UP_BOX); - e1rdt->color(FL_BACKGROUND_COLOR); - e1rdt->selection_color(FL_INACTIVE_COLOR); - e1rdt->labeltype(FL_NORMAL_LABEL); - e1rdt->labelfont(0); - e1rdt->labelsize(10); - e1rdt->labelcolor(FL_FOREGROUND_COLOR); - e1rdt->maximum(127); - e1rdt->step(1); - e1rdt->callback((Fl_Callback*)cb_e1rdt); - e1rdt->align(Fl_Align(FL_ALIGN_BOTTOM)); - e1rdt->when(FL_WHEN_CHANGED); - o->value(env->PR_dt); - } // WidgetPDial* e1rdt - { WidgetPDial* o = e1sval = new WidgetPDial(75, 20, 30, 30, "S.val"); - e1sval->tooltip("Sustain value"); - e1sval->box(FL_ROUND_UP_BOX); - e1sval->color(FL_BACKGROUND_COLOR); - e1sval->selection_color(FL_INACTIVE_COLOR); - e1sval->labeltype(FL_NORMAL_LABEL); - e1sval->labelfont(0); - e1sval->labelsize(10); - e1sval->labelcolor(FL_FOREGROUND_COLOR); - e1sval->maximum(127); - e1sval->step(1); - e1sval->callback((Fl_Callback*)cb_e1sval); - e1sval->align(Fl_Align(FL_ALIGN_BOTTOM)); - e1sval->when(FL_WHEN_CHANGED); - o->value(env->PS_val); - } // WidgetPDial* e1sval - { Fl_Check_Button* o = e1forcedrelease = new Fl_Check_Button(180, 35, 20, 15, "frcR"); - e1forcedrelease->tooltip("Forced Relase"); - e1forcedrelease->down_box(FL_DOWN_BOX); - e1forcedrelease->labelsize(10); - e1forcedrelease->callback((Fl_Callback*)cb_e1forcedrelease); - e1forcedrelease->align(Fl_Align(FL_ALIGN_BOTTOM_LEFT)); - o->value(env->Pforcedrelease); - } // Fl_Check_Button* e1forcedrelease - { WidgetPDial* o = e1envstretch = new WidgetPDial(145, 25, 25, 25, "Stretch"); - e1envstretch->tooltip("Envelope stretch (on lower notes makes the envelope longer)"); - e1envstretch->box(FL_ROUND_UP_BOX); - e1envstretch->color(FL_BACKGROUND_COLOR); - e1envstretch->selection_color(FL_INACTIVE_COLOR); - e1envstretch->labeltype(FL_NORMAL_LABEL); - e1envstretch->labelfont(0); - e1envstretch->labelsize(10); - e1envstretch->labelcolor(FL_FOREGROUND_COLOR); - e1envstretch->maximum(127); - e1envstretch->step(1); - e1envstretch->callback((Fl_Callback*)cb_e1envstretch); - e1envstretch->align(Fl_Align(FL_ALIGN_BOTTOM)); - e1envstretch->when(FL_WHEN_CHANGED); - o->value(env->Penvstretch); - } // WidgetPDial* e1envstretch - { Fl_Button* o = new Fl_Button(185, 5, 15, 15, "E"); - o->tooltip("Envelope window"); - o->box(FL_PLASTIC_UP_BOX); - o->labelfont(1); - o->labelsize(10); - o->callback((Fl_Callback*)cb_E); - } // Fl_Button* o - { Fl_Check_Button* o = e1linearenvelope = new Fl_Check_Button(180, 20, 15, 15, "L"); - e1linearenvelope->tooltip("The evelope is linear"); - e1linearenvelope->down_box(FL_DOWN_BOX); - e1linearenvelope->labelsize(10); - e1linearenvelope->callback((Fl_Callback*)cb_e1linearenvelope); - e1linearenvelope->align(Fl_Align(FL_ALIGN_LEFT)); - o->value(env->Plinearenvelope); - } // Fl_Check_Button* e1linearenvelope - { Fl_Button* o = new Fl_Button(150, 5, 15, 15, "C"); - o->box(FL_THIN_UP_BOX); - o->color((Fl_Color)179); - o->labelfont(1); - o->labelsize(10); - o->labelcolor(FL_BACKGROUND2_COLOR); - o->callback((Fl_Callback*)cb_C1); - } // Fl_Button* o - { Fl_Button* o = new Fl_Button(167, 5, 15, 15, "P"); - o->box(FL_THIN_UP_BOX); - o->color((Fl_Color)179); - o->labelfont(1); - o->labelsize(10); - o->labelcolor(FL_BACKGROUND2_COLOR); - o->callback((Fl_Callback*)cb_P1); - } // Fl_Button* o - o->end(); - } // Fl_Group* o - envADSR->end(); - } // Fl_Group* envADSR - return envADSR; -} - -Fl_Group* EnvelopeUI::make_ASR_window() { - { envASR = new Fl_Group(0, 0, 210, 70); - envASR->box(FL_FLAT_BOX); - envASR->color(FL_BACKGROUND_COLOR); - envASR->selection_color(FL_BACKGROUND_COLOR); - envASR->labeltype(FL_NO_LABEL); - envASR->labelfont(0); - envASR->labelsize(14); - envASR->labelcolor(FL_FOREGROUND_COLOR); - envASR->user_data((void*)(this)); - envASR->align(Fl_Align(FL_ALIGN_TOP)); - envASR->when(FL_WHEN_RELEASE); - { Fl_Group* o = new Fl_Group(0, 0, 210, 70, "Frequency Envelope"); - o->box(FL_PLASTIC_UP_BOX); - o->color(FL_CYAN); - o->labeltype(FL_ENGRAVED_LABEL); - o->labelsize(10); - o->align(Fl_Align(FL_ALIGN_TOP|FL_ALIGN_INSIDE)); - { WidgetPDial* o = e2aval = new WidgetPDial(5, 20, 30, 30, "A.val"); - e2aval->tooltip("Starting value"); - e2aval->box(FL_ROUND_UP_BOX); - e2aval->color(FL_BACKGROUND_COLOR); - e2aval->selection_color(FL_INACTIVE_COLOR); - e2aval->labeltype(FL_NORMAL_LABEL); - e2aval->labelfont(0); - e2aval->labelsize(10); - e2aval->labelcolor(FL_FOREGROUND_COLOR); - e2aval->maximum(127); - e2aval->step(1); - e2aval->callback((Fl_Callback*)cb_e2aval); - e2aval->align(Fl_Align(FL_ALIGN_BOTTOM)); - e2aval->when(FL_WHEN_CHANGED); - o->value(env->PA_val); - } // WidgetPDial* e2aval - { WidgetPDial* o = e2adt = new WidgetPDial(40, 20, 30, 30, "A.dt"); - e2adt->tooltip("Attack time"); - e2adt->box(FL_ROUND_UP_BOX); - e2adt->color(FL_BACKGROUND_COLOR); - e2adt->selection_color(FL_INACTIVE_COLOR); - e2adt->labeltype(FL_NORMAL_LABEL); - e2adt->labelfont(0); - e2adt->labelsize(10); - e2adt->labelcolor(FL_FOREGROUND_COLOR); - e2adt->maximum(127); - e2adt->step(1); - e2adt->callback((Fl_Callback*)cb_e2adt); - e2adt->align(Fl_Align(FL_ALIGN_BOTTOM)); - e2adt->when(FL_WHEN_CHANGED); - o->value(env->PA_dt); - } // WidgetPDial* e2adt - { WidgetPDial* o = e2rval = new WidgetPDial(110, 20, 30, 30, "R.val"); - e2rval->tooltip("Release value"); - e2rval->box(FL_ROUND_UP_BOX); - e2rval->color(FL_BACKGROUND_COLOR); - e2rval->selection_color(FL_INACTIVE_COLOR); - e2rval->labeltype(FL_NORMAL_LABEL); - e2rval->labelfont(0); - e2rval->labelsize(10); - e2rval->labelcolor(FL_FOREGROUND_COLOR); - e2rval->maximum(127); - e2rval->step(1); - e2rval->callback((Fl_Callback*)cb_e2rval); - e2rval->align(Fl_Align(FL_ALIGN_BOTTOM)); - e2rval->when(FL_WHEN_CHANGED); - o->value(env->PR_val); - } // WidgetPDial* e2rval - { WidgetPDial* o = e2rdt = new WidgetPDial(75, 20, 30, 30, "R.dt"); - e2rdt->tooltip("Release time"); - e2rdt->box(FL_ROUND_UP_BOX); - e2rdt->color(FL_BACKGROUND_COLOR); - e2rdt->selection_color(FL_INACTIVE_COLOR); - e2rdt->labeltype(FL_NORMAL_LABEL); - e2rdt->labelfont(0); - e2rdt->labelsize(10); - e2rdt->labelcolor(FL_FOREGROUND_COLOR); - e2rdt->maximum(127); - e2rdt->step(1); - e2rdt->callback((Fl_Callback*)cb_e2rdt); - e2rdt->align(Fl_Align(FL_ALIGN_BOTTOM)); - e2rdt->when(FL_WHEN_CHANGED); - o->value(env->PR_dt); - } // WidgetPDial* e2rdt - { WidgetPDial* o = e2envstretch = new WidgetPDial(145, 25, 25, 25, "Stretch"); - e2envstretch->tooltip("Envelope stretch (on lower notes makes the envelope longer)"); - e2envstretch->box(FL_ROUND_UP_BOX); - e2envstretch->color(FL_BACKGROUND_COLOR); - e2envstretch->selection_color(FL_INACTIVE_COLOR); - e2envstretch->labeltype(FL_NORMAL_LABEL); - e2envstretch->labelfont(0); - e2envstretch->labelsize(10); - e2envstretch->labelcolor(FL_FOREGROUND_COLOR); - e2envstretch->maximum(127); - e2envstretch->step(1); - e2envstretch->callback((Fl_Callback*)cb_e2envstretch); - e2envstretch->align(Fl_Align(FL_ALIGN_BOTTOM)); - e2envstretch->when(FL_WHEN_CHANGED); - o->value(env->Penvstretch); - } // WidgetPDial* e2envstretch - { Fl_Check_Button* o = e2forcedrelease = new Fl_Check_Button(180, 25, 15, 25, "frcR"); - e2forcedrelease->tooltip("Forced release"); - e2forcedrelease->down_box(FL_DOWN_BOX); - e2forcedrelease->labelsize(10); - e2forcedrelease->callback((Fl_Callback*)cb_e2forcedrelease); - e2forcedrelease->align(Fl_Align(FL_ALIGN_BOTTOM_LEFT)); - o->value(env->Pforcedrelease); - } // Fl_Check_Button* e2forcedrelease - { Fl_Button* o = new Fl_Button(155, 5, 15, 15, "C"); - o->box(FL_THIN_UP_BOX); - o->color((Fl_Color)179); - o->labelfont(1); - o->labelsize(10); - o->labelcolor(FL_BACKGROUND2_COLOR); - o->callback((Fl_Callback*)cb_C2); - } // Fl_Button* o - { Fl_Button* o = new Fl_Button(172, 5, 15, 15, "P"); - o->box(FL_THIN_UP_BOX); - o->color((Fl_Color)179); - o->labelfont(1); - o->labelsize(10); - o->labelcolor(FL_BACKGROUND2_COLOR); - o->callback((Fl_Callback*)cb_P2); - } // Fl_Button* o - o->end(); - } // Fl_Group* o - { Fl_Button* o = new Fl_Button(190, 5, 15, 15, "E"); - o->tooltip("Envelope window"); - o->box(FL_PLASTIC_UP_BOX); - o->labelfont(1); - o->labelsize(10); - o->callback((Fl_Callback*)cb_E1); - } // Fl_Button* o - envASR->end(); - } // Fl_Group* envASR - return envASR; -} - -Fl_Group* EnvelopeUI::make_ADSRfilter_window() { - { envADSRfilter = new Fl_Group(0, 0, 275, 70); - envADSRfilter->box(FL_FLAT_BOX); - envADSRfilter->color(FL_LIGHT1); - envADSRfilter->selection_color(FL_BACKGROUND_COLOR); - envADSRfilter->labeltype(FL_NO_LABEL); - envADSRfilter->labelfont(1); - envADSRfilter->labelsize(14); - envADSRfilter->labelcolor(FL_FOREGROUND_COLOR); - envADSRfilter->user_data((void*)(this)); - envADSRfilter->align(Fl_Align(FL_ALIGN_TOP)); - envADSRfilter->when(FL_WHEN_RELEASE); - { Fl_Group* o = new Fl_Group(0, 0, 275, 70, "Filter Envelope"); - o->box(FL_PLASTIC_UP_BOX); - o->color(FL_CYAN); - o->labeltype(FL_ENGRAVED_LABEL); - o->labelsize(10); - o->align(Fl_Align(FL_ALIGN_TOP|FL_ALIGN_INSIDE)); - { WidgetPDial* o = e3aval = new WidgetPDial(5, 20, 30, 30, "A.val"); - e3aval->tooltip("Starting value"); - e3aval->box(FL_ROUND_UP_BOX); - e3aval->color(FL_BACKGROUND_COLOR); - e3aval->selection_color(FL_INACTIVE_COLOR); - e3aval->labeltype(FL_NORMAL_LABEL); - e3aval->labelfont(0); - e3aval->labelsize(10); - e3aval->labelcolor(FL_FOREGROUND_COLOR); - e3aval->maximum(127); - e3aval->step(1); - e3aval->callback((Fl_Callback*)cb_e3aval); - e3aval->align(Fl_Align(FL_ALIGN_BOTTOM)); - e3aval->when(FL_WHEN_CHANGED); - o->value(env->PA_val); - } // WidgetPDial* e3aval - { WidgetPDial* o = e3adt = new WidgetPDial(40, 20, 30, 30, "A.dt"); - e3adt->tooltip("Attack time"); - e3adt->box(FL_ROUND_UP_BOX); - e3adt->color(FL_BACKGROUND_COLOR); - e3adt->selection_color(FL_INACTIVE_COLOR); - e3adt->labeltype(FL_NORMAL_LABEL); - e3adt->labelfont(0); - e3adt->labelsize(10); - e3adt->labelcolor(FL_FOREGROUND_COLOR); - e3adt->maximum(127); - e3adt->step(1); - e3adt->callback((Fl_Callback*)cb_e3adt); - e3adt->align(Fl_Align(FL_ALIGN_BOTTOM)); - e3adt->when(FL_WHEN_CHANGED); - o->value(env->PA_dt); - } // WidgetPDial* e3adt - { WidgetPDial* o = e3dval = new WidgetPDial(75, 20, 30, 30, "D.val"); - e3dval->tooltip("decay value"); - e3dval->box(FL_ROUND_UP_BOX); - e3dval->color(FL_BACKGROUND_COLOR); - e3dval->selection_color(FL_INACTIVE_COLOR); - e3dval->labeltype(FL_NORMAL_LABEL); - e3dval->labelfont(0); - e3dval->labelsize(10); - e3dval->labelcolor(FL_FOREGROUND_COLOR); - e3dval->maximum(127); - e3dval->step(1); - e3dval->callback((Fl_Callback*)cb_e3dval); - e3dval->align(Fl_Align(FL_ALIGN_BOTTOM)); - e3dval->when(FL_WHEN_CHANGED); - o->value(env->PD_val); - } // WidgetPDial* e3dval - { WidgetPDial* o = e3ddt = new WidgetPDial(110, 20, 30, 30, "D.dt"); - e3ddt->tooltip("decay time"); - e3ddt->box(FL_ROUND_UP_BOX); - e3ddt->color(FL_BACKGROUND_COLOR); - e3ddt->selection_color(FL_INACTIVE_COLOR); - e3ddt->labeltype(FL_NORMAL_LABEL); - e3ddt->labelfont(0); - e3ddt->labelsize(10); - e3ddt->labelcolor(FL_FOREGROUND_COLOR); - e3ddt->maximum(127); - e3ddt->step(1); - e3ddt->callback((Fl_Callback*)cb_e3ddt); - e3ddt->align(Fl_Align(FL_ALIGN_BOTTOM)); - e3ddt->when(FL_WHEN_CHANGED); - o->value(env->PD_dt); - } // WidgetPDial* e3ddt - { WidgetPDial* o = e3rdt = new WidgetPDial(145, 20, 30, 30, "R.dt"); - e3rdt->tooltip("Release time"); - e3rdt->box(FL_ROUND_UP_BOX); - e3rdt->color(FL_BACKGROUND_COLOR); - e3rdt->selection_color(FL_INACTIVE_COLOR); - e3rdt->labeltype(FL_NORMAL_LABEL); - e3rdt->labelfont(0); - e3rdt->labelsize(10); - e3rdt->labelcolor(FL_FOREGROUND_COLOR); - e3rdt->maximum(127); - e3rdt->step(1); - e3rdt->callback((Fl_Callback*)cb_e3rdt); - e3rdt->align(Fl_Align(FL_ALIGN_BOTTOM)); - e3rdt->when(FL_WHEN_CHANGED); - o->value(env->PR_dt); - } // WidgetPDial* e3rdt - { WidgetPDial* o = e3rval = new WidgetPDial(180, 20, 30, 30, "R.val"); - e3rval->tooltip("Release value"); - e3rval->box(FL_ROUND_UP_BOX); - e3rval->color(FL_BACKGROUND_COLOR); - e3rval->selection_color(FL_INACTIVE_COLOR); - e3rval->labeltype(FL_NORMAL_LABEL); - e3rval->labelfont(0); - e3rval->labelsize(10); - e3rval->labelcolor(FL_FOREGROUND_COLOR); - e3rval->maximum(127); - e3rval->step(1); - e3rval->callback((Fl_Callback*)cb_e3rval); - e3rval->align(Fl_Align(FL_ALIGN_BOTTOM)); - e3rval->when(FL_WHEN_CHANGED); - o->value(env->PR_val); - } // WidgetPDial* e3rval - { WidgetPDial* o = e3envstretch = new WidgetPDial(215, 25, 25, 25, "Stretch"); - e3envstretch->tooltip("Envelope stretch (on lower notes makes the envelope longer)"); - e3envstretch->box(FL_ROUND_UP_BOX); - e3envstretch->color(FL_BACKGROUND_COLOR); - e3envstretch->selection_color(FL_INACTIVE_COLOR); - e3envstretch->labeltype(FL_NORMAL_LABEL); - e3envstretch->labelfont(0); - e3envstretch->labelsize(10); - e3envstretch->labelcolor(FL_FOREGROUND_COLOR); - e3envstretch->maximum(127); - e3envstretch->step(1); - e3envstretch->callback((Fl_Callback*)cb_e3envstretch); - e3envstretch->align(Fl_Align(FL_ALIGN_BOTTOM)); - e3envstretch->when(FL_WHEN_CHANGED); - o->value(env->Penvstretch); - } // WidgetPDial* e3envstretch - { Fl_Check_Button* o = e3forcedrelease = new Fl_Check_Button(250, 30, 15, 20, "frcR"); - e3forcedrelease->tooltip("Forced Relase"); - e3forcedrelease->down_box(FL_DOWN_BOX); - e3forcedrelease->labelsize(10); - e3forcedrelease->callback((Fl_Callback*)cb_e3forcedrelease); - e3forcedrelease->align(Fl_Align(FL_ALIGN_BOTTOM_LEFT)); - o->value(env->Pforcedrelease); - } // Fl_Check_Button* e3forcedrelease - { Fl_Button* o = new Fl_Button(255, 5, 15, 15, "E"); - o->box(FL_PLASTIC_UP_BOX); - o->labelfont(1); - o->labelsize(10); - o->callback((Fl_Callback*)cb_E2); - } // Fl_Button* o - { Fl_Button* o = new Fl_Button(220, 5, 15, 15, "C"); - o->box(FL_THIN_UP_BOX); - o->color((Fl_Color)179); - o->labelfont(1); - o->labelsize(10); - o->labelcolor(FL_BACKGROUND2_COLOR); - o->callback((Fl_Callback*)cb_C3); - } // Fl_Button* o - { Fl_Button* o = new Fl_Button(237, 5, 15, 15, "P"); - o->box(FL_THIN_UP_BOX); - o->color((Fl_Color)179); - o->labelfont(1); - o->labelsize(10); - o->labelcolor(FL_BACKGROUND2_COLOR); - o->callback((Fl_Callback*)cb_P3); - } // Fl_Button* o - o->end(); - } // Fl_Group* o - envADSRfilter->end(); - } // Fl_Group* envADSRfilter - return envADSRfilter; -} - -Fl_Group* EnvelopeUI::make_ASRbw_window() { - { envASRbw = new Fl_Group(0, 0, 210, 70); - envASRbw->box(FL_FLAT_BOX); - envASRbw->color(FL_BACKGROUND_COLOR); - envASRbw->selection_color(FL_BACKGROUND_COLOR); - envASRbw->labeltype(FL_NO_LABEL); - envASRbw->labelfont(0); - envASRbw->labelsize(14); - envASRbw->labelcolor(FL_FOREGROUND_COLOR); - envASRbw->user_data((void*)(this)); - envASRbw->align(Fl_Align(FL_ALIGN_TOP)); - envASRbw->when(FL_WHEN_RELEASE); - { Fl_Group* o = new Fl_Group(0, 0, 210, 70, "BandWidth Envelope"); - o->box(FL_PLASTIC_UP_BOX); - o->color(FL_CYAN); - o->labeltype(FL_ENGRAVED_LABEL); - o->labelsize(10); - o->align(Fl_Align(FL_ALIGN_TOP|FL_ALIGN_INSIDE)); - { WidgetPDial* o = e4aval = new WidgetPDial(5, 20, 30, 30, "A.val"); - e4aval->tooltip("Starting value"); - e4aval->box(FL_ROUND_UP_BOX); - e4aval->color(FL_BACKGROUND_COLOR); - e4aval->selection_color(FL_INACTIVE_COLOR); - e4aval->labeltype(FL_NORMAL_LABEL); - e4aval->labelfont(0); - e4aval->labelsize(10); - e4aval->labelcolor(FL_FOREGROUND_COLOR); - e4aval->maximum(127); - e4aval->step(1); - e4aval->callback((Fl_Callback*)cb_e4aval); - e4aval->align(Fl_Align(FL_ALIGN_BOTTOM)); - e4aval->when(FL_WHEN_CHANGED); - o->value(env->PA_val); - } // WidgetPDial* e4aval - { WidgetPDial* o = e4adt = new WidgetPDial(40, 20, 30, 30, "A.dt"); - e4adt->tooltip("Attack time"); - e4adt->box(FL_ROUND_UP_BOX); - e4adt->color(FL_BACKGROUND_COLOR); - e4adt->selection_color(FL_INACTIVE_COLOR); - e4adt->labeltype(FL_NORMAL_LABEL); - e4adt->labelfont(0); - e4adt->labelsize(10); - e4adt->labelcolor(FL_FOREGROUND_COLOR); - e4adt->maximum(127); - e4adt->step(1); - e4adt->callback((Fl_Callback*)cb_e4adt); - e4adt->align(Fl_Align(FL_ALIGN_BOTTOM)); - e4adt->when(FL_WHEN_CHANGED); - o->value(env->PA_dt); - } // WidgetPDial* e4adt - { WidgetPDial* o = e4rval = new WidgetPDial(110, 20, 30, 30, "R.val"); - e4rval->tooltip("Release value"); - e4rval->box(FL_ROUND_UP_BOX); - e4rval->color(FL_BACKGROUND_COLOR); - e4rval->selection_color(FL_INACTIVE_COLOR); - e4rval->labeltype(FL_NORMAL_LABEL); - e4rval->labelfont(0); - e4rval->labelsize(10); - e4rval->labelcolor(FL_FOREGROUND_COLOR); - e4rval->maximum(127); - e4rval->step(1); - e4rval->callback((Fl_Callback*)cb_e4rval); - e4rval->align(Fl_Align(FL_ALIGN_BOTTOM)); - e4rval->when(FL_WHEN_CHANGED); - o->value(env->PR_val); - } // WidgetPDial* e4rval - { WidgetPDial* o = e4rdt = new WidgetPDial(75, 20, 30, 30, "R.dt"); - e4rdt->tooltip("Release time"); - e4rdt->box(FL_ROUND_UP_BOX); - e4rdt->color(FL_BACKGROUND_COLOR); - e4rdt->selection_color(FL_INACTIVE_COLOR); - e4rdt->labeltype(FL_NORMAL_LABEL); - e4rdt->labelfont(0); - e4rdt->labelsize(10); - e4rdt->labelcolor(FL_FOREGROUND_COLOR); - e4rdt->maximum(127); - e4rdt->step(1); - e4rdt->callback((Fl_Callback*)cb_e4rdt); - e4rdt->align(Fl_Align(FL_ALIGN_BOTTOM)); - e4rdt->when(FL_WHEN_CHANGED); - o->value(env->PR_dt); - } // WidgetPDial* e4rdt - { WidgetPDial* o = e4envstretch = new WidgetPDial(145, 25, 25, 25, "Stretch"); - e4envstretch->tooltip("Envelope stretch (on lower notes makes the envelope longer)"); - e4envstretch->box(FL_ROUND_UP_BOX); - e4envstretch->color(FL_BACKGROUND_COLOR); - e4envstretch->selection_color(FL_INACTIVE_COLOR); - e4envstretch->labeltype(FL_NORMAL_LABEL); - e4envstretch->labelfont(0); - e4envstretch->labelsize(10); - e4envstretch->labelcolor(FL_FOREGROUND_COLOR); - e4envstretch->maximum(127); - e4envstretch->step(1); - e4envstretch->callback((Fl_Callback*)cb_e4envstretch); - e4envstretch->align(Fl_Align(FL_ALIGN_BOTTOM)); - e4envstretch->when(FL_WHEN_CHANGED); - o->value(env->Penvstretch); - } // WidgetPDial* e4envstretch - { Fl_Check_Button* o = e4forcedrelease = new Fl_Check_Button(180, 25, 15, 25, "frcR"); - e4forcedrelease->tooltip("Forced release"); - e4forcedrelease->down_box(FL_DOWN_BOX); - e4forcedrelease->labelsize(10); - e4forcedrelease->callback((Fl_Callback*)cb_e4forcedrelease); - e4forcedrelease->align(Fl_Align(FL_ALIGN_BOTTOM_LEFT)); - o->value(env->Pforcedrelease); - } // Fl_Check_Button* e4forcedrelease - { Fl_Button* o = new Fl_Button(155, 5, 15, 15, "C"); - o->box(FL_THIN_UP_BOX); - o->color((Fl_Color)179); - o->labelfont(1); - o->labelsize(10); - o->labelcolor(FL_BACKGROUND2_COLOR); - o->callback((Fl_Callback*)cb_C4); - } // Fl_Button* o - { Fl_Button* o = new Fl_Button(172, 5, 15, 15, "P"); - o->box(FL_THIN_UP_BOX); - o->color((Fl_Color)179); - o->labelfont(1); - o->labelsize(10); - o->labelcolor(FL_BACKGROUND2_COLOR); - o->callback((Fl_Callback*)cb_P4); - } // Fl_Button* o - o->end(); - } // Fl_Group* o - { Fl_Button* o = new Fl_Button(190, 5, 15, 15, "E"); - o->box(FL_PLASTIC_UP_BOX); - o->labelfont(1); - o->labelsize(10); - o->callback((Fl_Callback*)cb_E3); - } // Fl_Button* o - envASRbw->end(); - } // Fl_Group* envASRbw - return envASRbw; -} - -Fl_Group* EnvelopeUI::make_free_window() { - { envfree = new Fl_Group(0, 0, 205, 70); - envfree->box(FL_FLAT_BOX); - envfree->color(FL_LIGHT1); - envfree->selection_color(FL_BACKGROUND_COLOR); - envfree->labeltype(FL_NO_LABEL); - envfree->labelfont(1); - envfree->labelsize(14); - envfree->labelcolor(FL_FOREGROUND_COLOR); - envfree->user_data((void*)(this)); - envfree->align(Fl_Align(FL_ALIGN_TOP)); - envfree->when(FL_WHEN_RELEASE); - { envfreegroup = new Fl_Group(0, 0, 205, 70, "Amplitude Envelope"); - envfreegroup->box(FL_PLASTIC_UP_BOX); - envfreegroup->color(FL_CYAN); - envfreegroup->labeltype(FL_ENGRAVED_LABEL); - envfreegroup->labelsize(10); - envfreegroup->align(Fl_Align(FL_ALIGN_TOP|FL_ALIGN_INSIDE)); - { EnvelopeFreeEdit* o = freeeditsmall = new EnvelopeFreeEdit(5, 20, 195, 45, "Envelope"); - freeeditsmall->box(FL_FLAT_BOX); - freeeditsmall->color(FL_FOREGROUND_COLOR); - freeeditsmall->selection_color(FL_BACKGROUND_COLOR); - freeeditsmall->labeltype(FL_NORMAL_LABEL); - freeeditsmall->labelfont(0); - freeeditsmall->labelsize(14); - freeeditsmall->labelcolor(FL_FOREGROUND_COLOR); - freeeditsmall->callback((Fl_Callback*)cb_freeeditsmall); - freeeditsmall->align(Fl_Align(FL_ALIGN_CENTER)); - freeeditsmall->when(FL_WHEN_RELEASE); - Fl_Group::current()->resizable(freeeditsmall); - o->init(env); - } // EnvelopeFreeEdit* freeeditsmall - { Fl_Button* o = new Fl_Button(185, 5, 15, 15, "E"); - o->box(FL_PLASTIC_UP_BOX); - o->labelfont(1); - o->labelsize(10); - o->callback((Fl_Callback*)cb_E4); - } // Fl_Button* o - { Fl_Button* o = new Fl_Button(150, 5, 15, 15, "C"); - o->box(FL_THIN_UP_BOX); - o->color((Fl_Color)179); - o->labelfont(1); - o->labelsize(10); - o->labelcolor(FL_BACKGROUND2_COLOR); - o->callback((Fl_Callback*)cb_C5); - } // Fl_Button* o - { Fl_Button* o = new Fl_Button(167, 5, 15, 15, "P"); - o->box(FL_THIN_UP_BOX); - o->color((Fl_Color)179); - o->labelfont(1); - o->labelsize(10); - o->labelcolor(FL_BACKGROUND2_COLOR); - o->callback((Fl_Callback*)cb_P5); - } // Fl_Button* o - envfreegroup->end(); - Fl_Group::current()->resizable(envfreegroup); - } // Fl_Group* envfreegroup - envfree->end(); - } // Fl_Group* envfree - return envfree; -} - -void EnvelopeUI::init(EnvelopeParams *env_) { - env=env_; - make_ADSR_window(); - make_ASR_window(); - make_ADSRfilter_window(); - make_ASRbw_window(); - make_free_window(); - - make_freemode_edit_window(); - - envwindow=NULL; - if (env->Envmode==3) envfreegroup->label("Frequency Envelope"); - if (env->Envmode==4) envfreegroup->label("Filter Envelope"); - if (env->Envmode==5) envfreegroup->label("Bandwidth Envelope"); - - freemodeeditwindow->label(this->label()); - - - freeeditsmall->setpair(freeedit); - freeedit->setpair(freeeditsmall); - - - refresh(); -} - -void EnvelopeUI::reinit() { - if (env->Pfreemode!=0){ - int answer=fl_choice("Disable the free mode of the Envelope?","No","Yes",NULL); - if (env->Pfreemode!=0) freemodebutton->value(1); - else freemodebutton->value(0); - if (answer==0) return; - }; - - if (env->Pfreemode==0) env->Pfreemode=1; - else env->Pfreemode=0; - - hide(); - int winx=freemodeeditwindow->x(); - int winy=freemodeeditwindow->y(); - - freemodeeditwindow->hide(); - - envwindow->hide(); - Fl_Group *par=envwindow->parent(); - par->hide(); - - - refresh(); - envwindow->show(); - par->redraw(); - - par->show(); - show(); - freemodeeditwindow->position(winx,winy); - freemodeeditwindow->show(); - - if (env->Pfreemode!=0) { - freemodebutton->value(1); - addpoint->show(); - deletepoint->show(); - forcedreleasecheck->show(); - }else{ - freemodebutton->value(0); - addpoint->hide(); - deletepoint->hide(); - forcedreleasecheck->hide(); - }; -} - -void EnvelopeUI::refresh() { - freemodebutton->value(env->Pfreemode); - - sustaincounter->value(env->Penvsustain); - if (env->Pfreemode==0) sustaincounter->hide(); - else sustaincounter->show(); - sustaincounter->maximum(env->Penvpoints-2); - - envstretchdial->value(env->Penvstretch); - if (env->Pfreemode==0) envstretchdial->hide(); - else envstretchdial->show(); - - linearenvelopecheck->value(env->Plinearenvelope); - if ((env->Pfreemode==0)||(env->Envmode>2)) linearenvelopecheck->hide(); - else linearenvelopecheck->show(); - - forcedreleasecheck->value(env->Pforcedrelease); - if (env->Pfreemode==0) forcedreleasecheck->hide(); - - freeedit->redraw(); - - - if (env->Pfreemode==0){ - switch(env->Envmode){ - case(1): - case(2): - e1adt->value(env->PA_dt); - e1ddt->value(env->PD_dt); - e1sval->value(env->PS_val); - e1rdt->value(env->PR_dt); - e1envstretch->value(env->Penvstretch); - e1linearenvelope->value(env->Plinearenvelope); - e1forcedrelease->value(env->Pforcedrelease); - break; - case(3): - e2aval->value(env->PA_val); - e2adt->value(env->PA_dt); - e2rdt->value(env->PR_dt); - e2rval->value(env->PR_val); - e2envstretch->value(env->Penvstretch); - e2forcedrelease->value(env->Pforcedrelease); - break; - case(4): - e3aval->value(env->PA_val); - e3adt->value(env->PA_dt); - e3dval->value(env->PD_val); - e3ddt->value(env->PD_dt); - e3rdt->value(env->PR_dt); - e3rval->value(env->PR_val); - e3envstretch->value(env->Penvstretch); - e3forcedrelease->value(env->Pforcedrelease); - break; - case(5): - e4aval->value(env->PA_val); - e4adt->value(env->PA_dt); - e4rdt->value(env->PR_dt); - e4rval->value(env->PR_val); - e4envstretch->value(env->Penvstretch); - e4forcedrelease->value(env->Pforcedrelease); - break; - default: - break; - }; - }else{ - envfree->redraw(); - }; - - - envADSR->hide(); - envASR->hide(); - envADSRfilter->hide(); - envASRbw->hide(); - envfree->hide(); - - if (env->Pfreemode==0){ - switch(env->Envmode){ - case(1): - case(2): - envwindow=envADSR; - break; - case(3): - envwindow=envASR; - break; - case(4): - envwindow=envADSRfilter; - break; - case(5): - envwindow=envASRbw; - break; - default: - break; - }; - }else{ - envwindow=envfree; - }; - - envwindow->resize(this->x(),this->y(),this->w(),this->h()); - - envwindow->show(); -} diff --git a/plugins/zynaddsubfx/src/UI/EnvelopeUI.fl b/plugins/zynaddsubfx/src/UI/EnvelopeUI.fl deleted file mode 100644 index eef5ad643..000000000 --- a/plugins/zynaddsubfx/src/UI/EnvelopeUI.fl +++ /dev/null @@ -1,851 +0,0 @@ -# data file for the Fltk User Interface Designer (fluid) -version 1.0106 -header_name {.h} -code_name {.cc} -decl {//Copyright (c) 2002-2005 Nasca Octavian Paul} {} - -decl {//License: GNU GPL version 2 or later} {} - -decl {\#include "WidgetPDial.h"} {public -} - -decl {\#include } {public -} - -decl {\#include } {public -} - -decl {\#include "../globals.h"} {public -} - -decl {\#include } {public -} - -decl {\#include "../Params/EnvelopeParams.h"} {public -} - -decl {\#include } {public -} - -decl {\#include } {public -} - -decl {\#include } {public -} - -decl {\#include "PresetsUI.h"} {public -} - -class EnvelopeFreeEdit {: {public Fl_Box} -} { - Function {EnvelopeFreeEdit(int x,int y, int w, int h, const char *label=0):Fl_Box(x,y,w,h,label)} {} { - code {env=NULL; -pair=NULL;} {} - } - Function {init(EnvelopeParams *env_)} {} { - code {env=env_; -oldx=-1; -currentpoint=-1; -cpx=0; -lastpoint=-1;} {} - } - Function {setpair(Fl_Box *pair_)} {} { - code {pair=pair_;} {} - } - Function {getpointx(int n)} {return_type int - } { - code {int lx=w()-10; -int npoints=env->Penvpoints; - -float sum=0; -for (int i=1;igetdt(i)+1; - -float sumbefore=0;//the sum of all points before the computed point -for (int i=1;i<=n;i++) sumbefore+=env->getdt(i)+1; - -return((int) (sumbefore/(REALTYPE) sum*lx));} {} - } - Function {getpointy(int n)} {return_type int - } { - code {int ly=h()-10; - -return((int) ((1.0-env->Penvval[n]/127.0)*ly));} {} - } - Function {getnearest(int x,int y)} {return_type int - } { - code {x-=5;y-=5; - -int nearestpoint=0; -int nearestval=1000000;//a big value -for (int i=0;iPenvpoints;i++){ - int distance=abs(x-getpointx(i))+abs(y-getpointy(i)); - if (distancePfreemode==0) env->converttofree(); -int npoints=env->Penvpoints; - -if (active_r()) fl_color(FL_BLACK); - else fl_color(90,90,90); -if (!active_r()) currentpoint=-1; - -fl_rectf(ox,oy,lx,ly); - -ox+=5;oy+=5;lx-=10;ly-=10; - -//draw the lines -fl_color(FL_GRAY); - -fl_line_style(FL_SOLID); -fl_line(ox+2,oy+ly/2,ox+lx-2,oy+ly/2); - -//draws the evelope points and lines -Fl_Color alb=FL_WHITE; -if (!active_r()) alb=fl_rgb_color(180,180,180); -fl_color(alb); -int oldxx=0,xx=0,oldyy=0,yy=getpointy(0); -fl_rectf(ox-3,oy+yy-3,6,6); -for (int i=1;i=0){ - fl_color(FL_CYAN); - fl_rectf(ox+getpointx(lastpoint)-5,oy+getpointy(lastpoint)-5,10,10); -}; - -//draw the sustain position -if (env->Penvsustain>0){ - fl_color(FL_YELLOW); - xx=getpointx(env->Penvsustain); - fl_line(ox+xx,oy+0,ox+xx,oy+ly); -}; - -//Show the envelope duration and the current line duration -fl_font(FL_HELVETICA|FL_BOLD,10); -float time=0.0; -if (currentpoint<=0){ - fl_color(alb); - for (int i=1;igetdt(i); -} else { - fl_color(255,0,0); - time=env->getdt(currentpoint); -}; -char tmpstr[20]; -if (time<1000.0) snprintf((char *)&tmpstr,20,"%.1fms",time); - else snprintf((char *)&tmpstr,20,"%.2fs",time/1000.0); -fl_draw(tmpstr,ox+lx-20,oy+ly-10,20,10,FL_ALIGN_RIGHT,NULL,0);} {} - } - Function {handle(int event)} {return_type int - } { - code {int x_=Fl::event_x()-x(); -int y_=Fl::event_y()-y(); - -if (event==FL_PUSH) { - currentpoint=getnearest(x_,y_); - cpx=x_; - cpdt=env->Penvdt[currentpoint]; - lastpoint=currentpoint; - redraw(); - if (pair!=NULL) pair->redraw(); -}; - -if (event==FL_RELEASE){ - currentpoint=-1; - redraw(); - if (pair!=NULL) pair->redraw(); -}; - -if ((event==FL_DRAG)&&(currentpoint>=0)){ - int ny=127-(int) (y_*127.0/h()); - if (ny<0) ny=0;if (ny>127) ny=127; - env->Penvval[currentpoint]=ny; - - int dx=(int)((x_-cpx)*0.1); - int newdt=cpdt+dx; - if (newdt<0) newdt=0;if (newdt>127) newdt=127; - if (currentpoint!=0) env->Penvdt[currentpoint]=newdt; - else env->Penvdt[currentpoint]=0; - - redraw(); - if (pair!=NULL) pair->redraw(); -}; - - -return(1);} {} - } - decl {Fl_Box *pair;} {} - decl {EnvelopeParams *env;} {} - decl {int oldx,oldy;} {} - decl {int currentpoint,cpx,cpdt;} {} - decl {int lastpoint;} {public - } -} - -class EnvelopeUI {: {public Fl_Group,PresetsUI_} -} { - Function {EnvelopeUI(int x,int y, int w, int h, const char *label=0):Fl_Group(x,y,w,h,label)} {} { - code {env=NULL; -freemodeeditwindow=NULL; -envADSR=NULL; -envASR=NULL; -envADSRfilter=NULL; -envASRbw=NULL; -envfree=NULL;} {} - } - Function {~EnvelopeUI()} {} { - code {envwindow->hide(); -hide(); -freemodeeditwindow->hide(); -delete (freemodeeditwindow);} {} - } - Function {make_freemode_edit_window()} {} { - Fl_Window freemodeeditwindow { - label Envelope - xywh {60 308 575 180} type Double hide - } { - Fl_Box freeedit { - label Envelope - xywh {5 5 565 145} box FLAT_BOX color 0 - code0 {o->init(env);} - class EnvelopeFreeEdit - } - Fl_Button addpoint { - label {Add point} - callback {int curpoint=freeedit->lastpoint; -if (curpoint<0) return; -//if (curpoint>=env->Penvpoints-1) return; -if (env->Penvpoints>=MAX_ENVELOPE_POINTS) return; - -for (int i=env->Penvpoints;i>=curpoint+1;i--){ - env->Penvdt[i]=env->Penvdt[i-1]; - env->Penvval[i]=env->Penvval[i-1]; -}; - -if (curpoint==0) { - env->Penvdt[1]=64; -}; - -env->Penvpoints++; -if (curpoint<=env->Penvsustain) env->Penvsustain++; - -freeedit->lastpoint+=1; -freeedit->redraw(); -envfree->redraw(); - -sustaincounter->value(env->Penvsustain); -sustaincounter->maximum(env->Penvpoints-2);} - xywh {115 155 80 20} box THIN_UP_BOX - code0 {if (env->Pfreemode==0) o->hide();} - } - Fl_Button deletepoint { - label {Delete point} - callback {int curpoint=freeedit->lastpoint; -if (curpoint<1) return; -if (curpoint>=env->Penvpoints-1) return; -if (env->Penvpoints<=3) return; - -for (int i=curpoint+1;iPenvpoints;i++){ - env->Penvdt[i-1]=env->Penvdt[i]; - env->Penvval[i-1]=env->Penvval[i]; -}; - -env->Penvpoints--; - -if (curpoint<=env->Penvsustain) env->Penvsustain--; - - -freeedit->lastpoint-=1; -freeedit->redraw(); -envfree->redraw(); - -sustaincounter->value(env->Penvsustain); -sustaincounter->maximum(env->Penvpoints-2);} - xywh {200 155 80 20} box THIN_UP_BOX - code0 {if (env->Pfreemode==0) o->hide();} - } - Fl_Light_Button freemodebutton { - label FreeMode - callback {reinit(); - -freeedit->lastpoint=-1; -freeedit->redraw();} - tooltip {Enable or disable the freemode} xywh {10 155 95 25} box PLASTIC_UP_BOX - } - Fl_Check_Button forcedreleasecheck { - label frcR - callback {env->Pforcedrelease=(int)o->value();} - tooltip {Forced Relase} xywh {410 165 40 15} down_box DOWN_BOX labelsize 10 - code0 {o->value(env->Pforcedrelease);} - code1 {if (env->Pfreemode==0) o->hide();} - } - Fl_Dial envstretchdial { - label {Str.} - callback {env->Penvstretch=(int)o->value();} - tooltip {Envelope stretch (on lower notes make the envelope longer)} xywh {380 155 25 25} box ROUND_UP_BOX labelsize 10 align 4 maximum 127 step 1 - code0 {o->value(env->Penvstretch);} - code1 {if (env->Pfreemode==0) o->hide();} - class WidgetPDial - } - Fl_Button {} { - label Close - callback {freemodeeditwindow->hide();} - xywh {510 155 60 25} box THIN_UP_BOX - } - Fl_Check_Button linearenvelopecheck { - label L - callback {env->Plinearenvelope=(int)o->value();} - tooltip {Linear Envelope} xywh {410 151 30 15} down_box DOWN_BOX labelsize 10 - code0 {o->value(env->Plinearenvelope);} - code1 {if ((env->Pfreemode==0)||(env->Envmode>2)) o->hide();} - } - Fl_Counter sustaincounter { - label Sust - callback {env->Penvsustain=(int) o->value(); -freeedit->redraw(); -envfree->redraw();} - tooltip {Sustain (0 is disabled)} xywh {315 155 40 15} type Simple labelsize 11 align 4 minimum 0 maximum 127 step 1 - code0 {o->value(env->Penvsustain);} - code1 {if (env->Pfreemode==0) o->hide();} - code2 {o->maximum(env->Penvpoints-2);} - } - Fl_Button {} { - label C - callback {presetsui->copy(env);} - xywh {465 160 15 15} box THIN_UP_BOX color 179 labelfont 1 labelsize 10 labelcolor 7 - } - Fl_Button {} { - label P - callback {presetsui->paste(env,this);} - xywh {482 160 15 15} box THIN_UP_BOX color 179 labelfont 1 labelsize 10 labelcolor 7 - } - } - } - Function {make_ADSR_window()} {} { - Fl_Window envADSR { - xywh {108 336 205 70} type Double color 50 labelfont 1 hide - class Fl_Group - } { - Fl_Group {} { - label {Amplitude Envelope} - xywh {0 0 205 70} box PLASTIC_UP_BOX color 223 labeltype ENGRAVED_LABEL labelsize 10 align 17 - } { - Fl_Dial e1adt { - label {A.dt} - callback {env->PA_dt=(int)o->value(); -freeedit->redraw();} - tooltip {Attack time} xywh {5 20 30 30} box ROUND_UP_BOX labelsize 10 maximum 127 step 1 - code0 {o->value(env->PA_dt);} - class WidgetPDial - } - Fl_Dial e1ddt { - label {D.dt} - callback {env->PD_dt=(int)o->value(); -freeedit->redraw();} - tooltip {Decay time} xywh {40 20 30 30} box ROUND_UP_BOX labelsize 10 maximum 127 step 1 - code0 {o->value(env->PD_dt);} - class WidgetPDial - } - Fl_Dial e1rdt { - label {R.dt} - callback {env->PR_dt=(int)o->value(); -freeedit->redraw();} - tooltip {Release time} xywh {110 20 30 30} box ROUND_UP_BOX labelsize 10 maximum 127 step 1 - code0 {o->value(env->PR_dt);} - class WidgetPDial - } - Fl_Dial e1sval { - label {S.val} - callback {env->PS_val=(int)o->value(); -freeedit->redraw();} - tooltip {Sustain value} xywh {75 20 30 30} box ROUND_UP_BOX labelsize 10 maximum 127 step 1 - code0 {o->value(env->PS_val);} - class WidgetPDial - } - Fl_Check_Button e1forcedrelease { - label frcR - callback {env->Pforcedrelease=(int)o->value();} - tooltip {Forced Relase} xywh {180 35 20 15} down_box DOWN_BOX labelsize 10 align 6 - code0 {o->value(env->Pforcedrelease);} - } - Fl_Dial e1envstretch { - label Stretch - callback {env->Penvstretch=(int)o->value();} - tooltip {Envelope stretch (on lower notes makes the envelope longer)} xywh {145 25 25 25} box ROUND_UP_BOX labelsize 10 maximum 127 step 1 - code0 {o->value(env->Penvstretch);} - class WidgetPDial - } - Fl_Button {} { - label E - callback {freemodeeditwindow->show();} - tooltip {Envelope window} xywh {185 5 15 15} box PLASTIC_UP_BOX labelfont 1 labelsize 10 - } - Fl_Check_Button e1linearenvelope { - label L - callback {env->Plinearenvelope=(int)o->value();} - tooltip {The evelope is linear} xywh {180 20 15 15} down_box DOWN_BOX labelsize 10 align 4 - code0 {o->value(env->Plinearenvelope);} - } - Fl_Button {} { - label C - callback {presetsui->copy(env);} - xywh {150 5 15 15} box THIN_UP_BOX color 179 labelfont 1 labelsize 10 labelcolor 7 - } - Fl_Button {} { - label P - callback {presetsui->paste(env,this);} - xywh {167 5 15 15} box THIN_UP_BOX color 179 labelfont 1 labelsize 10 labelcolor 7 - } - } - } - } - Function {make_ASR_window()} {} { - Fl_Window envASR { - xywh {71 320 210 70} type Double hide - class Fl_Group - } { - Fl_Group {} { - label {Frequency Envelope} - xywh {0 0 210 70} box PLASTIC_UP_BOX color 223 labeltype ENGRAVED_LABEL labelsize 10 align 17 - } { - Fl_Dial e2aval { - label {A.val} - callback {env->PA_val=(int)o->value(); -freeedit->redraw();} - tooltip {Starting value} xywh {5 20 30 30} box ROUND_UP_BOX labelsize 10 maximum 127 step 1 - code0 {o->value(env->PA_val);} - class WidgetPDial - } - Fl_Dial e2adt { - label {A.dt} - callback {env->PA_dt=(int)o->value(); -freeedit->redraw();} - tooltip {Attack time} xywh {40 20 30 30} box ROUND_UP_BOX labelsize 10 maximum 127 step 1 - code0 {o->value(env->PA_dt);} - class WidgetPDial - } - Fl_Dial e2rval { - label {R.val} - callback {env->PR_val=(int)o->value(); -freeedit->redraw();} - tooltip {Release value} xywh {110 20 30 30} box ROUND_UP_BOX labelsize 10 maximum 127 step 1 - code0 {o->value(env->PR_val);} - class WidgetPDial - } - Fl_Dial e2rdt { - label {R.dt} - callback {env->PR_dt=(int)o->value(); -freeedit->redraw();} - tooltip {Release time} xywh {75 20 30 30} box ROUND_UP_BOX labelsize 10 maximum 127 step 1 - code0 {o->value(env->PR_dt);} - class WidgetPDial - } - Fl_Dial e2envstretch { - label Stretch - callback {env->Penvstretch=(int)o->value();} - tooltip {Envelope stretch (on lower notes makes the envelope longer)} xywh {145 25 25 25} box ROUND_UP_BOX labelsize 10 maximum 127 step 1 - code0 {o->value(env->Penvstretch);} - class WidgetPDial - } - Fl_Check_Button e2forcedrelease { - label frcR - callback {env->Pforcedrelease=(int)o->value();} - tooltip {Forced release} xywh {180 25 15 25} down_box DOWN_BOX labelsize 10 align 6 - code0 {o->value(env->Pforcedrelease);} - } - Fl_Button {} { - label C - callback {presetsui->copy(env);} - xywh {155 5 15 15} box THIN_UP_BOX color 179 labelfont 1 labelsize 10 labelcolor 7 - } - Fl_Button {} { - label P - callback {presetsui->paste(env,this);} - xywh {172 5 15 15} box THIN_UP_BOX color 179 labelfont 1 labelsize 10 labelcolor 7 - } - } - Fl_Button {} { - label E - callback {freemodeeditwindow->show();} - tooltip {Envelope window} xywh {190 5 15 15} box PLASTIC_UP_BOX labelfont 1 labelsize 10 - } - } - } - Function {make_ADSRfilter_window()} {} { - Fl_Window envADSRfilter { - xywh {87 143 275 70} type Double color 50 labelfont 1 hide - class Fl_Group - } { - Fl_Group {} { - label {Filter Envelope} - xywh {0 0 275 70} box PLASTIC_UP_BOX color 223 labeltype ENGRAVED_LABEL labelsize 10 align 17 - } { - Fl_Dial e3aval { - label {A.val} - callback {env->PA_val=(int)o->value(); -freeedit->redraw();} - tooltip {Starting value} xywh {5 20 30 30} box ROUND_UP_BOX labelsize 10 maximum 127 step 1 - code0 {o->value(env->PA_val);} - class WidgetPDial - } - Fl_Dial e3adt { - label {A.dt} - callback {env->PA_dt=(int)o->value(); -freeedit->redraw();} - tooltip {Attack time} xywh {40 20 30 30} box ROUND_UP_BOX labelsize 10 maximum 127 step 1 - code0 {o->value(env->PA_dt);} - class WidgetPDial - } - Fl_Dial e3dval { - label {D.val} - callback {env->PD_val=(int)o->value(); -freeedit->redraw();} - tooltip {decay value} xywh {75 20 30 30} box ROUND_UP_BOX labelsize 10 maximum 127 step 1 - code0 {o->value(env->PD_val);} - class WidgetPDial - } - Fl_Dial e3ddt { - label {D.dt} - callback {env->PD_dt=(int)o->value(); -freeedit->redraw();} - tooltip {decay time} xywh {110 20 30 30} box ROUND_UP_BOX labelsize 10 maximum 127 step 1 - code0 {o->value(env->PD_dt);} - class WidgetPDial - } - Fl_Dial e3rdt { - label {R.dt} - callback {env->PR_dt=(int)o->value(); -freeedit->redraw();} - tooltip {Release time} xywh {145 20 30 30} box ROUND_UP_BOX labelsize 10 maximum 127 step 1 - code0 {o->value(env->PR_dt);} - class WidgetPDial - } - Fl_Dial e3rval { - label {R.val} - callback {env->PR_val=(int)o->value(); -freeedit->redraw();} - tooltip {Release value} xywh {180 20 30 30} box ROUND_UP_BOX labelsize 10 maximum 127 step 1 - code0 {o->value(env->PR_val);} - class WidgetPDial - } - Fl_Dial e3envstretch { - label Stretch - callback {env->Penvstretch=(int)o->value();} - tooltip {Envelope stretch (on lower notes makes the envelope longer)} xywh {215 25 25 25} box ROUND_UP_BOX labelsize 10 maximum 127 step 1 - code0 {o->value(env->Penvstretch);} - class WidgetPDial - } - Fl_Check_Button e3forcedrelease { - label frcR - callback {env->Pforcedrelease=(int)o->value();} - tooltip {Forced Relase} xywh {250 30 15 20} down_box DOWN_BOX labelsize 10 align 6 - code0 {o->value(env->Pforcedrelease);} - } - Fl_Button {} { - label E - callback {freemodeeditwindow->show();} - xywh {255 5 15 15} box PLASTIC_UP_BOX labelfont 1 labelsize 10 - } - Fl_Button {} { - label C - callback {presetsui->copy(env);} - xywh {220 5 15 15} box THIN_UP_BOX color 179 labelfont 1 labelsize 10 labelcolor 7 - } - Fl_Button {} { - label P - callback {presetsui->paste(env,this);} - xywh {237 5 15 15} box THIN_UP_BOX color 179 labelfont 1 labelsize 10 labelcolor 7 - } - } - } - } - Function {make_ASRbw_window()} {} { - Fl_Window envASRbw { - xywh {224 539 210 70} type Double hide - class Fl_Group - } { - Fl_Group {} { - label {BandWidth Envelope} - xywh {0 0 210 70} box PLASTIC_UP_BOX color 223 labeltype ENGRAVED_LABEL labelsize 10 align 17 - } { - Fl_Dial e4aval { - label {A.val} - callback {env->PA_val=(int)o->value(); -freeedit->redraw();} - tooltip {Starting value} xywh {5 20 30 30} box ROUND_UP_BOX labelsize 10 maximum 127 step 1 - code0 {o->value(env->PA_val);} - class WidgetPDial - } - Fl_Dial e4adt { - label {A.dt} - callback {env->PA_dt=(int)o->value(); -freeedit->redraw();} - tooltip {Attack time} xywh {40 20 30 30} box ROUND_UP_BOX labelsize 10 maximum 127 step 1 - code0 {o->value(env->PA_dt);} - class WidgetPDial - } - Fl_Dial e4rval { - label {R.val} - callback {env->PR_val=(int)o->value(); -freeedit->redraw();} - tooltip {Release value} xywh {110 20 30 30} box ROUND_UP_BOX labelsize 10 maximum 127 step 1 - code0 {o->value(env->PR_val);} - class WidgetPDial - } - Fl_Dial e4rdt { - label {R.dt} - callback {env->PR_dt=(int)o->value(); -freeedit->redraw();} - tooltip {Release time} xywh {75 20 30 30} box ROUND_UP_BOX labelsize 10 maximum 127 step 1 - code0 {o->value(env->PR_dt);} - class WidgetPDial - } - Fl_Dial e4envstretch { - label Stretch - callback {env->Penvstretch=(int)o->value();} - tooltip {Envelope stretch (on lower notes makes the envelope longer)} xywh {145 25 25 25} box ROUND_UP_BOX labelsize 10 maximum 127 step 1 - code0 {o->value(env->Penvstretch);} - class WidgetPDial - } - Fl_Check_Button e4forcedrelease { - label frcR - callback {env->Pforcedrelease=(int)o->value();} - tooltip {Forced release} xywh {180 25 15 25} down_box DOWN_BOX labelsize 10 align 6 - code0 {o->value(env->Pforcedrelease);} - } - Fl_Button {} { - label C - callback {presetsui->copy(env);} - xywh {155 5 15 15} box THIN_UP_BOX color 179 labelfont 1 labelsize 10 labelcolor 7 - } - Fl_Button {} { - label P - callback {presetsui->paste(env,this);} - xywh {172 5 15 15} box THIN_UP_BOX color 179 labelfont 1 labelsize 10 labelcolor 7 - } - } - Fl_Button {} { - label E - callback {freemodeeditwindow->show();} - xywh {190 5 15 15} box PLASTIC_UP_BOX labelfont 1 labelsize 10 - } - } - } - Function {make_free_window()} {} { - Fl_Window envfree { - xywh {373 413 205 70} type Double color 50 labelfont 1 hide resizable - class Fl_Group - } { - Fl_Group envfreegroup { - label {Amplitude Envelope} - xywh {0 0 205 70} box PLASTIC_UP_BOX color 223 labeltype ENGRAVED_LABEL labelsize 10 align 17 resizable - } { - Fl_Box freeeditsmall { - label Envelope - callback {envfree->redraw();} - xywh {5 20 195 45} box FLAT_BOX color 0 resizable - code0 {o->init(env);} - class EnvelopeFreeEdit - } - Fl_Button {} { - label E - callback {freemodeeditwindow->show();} - xywh {185 5 15 15} box PLASTIC_UP_BOX labelfont 1 labelsize 10 - } - Fl_Button {} { - label C - callback {presetsui->copy(env);} - xywh {150 5 15 15} box THIN_UP_BOX color 179 labelfont 1 labelsize 10 labelcolor 7 - } - Fl_Button {} { - label P - callback {presetsui->paste(env,this);} - xywh {167 5 15 15} box THIN_UP_BOX color 179 labelfont 1 labelsize 10 labelcolor 7 - } - } - } - } - Function {init(EnvelopeParams *env_)} {} { - code {env=env_; -make_ADSR_window(); -make_ASR_window(); -make_ADSRfilter_window(); -make_ASRbw_window(); -make_free_window(); - -make_freemode_edit_window(); - -envwindow=NULL; -if (env->Envmode==3) envfreegroup->label("Frequency Envelope"); -if (env->Envmode==4) envfreegroup->label("Filter Envelope"); -if (env->Envmode==5) envfreegroup->label("Bandwidth Envelope"); - -freemodeeditwindow->label(this->label()); - - -freeeditsmall->setpair(freeedit); -freeedit->setpair(freeeditsmall); - - -refresh();} {} - } - Function {reinit()} {} { - code {if (env->Pfreemode!=0){ - int answer=fl_choice("Disable the free mode of the Envelope?","No","Yes",NULL); - if (env->Pfreemode!=0) freemodebutton->value(1); - else freemodebutton->value(0); - if (answer==0) return; -}; - -if (env->Pfreemode==0) env->Pfreemode=1; - else env->Pfreemode=0; - -hide(); -int winx=freemodeeditwindow->x(); -int winy=freemodeeditwindow->y(); - -freemodeeditwindow->hide(); - -envwindow->hide(); -Fl_Group *par=envwindow->parent(); -par->hide(); - - -refresh(); -envwindow->show(); -par->redraw(); - -par->show(); -show(); -freemodeeditwindow->position(winx,winy); -freemodeeditwindow->show(); - -if (env->Pfreemode!=0) { - freemodebutton->value(1); - addpoint->show(); - deletepoint->show(); - forcedreleasecheck->show(); -}else{ - freemodebutton->value(0); - addpoint->hide(); - deletepoint->hide(); - forcedreleasecheck->hide(); -};} {selected - } - } - Function {refresh()} {} { - code {freemodebutton->value(env->Pfreemode); - -sustaincounter->value(env->Penvsustain); -if (env->Pfreemode==0) sustaincounter->hide(); - else sustaincounter->show(); -sustaincounter->maximum(env->Penvpoints-2); - -envstretchdial->value(env->Penvstretch); -if (env->Pfreemode==0) envstretchdial->hide(); - else envstretchdial->show(); - -linearenvelopecheck->value(env->Plinearenvelope); -if ((env->Pfreemode==0)||(env->Envmode>2)) linearenvelopecheck->hide(); - else linearenvelopecheck->show(); - -forcedreleasecheck->value(env->Pforcedrelease); -if (env->Pfreemode==0) forcedreleasecheck->hide(); - -freeedit->redraw(); - - -if (env->Pfreemode==0){ - switch(env->Envmode){ - case(1): - case(2): - e1adt->value(env->PA_dt); - e1ddt->value(env->PD_dt); - e1sval->value(env->PS_val); - e1rdt->value(env->PR_dt); - e1envstretch->value(env->Penvstretch); - e1linearenvelope->value(env->Plinearenvelope); - e1forcedrelease->value(env->Pforcedrelease); - break; - case(3): - e2aval->value(env->PA_val); - e2adt->value(env->PA_dt); - e2rdt->value(env->PR_dt); - e2rval->value(env->PR_val); - e2envstretch->value(env->Penvstretch); - e2forcedrelease->value(env->Pforcedrelease); - break; - case(4): - e3aval->value(env->PA_val); - e3adt->value(env->PA_dt); - e3dval->value(env->PD_val); - e3ddt->value(env->PD_dt); - e3rdt->value(env->PR_dt); - e3rval->value(env->PR_val); - e3envstretch->value(env->Penvstretch); - e3forcedrelease->value(env->Pforcedrelease); - break; - case(5): - e4aval->value(env->PA_val); - e4adt->value(env->PA_dt); - e4rdt->value(env->PR_dt); - e4rval->value(env->PR_val); - e4envstretch->value(env->Penvstretch); - e4forcedrelease->value(env->Pforcedrelease); - break; - default: - break; - }; -}else{ - envfree->redraw(); -}; - - -envADSR->hide(); -envASR->hide(); -envADSRfilter->hide(); -envASRbw->hide(); -envfree->hide(); - -if (env->Pfreemode==0){ - switch(env->Envmode){ - case(1): - case(2): - envwindow=envADSR; - break; - case(3): - envwindow=envASR; - break; - case(4): - envwindow=envADSRfilter; - break; - case(5): - envwindow=envASRbw; - break; - default: - break; - }; -}else{ - envwindow=envfree; -}; - -envwindow->resize(this->x(),this->y(),this->w(),this->h()); - -envwindow->show();} {} - } - decl {EnvelopeParams *env;} {} - decl {Fl_Group *envwindow;} {} -} diff --git a/plugins/zynaddsubfx/src/UI/EnvelopeUI.h b/plugins/zynaddsubfx/src/UI/EnvelopeUI.h deleted file mode 100644 index 0450433b3..000000000 --- a/plugins/zynaddsubfx/src/UI/EnvelopeUI.h +++ /dev/null @@ -1,280 +0,0 @@ -// generated by Fast Light User Interface Designer (fluid) version 1.0300 - -#ifndef EnvelopeUI_h -#define EnvelopeUI_h -#include -#include "WidgetPDial.h" -#include -#include -#include "../globals.h" -#include -#include "../Params/EnvelopeParams.h" -#include -#include -#include -#include "PresetsUI.h" - -class EnvelopeFreeEdit : public Fl_Box { -public: - EnvelopeFreeEdit(int x,int y, int w, int h, const char *label=0); - void init(EnvelopeParams *env_); - void setpair(Fl_Box *pair_); - int getpointx(int n); - int getpointy(int n); - int getnearest(int x,int y); -private: - void draw(); -public: - int handle(int event); -private: - Fl_Box *pair; - EnvelopeParams *env; - int oldx,oldy; - int currentpoint,cpx,cpdt; -public: - int lastpoint; -}; -#include -#include -#include -#include -#include -#include - -class EnvelopeUI : public Fl_Group,PresetsUI_ { -public: - EnvelopeUI(int x,int y, int w, int h, const char *label=0); - ~EnvelopeUI(); - Fl_Double_Window* make_freemode_edit_window(); - Fl_Double_Window *freemodeeditwindow; - EnvelopeFreeEdit *freeedit; - Fl_Button *addpoint; -private: - void cb_addpoint_i(Fl_Button*, void*); - static void cb_addpoint(Fl_Button*, void*); -public: - Fl_Button *deletepoint; -private: - void cb_deletepoint_i(Fl_Button*, void*); - static void cb_deletepoint(Fl_Button*, void*); -public: - Fl_Light_Button *freemodebutton; -private: - void cb_freemodebutton_i(Fl_Light_Button*, void*); - static void cb_freemodebutton(Fl_Light_Button*, void*); -public: - Fl_Check_Button *forcedreleasecheck; -private: - void cb_forcedreleasecheck_i(Fl_Check_Button*, void*); - static void cb_forcedreleasecheck(Fl_Check_Button*, void*); -public: - WidgetPDial *envstretchdial; -private: - void cb_envstretchdial_i(WidgetPDial*, void*); - static void cb_envstretchdial(WidgetPDial*, void*); - void cb_Close_i(Fl_Button*, void*); - static void cb_Close(Fl_Button*, void*); -public: - Fl_Check_Button *linearenvelopecheck; -private: - void cb_linearenvelopecheck_i(Fl_Check_Button*, void*); - static void cb_linearenvelopecheck(Fl_Check_Button*, void*); -public: - Fl_Counter *sustaincounter; -private: - void cb_sustaincounter_i(Fl_Counter*, void*); - static void cb_sustaincounter(Fl_Counter*, void*); - void cb_C_i(Fl_Button*, void*); - static void cb_C(Fl_Button*, void*); - void cb_P_i(Fl_Button*, void*); - static void cb_P(Fl_Button*, void*); -public: - Fl_Group* make_ADSR_window(); - Fl_Group *envADSR; - WidgetPDial *e1adt; -private: - void cb_e1adt_i(WidgetPDial*, void*); - static void cb_e1adt(WidgetPDial*, void*); -public: - WidgetPDial *e1ddt; -private: - void cb_e1ddt_i(WidgetPDial*, void*); - static void cb_e1ddt(WidgetPDial*, void*); -public: - WidgetPDial *e1rdt; -private: - void cb_e1rdt_i(WidgetPDial*, void*); - static void cb_e1rdt(WidgetPDial*, void*); -public: - WidgetPDial *e1sval; -private: - void cb_e1sval_i(WidgetPDial*, void*); - static void cb_e1sval(WidgetPDial*, void*); -public: - Fl_Check_Button *e1forcedrelease; -private: - void cb_e1forcedrelease_i(Fl_Check_Button*, void*); - static void cb_e1forcedrelease(Fl_Check_Button*, void*); -public: - WidgetPDial *e1envstretch; -private: - void cb_e1envstretch_i(WidgetPDial*, void*); - static void cb_e1envstretch(WidgetPDial*, void*); - void cb_E_i(Fl_Button*, void*); - static void cb_E(Fl_Button*, void*); -public: - Fl_Check_Button *e1linearenvelope; -private: - void cb_e1linearenvelope_i(Fl_Check_Button*, void*); - static void cb_e1linearenvelope(Fl_Check_Button*, void*); - void cb_C1_i(Fl_Button*, void*); - static void cb_C1(Fl_Button*, void*); - void cb_P1_i(Fl_Button*, void*); - static void cb_P1(Fl_Button*, void*); -public: - Fl_Group* make_ASR_window(); - Fl_Group *envASR; - WidgetPDial *e2aval; -private: - void cb_e2aval_i(WidgetPDial*, void*); - static void cb_e2aval(WidgetPDial*, void*); -public: - WidgetPDial *e2adt; -private: - void cb_e2adt_i(WidgetPDial*, void*); - static void cb_e2adt(WidgetPDial*, void*); -public: - WidgetPDial *e2rval; -private: - void cb_e2rval_i(WidgetPDial*, void*); - static void cb_e2rval(WidgetPDial*, void*); -public: - WidgetPDial *e2rdt; -private: - void cb_e2rdt_i(WidgetPDial*, void*); - static void cb_e2rdt(WidgetPDial*, void*); -public: - WidgetPDial *e2envstretch; -private: - void cb_e2envstretch_i(WidgetPDial*, void*); - static void cb_e2envstretch(WidgetPDial*, void*); -public: - Fl_Check_Button *e2forcedrelease; -private: - void cb_e2forcedrelease_i(Fl_Check_Button*, void*); - static void cb_e2forcedrelease(Fl_Check_Button*, void*); - void cb_C2_i(Fl_Button*, void*); - static void cb_C2(Fl_Button*, void*); - void cb_P2_i(Fl_Button*, void*); - static void cb_P2(Fl_Button*, void*); - void cb_E1_i(Fl_Button*, void*); - static void cb_E1(Fl_Button*, void*); -public: - Fl_Group* make_ADSRfilter_window(); - Fl_Group *envADSRfilter; - WidgetPDial *e3aval; -private: - void cb_e3aval_i(WidgetPDial*, void*); - static void cb_e3aval(WidgetPDial*, void*); -public: - WidgetPDial *e3adt; -private: - void cb_e3adt_i(WidgetPDial*, void*); - static void cb_e3adt(WidgetPDial*, void*); -public: - WidgetPDial *e3dval; -private: - void cb_e3dval_i(WidgetPDial*, void*); - static void cb_e3dval(WidgetPDial*, void*); -public: - WidgetPDial *e3ddt; -private: - void cb_e3ddt_i(WidgetPDial*, void*); - static void cb_e3ddt(WidgetPDial*, void*); -public: - WidgetPDial *e3rdt; -private: - void cb_e3rdt_i(WidgetPDial*, void*); - static void cb_e3rdt(WidgetPDial*, void*); -public: - WidgetPDial *e3rval; -private: - void cb_e3rval_i(WidgetPDial*, void*); - static void cb_e3rval(WidgetPDial*, void*); -public: - WidgetPDial *e3envstretch; -private: - void cb_e3envstretch_i(WidgetPDial*, void*); - static void cb_e3envstretch(WidgetPDial*, void*); -public: - Fl_Check_Button *e3forcedrelease; -private: - void cb_e3forcedrelease_i(Fl_Check_Button*, void*); - static void cb_e3forcedrelease(Fl_Check_Button*, void*); - void cb_E2_i(Fl_Button*, void*); - static void cb_E2(Fl_Button*, void*); - void cb_C3_i(Fl_Button*, void*); - static void cb_C3(Fl_Button*, void*); - void cb_P3_i(Fl_Button*, void*); - static void cb_P3(Fl_Button*, void*); -public: - Fl_Group* make_ASRbw_window(); - Fl_Group *envASRbw; - WidgetPDial *e4aval; -private: - void cb_e4aval_i(WidgetPDial*, void*); - static void cb_e4aval(WidgetPDial*, void*); -public: - WidgetPDial *e4adt; -private: - void cb_e4adt_i(WidgetPDial*, void*); - static void cb_e4adt(WidgetPDial*, void*); -public: - WidgetPDial *e4rval; -private: - void cb_e4rval_i(WidgetPDial*, void*); - static void cb_e4rval(WidgetPDial*, void*); -public: - WidgetPDial *e4rdt; -private: - void cb_e4rdt_i(WidgetPDial*, void*); - static void cb_e4rdt(WidgetPDial*, void*); -public: - WidgetPDial *e4envstretch; -private: - void cb_e4envstretch_i(WidgetPDial*, void*); - static void cb_e4envstretch(WidgetPDial*, void*); -public: - Fl_Check_Button *e4forcedrelease; -private: - void cb_e4forcedrelease_i(Fl_Check_Button*, void*); - static void cb_e4forcedrelease(Fl_Check_Button*, void*); - void cb_C4_i(Fl_Button*, void*); - static void cb_C4(Fl_Button*, void*); - void cb_P4_i(Fl_Button*, void*); - static void cb_P4(Fl_Button*, void*); - void cb_E3_i(Fl_Button*, void*); - static void cb_E3(Fl_Button*, void*); -public: - Fl_Group* make_free_window(); - Fl_Group *envfree; - Fl_Group *envfreegroup; - EnvelopeFreeEdit *freeeditsmall; -private: - void cb_freeeditsmall_i(EnvelopeFreeEdit*, void*); - static void cb_freeeditsmall(EnvelopeFreeEdit*, void*); - void cb_E4_i(Fl_Button*, void*); - static void cb_E4(Fl_Button*, void*); - void cb_C5_i(Fl_Button*, void*); - static void cb_C5(Fl_Button*, void*); - void cb_P5_i(Fl_Button*, void*); - static void cb_P5(Fl_Button*, void*); -public: - void init(EnvelopeParams *env_); - void reinit(); - void refresh(); -private: - EnvelopeParams *env; - Fl_Group *envwindow; -}; -#endif diff --git a/plugins/zynaddsubfx/src/UI/FilterUI.cc b/plugins/zynaddsubfx/src/UI/FilterUI.cc deleted file mode 100644 index 935f2f513..000000000 --- a/plugins/zynaddsubfx/src/UI/FilterUI.cc +++ /dev/null @@ -1,987 +0,0 @@ -// generated by Fast Light User Interface Designer (fluid) version 1.0300 - -#include "FilterUI.h" -//Copyright (c) 2002-2005 Nasca Octavian Paul -//License: GNU GPL version 2 or later - -FormantFilterGraph::FormantFilterGraph(int x,int y, int w, int h, const char *label):Fl_Box(x,y,w,h,label) { - pars=NULL; - nvowel=NULL; - nformant=NULL; - graphpoints=NULL; -} - -void FormantFilterGraph::init(FilterParams *pars_,int *nvowel_,int *nformant_) { - pars=pars_; - nvowel=nvowel_; - nformant=nformant_; - oldx=-1; - graphpoints=new REALTYPE [w()]; -} - -void FormantFilterGraph::draw_freq_line(REALTYPE freq,int type) { - REALTYPE freqx=pars->getfreqpos(freq); - switch(type){ - case 0:fl_line_style(FL_SOLID);break; - case 1:fl_line_style(FL_DOT);break; - case 2:fl_line_style(FL_DASH);break; - }; - - - if ((freqx>0.0)&&(freqx<1.0)) - fl_line(x()+(int) (freqx*w()),y(), - x()+(int) (freqx*w()),y()+h()); -} - -void FormantFilterGraph::draw() { - int maxdB=30; - int ox=x(),oy=y(),lx=w(),ly=h(),i,oiy; - REALTYPE freqx; - - fl_color(FL_BLACK); - fl_rectf(ox,oy,lx,ly); - - - //draw the lines - fl_color(FL_GRAY); - - fl_line_style(FL_SOLID); - //fl_line(ox+2,oy+ly/2,ox+lx-2,oy+ly/2); - - freqx=pars->getfreqpos(1000.0); - if ((freqx>0.0)&&(freqx<1.0)) - fl_line(ox+(int) (freqx*lx),oy, - ox+(int) (freqx*lx),oy+ly); - - for (i=1;i<10;i++){ - if(i==1){ - draw_freq_line(i*100.0,0); - draw_freq_line(i*1000.0,0); - }else - if (i==5){ - draw_freq_line(i*100.0,2); - draw_freq_line(i*1000.0,2); - }else{ - draw_freq_line(i*100.0,1); - draw_freq_line(i*1000.0,1); - }; - }; - - draw_freq_line(10000.0,0); - draw_freq_line(20000.0,1); - - fl_line_style(FL_DOT); - int GY=10;if (lyPnumformants){ - draw_freq_line(pars->getformantfreq(pars->Pvowels[*nvowel].formants[*nformant].freq),2); - - //show some information (like current formant frequency,amplitude) - char tmpstr[20]; - - snprintf(tmpstr,20,"%.2f kHz",pars->getformantfreq(pars->Pvowels[*nvowel].formants[*nformant].freq)*0.001); - fl_draw(tmpstr,ox+1,oy+1,40,12,FL_ALIGN_LEFT,NULL,0); - - snprintf(tmpstr,20,"%d dB",(int)( rap2dB(1e-9 + pars->getformantamp(pars->Pvowels[*nvowel].formants[*nformant].amp)) + pars->getgain() )); - fl_draw(tmpstr,ox+1,oy+15,40,12,FL_ALIGN_LEFT,NULL,0); - - }; - - //draw the data - - fl_color(FL_RED); - fl_line_style(FL_SOLID); - - pars->formantfilterH(*nvowel,lx,graphpoints); - - oiy=(int) ((graphpoints[0]/maxdB+1.0)*ly/2.0); - for (i=1;i=0)&&(oiy>=0)&&(iyPtype=(int)o->value(); -pars->changed=true; -} -void FilterUI::cb_analogfiltertypechoice(Fl_Choice* o, void* v) { - ((FilterUI*)(o->parent()->parent()->user_data()))->cb_analogfiltertypechoice_i(o,v); -} - -Fl_Menu_Item FilterUI::menu_analogfiltertypechoice[] = { - {"LPF1", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {"HPF1", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {"LPF2", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {"HPF2", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {"BPF2", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {"NF2", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {"PkF2", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {"LSh2", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {"HSh2", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {0,0,0,0,0,0,0,0,0} -}; - -void FilterUI::cb_svfiltertypechoice_i(Fl_Choice* o, void*) { - pars->Ptype=(int)o->value(); -pars->changed=true; -} -void FilterUI::cb_svfiltertypechoice(Fl_Choice* o, void* v) { - ((FilterUI*)(o->parent()->parent()->user_data()))->cb_svfiltertypechoice_i(o,v); -} - -Fl_Menu_Item FilterUI::menu_svfiltertypechoice[] = { - {"1LPF", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {"1HPF", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {"1BPF", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {"1NF", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {0,0,0,0,0,0,0,0,0} -}; - -void FilterUI::cb_filtertype_i(Fl_Choice* o, void*) { - switchcategory((int)o->value()); -pars->changed=true; -} -void FilterUI::cb_filtertype(Fl_Choice* o, void* v) { - ((FilterUI*)(o->parent()->parent()->user_data()))->cb_filtertype_i(o,v); -} - -Fl_Menu_Item FilterUI::menu_filtertype[] = { - {"Analog", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {"Formant", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {"StVarF", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {0,0,0,0,0,0,0,0,0} -}; - -void FilterUI::cb_cfreqdial_i(WidgetPDial* o, void*) { - pars->Pfreq=(int)o->value(); -} -void FilterUI::cb_cfreqdial(WidgetPDial* o, void* v) { - ((FilterUI*)(o->parent()->parent()->user_data()))->cb_cfreqdial_i(o,v); -} - -void FilterUI::cb_qdial_i(WidgetPDial* o, void*) { - pars->Pq=(int)o->value(); -formantfiltergraph->redraw(); -} -void FilterUI::cb_qdial(WidgetPDial* o, void* v) { - ((FilterUI*)(o->parent()->parent()->user_data()))->cb_qdial_i(o,v); -} - -void FilterUI::cb_freqtrdial_i(WidgetPDial* o, void*) { - pars->Pfreqtrack=(int) o->value(); -} -void FilterUI::cb_freqtrdial(WidgetPDial* o, void* v) { - ((FilterUI*)(o->parent()->parent()->user_data()))->cb_freqtrdial_i(o,v); -} - -void FilterUI::cb_vsnsadial_i(WidgetPDial* o, void*) { - if (velsnsamp!=NULL) *velsnsamp=(int)o->value(); -} -void FilterUI::cb_vsnsadial(WidgetPDial* o, void* v) { - ((FilterUI*)(o->parent()->parent()->user_data()))->cb_vsnsadial_i(o,v); -} - -void FilterUI::cb_vsnsdial_i(WidgetPDial* o, void*) { - if (velsns!=NULL) *velsns=(int)o->value(); -} -void FilterUI::cb_vsnsdial(WidgetPDial* o, void* v) { - ((FilterUI*)(o->parent()->parent()->user_data()))->cb_vsnsdial_i(o,v); -} - -void FilterUI::cb_gaindial_i(WidgetPDial* o, void*) { - pars->Pgain=(int)o->value(); -formantfiltergraph->redraw(); -pars->changed=true; -} -void FilterUI::cb_gaindial(WidgetPDial* o, void* v) { - ((FilterUI*)(o->parent()->parent()->user_data()))->cb_gaindial_i(o,v); -} - -void FilterUI::cb_stcounter_i(Fl_Choice* o, void*) { - pars->Pstages=(int)o->value(); -formantfiltergraph->redraw(); -pars->changed=true; -} -void FilterUI::cb_stcounter(Fl_Choice* o, void* v) { - ((FilterUI*)(o->parent()->parent()->user_data()))->cb_stcounter_i(o,v); -} - -void FilterUI::cb_editbutton_i(Fl_Button*, void*) { - formantparswindow->show(); -} -void FilterUI::cb_editbutton(Fl_Button* o, void* v) { - ((FilterUI*)(o->parent()->user_data()))->cb_editbutton_i(o,v); -} - -void FilterUI::cb_C_i(Fl_Button*, void*) { - presetsui->copy(pars); -} -void FilterUI::cb_C(Fl_Button* o, void* v) { - ((FilterUI*)(o->parent()->user_data()))->cb_C_i(o,v); -} - -void FilterUI::cb_P_i(Fl_Button*, void*) { - presetsui->paste(pars,this); -} -void FilterUI::cb_P(Fl_Button* o, void* v) { - ((FilterUI*)(o->parent()->user_data()))->cb_P_i(o,v); -} - -void FilterUI::cb_Formant_i(Fl_Counter* o, void*) { - nformant=(int) o->value(); -update_formant_window(); -formantfiltergraph->redraw(); -} -void FilterUI::cb_Formant(Fl_Counter* o, void* v) { - ((FilterUI*)(o->parent()->parent()->user_data()))->cb_Formant_i(o,v); -} - -void FilterUI::cb_Vowel_i(Fl_Counter* o, void*) { - nvowel=(int) o->value(); -update_formant_window(); -formantfiltergraph->redraw(); -} -void FilterUI::cb_Vowel(Fl_Counter* o, void* v) { - ((FilterUI*)(o->parent()->parent()->user_data()))->cb_Vowel_i(o,v); -} - -void FilterUI::cb_formant_freq_dial_i(WidgetPDial* o, void*) { - pars->Pvowels[nvowel].formants[nformant].freq=(int) o->value(); -formantfiltergraph->redraw(); -pars->changed=true; -} -void FilterUI::cb_formant_freq_dial(WidgetPDial* o, void* v) { - ((FilterUI*)(o->parent()->parent()->parent()->user_data()))->cb_formant_freq_dial_i(o,v); -} - -void FilterUI::cb_formant_q_dial_i(WidgetPDial* o, void*) { - pars->Pvowels[nvowel].formants[nformant].q=(int) o->value(); -formantfiltergraph->redraw(); -pars->changed=true; -} -void FilterUI::cb_formant_q_dial(WidgetPDial* o, void* v) { - ((FilterUI*)(o->parent()->parent()->parent()->user_data()))->cb_formant_q_dial_i(o,v); -} - -void FilterUI::cb_formant_amp_dial_i(WidgetPDial* o, void*) { - pars->Pvowels[nvowel].formants[nformant].amp=(int) o->value(); -formantfiltergraph->redraw(); -pars->changed=true; -} -void FilterUI::cb_formant_amp_dial(WidgetPDial* o, void* v) { - ((FilterUI*)(o->parent()->parent()->parent()->user_data()))->cb_formant_amp_dial_i(o,v); -} - -void FilterUI::cb_Seq_i(Fl_Counter* o, void*) { - pars->Psequencesize=(int) o->value(); -update_formant_window(); -pars->changed=true; -} -void FilterUI::cb_Seq(Fl_Counter* o, void* v) { - ((FilterUI*)(o->parent()->parent()->user_data()))->cb_Seq_i(o,v); -} - -void FilterUI::cb_S_i(Fl_Counter* o, void*) { - nseqpos=(int) o->value(); -update_formant_window(); -pars->changed=true; -} -void FilterUI::cb_S(Fl_Counter* o, void* v) { - ((FilterUI*)(o->parent()->parent()->user_data()))->cb_S_i(o,v); -} - -void FilterUI::cb_vowel_counter_i(Fl_Counter* o, void*) { - pars->Psequence[nseqpos].nvowel=(int) o->value(); -pars->changed=true; -} -void FilterUI::cb_vowel_counter(Fl_Counter* o, void* v) { - ((FilterUI*)(o->parent()->parent()->user_data()))->cb_vowel_counter_i(o,v); -} - -void FilterUI::cb_Neg_i(Fl_Check_Button* o, void*) { - pars->Psequencereversed=(int) o->value(); -pars->changed=true; -} -void FilterUI::cb_Neg(Fl_Check_Button* o, void* v) { - ((FilterUI*)(o->parent()->parent()->user_data()))->cb_Neg_i(o,v); -} - -void FilterUI::cb_strchdial_i(WidgetPDial* o, void*) { - pars->Psequencestretch=(int) o->value(); -pars->changed=true; -} -void FilterUI::cb_strchdial(WidgetPDial* o, void* v) { - ((FilterUI*)(o->parent()->parent()->user_data()))->cb_strchdial_i(o,v); -} - -void FilterUI::cb_Num_i(Fl_Counter* o, void*) { - pars->Pnumformants=(int) o->value(); -update_formant_window(); -pars->changed=true; -formantfiltergraph->redraw(); -} -void FilterUI::cb_Num(Fl_Counter* o, void* v) { - ((FilterUI*)(o->parent()->user_data()))->cb_Num_i(o,v); -} - -void FilterUI::cb_frsldial_i(WidgetPDial* o, void*) { - pars->Pformantslowness=(int) o->value(); -pars->changed=true; -} -void FilterUI::cb_frsldial(WidgetPDial* o, void* v) { - ((FilterUI*)(o->parent()->user_data()))->cb_frsldial_i(o,v); -} - -void FilterUI::cb_centerfreqvo_i(Fl_Value_Output* o, void*) { - o->value(pars->getcenterfreq()/1000.0); -} -void FilterUI::cb_centerfreqvo(Fl_Value_Output* o, void* v) { - ((FilterUI*)(o->parent()->user_data()))->cb_centerfreqvo_i(o,v); -} - -void FilterUI::cb_octavesfreqvo_i(Fl_Value_Output* o, void*) { - o->value(pars->getoctavesfreq()); -} -void FilterUI::cb_octavesfreqvo(Fl_Value_Output* o, void* v) { - ((FilterUI*)(o->parent()->user_data()))->cb_octavesfreqvo_i(o,v); -} - -void FilterUI::cb_cfknob_i(Fl_Slider* o, void*) { - pars->Pcenterfreq=(int)o->value(); -centerfreqvo->do_callback(); -formantfiltergraph->redraw(); -pars->changed=true; -} -void FilterUI::cb_cfknob(Fl_Slider* o, void* v) { - ((FilterUI*)(o->parent()->user_data()))->cb_cfknob_i(o,v); -} - -void FilterUI::cb_octknob_i(Fl_Slider* o, void*) { - pars->Poctavesfreq=(int)o->value(); -octavesfreqvo->do_callback(); -formantfiltergraph->redraw(); -} -void FilterUI::cb_octknob(Fl_Slider* o, void* v) { - ((FilterUI*)(o->parent()->user_data()))->cb_octknob_i(o,v); -} - -void FilterUI::cb_wvknob_i(WidgetPDial* o, void*) { - pars->Pvowelclearness=(int) o->value(); -pars->changed=true; -} -void FilterUI::cb_wvknob(WidgetPDial* o, void* v) { - ((FilterUI*)(o->parent()->user_data()))->cb_wvknob_i(o,v); -} - -void FilterUI::cb_Close_i(Fl_Button*, void*) { - formantparswindow->hide(); -} -void FilterUI::cb_Close(Fl_Button* o, void* v) { - ((FilterUI*)(o->parent()->user_data()))->cb_Close_i(o,v); -} - -void FilterUI::cb_C1_i(Fl_Button*, void*) { - presetsui->copy(pars,nvowel); -} -void FilterUI::cb_C1(Fl_Button* o, void* v) { - ((FilterUI*)(o->parent()->user_data()))->cb_C1_i(o,v); -} - -void FilterUI::cb_P1_i(Fl_Button*, void*) { - presetsui->paste(pars,this,nvowel); -} -void FilterUI::cb_P1(Fl_Button* o, void* v) { - ((FilterUI*)(o->parent()->user_data()))->cb_P1_i(o,v); -} - -FilterUI::FilterUI(int x,int y, int w, int h, const char *label):Fl_Group(x,y,w,h,label) { - pars=NULL; - velsnsamp=NULL; - velsns=NULL; - nvowel=0;nformant=0;nseqpos=0; -} - -FilterUI::~FilterUI() { - filterui->hide(); - formantparswindow->hide(); - hide(); - //delete (filterui); - delete (formantparswindow); -} - -Fl_Group* FilterUI::make_window() { - { filterui = new Fl_Group(0, 0, 275, 75); - filterui->box(FL_FLAT_BOX); - filterui->color(FL_LIGHT1); - filterui->selection_color(FL_BACKGROUND_COLOR); - filterui->labeltype(FL_NO_LABEL); - filterui->labelfont(1); - filterui->labelsize(14); - filterui->labelcolor(FL_FOREGROUND_COLOR); - filterui->user_data((void*)(this)); - filterui->align(Fl_Align(FL_ALIGN_TOP)); - filterui->when(FL_WHEN_RELEASE); - { filterparamswindow = new Fl_Group(0, 0, 275, 75, "Filter Parameters"); - filterparamswindow->box(FL_PLASTIC_UP_BOX); - filterparamswindow->color((Fl_Color)183); - filterparamswindow->labeltype(FL_ENGRAVED_LABEL); - filterparamswindow->labelsize(10); - filterparamswindow->align(Fl_Align(FL_ALIGN_TOP|FL_ALIGN_INSIDE)); - { Fl_Choice* o = analogfiltertypechoice = new Fl_Choice(10, 50, 50, 15, "FilterType"); - analogfiltertypechoice->tooltip("The Filter type"); - analogfiltertypechoice->down_box(FL_BORDER_BOX); - analogfiltertypechoice->labelsize(10); - analogfiltertypechoice->textsize(10); - analogfiltertypechoice->callback((Fl_Callback*)cb_analogfiltertypechoice); - analogfiltertypechoice->align(Fl_Align(FL_ALIGN_TOP_LEFT)); - analogfiltertypechoice->menu(menu_analogfiltertypechoice); - o->value(pars->Ptype); - } // Fl_Choice* analogfiltertypechoice - { Fl_Choice* o = svfiltertypechoice = new Fl_Choice(10, 50, 50, 15, "FilterType"); - svfiltertypechoice->tooltip("The Filter type"); - svfiltertypechoice->down_box(FL_BORDER_BOX); - svfiltertypechoice->labelsize(10); - svfiltertypechoice->textsize(10); - svfiltertypechoice->callback((Fl_Callback*)cb_svfiltertypechoice); - svfiltertypechoice->align(Fl_Align(FL_ALIGN_TOP_LEFT)); - svfiltertypechoice->menu(menu_svfiltertypechoice); - o->value(pars->Ptype); - } // Fl_Choice* svfiltertypechoice - { Fl_Choice* o = filtertype = new Fl_Choice(10, 20, 60, 15, "Category"); - filtertype->tooltip("The Category of the Filter (Analog/Formantic/etc.)"); - filtertype->down_box(FL_BORDER_BOX); - filtertype->labelsize(10); - filtertype->textsize(10); - filtertype->callback((Fl_Callback*)cb_filtertype); - filtertype->align(Fl_Align(FL_ALIGN_TOP_LEFT)); - filtertype->menu(menu_filtertype); - o->value(pars->Pcategory); - } // Fl_Choice* filtertype - { WidgetPDial* o = cfreqdial = new WidgetPDial(75, 25, 30, 30, "C.Freq"); - cfreqdial->tooltip("Center Frequency of the Filter or the base position in the vowel\'s sequence"); - cfreqdial->box(FL_ROUND_UP_BOX); - cfreqdial->color(FL_BACKGROUND_COLOR); - cfreqdial->selection_color(FL_INACTIVE_COLOR); - cfreqdial->labeltype(FL_NORMAL_LABEL); - cfreqdial->labelfont(0); - cfreqdial->labelsize(10); - cfreqdial->labelcolor(FL_FOREGROUND_COLOR); - cfreqdial->maximum(127); - cfreqdial->step(1); - cfreqdial->callback((Fl_Callback*)cb_cfreqdial); - cfreqdial->align(Fl_Align(FL_ALIGN_BOTTOM)); - cfreqdial->when(FL_WHEN_CHANGED); - o->value(pars->Pfreq); - } // WidgetPDial* cfreqdial - { WidgetPDial* o = qdial = new WidgetPDial(110, 25, 30, 30, "Q"); - qdial->tooltip("Filter resonance or bandwidth"); - qdial->box(FL_ROUND_UP_BOX); - qdial->color(FL_BACKGROUND_COLOR); - qdial->selection_color(FL_INACTIVE_COLOR); - qdial->labeltype(FL_NORMAL_LABEL); - qdial->labelfont(0); - qdial->labelsize(10); - qdial->labelcolor(FL_FOREGROUND_COLOR); - qdial->maximum(127); - qdial->step(1); - qdial->callback((Fl_Callback*)cb_qdial); - qdial->align(Fl_Align(FL_ALIGN_BOTTOM)); - qdial->when(FL_WHEN_CHANGED); - o->value(pars->Pq); - } // WidgetPDial* qdial - { WidgetPDial* o = freqtrdial = new WidgetPDial(215, 25, 30, 30, "freq.tr."); - freqtrdial->tooltip("Filter frequency tracking (left is negative, middle is 0, and right is positi\ -ve)"); - freqtrdial->box(FL_ROUND_UP_BOX); - freqtrdial->color(FL_BACKGROUND_COLOR); - freqtrdial->selection_color(FL_INACTIVE_COLOR); - freqtrdial->labeltype(FL_NORMAL_LABEL); - freqtrdial->labelfont(0); - freqtrdial->labelsize(10); - freqtrdial->labelcolor(FL_FOREGROUND_COLOR); - freqtrdial->maximum(127); - freqtrdial->step(1); - freqtrdial->callback((Fl_Callback*)cb_freqtrdial); - freqtrdial->align(Fl_Align(FL_ALIGN_BOTTOM)); - freqtrdial->when(FL_WHEN_CHANGED); - o->value(pars->Pfreqtrack); - } // WidgetPDial* freqtrdial - { vsnsadial = new WidgetPDial(145, 25, 30, 30, "V.SnsA."); - vsnsadial->tooltip("Velocity sensing amount of the Filter"); - vsnsadial->box(FL_ROUND_UP_BOX); - vsnsadial->color(FL_BACKGROUND_COLOR); - vsnsadial->selection_color(FL_INACTIVE_COLOR); - vsnsadial->labeltype(FL_NORMAL_LABEL); - vsnsadial->labelfont(0); - vsnsadial->labelsize(10); - vsnsadial->labelcolor(FL_FOREGROUND_COLOR); - vsnsadial->maximum(127); - vsnsadial->step(1); - vsnsadial->callback((Fl_Callback*)cb_vsnsadial); - vsnsadial->align(Fl_Align(FL_ALIGN_BOTTOM)); - vsnsadial->when(FL_WHEN_CHANGED); - } // WidgetPDial* vsnsadial - { vsnsdial = new WidgetPDial(180, 25, 30, 30, "V.Sns."); - vsnsdial->tooltip("Velocity Sensing Function of the Filter"); - vsnsdial->box(FL_ROUND_UP_BOX); - vsnsdial->color(FL_BACKGROUND_COLOR); - vsnsdial->selection_color(FL_INACTIVE_COLOR); - vsnsdial->labeltype(FL_NORMAL_LABEL); - vsnsdial->labelfont(0); - vsnsdial->labelsize(10); - vsnsdial->labelcolor(FL_FOREGROUND_COLOR); - vsnsdial->maximum(127); - vsnsdial->step(1); - vsnsdial->callback((Fl_Callback*)cb_vsnsdial); - vsnsdial->align(Fl_Align(FL_ALIGN_BOTTOM)); - vsnsdial->when(FL_WHEN_CHANGED); - } // WidgetPDial* vsnsdial - { WidgetPDial* o = gaindial = new WidgetPDial(250, 35, 20, 20, "gain"); - gaindial->tooltip("Filter output gain/damp"); - gaindial->box(FL_ROUND_UP_BOX); - gaindial->color(FL_BACKGROUND_COLOR); - gaindial->selection_color(FL_INACTIVE_COLOR); - gaindial->labeltype(FL_NORMAL_LABEL); - gaindial->labelfont(0); - gaindial->labelsize(10); - gaindial->labelcolor(FL_FOREGROUND_COLOR); - gaindial->maximum(127); - gaindial->step(1); - gaindial->callback((Fl_Callback*)cb_gaindial); - gaindial->align(Fl_Align(FL_ALIGN_BOTTOM)); - gaindial->when(FL_WHEN_CHANGED); - o->value(pars->Pgain); - } // WidgetPDial* gaindial - { Fl_Choice* o = stcounter = new Fl_Choice(235, 5, 35, 15, "St"); - stcounter->tooltip("Filter stages (in order to increase dB/oct. value and the order of the filter\ -)"); - stcounter->down_box(FL_BORDER_BOX); - stcounter->labelsize(10); - stcounter->textfont(1); - stcounter->textsize(10); - stcounter->callback((Fl_Callback*)cb_stcounter); - for (int i=0;iadd(tmp);}; - o->value(pars->Pstages); - } // Fl_Choice* stcounter - filterparamswindow->end(); - } // Fl_Group* filterparamswindow - { editbutton = new Fl_Button(15, 40, 50, 25, "Edit"); - editbutton->box(FL_PLASTIC_UP_BOX); - editbutton->labelfont(1); - editbutton->labelsize(11); - editbutton->callback((Fl_Callback*)cb_editbutton); - } // Fl_Button* editbutton - { Fl_Button* o = new Fl_Button(186, 5, 15, 15, "C"); - o->box(FL_THIN_UP_BOX); - o->color((Fl_Color)179); - o->labelfont(1); - o->labelsize(10); - o->labelcolor(FL_BACKGROUND2_COLOR); - o->callback((Fl_Callback*)cb_C); - } // Fl_Button* o - { Fl_Button* o = new Fl_Button(203, 5, 15, 15, "P"); - o->box(FL_THIN_UP_BOX); - o->color((Fl_Color)179); - o->labelfont(1); - o->labelsize(10); - o->labelcolor(FL_BACKGROUND2_COLOR); - o->callback((Fl_Callback*)cb_P); - } // Fl_Button* o - filterui->end(); - } // Fl_Group* filterui - return filterui; -} - -Fl_Double_Window* FilterUI::make_formant_window() { - { formantparswindow = new Fl_Double_Window(700, 205, "Formant Filter Parameters"); - formantparswindow->user_data((void*)(this)); - { Fl_Group* o = new Fl_Group(485, 47, 105, 113); - o->box(FL_THIN_UP_BOX); - { Fl_Counter* o = new Fl_Counter(545, 80, 40, 15, "Formant "); - o->type(1); - o->labelfont(1); - o->labelsize(10); - o->minimum(0); - o->maximum(127); - o->step(1); - o->textsize(10); - o->callback((Fl_Callback*)cb_Formant); - o->align(Fl_Align(FL_ALIGN_LEFT)); - o->bounds(0,FF_MAX_FORMANTS-1); - o->value(nformant); - } // Fl_Counter* o - { Fl_Counter* o = new Fl_Counter(545, 55, 40, 20, "Vowel no."); - o->type(1); - o->labelfont(1); - o->labelsize(10); - o->minimum(0); - o->maximum(127); - o->step(1); - o->textfont(1); - o->textsize(11); - o->callback((Fl_Callback*)cb_Vowel); - o->align(Fl_Align(FL_ALIGN_LEFT)); - o->bounds(0,FF_MAX_VOWELS-1); - o->value(nvowel); - } // Fl_Counter* o - { formantparsgroup = new Fl_Group(490, 105, 95, 50); - formantparsgroup->box(FL_ENGRAVED_FRAME); - { formant_freq_dial = new WidgetPDial(495, 115, 25, 25, "freq"); - formant_freq_dial->tooltip("Formant frequency"); - formant_freq_dial->box(FL_ROUND_UP_BOX); - formant_freq_dial->color(FL_BACKGROUND_COLOR); - formant_freq_dial->selection_color(FL_INACTIVE_COLOR); - formant_freq_dial->labeltype(FL_NORMAL_LABEL); - formant_freq_dial->labelfont(0); - formant_freq_dial->labelsize(10); - formant_freq_dial->labelcolor(FL_FOREGROUND_COLOR); - formant_freq_dial->maximum(127); - formant_freq_dial->step(1); - formant_freq_dial->callback((Fl_Callback*)cb_formant_freq_dial); - formant_freq_dial->align(Fl_Align(FL_ALIGN_BOTTOM)); - formant_freq_dial->when(FL_WHEN_CHANGED); - } // WidgetPDial* formant_freq_dial - { formant_q_dial = new WidgetPDial(525, 115, 24, 25, "Q"); - formant_q_dial->tooltip("Formant\'s Q"); - formant_q_dial->box(FL_ROUND_UP_BOX); - formant_q_dial->color(FL_BACKGROUND_COLOR); - formant_q_dial->selection_color(FL_INACTIVE_COLOR); - formant_q_dial->labeltype(FL_NORMAL_LABEL); - formant_q_dial->labelfont(0); - formant_q_dial->labelsize(10); - formant_q_dial->labelcolor(FL_FOREGROUND_COLOR); - formant_q_dial->maximum(127); - formant_q_dial->step(1); - formant_q_dial->callback((Fl_Callback*)cb_formant_q_dial); - formant_q_dial->align(Fl_Align(FL_ALIGN_BOTTOM)); - formant_q_dial->when(FL_WHEN_CHANGED); - } // WidgetPDial* formant_q_dial - { formant_amp_dial = new WidgetPDial(555, 115, 24, 25, "amp"); - formant_amp_dial->tooltip("Formant amplitude"); - formant_amp_dial->box(FL_ROUND_UP_BOX); - formant_amp_dial->color(FL_BACKGROUND_COLOR); - formant_amp_dial->selection_color(FL_INACTIVE_COLOR); - formant_amp_dial->labeltype(FL_NORMAL_LABEL); - formant_amp_dial->labelfont(0); - formant_amp_dial->labelsize(10); - formant_amp_dial->labelcolor(FL_FOREGROUND_COLOR); - formant_amp_dial->maximum(127); - formant_amp_dial->step(1); - formant_amp_dial->callback((Fl_Callback*)cb_formant_amp_dial); - formant_amp_dial->align(Fl_Align(FL_ALIGN_BOTTOM)); - formant_amp_dial->when(FL_WHEN_CHANGED); - } // WidgetPDial* formant_amp_dial - formantparsgroup->end(); - } // Fl_Group* formantparsgroup - o->end(); - } // Fl_Group* o - { Fl_Group* o = new Fl_Group(590, 47, 100, 113); - o->box(FL_THIN_UP_BOX); - { Fl_Counter* o = new Fl_Counter(595, 62, 55, 20, "Seq.Size"); - o->type(1); - o->labelfont(1); - o->labelsize(10); - o->minimum(0); - o->maximum(127); - o->step(1); - o->textfont(1); - o->textsize(11); - o->callback((Fl_Callback*)cb_Seq); - o->align(Fl_Align(FL_ALIGN_TOP_LEFT)); - o->bounds(1,FF_MAX_SEQUENCE-1); - o->value(pars->Psequencesize); - } // Fl_Counter* o - { Fl_Counter* o = new Fl_Counter(595, 97, 40, 15, "S.Pos."); - o->tooltip("Current position from the sequence"); - o->type(1); - o->labelfont(1); - o->labelsize(10); - o->minimum(0); - o->maximum(127); - o->step(1); - o->textsize(10); - o->callback((Fl_Callback*)cb_S); - o->align(Fl_Align(FL_ALIGN_TOP_RIGHT)); - o->bounds(0,FF_MAX_SEQUENCE-2); - o->value(nseqpos); - } // Fl_Counter* o - { Fl_Counter* o = vowel_counter = new Fl_Counter(640, 97, 40, 15, "Vowel"); - vowel_counter->type(1); - vowel_counter->labelsize(10); - vowel_counter->minimum(0); - vowel_counter->maximum(127); - vowel_counter->step(1); - vowel_counter->textsize(10); - vowel_counter->callback((Fl_Callback*)cb_vowel_counter); - vowel_counter->align(Fl_Align(FL_ALIGN_TOP)); - o->bounds(0,FF_MAX_VOWELS-1); - } // Fl_Counter* vowel_counter - { Fl_Check_Button* o = new Fl_Check_Button(625, 132, 60, 20, "Neg.Input"); - o->tooltip("Negate the input from LFO/envelopes/etc."); - o->down_box(FL_DOWN_BOX); - o->labelsize(10); - o->callback((Fl_Callback*)cb_Neg); - o->value(pars->Psequencereversed); - } // Fl_Check_Button* o - { WidgetPDial* o = strchdial = new WidgetPDial(595, 130, 25, 25, "Strch"); - strchdial->tooltip("Sequence Stretch"); - strchdial->box(FL_ROUND_UP_BOX); - strchdial->color(FL_BACKGROUND_COLOR); - strchdial->selection_color(FL_INACTIVE_COLOR); - strchdial->labeltype(FL_NORMAL_LABEL); - strchdial->labelfont(0); - strchdial->labelsize(10); - strchdial->labelcolor(FL_FOREGROUND_COLOR); - strchdial->maximum(127); - strchdial->step(1); - strchdial->callback((Fl_Callback*)cb_strchdial); - strchdial->align(Fl_Align(FL_ALIGN_TOP)); - strchdial->when(FL_WHEN_CHANGED); - o->value(pars->Psequencestretch); - } // WidgetPDial* strchdial - o->end(); - } // Fl_Group* o - { Fl_Counter* o = new Fl_Counter(485, 15, 65, 20, "Num.Formants"); - o->type(1); - o->labelfont(1); - o->labelsize(10); - o->minimum(0); - o->maximum(127); - o->step(1); - o->callback((Fl_Callback*)cb_Num); - o->align(Fl_Align(FL_ALIGN_TOP_LEFT)); - o->bounds(1,FF_MAX_FORMANTS); - o->value(pars->Pnumformants); - } // Fl_Counter* o - { WidgetPDial* o = frsldial = new WidgetPDial(565, 15, 25, 25, "Fr.Sl."); - frsldial->tooltip("Formant\'s Slowness (Morphing)"); - frsldial->box(FL_ROUND_UP_BOX); - frsldial->color(FL_BACKGROUND_COLOR); - frsldial->selection_color(FL_INACTIVE_COLOR); - frsldial->labeltype(FL_NORMAL_LABEL); - frsldial->labelfont(1); - frsldial->labelsize(10); - frsldial->labelcolor(FL_FOREGROUND_COLOR); - frsldial->maximum(127); - frsldial->step(1); - frsldial->callback((Fl_Callback*)cb_frsldial); - frsldial->align(Fl_Align(FL_ALIGN_TOP)); - frsldial->when(FL_WHEN_CHANGED); - o->value(pars->Pformantslowness); - } // WidgetPDial* frsldial - { Fl_Value_Output* o = centerfreqvo = new Fl_Value_Output(515, 164, 33, 18, "C.f."); - centerfreqvo->tooltip("Center Frequency (kHz)"); - centerfreqvo->minimum(1); - centerfreqvo->maximum(10); - centerfreqvo->step(0.01); - centerfreqvo->value(1); - centerfreqvo->textfont(1); - centerfreqvo->callback((Fl_Callback*)cb_centerfreqvo); - centerfreqvo->when(3); - o->value(pars->getcenterfreq()/1000.0); - } // Fl_Value_Output* centerfreqvo - { Fl_Value_Output* o = octavesfreqvo = new Fl_Value_Output(515, 182, 33, 18, "Oct."); - octavesfreqvo->tooltip("No. of octaves"); - octavesfreqvo->minimum(1); - octavesfreqvo->maximum(127); - octavesfreqvo->step(1); - octavesfreqvo->value(5); - octavesfreqvo->textfont(1); - octavesfreqvo->callback((Fl_Callback*)cb_octavesfreqvo); - octavesfreqvo->when(3); - o->value(pars->getoctavesfreq()); - } // Fl_Value_Output* octavesfreqvo - { Fl_Slider* o = cfknob = new Fl_Slider(551, 167, 84, 15); - cfknob->type(5); - cfknob->box(FL_FLAT_BOX); - cfknob->maximum(127); - cfknob->callback((Fl_Callback*)cb_cfknob); - o->value(pars->Pcenterfreq); - } // Fl_Slider* cfknob - { Fl_Slider* o = octknob = new Fl_Slider(551, 185, 84, 15); - octknob->type(5); - octknob->box(FL_FLAT_BOX); - octknob->maximum(127); - octknob->callback((Fl_Callback*)cb_octknob); - o->value(pars->Poctavesfreq); - } // Fl_Slider* octknob - { FormantFilterGraph* o = formantfiltergraph = new FormantFilterGraph(5, 5, 475, 195); - formantfiltergraph->box(FL_BORDER_BOX); - formantfiltergraph->color(FL_BACKGROUND_COLOR); - formantfiltergraph->selection_color(FL_BACKGROUND_COLOR); - formantfiltergraph->labeltype(FL_NORMAL_LABEL); - formantfiltergraph->labelfont(0); - formantfiltergraph->labelsize(14); - formantfiltergraph->labelcolor(FL_FOREGROUND_COLOR); - formantfiltergraph->align(Fl_Align(FL_ALIGN_CENTER)); - formantfiltergraph->when(FL_WHEN_RELEASE); - o->init(pars,&nvowel,&nformant); - } // FormantFilterGraph* formantfiltergraph - { WidgetPDial* o = wvknob = new WidgetPDial(600, 15, 25, 25, "Vw.Cl."); - wvknob->tooltip("Vowel \"clearness\" (how the mixed vowels are avoided)"); - wvknob->box(FL_ROUND_UP_BOX); - wvknob->color(FL_BACKGROUND_COLOR); - wvknob->selection_color(FL_INACTIVE_COLOR); - wvknob->labeltype(FL_NORMAL_LABEL); - wvknob->labelfont(1); - wvknob->labelsize(10); - wvknob->labelcolor(FL_FOREGROUND_COLOR); - wvknob->maximum(127); - wvknob->step(1); - wvknob->callback((Fl_Callback*)cb_wvknob); - wvknob->align(Fl_Align(FL_ALIGN_TOP)); - wvknob->when(FL_WHEN_CHANGED); - o->value(pars->Pvowelclearness); - } // WidgetPDial* wvknob - { Fl_Button* o = new Fl_Button(645, 180, 50, 25, "Close"); - o->box(FL_THIN_UP_BOX); - o->callback((Fl_Callback*)cb_Close); - } // Fl_Button* o - { Fl_Button* o = new Fl_Button(635, 25, 25, 15, "C"); - o->box(FL_THIN_UP_BOX); - o->color((Fl_Color)179); - o->labelfont(1); - o->labelsize(11); - o->labelcolor(FL_BACKGROUND2_COLOR); - o->callback((Fl_Callback*)cb_C1); - } // Fl_Button* o - { Fl_Button* o = new Fl_Button(665, 25, 25, 15, "P"); - o->box(FL_THIN_UP_BOX); - o->color((Fl_Color)179); - o->labelfont(1); - o->labelsize(11); - o->labelcolor(FL_BACKGROUND2_COLOR); - o->callback((Fl_Callback*)cb_P1); - } // Fl_Button* o - { new Fl_Box(635, 10, 55, 15, "Vowel"); - } // Fl_Box* o - formantparswindow->end(); - } // Fl_Double_Window* formantparswindow - return formantparswindow; -} - -void FilterUI::update_formant_window() { - formant_freq_dial->value(pars->Pvowels[nvowel].formants[nformant].freq); - formant_q_dial->value(pars->Pvowels[nvowel].formants[nformant].q); - formant_amp_dial->value(pars->Pvowels[nvowel].formants[nformant].amp); - if (nformantPnumformants) formantparsgroup->activate(); - else formantparsgroup->deactivate(); - - if (nseqposPsequencesize) vowel_counter->activate(); - else vowel_counter->deactivate(); - - - vowel_counter->value(pars->Psequence[nseqpos].nvowel); -} - -void FilterUI::refresh() { - update_formant_window(); - formantfiltergraph->redraw(); - - if (pars->Pcategory==0) svfiltertypechoice->value(pars->Ptype); - if (pars->Pcategory==2) analogfiltertypechoice->value(pars->Ptype); - - filtertype->value(pars->Pcategory); - - cfreqdial->value(pars->Pfreq); - qdial->value(pars->Pq); - - freqtrdial->value(pars->Pfreqtrack); - gaindial->value(pars->Pgain); - - stcounter->value(pars->Pstages); - - int categ=pars->Pcategory; - if ((categ==0)||(categ==2)) { - if (categ==0) { - analogfiltertypechoice->show(); - svfiltertypechoice->hide(); - } else { - svfiltertypechoice->show(); - analogfiltertypechoice->hide(); - }; - editbutton->hide(); - formantparswindow->hide(); - cfreqdial->label("C.freq"); - } else { - analogfiltertypechoice->hide(); - svfiltertypechoice->hide(); - editbutton->show(); - cfreqdial->label("BS.pos"); - }; - - filterparamswindow->redraw(); -} - -void FilterUI::init(FilterParams *filterpars_,unsigned char *velsnsamp_,unsigned char *velsns_) { - pars=filterpars_; - velsnsamp=velsnsamp_; - velsns=velsns_; - - make_window(); - end(); - make_formant_window(); - - - filterui->resize(this->x(),this->y(),this->w(),this->h()); - - - if (velsnsamp==NULL){ - vsnsadial->deactivate(); - vsnsadial->value(127); - } else vsnsadial->value(*velsnsamp); - - if (velsns==NULL){ - vsnsdial->deactivate(); - vsnsdial->value(127); - } else vsnsdial->value(*velsns); - - switchcategory(pars->Pcategory); - - - formantparswindow->label(this->label()); - - update_formant_window(); -} - -void FilterUI::switchcategory(int newcat) { - if (pars->Pcategory!=newcat){ - pars->Pgain=64; - gaindial->value(64); - analogfiltertypechoice->value(0); - analogfiltertypechoice->do_callback(); - svfiltertypechoice->value(0); - svfiltertypechoice->do_callback(); - }; - pars->Pcategory=newcat; - - refresh(); -} - -void FilterUI::use_for_dynamic_filter() { - freqtrdial->deactivate(); - gaindial->when(0); - - cfknob->when(FL_WHEN_RELEASE); - octknob->when(FL_WHEN_RELEASE); - - frsldial->when(0); - wvknob->when(0); - formant_freq_dial->when(0); - formant_q_dial->when(0); - formant_amp_dial->when(0); - strchdial->when(0); -} diff --git a/plugins/zynaddsubfx/src/UI/FilterUI.fl b/plugins/zynaddsubfx/src/UI/FilterUI.fl deleted file mode 100644 index e2da82e12..000000000 --- a/plugins/zynaddsubfx/src/UI/FilterUI.fl +++ /dev/null @@ -1,624 +0,0 @@ -# data file for the Fltk User Interface Designer (fluid) -version 1.0106 -header_name {.h} -code_name {.cc} -decl {//Copyright (c) 2002-2005 Nasca Octavian Paul} {} - -decl {//License: GNU GPL version 2 or later} {} - -decl {\#include "WidgetPDial.h"} {public -} - -decl {\#include } {public -} - -decl {\#include } {public -} - -decl {\#include "../globals.h"} {public -} - -decl {\#include } {public -} - -decl {\#include "../Params/FilterParams.h"} {public -} - -decl {\#include } {public -} - -decl {\#include } {public -} - -decl {\#include } {public -} - -decl {\#include "PresetsUI.h"} {public -} - -class FormantFilterGraph {: {public Fl_Box} -} { - Function {FormantFilterGraph(int x,int y, int w, int h, const char *label=0):Fl_Box(x,y,w,h,label)} {} { - code {pars=NULL; -nvowel=NULL; -nformant=NULL; -graphpoints=NULL;} {} - } - Function {init(FilterParams *pars_,int *nvowel_,int *nformant_)} {} { - code {pars=pars_; -nvowel=nvowel_; -nformant=nformant_; -oldx=-1; -graphpoints=new REALTYPE [w()];} {} - } - Function {draw_freq_line(REALTYPE freq,int type)} {} { - code {REALTYPE freqx=pars->getfreqpos(freq); -switch(type){ - case 0:fl_line_style(FL_SOLID);break; - case 1:fl_line_style(FL_DOT);break; - case 2:fl_line_style(FL_DASH);break; -}; - - -if ((freqx>0.0)&&(freqx<1.0)) - fl_line(x()+(int) (freqx*w()),y(), - x()+(int) (freqx*w()),y()+h());} {} - } - Function {draw()} {open - } { - code {int maxdB=30; -int ox=x(),oy=y(),lx=w(),ly=h(),i,oiy; -REALTYPE freqx; - -fl_color(FL_BLACK); -fl_rectf(ox,oy,lx,ly); - - -//draw the lines -fl_color(FL_GRAY); - -fl_line_style(FL_SOLID); -//fl_line(ox+2,oy+ly/2,ox+lx-2,oy+ly/2); - -freqx=pars->getfreqpos(1000.0); -if ((freqx>0.0)&&(freqx<1.0)) - fl_line(ox+(int) (freqx*lx),oy, - ox+(int) (freqx*lx),oy+ly); - -for (i=1;i<10;i++){ - if(i==1){ - draw_freq_line(i*100.0,0); - draw_freq_line(i*1000.0,0); - }else - if (i==5){ - draw_freq_line(i*100.0,2); - draw_freq_line(i*1000.0,2); - }else{ - draw_freq_line(i*100.0,1); - draw_freq_line(i*1000.0,1); - }; -}; - -draw_freq_line(10000.0,0); -draw_freq_line(20000.0,1); - -fl_line_style(FL_DOT); -int GY=10;if (lyPnumformants){ - draw_freq_line(pars->getformantfreq(pars->Pvowels[*nvowel].formants[*nformant].freq),2); - -//show some information (like current formant frequency,amplitude) - char tmpstr[20]; - - snprintf(tmpstr,20,"%.2f kHz",pars->getformantfreq(pars->Pvowels[*nvowel].formants[*nformant].freq)*0.001); - fl_draw(tmpstr,ox+1,oy+1,40,12,FL_ALIGN_LEFT,NULL,0); - - snprintf(tmpstr,20,"%d dB",(int)( rap2dB(1e-9 + pars->getformantamp(pars->Pvowels[*nvowel].formants[*nformant].amp)) + pars->getgain() )); - fl_draw(tmpstr,ox+1,oy+15,40,12,FL_ALIGN_LEFT,NULL,0); - -}; - -//draw the data - -fl_color(FL_RED); -fl_line_style(FL_SOLID); - -pars->formantfilterH(*nvowel,lx,graphpoints); - -oiy=(int) ((graphpoints[0]/maxdB+1.0)*ly/2.0); -for (i=1;i=0)&&(oiy>=0)&&(iyhide(); -formantparswindow->hide(); -hide(); -//delete (filterui); -delete (formantparswindow);} {} - } - Function {make_window()} {} { - Fl_Window filterui { - xywh {211 312 275 75} type Double color 50 labelfont 1 hide - class Fl_Group - } { - Fl_Group filterparamswindow { - label {Filter Parameters} - xywh {0 0 275 75} box PLASTIC_UP_BOX color 183 labeltype ENGRAVED_LABEL labelsize 10 align 17 - } { - Fl_Choice analogfiltertypechoice { - label FilterType - callback {pars->Ptype=(int)o->value(); -pars->changed=true;} - tooltip {The Filter type} xywh {10 50 50 15} down_box BORDER_BOX labelsize 10 align 5 textsize 10 - code1 {o->value(pars->Ptype);} - } { - menuitem {} { - label LPF1 - xywh {40 40 100 20} labelfont 1 labelsize 10 - } - menuitem {} { - label HPF1 - xywh {50 50 100 20} labelfont 1 labelsize 10 - } - menuitem {} { - label LPF2 - xywh {60 60 100 20} labelfont 1 labelsize 10 - } - menuitem {} { - label HPF2 - xywh {70 70 100 20} labelfont 1 labelsize 10 - } - menuitem {} { - label BPF2 - xywh {82 82 100 20} labelfont 1 labelsize 10 - } - menuitem {} { - label NF2 - xywh {94 94 100 20} labelfont 1 labelsize 10 - } - menuitem {} { - label PkF2 - xywh {104 104 100 20} labelfont 1 labelsize 10 - } - menuitem {} { - label LSh2 - xywh {114 114 100 20} labelfont 1 labelsize 10 - } - menuitem {} { - label HSh2 - xywh {124 124 100 20} labelfont 1 labelsize 10 - } - } - Fl_Choice svfiltertypechoice { - label FilterType - callback {pars->Ptype=(int)o->value(); -pars->changed=true;} - tooltip {The Filter type} xywh {10 50 50 15} down_box BORDER_BOX labelsize 10 align 5 textsize 10 - code1 {o->value(pars->Ptype);} - } { - menuitem {} { - label 1LPF - xywh {134 134 100 20} labelfont 1 labelsize 10 - } - menuitem {} { - label 1HPF - xywh {144 144 100 20} labelfont 1 labelsize 10 - } - menuitem {} { - label 1BPF - xywh {154 154 100 20} labelfont 1 labelsize 10 - } - menuitem {} { - label 1NF - xywh {164 164 100 20} labelfont 1 labelsize 10 - } - } - Fl_Choice filtertype { - label Category - callback {switchcategory((int)o->value()); -pars->changed=true;} - tooltip {The Category of the Filter (Analog/Formantic/etc.)} xywh {10 20 60 15} down_box BORDER_BOX labelsize 10 align 5 textsize 10 - code0 {o->value(pars->Pcategory);} - } { - menuitem {} { - label Analog - xywh {50 50 100 20} labelfont 1 labelsize 10 - } - menuitem {} { - label Formant - xywh {60 60 100 20} labelfont 1 labelsize 10 - } - menuitem {} { - label StVarF - xywh {70 70 100 20} labelfont 1 labelsize 10 - } - } - Fl_Dial cfreqdial { - label {C.Freq} - callback {pars->Pfreq=(int)o->value();} - tooltip {Center Frequency of the Filter or the base position in the vowel's sequence} xywh {75 25 30 30} box ROUND_UP_BOX labelsize 10 maximum 127 step 1 - code0 {o->value(pars->Pfreq);} - class WidgetPDial - } - Fl_Dial qdial { - label Q - callback {pars->Pq=(int)o->value(); -formantfiltergraph->redraw();} - tooltip {Filter resonance or bandwidth} xywh {110 25 30 30} box ROUND_UP_BOX labelsize 10 maximum 127 step 1 - code0 {o->value(pars->Pq);} - class WidgetPDial - } - Fl_Dial freqtrdial { - label {freq.tr.} - callback {pars->Pfreqtrack=(int) o->value();} - tooltip {Filter frequency tracking (left is negative, middle is 0, and right is positive)} xywh {215 25 30 30} box ROUND_UP_BOX labelsize 10 maximum 127 step 1 - code0 {o->value(pars->Pfreqtrack);} - class WidgetPDial - } - Fl_Dial vsnsadial { - label {V.SnsA.} - callback {if (velsnsamp!=NULL) *velsnsamp=(int)o->value();} - tooltip {Velocity sensing amount of the Filter} xywh {145 25 30 30} box ROUND_UP_BOX labelsize 10 maximum 127 step 1 - class WidgetPDial - } - Fl_Dial vsnsdial { - label {V.Sns.} - callback {if (velsns!=NULL) *velsns=(int)o->value();} - tooltip {Velocity Sensing Function of the Filter} xywh {180 25 30 30} box ROUND_UP_BOX labelsize 10 maximum 127 step 1 - class WidgetPDial - } - Fl_Dial gaindial { - label gain - callback {pars->Pgain=(int)o->value(); -formantfiltergraph->redraw(); -pars->changed=true;} - tooltip {Filter output gain/damp} xywh {250 35 20 20} box ROUND_UP_BOX labelsize 10 maximum 127 step 1 - code0 {o->value(pars->Pgain);} - class WidgetPDial - } - Fl_Choice stcounter { - label St - callback {pars->Pstages=(int)o->value(); -formantfiltergraph->redraw(); -pars->changed=true;} open - tooltip {Filter stages (in order to increase dB/oct. value and the order of the filter)} xywh {235 5 35 15} down_box BORDER_BOX labelsize 10 textfont 1 textsize 10 - code1 {for (int i=0;iadd(tmp);};} - code2 {o->value(pars->Pstages);} - } {} - } - Fl_Button editbutton { - label Edit - callback {formantparswindow->show();} - xywh {15 40 50 25} box PLASTIC_UP_BOX labelfont 1 labelsize 11 - } - Fl_Button {} { - label C - callback {presetsui->copy(pars);} - xywh {186 5 15 15} box THIN_UP_BOX color 179 labelfont 1 labelsize 10 labelcolor 7 - } - Fl_Button {} { - label P - callback {presetsui->paste(pars,this);} - xywh {203 5 15 15} box THIN_UP_BOX color 179 labelfont 1 labelsize 10 labelcolor 7 - } - } - } - Function {make_formant_window()} {} { - Fl_Window formantparswindow { - label {Formant Filter Parameters} - xywh {47 301 700 205} type Double hide - } { - Fl_Group {} { - xywh {485 47 105 113} box THIN_UP_BOX - } { - Fl_Counter {} { - label {Formant } - callback {nformant=(int) o->value(); -update_formant_window(); -formantfiltergraph->redraw();} - xywh {545 80 40 15} type Simple labelfont 1 labelsize 10 align 4 minimum 0 maximum 127 step 1 textsize 10 - code0 {o->bounds(0,FF_MAX_FORMANTS-1);} - code1 {o->value(nformant);} - } - Fl_Counter {} { - label {Vowel no.} - callback {nvowel=(int) o->value(); -update_formant_window(); -formantfiltergraph->redraw();} - xywh {545 55 40 20} type Simple labelfont 1 labelsize 10 align 4 minimum 0 maximum 127 step 1 textfont 1 textsize 11 - code0 {o->bounds(0,FF_MAX_VOWELS-1);} - code1 {o->value(nvowel);} - } - Fl_Group formantparsgroup { - xywh {490 105 95 50} box ENGRAVED_FRAME - } { - Fl_Dial formant_freq_dial { - label freq - callback {pars->Pvowels[nvowel].formants[nformant].freq=(int) o->value(); -formantfiltergraph->redraw(); -pars->changed=true;} - tooltip {Formant frequency} xywh {495 115 25 25} box ROUND_UP_BOX labelsize 10 maximum 127 step 1 - class WidgetPDial - } - Fl_Dial formant_q_dial { - label Q - callback {pars->Pvowels[nvowel].formants[nformant].q=(int) o->value(); -formantfiltergraph->redraw(); -pars->changed=true;} - tooltip {Formant's Q} xywh {525 115 24 25} box ROUND_UP_BOX labelsize 10 maximum 127 step 1 - class WidgetPDial - } - Fl_Dial formant_amp_dial { - label amp - callback {pars->Pvowels[nvowel].formants[nformant].amp=(int) o->value(); -formantfiltergraph->redraw(); -pars->changed=true;} - tooltip {Formant amplitude} xywh {555 115 24 25} box ROUND_UP_BOX labelsize 10 maximum 127 step 1 - class WidgetPDial - } - } - } - Fl_Group {} { - xywh {590 47 100 113} box THIN_UP_BOX - } { - Fl_Counter {} { - label {Seq.Size} - callback {pars->Psequencesize=(int) o->value(); -update_formant_window(); -pars->changed=true;} - xywh {595 62 55 20} type Simple labelfont 1 labelsize 10 align 5 minimum 0 maximum 127 step 1 textfont 1 textsize 11 - code0 {o->bounds(1,FF_MAX_SEQUENCE-1);} - code1 {o->value(pars->Psequencesize);} - } - Fl_Counter {} { - label {S.Pos.} - callback {nseqpos=(int) o->value(); -update_formant_window(); -pars->changed=true;} - tooltip {Current position from the sequence} xywh {595 97 40 15} type Simple labelfont 1 labelsize 10 align 9 minimum 0 maximum 127 step 1 textsize 10 - code0 {o->bounds(0,FF_MAX_SEQUENCE-2);} - code1 {o->value(nseqpos);} - } - Fl_Counter vowel_counter { - label Vowel - callback {pars->Psequence[nseqpos].nvowel=(int) o->value(); -pars->changed=true;} - xywh {640 97 40 15} type Simple labelsize 10 align 1 minimum 0 maximum 127 step 1 textsize 10 - code0 {o->bounds(0,FF_MAX_VOWELS-1);} - } - Fl_Check_Button {} { - label {Neg.Input} - callback {pars->Psequencereversed=(int) o->value(); -pars->changed=true;} - tooltip {Negate the input from LFO/envelopes/etc.} xywh {625 132 60 20} down_box DOWN_BOX labelsize 10 - code0 {o->value(pars->Psequencereversed);} - } - Fl_Dial strchdial { - label Strch - callback {pars->Psequencestretch=(int) o->value(); -pars->changed=true;} - tooltip {Sequence Stretch} xywh {595 130 25 25} box ROUND_UP_BOX labelsize 10 align 1 maximum 127 step 1 - code0 {o->value(pars->Psequencestretch);} - class WidgetPDial - } - } - Fl_Counter {} { - label {Num.Formants} - callback {pars->Pnumformants=(int) o->value(); -update_formant_window(); -pars->changed=true; -formantfiltergraph->redraw();} - xywh {485 15 65 20} type Simple labelfont 1 labelsize 10 align 5 minimum 0 maximum 127 step 1 - code0 {o->bounds(1,FF_MAX_FORMANTS);} - code1 {o->value(pars->Pnumformants);} - } - Fl_Dial frsldial { - label {Fr.Sl.} - callback {pars->Pformantslowness=(int) o->value(); -pars->changed=true;} - tooltip {Formant's Slowness (Morphing)} xywh {565 15 25 25} box ROUND_UP_BOX labelfont 1 labelsize 10 align 1 maximum 127 step 1 - code0 {o->value(pars->Pformantslowness);} - class WidgetPDial - } - Fl_Value_Output centerfreqvo { - label {C.f.} - callback {o->value(pars->getcenterfreq()/1000.0);} - tooltip {Center Frequency (kHz)} xywh {515 164 33 18} when 3 minimum 1 maximum 10 step 0.01 value 1 textfont 1 - code0 {o->value(pars->getcenterfreq()/1000.0);} - } - Fl_Value_Output octavesfreqvo { - label {Oct.} - callback {o->value(pars->getoctavesfreq());} - tooltip {No. of octaves} xywh {515 182 33 18} when 3 minimum 1 maximum 127 step 1 value 5 textfont 1 - code0 {o->value(pars->getoctavesfreq());} - } - Fl_Slider cfknob { - callback {pars->Pcenterfreq=(int)o->value(); -centerfreqvo->do_callback(); -formantfiltergraph->redraw(); -pars->changed=true;} - xywh {551 167 84 15} type {Horz Knob} box FLAT_BOX maximum 127 - code0 {o->value(pars->Pcenterfreq);} - } - Fl_Slider octknob { - callback {pars->Poctavesfreq=(int)o->value(); -octavesfreqvo->do_callback(); -formantfiltergraph->redraw();} - xywh {551 185 84 15} type {Horz Knob} box FLAT_BOX maximum 127 - code0 {o->value(pars->Poctavesfreq);} - } - Fl_Box formantfiltergraph { - xywh {5 5 475 195} box BORDER_BOX - code0 {o->init(pars,&nvowel,&nformant);} - class FormantFilterGraph - } - Fl_Dial wvknob { - label {Vw.Cl.} - callback {pars->Pvowelclearness=(int) o->value(); -pars->changed=true;} - tooltip {Vowel "clearness" (how the mixed vowels are avoided)} xywh {600 15 25 25} box ROUND_UP_BOX labelfont 1 labelsize 10 align 1 maximum 127 step 1 - code0 {o->value(pars->Pvowelclearness);} - class WidgetPDial - } - Fl_Button {} { - label Close - callback {formantparswindow->hide();} - xywh {645 180 50 25} box THIN_UP_BOX - } - Fl_Button {} { - label C - callback {presetsui->copy(pars,nvowel);} - xywh {635 25 25 15} box THIN_UP_BOX color 179 labelfont 1 labelsize 11 labelcolor 7 - } - Fl_Button {} { - label P - callback {presetsui->paste(pars,this,nvowel);} - xywh {665 25 25 15} box THIN_UP_BOX color 179 labelfont 1 labelsize 11 labelcolor 7 - } - Fl_Box {} { - label Vowel - xywh {635 10 55 15} - } - } - } - Function {update_formant_window()} {} { - code {formant_freq_dial->value(pars->Pvowels[nvowel].formants[nformant].freq); -formant_q_dial->value(pars->Pvowels[nvowel].formants[nformant].q); -formant_amp_dial->value(pars->Pvowels[nvowel].formants[nformant].amp); -if (nformantPnumformants) formantparsgroup->activate(); - else formantparsgroup->deactivate(); - -if (nseqposPsequencesize) vowel_counter->activate(); - else vowel_counter->deactivate(); - - -vowel_counter->value(pars->Psequence[nseqpos].nvowel);} {} - } - Function {refresh()} {} { - code {update_formant_window(); -formantfiltergraph->redraw(); - -if (pars->Pcategory==0) svfiltertypechoice->value(pars->Ptype); -if (pars->Pcategory==2) analogfiltertypechoice->value(pars->Ptype); - -filtertype->value(pars->Pcategory); - -cfreqdial->value(pars->Pfreq); -qdial->value(pars->Pq); - -freqtrdial->value(pars->Pfreqtrack); -gaindial->value(pars->Pgain); - -stcounter->value(pars->Pstages); - -int categ=pars->Pcategory; -if ((categ==0)||(categ==2)) { - if (categ==0) { - analogfiltertypechoice->show(); - svfiltertypechoice->hide(); - } else { - svfiltertypechoice->show(); - analogfiltertypechoice->hide(); - }; - editbutton->hide(); - formantparswindow->hide(); - cfreqdial->label("C.freq"); -} else { - analogfiltertypechoice->hide(); - svfiltertypechoice->hide(); - editbutton->show(); - cfreqdial->label("BS.pos"); -}; - -filterparamswindow->redraw();} {selected - } - } - Function {init(FilterParams *filterpars_,unsigned char *velsnsamp_,unsigned char *velsns_)} {} { - code {pars=filterpars_; -velsnsamp=velsnsamp_; -velsns=velsns_; - -make_window(); -end(); -make_formant_window(); - - -filterui->resize(this->x(),this->y(),this->w(),this->h()); - - -if (velsnsamp==NULL){ - vsnsadial->deactivate(); - vsnsadial->value(127); - } else vsnsadial->value(*velsnsamp); - -if (velsns==NULL){ - vsnsdial->deactivate(); - vsnsdial->value(127); - } else vsnsdial->value(*velsns); - -switchcategory(pars->Pcategory); - - -formantparswindow->label(this->label()); - -update_formant_window();} {} - } - Function {switchcategory(int newcat)} {} { - code {if (pars->Pcategory!=newcat){ - pars->Pgain=64; - gaindial->value(64); - analogfiltertypechoice->value(0); - analogfiltertypechoice->do_callback(); - svfiltertypechoice->value(0); - svfiltertypechoice->do_callback(); -}; -pars->Pcategory=newcat; - -refresh();} {} - } - Function {use_for_dynamic_filter()} {} { - code {freqtrdial->deactivate(); -gaindial->when(0); - -cfknob->when(FL_WHEN_RELEASE); -octknob->when(FL_WHEN_RELEASE); - -frsldial->when(0); -wvknob->when(0); -formant_freq_dial->when(0); -formant_q_dial->when(0); -formant_amp_dial->when(0); -strchdial->when(0);} {} - } - decl {FilterParams *pars;} {} - decl {unsigned char *velsnsamp,*velsns;} {} - decl {int nvowel,nformant,nseqpos;} {} -} diff --git a/plugins/zynaddsubfx/src/UI/FilterUI.h b/plugins/zynaddsubfx/src/UI/FilterUI.h deleted file mode 100644 index e8226d4e6..000000000 --- a/plugins/zynaddsubfx/src/UI/FilterUI.h +++ /dev/null @@ -1,198 +0,0 @@ -// generated by Fast Light User Interface Designer (fluid) version 1.0300 - -#ifndef FilterUI_h -#define FilterUI_h -#include -#include "WidgetPDial.h" -#include -#include -#include "../globals.h" -#include -#include "../Params/FilterParams.h" -#include -#include -#include -#include "PresetsUI.h" - -class FormantFilterGraph : public Fl_Box { -public: - FormantFilterGraph(int x,int y, int w, int h, const char *label=0); - void init(FilterParams *pars_,int *nvowel_,int *nformant_); - void draw_freq_line(REALTYPE freq,int type); - void draw(); - ~FormantFilterGraph(); -private: - FilterParams *pars; - int oldx,oldy; - int *nvowel,*nformant; - REALTYPE *graphpoints; -}; -#include -#include -#include -#include -#include -#include -#include -#include -#include - -class FilterUI : public Fl_Group,PresetsUI_ { -public: - FilterUI(int x,int y, int w, int h, const char *label=0); - ~FilterUI(); - Fl_Group* make_window(); - Fl_Group *filterui; - Fl_Group *filterparamswindow; - Fl_Choice *analogfiltertypechoice; -private: - void cb_analogfiltertypechoice_i(Fl_Choice*, void*); - static void cb_analogfiltertypechoice(Fl_Choice*, void*); - static Fl_Menu_Item menu_analogfiltertypechoice[]; -public: - Fl_Choice *svfiltertypechoice; -private: - void cb_svfiltertypechoice_i(Fl_Choice*, void*); - static void cb_svfiltertypechoice(Fl_Choice*, void*); - static Fl_Menu_Item menu_svfiltertypechoice[]; -public: - Fl_Choice *filtertype; -private: - void cb_filtertype_i(Fl_Choice*, void*); - static void cb_filtertype(Fl_Choice*, void*); - static Fl_Menu_Item menu_filtertype[]; -public: - WidgetPDial *cfreqdial; -private: - void cb_cfreqdial_i(WidgetPDial*, void*); - static void cb_cfreqdial(WidgetPDial*, void*); -public: - WidgetPDial *qdial; -private: - void cb_qdial_i(WidgetPDial*, void*); - static void cb_qdial(WidgetPDial*, void*); -public: - WidgetPDial *freqtrdial; -private: - void cb_freqtrdial_i(WidgetPDial*, void*); - static void cb_freqtrdial(WidgetPDial*, void*); -public: - WidgetPDial *vsnsadial; -private: - void cb_vsnsadial_i(WidgetPDial*, void*); - static void cb_vsnsadial(WidgetPDial*, void*); -public: - WidgetPDial *vsnsdial; -private: - void cb_vsnsdial_i(WidgetPDial*, void*); - static void cb_vsnsdial(WidgetPDial*, void*); -public: - WidgetPDial *gaindial; -private: - void cb_gaindial_i(WidgetPDial*, void*); - static void cb_gaindial(WidgetPDial*, void*); -public: - Fl_Choice *stcounter; -private: - void cb_stcounter_i(Fl_Choice*, void*); - static void cb_stcounter(Fl_Choice*, void*); -public: - Fl_Button *editbutton; -private: - void cb_editbutton_i(Fl_Button*, void*); - static void cb_editbutton(Fl_Button*, void*); - void cb_C_i(Fl_Button*, void*); - static void cb_C(Fl_Button*, void*); - void cb_P_i(Fl_Button*, void*); - static void cb_P(Fl_Button*, void*); -public: - Fl_Double_Window* make_formant_window(); - Fl_Double_Window *formantparswindow; -private: - void cb_Formant_i(Fl_Counter*, void*); - static void cb_Formant(Fl_Counter*, void*); - void cb_Vowel_i(Fl_Counter*, void*); - static void cb_Vowel(Fl_Counter*, void*); -public: - Fl_Group *formantparsgroup; - WidgetPDial *formant_freq_dial; -private: - void cb_formant_freq_dial_i(WidgetPDial*, void*); - static void cb_formant_freq_dial(WidgetPDial*, void*); -public: - WidgetPDial *formant_q_dial; -private: - void cb_formant_q_dial_i(WidgetPDial*, void*); - static void cb_formant_q_dial(WidgetPDial*, void*); -public: - WidgetPDial *formant_amp_dial; -private: - void cb_formant_amp_dial_i(WidgetPDial*, void*); - static void cb_formant_amp_dial(WidgetPDial*, void*); - void cb_Seq_i(Fl_Counter*, void*); - static void cb_Seq(Fl_Counter*, void*); - void cb_S_i(Fl_Counter*, void*); - static void cb_S(Fl_Counter*, void*); -public: - Fl_Counter *vowel_counter; -private: - void cb_vowel_counter_i(Fl_Counter*, void*); - static void cb_vowel_counter(Fl_Counter*, void*); - void cb_Neg_i(Fl_Check_Button*, void*); - static void cb_Neg(Fl_Check_Button*, void*); -public: - WidgetPDial *strchdial; -private: - void cb_strchdial_i(WidgetPDial*, void*); - static void cb_strchdial(WidgetPDial*, void*); - void cb_Num_i(Fl_Counter*, void*); - static void cb_Num(Fl_Counter*, void*); -public: - WidgetPDial *frsldial; -private: - void cb_frsldial_i(WidgetPDial*, void*); - static void cb_frsldial(WidgetPDial*, void*); -public: - Fl_Value_Output *centerfreqvo; -private: - void cb_centerfreqvo_i(Fl_Value_Output*, void*); - static void cb_centerfreqvo(Fl_Value_Output*, void*); -public: - Fl_Value_Output *octavesfreqvo; -private: - void cb_octavesfreqvo_i(Fl_Value_Output*, void*); - static void cb_octavesfreqvo(Fl_Value_Output*, void*); -public: - Fl_Slider *cfknob; -private: - void cb_cfknob_i(Fl_Slider*, void*); - static void cb_cfknob(Fl_Slider*, void*); -public: - Fl_Slider *octknob; -private: - void cb_octknob_i(Fl_Slider*, void*); - static void cb_octknob(Fl_Slider*, void*); -public: - FormantFilterGraph *formantfiltergraph; - WidgetPDial *wvknob; -private: - void cb_wvknob_i(WidgetPDial*, void*); - static void cb_wvknob(WidgetPDial*, void*); - void cb_Close_i(Fl_Button*, void*); - static void cb_Close(Fl_Button*, void*); - void cb_C1_i(Fl_Button*, void*); - static void cb_C1(Fl_Button*, void*); - void cb_P1_i(Fl_Button*, void*); - static void cb_P1(Fl_Button*, void*); -public: - void update_formant_window(); - void refresh(); - void init(FilterParams *filterpars_,unsigned char *velsnsamp_,unsigned char *velsns_); - void switchcategory(int newcat); - void use_for_dynamic_filter(); -private: - FilterParams *pars; - unsigned char *velsnsamp,*velsns; - int nvowel,nformant,nseqpos; -}; -#endif diff --git a/plugins/zynaddsubfx/src/UI/LFOUI.cc b/plugins/zynaddsubfx/src/UI/LFOUI.cc deleted file mode 100644 index 120600891..000000000 --- a/plugins/zynaddsubfx/src/UI/LFOUI.cc +++ /dev/null @@ -1,289 +0,0 @@ -// generated by Fast Light User Interface Designer (fluid) version 1.0300 - -#include "LFOUI.h" -//Copyright (c) 2002-2005 Nasca Octavian Paul -//License: GNU GPL version 2 or later - -void LFOUI::cb_freq_i(WidgetPDial* o, void*) { - pars->Pfreq=o->value(); -} -void LFOUI::cb_freq(WidgetPDial* o, void* v) { - ((LFOUI*)(o->parent()->parent()->user_data()))->cb_freq_i(o,v); -} - -void LFOUI::cb_intensity_i(WidgetPDial* o, void*) { - pars->Pintensity=(int)o->value(); -} -void LFOUI::cb_intensity(WidgetPDial* o, void* v) { - ((LFOUI*)(o->parent()->parent()->user_data()))->cb_intensity_i(o,v); -} - -void LFOUI::cb_delay_i(WidgetPDial* o, void*) { - pars->Pdelay=(int)o->value(); -} -void LFOUI::cb_delay(WidgetPDial* o, void* v) { - ((LFOUI*)(o->parent()->parent()->user_data()))->cb_delay_i(o,v); -} - -void LFOUI::cb_startphase_i(WidgetPDial* o, void*) { - pars->Pstartphase=(int)o->value(); -} -void LFOUI::cb_startphase(WidgetPDial* o, void* v) { - ((LFOUI*)(o->parent()->parent()->user_data()))->cb_startphase_i(o,v); -} - -void LFOUI::cb_randomness_i(WidgetPDial* o, void*) { - pars->Prandomness=(int)o->value(); -} -void LFOUI::cb_randomness(WidgetPDial* o, void* v) { - ((LFOUI*)(o->parent()->parent()->user_data()))->cb_randomness_i(o,v); -} - -void LFOUI::cb_LFOtype_i(Fl_Choice* o, void*) { - pars->PLFOtype=(int)o->value(); -} -void LFOUI::cb_LFOtype(Fl_Choice* o, void* v) { - ((LFOUI*)(o->parent()->parent()->user_data()))->cb_LFOtype_i(o,v); -} - -Fl_Menu_Item LFOUI::menu_LFOtype[] = { - {"SINE", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {"TRI", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {"SQR", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {"R.up", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {"R.dn", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {"E1dn", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {"E2dn", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {0,0,0,0,0,0,0,0,0} -}; - -void LFOUI::cb_continous_i(Fl_Check_Button* o, void*) { - pars->Pcontinous=(int)o->value(); -} -void LFOUI::cb_continous(Fl_Check_Button* o, void* v) { - ((LFOUI*)(o->parent()->parent()->user_data()))->cb_continous_i(o,v); -} - -void LFOUI::cb_freqrand_i(WidgetPDial* o, void*) { - pars->Pfreqrand=(int)o->value(); -} -void LFOUI::cb_freqrand(WidgetPDial* o, void* v) { - ((LFOUI*)(o->parent()->parent()->user_data()))->cb_freqrand_i(o,v); -} - -void LFOUI::cb_stretch_i(WidgetPDial* o, void*) { - pars->Pstretch=(int)o->value(); -} -void LFOUI::cb_stretch(WidgetPDial* o, void* v) { - ((LFOUI*)(o->parent()->parent()->user_data()))->cb_stretch_i(o,v); -} - -void LFOUI::cb_C_i(Fl_Button*, void*) { - presetsui->copy(pars); -} -void LFOUI::cb_C(Fl_Button* o, void* v) { - ((LFOUI*)(o->parent()->parent()->user_data()))->cb_C_i(o,v); -} - -void LFOUI::cb_P_i(Fl_Button*, void*) { - presetsui->paste(pars,this); -} -void LFOUI::cb_P(Fl_Button* o, void* v) { - ((LFOUI*)(o->parent()->parent()->user_data()))->cb_P_i(o,v); -} - -LFOUI::LFOUI(int x,int y, int w, int h, const char *label):Fl_Group(x,y,w,h,label) { - pars=NULL; -} - -LFOUI::~LFOUI() { - lfoui->hide(); - hide(); - //delete (lfoui); -} - -Fl_Group* LFOUI::make_window() { - { lfoui = new Fl_Group(0, 0, 230, 70); - lfoui->box(FL_FLAT_BOX); - lfoui->color(FL_LIGHT1); - lfoui->selection_color(FL_BACKGROUND_COLOR); - lfoui->labeltype(FL_NO_LABEL); - lfoui->labelfont(1); - lfoui->labelsize(14); - lfoui->labelcolor(FL_FOREGROUND_COLOR); - lfoui->user_data((void*)(this)); - lfoui->align(Fl_Align(FL_ALIGN_TOP)); - lfoui->when(FL_WHEN_RELEASE); - { lfoparamswindow = new Fl_Group(0, 0, 230, 70, "LFO"); - lfoparamswindow->box(FL_PLASTIC_UP_BOX); - lfoparamswindow->color(FL_CYAN); - lfoparamswindow->labeltype(FL_ENGRAVED_LABEL); - lfoparamswindow->labelsize(10); - lfoparamswindow->align(Fl_Align(FL_ALIGN_TOP|FL_ALIGN_INSIDE)); - { freq = new WidgetPDial(5, 20, 30, 30, "Freq."); - freq->tooltip("LFO Frequency"); - freq->box(FL_ROUND_UP_BOX); - freq->color(FL_BACKGROUND_COLOR); - freq->selection_color(FL_INACTIVE_COLOR); - freq->labeltype(FL_NORMAL_LABEL); - freq->labelfont(0); - freq->labelsize(10); - freq->labelcolor(FL_FOREGROUND_COLOR); - freq->step(1e-05); - freq->callback((Fl_Callback*)cb_freq); - freq->align(Fl_Align(FL_ALIGN_BOTTOM)); - freq->when(FL_WHEN_CHANGED); - } // WidgetPDial* freq - { intensity = new WidgetPDial(40, 20, 30, 30, "Depth"); - intensity->tooltip("LFO Amount"); - intensity->box(FL_ROUND_UP_BOX); - intensity->color(FL_BACKGROUND_COLOR); - intensity->selection_color(FL_INACTIVE_COLOR); - intensity->labeltype(FL_NORMAL_LABEL); - intensity->labelfont(0); - intensity->labelsize(10); - intensity->labelcolor(FL_FOREGROUND_COLOR); - intensity->maximum(127); - intensity->step(1); - intensity->callback((Fl_Callback*)cb_intensity); - intensity->align(Fl_Align(FL_ALIGN_BOTTOM)); - intensity->when(FL_WHEN_CHANGED); - } // WidgetPDial* intensity - { delay = new WidgetPDial(110, 20, 30, 30, "Delay"); - delay->tooltip("LFO delay"); - delay->box(FL_ROUND_UP_BOX); - delay->color(FL_BACKGROUND_COLOR); - delay->selection_color(FL_INACTIVE_COLOR); - delay->labeltype(FL_NORMAL_LABEL); - delay->labelfont(0); - delay->labelsize(10); - delay->labelcolor(FL_FOREGROUND_COLOR); - delay->maximum(127); - delay->step(1); - delay->callback((Fl_Callback*)cb_delay); - delay->align(Fl_Align(FL_ALIGN_BOTTOM)); - delay->when(FL_WHEN_CHANGED); - } // WidgetPDial* delay - { startphase = new WidgetPDial(75, 20, 30, 30, "Start"); - startphase->tooltip("LFO Startphase (leftmost is Random)"); - startphase->box(FL_ROUND_UP_BOX); - startphase->color(FL_BACKGROUND_COLOR); - startphase->selection_color(FL_INACTIVE_COLOR); - startphase->labeltype(FL_NORMAL_LABEL); - startphase->labelfont(0); - startphase->labelsize(10); - startphase->labelcolor(FL_FOREGROUND_COLOR); - startphase->maximum(127); - startphase->step(1); - startphase->callback((Fl_Callback*)cb_startphase); - startphase->align(Fl_Align(FL_ALIGN_BOTTOM)); - startphase->when(FL_WHEN_CHANGED); - } // WidgetPDial* startphase - { randomness = new WidgetPDial(180, 7, 20, 20, "A.R."); - randomness->tooltip("LFO Amplitude Randomness"); - randomness->box(FL_ROUND_UP_BOX); - randomness->color(FL_BACKGROUND_COLOR); - randomness->selection_color(FL_INACTIVE_COLOR); - randomness->labeltype(FL_NORMAL_LABEL); - randomness->labelfont(0); - randomness->labelsize(10); - randomness->labelcolor(FL_FOREGROUND_COLOR); - randomness->maximum(127); - randomness->step(1); - randomness->callback((Fl_Callback*)cb_randomness); - randomness->align(Fl_Align(FL_ALIGN_BOTTOM)); - randomness->when(FL_WHEN_CHANGED); - } // WidgetPDial* randomness - { LFOtype = new Fl_Choice(180, 40, 45, 15, "Type"); - LFOtype->tooltip("LFO function"); - LFOtype->down_box(FL_BORDER_BOX); - LFOtype->labelsize(10); - LFOtype->textsize(8); - LFOtype->callback((Fl_Callback*)cb_LFOtype); - LFOtype->align(Fl_Align(FL_ALIGN_BOTTOM)); - LFOtype->menu(menu_LFOtype); - } // Fl_Choice* LFOtype - { continous = new Fl_Check_Button(165, 35, 15, 15, "C."); - continous->tooltip("Continous LFO"); - continous->down_box(FL_DOWN_BOX); - continous->labelsize(10); - continous->callback((Fl_Callback*)cb_continous); - continous->align(Fl_Align(FL_ALIGN_BOTTOM)); - } // Fl_Check_Button* continous - { freqrand = new WidgetPDial(205, 7, 20, 20, "F.R."); - freqrand->tooltip("LFO Frequency Randomness"); - freqrand->box(FL_ROUND_UP_BOX); - freqrand->color(FL_BACKGROUND_COLOR); - freqrand->selection_color(FL_INACTIVE_COLOR); - freqrand->labeltype(FL_NORMAL_LABEL); - freqrand->labelfont(0); - freqrand->labelsize(10); - freqrand->labelcolor(FL_FOREGROUND_COLOR); - freqrand->maximum(127); - freqrand->step(1); - freqrand->callback((Fl_Callback*)cb_freqrand); - freqrand->align(Fl_Align(FL_ALIGN_BOTTOM)); - freqrand->when(FL_WHEN_CHANGED); - } // WidgetPDial* freqrand - { stretch = new WidgetPDial(144, 30, 20, 20, "Str."); - stretch->tooltip("LFO stretch"); - stretch->box(FL_ROUND_UP_BOX); - stretch->color(FL_BACKGROUND_COLOR); - stretch->selection_color(FL_INACTIVE_COLOR); - stretch->labeltype(FL_NORMAL_LABEL); - stretch->labelfont(0); - stretch->labelsize(10); - stretch->labelcolor(FL_FOREGROUND_COLOR); - stretch->maximum(127); - stretch->step(1); - stretch->callback((Fl_Callback*)cb_stretch); - stretch->align(Fl_Align(FL_ALIGN_BOTTOM)); - stretch->when(FL_WHEN_CHANGED); - } // WidgetPDial* stretch - { Fl_Button* o = new Fl_Button(145, 10, 15, 15, "C"); - o->box(FL_THIN_UP_BOX); - o->color((Fl_Color)179); - o->labelfont(1); - o->labelsize(10); - o->labelcolor(FL_BACKGROUND2_COLOR); - o->callback((Fl_Callback*)cb_C); - } // Fl_Button* o - { Fl_Button* o = new Fl_Button(162, 10, 15, 15, "P"); - o->box(FL_THIN_UP_BOX); - o->color((Fl_Color)179); - o->labelfont(1); - o->labelsize(10); - o->labelcolor(FL_BACKGROUND2_COLOR); - o->callback((Fl_Callback*)cb_P); - } // Fl_Button* o - lfoparamswindow->end(); - } // Fl_Group* lfoparamswindow - lfoui->end(); - } // Fl_Group* lfoui - return lfoui; -} - -void LFOUI::refresh() { - freq->value(pars->Pfreq); - intensity->value(pars->Pintensity); - startphase->value(pars->Pstartphase); - delay->value(pars->Pdelay); - continous->value(pars->Pcontinous); - stretch->value(pars->Pstretch); - randomness->value(pars->Prandomness); - freqrand->value(pars->Pfreqrand); - LFOtype->value(pars->PLFOtype); -} - -void LFOUI::init(LFOParams *lfopars_) { - pars=lfopars_; - - make_window(); - end(); - - refresh(); - - lfoui->resize(this->x(),this->y(),this->w(),this->h()); - - lfoparamswindow->label(this->label()); -} diff --git a/plugins/zynaddsubfx/src/UI/LFOUI.fl b/plugins/zynaddsubfx/src/UI/LFOUI.fl deleted file mode 100644 index ca0433a2d..000000000 --- a/plugins/zynaddsubfx/src/UI/LFOUI.fl +++ /dev/null @@ -1,176 +0,0 @@ -# data file for the Fltk User Interface Designer (fluid) -version 1.0105 -header_name {.h} -code_name {.cc} -decl {//Copyright (c) 2002-2005 Nasca Octavian Paul} {} - -decl {//License: GNU GPL version 2 or later} {} - -decl {\#include "WidgetPDial.h"} {public -} - -decl {\#include } {public -} - -decl {\#include } {public -} - -decl {\#include "../globals.h"} {public -} - -decl {\#include } {public -} - -decl {\#include "../Params/LFOParams.h"} {public -} - -decl {\#include } {public -} - -decl {\#include } {public -} - -decl {\#include } {public -} - -decl {\#include "PresetsUI.h"} {public -} - -class LFOUI {: {public Fl_Group, PresetsUI_} -} { - Function {LFOUI(int x,int y, int w, int h, const char *label=0):Fl_Group(x,y,w,h,label)} {} { - code {pars=NULL;} {} - } - Function {~LFOUI()} {} { - code {lfoui->hide(); -hide(); -//delete (lfoui);} {} - } - Function {make_window()} {} { - Fl_Window lfoui { - xywh {66 328 230 70} type Double color 50 labelfont 1 hide - class Fl_Group - } { - Fl_Group lfoparamswindow { - label LFO - xywh {0 0 230 70} box PLASTIC_UP_BOX color 223 labeltype ENGRAVED_LABEL labelsize 10 align 17 - } { - Fl_Dial freq { - label {Freq.} - callback {pars->Pfreq=o->value();} - tooltip {LFO Frequency} xywh {5 20 30 30} box ROUND_UP_BOX labelsize 10 step 1e-05 - class WidgetPDial - } - Fl_Dial intensity { - label Depth - callback {pars->Pintensity=(int)o->value();} - tooltip {LFO Amount} xywh {40 20 30 30} box ROUND_UP_BOX labelsize 10 maximum 127 step 1 - class WidgetPDial - } - Fl_Dial delay { - label Delay - callback {pars->Pdelay=(int)o->value();} - tooltip {LFO delay} xywh {110 20 30 30} box ROUND_UP_BOX labelsize 10 maximum 127 step 1 - class WidgetPDial - } - Fl_Dial startphase { - label Start - callback {pars->Pstartphase=(int)o->value();} - tooltip {LFO Startphase (leftmost is Random)} xywh {75 20 30 30} box ROUND_UP_BOX labelsize 10 maximum 127 step 1 - class WidgetPDial - } - Fl_Dial randomness { - label {A.R.} - callback {pars->Prandomness=(int)o->value();} - tooltip {LFO Amplitude Randomness} xywh {180 7 20 20} box ROUND_UP_BOX labelsize 10 maximum 127 step 1 - class WidgetPDial - } - Fl_Choice LFOtype { - label Type - callback {pars->PLFOtype=(int)o->value();} - tooltip {LFO function} xywh {180 40 45 15} down_box BORDER_BOX labelsize 10 align 2 textsize 8 - } { - menuitem {} { - label SINE - xywh {20 20 100 20} labelfont 1 labelsize 10 - } - menuitem {} { - label TRI - xywh {30 30 100 20} labelfont 1 labelsize 10 - } - menuitem {} { - label SQR - xywh {30 30 100 20} labelfont 1 labelsize 10 - } - menuitem {} { - label {R.up} - xywh {40 40 100 20} labelfont 1 labelsize 10 - } - menuitem {} { - label {R.dn} - xywh {50 50 100 20} labelfont 1 labelsize 10 - } - menuitem {} { - label E1dn - xywh {60 60 100 20} labelfont 1 labelsize 10 - } - menuitem {} { - label E2dn - xywh {70 70 100 20} labelfont 1 labelsize 10 - } - } - Fl_Check_Button continous { - label {C.} - callback {pars->Pcontinous=(int)o->value();} - tooltip {Continous LFO} xywh {165 35 15 15} down_box DOWN_BOX labelsize 10 align 2 - } - Fl_Dial freqrand { - label {F.R.} - callback {pars->Pfreqrand=(int)o->value();} - tooltip {LFO Frequency Randomness} xywh {205 7 20 20} box ROUND_UP_BOX labelsize 10 maximum 127 step 1 - class WidgetPDial - } - Fl_Dial stretch { - label {Str.} - callback {pars->Pstretch=(int)o->value();} - tooltip {LFO stretch} xywh {144 30 20 20} box ROUND_UP_BOX labelsize 10 maximum 127 step 1 - class WidgetPDial - } - Fl_Button {} { - label C - callback {presetsui->copy(pars);} selected - xywh {145 10 15 15} box THIN_UP_BOX color 179 labelfont 1 labelsize 10 labelcolor 7 - } - Fl_Button {} { - label P - callback {presetsui->paste(pars,this);} selected - xywh {162 10 15 15} box THIN_UP_BOX color 179 labelfont 1 labelsize 10 labelcolor 7 - } - } - } - } - Function {refresh()} {} { - code {freq->value(pars->Pfreq); -intensity->value(pars->Pintensity); -startphase->value(pars->Pstartphase); -delay->value(pars->Pdelay); -continous->value(pars->Pcontinous); -stretch->value(pars->Pstretch); -randomness->value(pars->Prandomness); -freqrand->value(pars->Pfreqrand); -LFOtype->value(pars->PLFOtype);} {} - } - Function {init(LFOParams *lfopars_)} {} { - code {pars=lfopars_; - -make_window(); -end(); - -refresh(); - -lfoui->resize(this->x(),this->y(),this->w(),this->h()); - -lfoparamswindow->label(this->label());} {} - } - decl {LFOParams *pars;} {} -} diff --git a/plugins/zynaddsubfx/src/UI/LFOUI.h b/plugins/zynaddsubfx/src/UI/LFOUI.h deleted file mode 100644 index 6959fe3f3..000000000 --- a/plugins/zynaddsubfx/src/UI/LFOUI.h +++ /dev/null @@ -1,83 +0,0 @@ -// generated by Fast Light User Interface Designer (fluid) version 1.0300 - -#ifndef LFOUI_h -#define LFOUI_h -#include -#include "WidgetPDial.h" -#include -#include -#include "../globals.h" -#include -#include "../Params/LFOParams.h" -#include -#include -#include -#include "PresetsUI.h" -#include -#include -#include -#include - -class LFOUI : public Fl_Group, PresetsUI_ { -public: - LFOUI(int x,int y, int w, int h, const char *label=0); - ~LFOUI(); - Fl_Group* make_window(); - Fl_Group *lfoui; - Fl_Group *lfoparamswindow; - WidgetPDial *freq; -private: - void cb_freq_i(WidgetPDial*, void*); - static void cb_freq(WidgetPDial*, void*); -public: - WidgetPDial *intensity; -private: - void cb_intensity_i(WidgetPDial*, void*); - static void cb_intensity(WidgetPDial*, void*); -public: - WidgetPDial *delay; -private: - void cb_delay_i(WidgetPDial*, void*); - static void cb_delay(WidgetPDial*, void*); -public: - WidgetPDial *startphase; -private: - void cb_startphase_i(WidgetPDial*, void*); - static void cb_startphase(WidgetPDial*, void*); -public: - WidgetPDial *randomness; -private: - void cb_randomness_i(WidgetPDial*, void*); - static void cb_randomness(WidgetPDial*, void*); -public: - Fl_Choice *LFOtype; -private: - void cb_LFOtype_i(Fl_Choice*, void*); - static void cb_LFOtype(Fl_Choice*, void*); - static Fl_Menu_Item menu_LFOtype[]; -public: - Fl_Check_Button *continous; -private: - void cb_continous_i(Fl_Check_Button*, void*); - static void cb_continous(Fl_Check_Button*, void*); -public: - WidgetPDial *freqrand; -private: - void cb_freqrand_i(WidgetPDial*, void*); - static void cb_freqrand(WidgetPDial*, void*); -public: - WidgetPDial *stretch; -private: - void cb_stretch_i(WidgetPDial*, void*); - static void cb_stretch(WidgetPDial*, void*); - void cb_C_i(Fl_Button*, void*); - static void cb_C(Fl_Button*, void*); - void cb_P_i(Fl_Button*, void*); - static void cb_P(Fl_Button*, void*); -public: - void refresh(); - void init(LFOParams *lfopars_); -private: - LFOParams *pars; -}; -#endif diff --git a/plugins/zynaddsubfx/src/UI/MasterUI.cc b/plugins/zynaddsubfx/src/UI/MasterUI.cc deleted file mode 100644 index 966088460..000000000 --- a/plugins/zynaddsubfx/src/UI/MasterUI.cc +++ /dev/null @@ -1,2504 +0,0 @@ -// generated by Fast Light User Interface Designer (fluid) version 1.0300 - -#include "MasterUI.h" -//Copyright (c) 2002-2009 Nasca Octavian Paul -//License: GNU GPL version 2 or later - -VUMeter::VUMeter(int x,int y, int w, int h, const char *label):Fl_Box(x,y,w,h,label) { - master=NULL; - npart=-1; -} - -void VUMeter::init(Master *master_,int part_) { - //the "part_" parameters sets the part (if it is >=0), else it sets the master - master=master_; - label(NULL); - npart=part_; - olddbl=0.0; - olddbr=0.0; - oldrmsdbl=0.0; - oldrmsdbr=0.0; -} - -void VUMeter::draw_master() { - #define MIN_DB (-48) - - int ox=x(); int oy=y(); int lx=w(); int ly=h(); - - pthread_mutex_lock(&master->mutex); - REALTYPE dbl=rap2dB(master->vuoutpeakl); - REALTYPE dbr=rap2dB(master->vuoutpeakr); - REALTYPE rmsdbl=rap2dB(master->vurmspeakl); - REALTYPE rmsdbr=rap2dB(master->vurmspeakr); - REALTYPE maxdbl=rap2dB(master->vumaxoutpeakl); - REALTYPE maxdbr=rap2dB(master->vumaxoutpeakr); - int clipped=master->vuclipped; - pthread_mutex_unlock(&master->mutex); - - dbl=(MIN_DB-dbl)/MIN_DB; - if (dbl<0.0) dbl=0.0; - else if (dbl>1.0)dbl=1.0; - - dbr=(MIN_DB-dbr)/MIN_DB; - if (dbr<0.0) dbr=0.0; - else if (dbr>1.0) dbr=1.0; - - dbl=dbl*0.4+olddbl*0.6; - dbr=dbr*0.4+olddbr*0.6; - - olddbl=dbl; - olddbr=dbr; - - #define VULENX (lx-35) - #define VULENY (ly/2-3) - - dbl*=VULENX;dbr*=VULENX; - - int idbl=(int) dbl; - int idbr=(int) dbr; - - //compute RMS - start - rmsdbl=(MIN_DB-rmsdbl)/MIN_DB; - if (rmsdbl<0.0) rmsdbl=0.0; - else if (rmsdbl>1.0) rmsdbl=1.0; - - rmsdbr=(MIN_DB-rmsdbr)/MIN_DB; - if (rmsdbr<0.0) rmsdbr=0.0; - else if (rmsdbr>1.0) rmsdbr=1.0; - - rmsdbl=rmsdbl*0.4+oldrmsdbl*0.6; - rmsdbr=rmsdbr*0.4+oldrmsdbr*0.6; - - oldrmsdbl=rmsdbl; - oldrmsdbr=rmsdbr; - - - rmsdbl*=VULENX;rmsdbr*=VULENX; - - int irmsdbl=(int) rmsdbl; - int irmsdbr=(int) rmsdbr; - //compute RMS - end - - - - //draw the vu-meter lines - //db - fl_rectf(ox,oy,idbr,VULENY,0,200,255); - fl_rectf(ox,oy+ly/2,idbl,VULENY,0,200,255); - //black - fl_rectf(ox+idbr,oy,VULENX-idbr,VULENY,0,0,0); - fl_rectf(ox+idbl,oy+ly/2,VULENX-idbl,VULENY,0,0,0); - - //draw the scales - REALTYPE tmp=VULENX*1.0/MIN_DB; - for (int i=1;i<1-MIN_DB;i++){ - int tx=VULENX+(int) (tmp*i); - fl_rectf(ox+tx,oy,1,VULENY+ly/2,0,160,200); - if (i%5==0) fl_rectf(ox+tx,oy,1,VULENY+ly/2,0,230,240); - if (i%10==0) fl_rectf(ox+tx-1,oy,2,VULENY+ly/2,0,225,255); - }; - - //rms - if (irmsdbr>2) fl_rectf(ox+irmsdbr-1,oy,3,VULENY,255,255,0); - if (irmsdbl>2) fl_rectf(ox+irmsdbl-1,oy+ly/2,3,VULENY,255,255,0); - - - //draw the red box if clipping has occured - if (clipped==0) fl_rectf(ox+VULENX+2,oy+1,lx-VULENX-3,ly-4,0,0,10); - else fl_rectf(ox+VULENX+2,oy+1,lx-VULENX-3,ly-4,250,10,10); - - //draw the maxdB - fl_font(FL_HELVETICA|FL_BOLD,10); - fl_color(255,255,255); - char tmpstr[10]; - if ((maxdbl>MIN_DB-20)){ - snprintf((char *)&tmpstr,10,"%ddB",(int)maxdbr); - fl_draw(tmpstr,ox+VULENX+1,oy+1,lx-VULENX-1,VULENY,FL_ALIGN_RIGHT,NULL,0); - }; - if ((maxdbr>MIN_DB-20)){ - snprintf((char *)&tmpstr,10,"%ddB",(int)maxdbl); - fl_draw(tmpstr,ox+VULENX+1,oy+ly/2+1,lx-VULENX-1,VULENY,FL_ALIGN_RIGHT,NULL,0); - }; -} - -void VUMeter::draw_part() { - #define MIN_DB (-48) - int ox=x(); int oy=y(); int lx=w(); int ly=h(); - - if (!active_r()){ - pthread_mutex_lock(&master->mutex); - int fakedb=master->fakepeakpart[npart]; - pthread_mutex_unlock(&master->mutex); - fl_rectf(ox,oy,lx,ly,140,140,140); - if (fakedb>0){ - fakedb=(int)(fakedb/255.0*ly)+4; - fl_rectf(ox+2,oy+ly-fakedb,lx-4,fakedb,0,0,0); - }; - - return; - }; - - //draw the vu lines - pthread_mutex_lock(&master->mutex); - REALTYPE db=rap2dB(master->vuoutpeakpart[npart]); - pthread_mutex_unlock(&master->mutex); - - db=(MIN_DB-db)/MIN_DB; - if (db<0.0) db=0.0; - else if (db>1.0) db=1.0; - - db*=ly-2; - - int idb=(int) db; - - fl_rectf(ox,oy+ly-idb,lx,idb,0,200,255); - fl_rectf(ox,oy,lx,ly-idb,0,0,0); - - - //draw the scales - REALTYPE tmp=ly*1.0/MIN_DB; - for (int i=1;i<1-MIN_DB;i++){ - int ty=ly+(int) (tmp*i); - if (i%5==0) fl_rectf(ox,oy+ly-ty,lx,1,0,160,200); - if (i%10==0) fl_rectf(ox,oy+ly-ty,lx,1,0,230,240); - }; -} - -void VUMeter::draw() { - if (npart>=0) draw_part(); - else draw_master(); -} - -void VUMeter::tickdraw(VUMeter *o) { - o->redraw(); -} - -void VUMeter::tick(void *v) { - tickdraw((VUMeter *) v); - Fl::add_timeout(1.0/25.0,tick,v);//25 fps -} - -int VUMeter::handle(int event) { - switch(event){ - case FL_SHOW: - tick(this); - break; - case FL_HIDE: - Fl::remove_timeout(tick,this); - break; - case FL_PUSH: - if (npart>=0) break; - pthread_mutex_lock(&master->mutex); - master->vuresetpeaks(); - pthread_mutex_unlock(&master->mutex); - break; - }; - return(1); -} - -SysEffSend::SysEffSend(int x,int y, int w, int h, const char *label):WidgetPDial(x,y,w,h,label) { - master=NULL; - neff1=0; - neff2=0; -} - -void SysEffSend::init(Master *master_,int neff1_,int neff2_) { - neff1=neff1_; - neff2=neff2_; - master=master_; - minimum(0); - maximum(127); - step(1); - labelfont(1); - labelsize(10); - align(FL_ALIGN_TOP); - - value(master->Psysefxsend[neff1][neff2]); - char tmp[20];snprintf(tmp,20,"%d->%d",neff1+1,neff2+1); - this->copy_label(tmp); -} - -SysEffSend::~SysEffSend() { - hide(); -} - -int SysEffSend::handle(int event) { - if ((event==FL_PUSH) || (event==FL_DRAG)){ - master->setPsysefxsend(neff1,neff2,(int) value()); - }; - - return(WidgetPDial::handle(event)); -} - -void Panellistitem::cb_partname_i(Fl_Button*, void*) { - if ((int)bankui->cbwig->value()!=(npart+1)){ - bankui->cbwig->value(npart+1); - bankui->cbwig->do_callback(); -}; -bankui->show(); -} -void Panellistitem::cb_partname(Fl_Button* o, void* v) { - ((Panellistitem*)(o->parent()->parent()->user_data()))->cb_partname_i(o,v); -} - -void Panellistitem::cb_partvolume_i(Fl_Slider* o, void*) { - master->part[npart]->setPvolume((int) o->value()); -} -void Panellistitem::cb_partvolume(Fl_Slider* o, void* v) { - ((Panellistitem*)(o->parent()->parent()->user_data()))->cb_partvolume_i(o,v); -} - -void Panellistitem::cb_partpanning_i(WidgetPDial* o, void*) { - master->part[npart]->setPpanning((int) o->value()); -} -void Panellistitem::cb_partpanning(WidgetPDial* o, void* v) { - ((Panellistitem*)(o->parent()->parent()->user_data()))->cb_partpanning_i(o,v); -} - -void Panellistitem::cb_edit_i(Fl_Button*, void*) { - if ((int)bankui->cbwig->value()!=(npart+1)){ - bankui->cbwig->value(npart+1); - bankui->cbwig->do_callback(); -}; -} -void Panellistitem::cb_edit(Fl_Button* o, void* v) { - ((Panellistitem*)(o->parent()->parent()->user_data()))->cb_edit_i(o,v); -} - -void Panellistitem::cb_partrcv_i(Fl_Choice* o, void*) { - master->part[npart]->Prcvchn=(int) o->value(); -} -void Panellistitem::cb_partrcv(Fl_Choice* o, void* v) { - ((Panellistitem*)(o->parent()->parent()->user_data()))->cb_partrcv_i(o,v); -} - -void Panellistitem::cb_partenabled_i(Fl_Check_Button* o, void*) { - pthread_mutex_lock(&master->mutex); - master->partonoff(npart,(int) o->value()); -pthread_mutex_unlock(&master->mutex); - -if ((int) o->value()==0) panellistitemgroup->deactivate(); - else { - panellistitemgroup->activate(); - if ((int)bankui->cbwig->value()!=(npart+1)){ - bankui->cbwig->value(npart+1); - bankui->cbwig->do_callback(); - }; -}; - -o->redraw(); -} -void Panellistitem::cb_partenabled(Fl_Check_Button* o, void* v) { - ((Panellistitem*)(o->parent()->user_data()))->cb_partenabled_i(o,v); -} - -Fl_Group* Panellistitem::make_window() { - { panellistitem = new Fl_Group(0, 0, 70, 260); - panellistitem->box(FL_FLAT_BOX); - panellistitem->color(FL_BACKGROUND_COLOR); - panellistitem->selection_color(FL_BACKGROUND_COLOR); - panellistitem->labeltype(FL_NO_LABEL); - panellistitem->labelfont(0); - panellistitem->labelsize(14); - panellistitem->labelcolor(FL_FOREGROUND_COLOR); - panellistitem->user_data((void*)(this)); - panellistitem->align(Fl_Align(FL_ALIGN_TOP)); - panellistitem->when(FL_WHEN_RELEASE); - { Fl_Group* o = panellistitemgroup = new Fl_Group(0, 20, 70, 240); - panellistitemgroup->box(FL_PLASTIC_THIN_UP_BOX); - { Fl_Group* o = new Fl_Group(45, 65, 15, 110); - o->box(FL_ENGRAVED_FRAME); - { VUMeter* o = new VUMeter(45, 65, 15, 110, "V U"); - o->box(FL_FLAT_BOX); - o->color(FL_FOREGROUND_COLOR); - o->selection_color((Fl_Color)75); - o->labeltype(FL_NORMAL_LABEL); - o->labelfont(0); - o->labelsize(14); - o->labelcolor((Fl_Color)55); - o->align(Fl_Align(FL_ALIGN_WRAP)); - o->when(FL_WHEN_RELEASE); - o->init(master,npart); - } // VUMeter* o - o->end(); - } // Fl_Group* o - { partname = new Fl_Button(5, 27, 60, 30, " "); - partname->box(FL_THIN_DOWN_BOX); - partname->down_box(FL_FLAT_BOX); - partname->labelfont(1); - partname->labelsize(10); - partname->callback((Fl_Callback*)cb_partname); - partname->align(Fl_Align(192|FL_ALIGN_INSIDE)); - } // Fl_Button* partname - { Fl_Slider* o = partvolume = new Fl_Slider(10, 65, 30, 110); - partvolume->type(4); - partvolume->box(FL_FLAT_BOX); - partvolume->minimum(127); - partvolume->maximum(0); - partvolume->step(1); - partvolume->value(127); - partvolume->callback((Fl_Callback*)cb_partvolume); - o->value(master->part[npart]->Pvolume); - } // Fl_Slider* partvolume - { WidgetPDial* o = partpanning = new WidgetPDial(20, 180, 30, 30); - partpanning->box(FL_OVAL_BOX); - partpanning->color(FL_BACKGROUND_COLOR); - partpanning->selection_color(FL_INACTIVE_COLOR); - partpanning->labeltype(FL_NORMAL_LABEL); - partpanning->labelfont(0); - partpanning->labelsize(14); - partpanning->labelcolor(FL_FOREGROUND_COLOR); - partpanning->maximum(127); - partpanning->step(1); - partpanning->callback((Fl_Callback*)cb_partpanning); - partpanning->align(Fl_Align(FL_ALIGN_BOTTOM)); - partpanning->when(FL_WHEN_CHANGED); - o->value(master->part[npart]->Ppanning); - } // WidgetPDial* partpanning - { Fl_Button* o = new Fl_Button(15, 235, 40, 20, "edit"); - o->box(FL_PLASTIC_UP_BOX); - o->labelsize(10); - o->callback((Fl_Callback*)cb_edit); - } // Fl_Button* o - { Fl_Choice* o = partrcv = new Fl_Choice(10, 213, 50, 15); - partrcv->tooltip("receive from Midi channel"); - partrcv->down_box(FL_BORDER_BOX); - partrcv->labelsize(10); - partrcv->textfont(1); - partrcv->textsize(10); - partrcv->callback((Fl_Callback*)cb_partrcv); - partrcv->align(Fl_Align(FL_ALIGN_TOP_LEFT)); - char nrstr[10]; for(int i=0;iadd(nrstr); else o->add("Dr10");}; - o->value(master->part[npart]->Prcvchn); - } // Fl_Choice* partrcv - if (master->part[npart]->Penabled==0) o->deactivate(); - panellistitemgroup->end(); - } // Fl_Group* panellistitemgroup - { Fl_Check_Button* o = partenabled = new Fl_Check_Button(5, 0, 45, 20, "01"); - partenabled->down_box(FL_DOWN_BOX); - partenabled->labeltype(FL_EMBOSSED_LABEL); - partenabled->labelfont(1); - partenabled->labelsize(13); - partenabled->callback((Fl_Callback*)cb_partenabled); - partenabled->align(Fl_Align(FL_ALIGN_RIGHT|FL_ALIGN_INSIDE)); - char tmp[10];snprintf(tmp,10,"%d",npart+1);o->copy_label(tmp); - o->value(master->part[npart]->Penabled); - } // Fl_Check_Button* partenabled - panellistitem->end(); - } // Fl_Group* panellistitem - return panellistitem; -} - -Panellistitem::Panellistitem(int x,int y, int w, int h, const char *label):Fl_Group(x,y,w,h,label) { - npart=0; - master=NULL; - bankui=NULL; -} - -void Panellistitem::init(Master *master_, int npart_,BankUI *bankui_) { - npart=npart_; - master=master_; - bankui=bankui_; - - make_window(); - panellistitem->show(); - end(); -} - -void Panellistitem::refresh() { - partenabled->value(master->part[npart]->Penabled); - if (master->part[npart]->Penabled!=0) panellistitemgroup->activate(); - else panellistitemgroup->deactivate(); - - partvolume->value(master->part[npart]->Pvolume); - partpanning->value(master->part[npart]->Ppanning); - partrcv->value(master->part[npart]->Prcvchn); - - partname->label((char *)master->part[npart]->Pname); - - if ((int)bankui->cbwig->value()!=(npart+1)) - panellistitemgroup->color(fl_rgb_color(160,160,160)); - else - panellistitemgroup->color(fl_rgb_color(50,190,240)); - - panellistitemgroup->redraw(); -} - -Panellistitem::~Panellistitem() { - panellistitem->hide(); - //delete(panellistitem); -} - -void MasterUI::cb_masterwindow_i(Fl_Double_Window*, void*) { - #ifdef VSTAUDIOOUT -fl_alert("ZynAddSubFX could not be closed this way, because it's a VST plugin. Please use the host aplication to close it."); -#else -//if (fl_choice("Exit and leave the unsaved data?","No","Yes",NULL)) { - config.save(); - *exitprogram=1; -//}; -#endif -} -void MasterUI::cb_masterwindow(Fl_Double_Window* o, void* v) { - ((MasterUI*)(o->user_data()))->cb_masterwindow_i(o,v); -} - -void MasterUI::cb_New_i(Fl_Menu_*, void*) { - do_new_master(); -} -void MasterUI::cb_New(Fl_Menu_* o, void* v) { - ((MasterUI*)(o->parent()->user_data()))->cb_New_i(o,v); -} - -void MasterUI::cb_Open_i(Fl_Menu_*, void*) { - do_load_master(); -} -void MasterUI::cb_Open(Fl_Menu_* o, void* v) { - ((MasterUI*)(o->parent()->user_data()))->cb_Open_i(o,v); -} - -void MasterUI::cb_Save_i(Fl_Menu_*, void*) { - do_save_master(); -} -void MasterUI::cb_Save(Fl_Menu_* o, void* v) { - ((MasterUI*)(o->parent()->user_data()))->cb_Save_i(o,v); -} - -void MasterUI::cb_Load_i(Fl_Menu_*, void*) { - char *filename; -filename=fl_file_chooser("Open:","({*.xsz})",NULL,0); -if (filename==NULL) return; - -pthread_mutex_lock(&master->mutex); - //clear all parameters - master->microtonal.defaults(); - - //load the data - int result=master->microtonal.loadXML(filename); -pthread_mutex_unlock(&master->mutex); - - - delete microtonalui; - microtonalui=new MicrotonalUI(&master->microtonal); - -if (result==-10) fl_alert("Error: Could not load the file\nbecause it is not a scale file."); - else if (result<0) fl_alert("Error: Could not load the file."); -} -void MasterUI::cb_Load(Fl_Menu_* o, void* v) { - ((MasterUI*)(o->parent()->user_data()))->cb_Load_i(o,v); -} - -void MasterUI::cb_Save1_i(Fl_Menu_*, void*) { - char *filename; -int result=0; - -filename=fl_file_chooser("Save:","({*.xsz})",NULL,0); -if (filename==NULL) return; -filename=fl_filename_setext(filename,".xsz"); - -result=fileexists(filename); -if (result) { - result=0; - if (!fl_choice("The file exists. \nOverwrite it?","No","Yes",NULL)) return; - -}; - - -pthread_mutex_lock(&master->mutex); -result=master->microtonal.saveXML(filename); -pthread_mutex_unlock(&master->mutex); - -if (result<0) fl_alert("Error: Could not save the file."); - - -updatepanel(); -} -void MasterUI::cb_Save1(Fl_Menu_* o, void* v) { - ((MasterUI*)(o->parent()->user_data()))->cb_Save1_i(o,v); -} - -void MasterUI::cb_Show_i(Fl_Menu_*, void*) { - microtonalui->show(); -} -void MasterUI::cb_Show(Fl_Menu_* o, void* v) { - ((MasterUI*)(o->parent()->user_data()))->cb_Show_i(o,v); -} - -void MasterUI::cb_Settings_i(Fl_Menu_*, void*) { - configui->show(); -} -void MasterUI::cb_Settings(Fl_Menu_* o, void* v) { - ((MasterUI*)(o->parent()->user_data()))->cb_Settings_i(o,v); -} - -void MasterUI::cb_Copyright_i(Fl_Menu_*, void*) { - aboutwindow->show(); -} -void MasterUI::cb_Copyright(Fl_Menu_* o, void* v) { - ((MasterUI*)(o->parent()->user_data()))->cb_Copyright_i(o,v); -} - -void MasterUI::cb_E_i(Fl_Menu_*, void*) { - masterwindow->do_callback(); -} -void MasterUI::cb_E(Fl_Menu_* o, void* v) { - ((MasterUI*)(o->parent()->user_data()))->cb_E_i(o,v); -} - -void MasterUI::cb_Clear_i(Fl_Menu_*, void*) { - if (fl_choice("Clear instrument's parameters ?","No","Yes",NULL)){ -// int npart=(int)npartcounter->value()-1; - pthread_mutex_lock(&master->mutex); - master->part[npart]->defaultsinstrument(); - pthread_mutex_unlock(&master->mutex); - - npartcounter->do_callback(); -}; - -updatepanel(); -} -void MasterUI::cb_Clear(Fl_Menu_* o, void* v) { - ((MasterUI*)(o->parent()->user_data()))->cb_Clear_i(o,v); -} - -void MasterUI::cb_Open1_i(Fl_Menu_*, void*) { - const char *filename; -filename=fl_file_chooser("Load:","({*.xiz})",NULL,0); -if (filename==NULL) return; - - -pthread_mutex_lock(&master->mutex); -// int npart=(int)npartcounter->value()-1; - - //clear all instrument parameters, first - master->part[npart]->defaultsinstrument(); - - //load the instr. parameters - int result=master->part[npart]->loadXMLinstrument(filename); - -pthread_mutex_unlock(&master->mutex); -master->part[npart]->applyparameters(); - -npartcounter->do_callback(); -updatepanel(); - -if (result==-10) fl_alert("Error: Could not load the file\nbecause it is not an instrument file."); - else if (result<0) fl_alert("Error: Could not load the file."); -} -void MasterUI::cb_Open1(Fl_Menu_* o, void* v) { - ((MasterUI*)(o->parent()->user_data()))->cb_Open1_i(o,v); -} - -void MasterUI::cb_Save2_i(Fl_Menu_*, void*) { - char *filename; - -filename=fl_file_chooser("Save:","({*.xiz})",NULL,0); -if (filename==NULL) return; -filename=fl_filename_setext(filename,".xiz"); - -int result=fileexists(filename); -if (result) { - result=0; - if (!fl_choice("The file exists. \nOverwrite it?","No","Yes",NULL)) return; - -}; - - -pthread_mutex_lock(&master->mutex); -result=master->part[npart]->saveXML(filename); -pthread_mutex_unlock(&master->mutex); - -if (result<0) fl_alert("Error: Could not save the file."); - -updatepanel(); -} -void MasterUI::cb_Save2(Fl_Menu_* o, void* v) { - ((MasterUI*)(o->parent()->user_data()))->cb_Save2_i(o,v); -} - -void MasterUI::cb_Show1_i(Fl_Menu_*, void*) { - bankui->show(); -} -void MasterUI::cb_Show1(Fl_Menu_* o, void* v) { - ((MasterUI*)(o->parent()->user_data()))->cb_Show1_i(o,v); -} - -void MasterUI::cb_Virtual_i(Fl_Menu_*, void*) { - virkeyboard->show(); -} -void MasterUI::cb_Virtual(Fl_Menu_* o, void* v) { - ((MasterUI*)(o->parent()->user_data()))->cb_Virtual_i(o,v); -} - -void MasterUI::cb_Choose_i(Fl_Menu_*, void*) { - char *filename; -recordbutton->deactivate(); -pausebutton->deactivate(); -pauselabel->deactivate(); -stopbutton->deactivate(); -filename=fl_file_chooser("Record to audio file:","(*.wav)",NULL,0); -if (filename==NULL) return; -fl_filename_setext(filename,".wav"); - -int result=master->HDDRecorder.preparefile(filename,0); -if (result==1) { - result=0; - if (fl_choice("The file exists. \nOverwrite it?","No","Yes",NULL)) - master->HDDRecorder.preparefile(filename,1); -}; -if (result==0) recordbutton->activate(); - -if (result!=0) fl_alert("Error: Could not save the file."); -} -void MasterUI::cb_Choose(Fl_Menu_* o, void* v) { - ((MasterUI*)(o->parent()->user_data()))->cb_Choose_i(o,v); -} - -void MasterUI::cb_Show2_i(Fl_Menu_*, void*) { - sequi->show(); -} -void MasterUI::cb_Show2(Fl_Menu_* o, void* v) { - ((MasterUI*)(o->parent()->user_data()))->cb_Show2_i(o,v); -} - -void MasterUI::cb_Switch_i(Fl_Menu_*, void*) { - if (fl_choice("Switch the User Interface to Beginner mode ?","No","Yes",NULL)){ - masterwindow->hide(); - refresh_master_ui(); - simplemasterwindow->show(); - config.cfg.UserInterfaceMode=2; -}; -} -void MasterUI::cb_Switch(Fl_Menu_* o, void* v) { - ((MasterUI*)(o->parent()->user_data()))->cb_Switch_i(o,v); -} - -Fl_Menu_Item MasterUI::menu_mastermenu[] = { - {"&File", 0, 0, 0, 64, FL_NORMAL_LABEL, 0, 14, 0}, - {"&New (erase all)...", 0, (Fl_Callback*)MasterUI::cb_New, 0, 0, FL_NORMAL_LABEL, 0, 14, 0}, - {"&Open Parameters...", 0, (Fl_Callback*)MasterUI::cb_Open, 0, 0, FL_NORMAL_LABEL, 0, 14, 0}, - {"&Save All Parameters...", 0, (Fl_Callback*)MasterUI::cb_Save, 0, 128, FL_NORMAL_LABEL, 0, 14, 0}, - {"&Load Scale Settings...", 0, (Fl_Callback*)MasterUI::cb_Load, 0, 0, FL_NORMAL_LABEL, 0, 14, 0}, - {"Save Sc&ale Settings ..", 0, (Fl_Callback*)MasterUI::cb_Save1, 0, 0, FL_NORMAL_LABEL, 0, 14, 0}, - {"Show Scale Settings...", 0, (Fl_Callback*)MasterUI::cb_Show, 0, 128, FL_NORMAL_LABEL, 0, 14, 0}, - {"&Settings...", 0, (Fl_Callback*)MasterUI::cb_Settings, 0, 128, FL_NORMAL_LABEL, 0, 14, 0}, - {"&Copyright...", 0, (Fl_Callback*)MasterUI::cb_Copyright, 0, 128, FL_NORMAL_LABEL, 0, 14, 0}, - {"E&xit", 0, (Fl_Callback*)MasterUI::cb_E, 0, 0, FL_NORMAL_LABEL, 0, 14, 0}, - {0,0,0,0,0,0,0,0,0}, - {"&Instrument", 0, 0, 0, 64, FL_NORMAL_LABEL, 0, 14, 0}, - {"&Clear Instrument...", 0, (Fl_Callback*)MasterUI::cb_Clear, 0, 0, FL_NORMAL_LABEL, 0, 14, 0}, - {"&Open Instrument...", 0, (Fl_Callback*)MasterUI::cb_Open1, 0, 0, FL_NORMAL_LABEL, 0, 14, 0}, - {"&Save Instrument ...", 0, (Fl_Callback*)MasterUI::cb_Save2, 0, 128, FL_NORMAL_LABEL, 0, 14, 0}, - {"Show Instrument &Bank...", 0, (Fl_Callback*)MasterUI::cb_Show1, 0, 128, FL_NORMAL_LABEL, 0, 14, 0}, - {"&Virtual Keyboard...", 0, (Fl_Callback*)MasterUI::cb_Virtual, 0, 0, FL_NORMAL_LABEL, 0, 14, 0}, - {0,0,0,0,0,0,0,0,0}, - {"&Record", 0, 0, 0, 64, FL_NORMAL_LABEL, 0, 14, 0}, - {"&Choose WAV file...", 0, (Fl_Callback*)MasterUI::cb_Choose, 0, 0, FL_NORMAL_LABEL, 0, 14, 0}, - {0,0,0,0,0,0,0,0,0}, - {"&Sequencer", 0, 0, 0, 80, FL_NORMAL_LABEL, 0, 14, 0}, - {"Show &Sequencer...", 0, (Fl_Callback*)MasterUI::cb_Show2, 0, 0, FL_NORMAL_LABEL, 0, 14, 0}, - {0,0,0,0,0,0,0,0,0}, - {"Misc", 0, 0, 0, 64, FL_NORMAL_LABEL, 0, 14, 0}, - {"Switch User Interface Mode", 0, (Fl_Callback*)MasterUI::cb_Switch, 0, 0, FL_NORMAL_LABEL, 0, 14, 0}, - {0,0,0,0,0,0,0,0,0}, - {0,0,0,0,0,0,0,0,0} -}; -Fl_Menu_Item* MasterUI::recordmenu = MasterUI::menu_mastermenu + 18; - -void MasterUI::cb_mastervolumedial_i(WidgetPDial* o, void*) { - master->setPvolume((int) o->value()); -} -void MasterUI::cb_mastervolumedial(WidgetPDial* o, void* v) { - ((MasterUI*)(o->parent()->user_data()))->cb_mastervolumedial_i(o,v); -} - -void MasterUI::cb_masterkeyshiftcounter_i(Fl_Counter* o, void*) { - master->setPkeyshift((int) o->value()+64); -} -void MasterUI::cb_masterkeyshiftcounter(Fl_Counter* o, void* v) { - ((MasterUI*)(o->parent()->user_data()))->cb_masterkeyshiftcounter_i(o,v); -} - -void MasterUI::cb_Panic_i(Fl_Button*, void*) { - virkeyboard->relaseallkeys(); -pthread_mutex_lock(&master->mutex); -master->shutup=1; -pthread_mutex_unlock(&master->mutex); -} -void MasterUI::cb_Panic(Fl_Button* o, void* v) { - ((MasterUI*)(o->parent()->user_data()))->cb_Panic_i(o,v); -} - -void MasterUI::cb_syseffnocounter_i(Fl_Counter* o, void*) { - nsyseff=(int) o->value()-1; -sysefftype->value(master->sysefx[nsyseff]->geteffect()); -syseffectui->refresh(master->sysefx[nsyseff]); -} -void MasterUI::cb_syseffnocounter(Fl_Counter* o, void* v) { - ((MasterUI*)(o->parent()->parent()->parent()->user_data()))->cb_syseffnocounter_i(o,v); -} - -void MasterUI::cb_sysefftype_i(Fl_Choice* o, void*) { - pthread_mutex_lock(&master->mutex); -master->sysefx[nsyseff]->changeeffect((int) o->value()); -pthread_mutex_unlock(&master->mutex); -syseffectui->refresh(master->sysefx[nsyseff]); -} -void MasterUI::cb_sysefftype(Fl_Choice* o, void* v) { - ((MasterUI*)(o->parent()->parent()->parent()->user_data()))->cb_sysefftype_i(o,v); -} - -Fl_Menu_Item MasterUI::menu_sysefftype[] = { - {"No Effect", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {"Reverb", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {"Echo", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {"Chorus", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {"Phaser", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {"AlienWah", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {"Distortion", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {"EQ", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {"DynFilter", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {0,0,0,0,0,0,0,0,0} -}; - -void MasterUI::cb_Send_i(Fl_Button*, void*) { - syseffsendwindow->show(); -} -void MasterUI::cb_Send(Fl_Button* o, void* v) { - ((MasterUI*)(o->parent()->parent()->parent()->user_data()))->cb_Send_i(o,v); -} - -void MasterUI::cb_C_i(Fl_Button*, void*) { - presetsui->copy(master->sysefx[nsyseff]); -} -void MasterUI::cb_C(Fl_Button* o, void* v) { - ((MasterUI*)(o->parent()->parent()->parent()->user_data()))->cb_C_i(o,v); -} - -void MasterUI::cb_P_i(Fl_Button*, void*) { - pthread_mutex_lock(&master->mutex); -presetsui->paste(master->sysefx[nsyseff],syseffectui); -pthread_mutex_unlock(&master->mutex); -} -void MasterUI::cb_P(Fl_Button* o, void* v) { - ((MasterUI*)(o->parent()->parent()->parent()->user_data()))->cb_P_i(o,v); -} - -void MasterUI::cb_inseffnocounter_i(Fl_Counter* o, void*) { - ninseff=(int) o->value()-1; -insefftype->value(master->insefx[ninseff]->geteffect()); -inseffpart->value(master->Pinsparts[ninseff]+2); -inseffectui->refresh(master->insefx[ninseff]); - -if (master->Pinsparts[ninseff]!=-1) { - insefftype->activate(); - inseffectui->activate(); - inseffectuigroup->activate(); -} else { - insefftype->deactivate(); - inseffectui->deactivate(); - inseffectuigroup->deactivate(); -}; -} -void MasterUI::cb_inseffnocounter(Fl_Counter* o, void* v) { - ((MasterUI*)(o->parent()->parent()->parent()->user_data()))->cb_inseffnocounter_i(o,v); -} - -void MasterUI::cb_insefftype_i(Fl_Choice* o, void*) { - pthread_mutex_lock(&master->mutex); -master->insefx[ninseff]->changeeffect((int) o->value()); -pthread_mutex_unlock(&master->mutex); -inseffectui->refresh(master->insefx[ninseff]); -inseffectui->show(); -} -void MasterUI::cb_insefftype(Fl_Choice* o, void* v) { - ((MasterUI*)(o->parent()->parent()->parent()->user_data()))->cb_insefftype_i(o,v); -} - -Fl_Menu_Item MasterUI::menu_insefftype[] = { - {"No Effect", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {"Reverb", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {"Echo", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {"Chorus", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {"Phaser", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {"AlienWah", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {"Distortion", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {"EQ", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {"DynFilter", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {0,0,0,0,0,0,0,0,0} -}; - -void MasterUI::cb_inseffpart_i(Fl_Choice* o, void*) { - master->Pinsparts[ninseff]=(int) o->value()-2; -if ((int) o->value()==1){ - inseffectuigroup->deactivate(); - insefftype->deactivate(); - inseffectui->deactivate(); -} else { - inseffectuigroup->activate(); - insefftype->activate(); - inseffectui->activate(); -}; -master->insefx[ninseff]->cleanup(); -} -void MasterUI::cb_inseffpart(Fl_Choice* o, void* v) { - ((MasterUI*)(o->parent()->parent()->parent()->user_data()))->cb_inseffpart_i(o,v); -} - -void MasterUI::cb_C1_i(Fl_Button*, void*) { - presetsui->copy(master->insefx[ninseff]); -} -void MasterUI::cb_C1(Fl_Button* o, void* v) { - ((MasterUI*)(o->parent()->parent()->parent()->user_data()))->cb_C1_i(o,v); -} - -void MasterUI::cb_P1_i(Fl_Button*, void*) { - pthread_mutex_lock(&master->mutex); -presetsui->paste(master->insefx[ninseff],inseffectui); -pthread_mutex_unlock(&master->mutex); -} -void MasterUI::cb_P1(Fl_Button* o, void* v) { - ((MasterUI*)(o->parent()->parent()->parent()->user_data()))->cb_P1_i(o,v); -} - -void MasterUI::cb_Scales_i(Fl_Button*, void*) { - microtonalui->show(); -} -void MasterUI::cb_Scales(Fl_Button* o, void* v) { - ((MasterUI*)(o->parent()->user_data()))->cb_Scales_i(o,v); -} - -void MasterUI::cb_recordbutton_i(Fl_Button* o, void*) { - o->deactivate(); -recordmenu->deactivate(); -recordmenu->label("&Record(*)"); -stopbutton->activate(); -pausebutton->activate(); -pauselabel->activate(); -master->HDDRecorder.start(); -master->vuresetpeaks(); -mastermenu->redraw(); -} -void MasterUI::cb_recordbutton(Fl_Button* o, void* v) { - ((MasterUI*)(o->parent()->parent()->user_data()))->cb_recordbutton_i(o,v); -} - -void MasterUI::cb_stopbutton_i(Fl_Button* o, void*) { - o->deactivate(); -master->HDDRecorder.stop(); -recordbutton->deactivate(); -pausebutton->deactivate(); -pauselabel->deactivate(); -recordmenu->activate(); -recordmenu->label("&Record"); -mastermenu->redraw(); -} -void MasterUI::cb_stopbutton(Fl_Button* o, void* v) { - ((MasterUI*)(o->parent()->parent()->user_data()))->cb_stopbutton_i(o,v); -} - -void MasterUI::cb_pausebutton_i(Fl_Button* o, void*) { - o->deactivate(); -master->HDDRecorder.pause(); -recordbutton->activate(); -mastermenu->redraw(); -} -void MasterUI::cb_pausebutton(Fl_Button* o, void* v) { - ((MasterUI*)(o->parent()->parent()->user_data()))->cb_pausebutton_i(o,v); -} - -void MasterUI::cb_nrpnbutton_i(Fl_Check_Button* o, void*) { - master->ctl.NRPN.receive=(int) o->value(); -} -void MasterUI::cb_nrpnbutton(Fl_Check_Button* o, void* v) { - ((MasterUI*)(o->parent()->user_data()))->cb_nrpnbutton_i(o,v); -} - -void MasterUI::cb_npartcounter_i(Fl_Counter* o, void*) { - int nval=(int) o->value()-1; -partuigroup->remove(partui); -delete partui; -partui=new PartUI(0,0,765,525); -partuigroup->add(partui); -partui->init(master->part[nval],master,nval,bankui); -partui->redraw(); -o->redraw(); -npart=nval; - -updatepanel(); -simplenpartcounter->value(nval+1); -simplenpartcounter->do_callback(); -} -void MasterUI::cb_npartcounter(Fl_Counter* o, void* v) { - ((MasterUI*)(o->parent()->user_data()))->cb_npartcounter_i(o,v); -} - -void MasterUI::cb_vK_i(Fl_Button*, void*) { - virkeyboard->show(); -} -void MasterUI::cb_vK(Fl_Button* o, void* v) { - ((MasterUI*)(o->parent()->user_data()))->cb_vK_i(o,v); -} - -void MasterUI::cb_R_i(Fl_Button*, void*) { - globalfinedetuneslider->value(64.0); -globalfinedetuneslider->do_callback(); -} -void MasterUI::cb_R(Fl_Button* o, void* v) { - ((MasterUI*)(o->parent()->user_data()))->cb_R_i(o,v); -} - -void MasterUI::cb_globalfinedetuneslider_i(WidgetPDial* o, void*) { - master->microtonal.Pglobalfinedetune=(int) o->value(); -} -void MasterUI::cb_globalfinedetuneslider(WidgetPDial* o, void* v) { - ((MasterUI*)(o->parent()->user_data()))->cb_globalfinedetuneslider_i(o,v); -} - -void MasterUI::cb_Panel_i(Fl_Button*, void*) { - updatepanel(); -panelwindow->show(); -} -void MasterUI::cb_Panel(Fl_Button* o, void* v) { - ((MasterUI*)(o->parent()->user_data()))->cb_Panel_i(o,v); -} - -void MasterUI::cb_Close_i(Fl_Button*, void*) { - aboutwindow->hide(); -} -void MasterUI::cb_Close(Fl_Button* o, void* v) { - ((MasterUI*)(o->parent()->user_data()))->cb_Close_i(o,v); -} - -void MasterUI::cb_Close1_i(Fl_Button*, void*) { - syseffsendwindow->hide(); -} -void MasterUI::cb_Close1(Fl_Button* o, void* v) { - ((MasterUI*)(o->parent()->user_data()))->cb_Close1_i(o,v); -} - -void MasterUI::cb_Close2_i(Fl_Button*, void*) { - panelwindow->hide(); -updatepanel(); -} -void MasterUI::cb_Close2(Fl_Button* o, void* v) { - ((MasterUI*)(o->parent()->user_data()))->cb_Close2_i(o,v); -} - -void MasterUI::cb_Refresh_i(Fl_Button*, void*) { - updatepanel(); -} -void MasterUI::cb_Refresh(Fl_Button* o, void* v) { - ((MasterUI*)(o->parent()->user_data()))->cb_Refresh_i(o,v); -} - -void MasterUI::cb_simplemasterwindow_i(Fl_Double_Window*, void*) { - #ifdef VSTAUDIOOUT -fl_alert("ZynAddSubFX could not be closed this way, because it's a VST plugin. Please use the host aplication to close it."); -#else -//if (fl_choice("Exit and leave the unsaved data?","No","Yes",NULL)) { - config.save(); - *exitprogram=1; -//}; -#endif -} -void MasterUI::cb_simplemasterwindow(Fl_Double_Window* o, void* v) { - ((MasterUI*)(o->user_data()))->cb_simplemasterwindow_i(o,v); -} - -void MasterUI::cb_New1_i(Fl_Menu_*, void*) { - do_new_master(); -} -void MasterUI::cb_New1(Fl_Menu_* o, void* v) { - ((MasterUI*)(o->parent()->user_data()))->cb_New1_i(o,v); -} - -void MasterUI::cb_Open2_i(Fl_Menu_*, void*) { - do_load_master(); -} -void MasterUI::cb_Open2(Fl_Menu_* o, void* v) { - ((MasterUI*)(o->parent()->user_data()))->cb_Open2_i(o,v); -} - -void MasterUI::cb_Save3_i(Fl_Menu_*, void*) { - do_save_master(); -} -void MasterUI::cb_Save3(Fl_Menu_* o, void* v) { - ((MasterUI*)(o->parent()->user_data()))->cb_Save3_i(o,v); -} - -void MasterUI::cb_Settings1_i(Fl_Menu_*, void*) { - configui->show(); -} -void MasterUI::cb_Settings1(Fl_Menu_* o, void* v) { - ((MasterUI*)(o->parent()->user_data()))->cb_Settings1_i(o,v); -} - -void MasterUI::cb_Copyright1_i(Fl_Menu_*, void*) { - aboutwindow->show(); -} -void MasterUI::cb_Copyright1(Fl_Menu_* o, void* v) { - ((MasterUI*)(o->parent()->user_data()))->cb_Copyright1_i(o,v); -} - -void MasterUI::cb_E1_i(Fl_Menu_*, void*) { - masterwindow->do_callback(); -} -void MasterUI::cb_E1(Fl_Menu_* o, void* v) { - ((MasterUI*)(o->parent()->user_data()))->cb_E1_i(o,v); -} - -void MasterUI::cb_Open3_i(Fl_Menu_*, void*) { - const char *filename; -filename=fl_file_chooser("Load:","({*.xiz})",NULL,0); -if (filename==NULL) return; - - -pthread_mutex_lock(&master->mutex); -// int npart=(int)npartcounter->value()-1; - - //clear all instrument parameters, first - master->part[npart]->defaultsinstrument(); - - //load the instr. parameters - int result=master->part[npart]->loadXMLinstrument(filename); - -pthread_mutex_unlock(&master->mutex); -master->part[npart]->applyparameters(); - -simplenpartcounter->do_callback(); - -if (result==-10) fl_alert("Error: Could not load the file\nbecause it is not an instrument file."); - else if (result<0) fl_alert("Error: Could not load the file."); -} -void MasterUI::cb_Open3(Fl_Menu_* o, void* v) { - ((MasterUI*)(o->parent()->user_data()))->cb_Open3_i(o,v); -} - -void MasterUI::cb_Show3_i(Fl_Menu_*, void*) { - bankui->show(); -} -void MasterUI::cb_Show3(Fl_Menu_* o, void* v) { - ((MasterUI*)(o->parent()->user_data()))->cb_Show3_i(o,v); -} - -void MasterUI::cb_Switch1_i(Fl_Menu_*, void*) { - if (fl_choice("Switch the User Interface to Advanced mode ?","No","Yes",NULL)){ - simplemasterwindow->hide(); - refresh_master_ui(); - masterwindow->show(); - config.cfg.UserInterfaceMode=1; -}; -} -void MasterUI::cb_Switch1(Fl_Menu_* o, void* v) { - ((MasterUI*)(o->parent()->user_data()))->cb_Switch1_i(o,v); -} - -Fl_Menu_Item MasterUI::menu_[] = { - {"&File", 0, 0, 0, 64, FL_NORMAL_LABEL, 0, 14, 0}, - {"&New (erase all)...", 0, (Fl_Callback*)MasterUI::cb_New1, 0, 0, FL_NORMAL_LABEL, 0, 14, 0}, - {"&Open Parameters...", 0, (Fl_Callback*)MasterUI::cb_Open2, 0, 0, FL_NORMAL_LABEL, 0, 14, 0}, - {"&Save All Parameters...", 0, (Fl_Callback*)MasterUI::cb_Save3, 0, 128, FL_NORMAL_LABEL, 0, 14, 0}, - {"&Settings...", 0, (Fl_Callback*)MasterUI::cb_Settings1, 0, 128, FL_NORMAL_LABEL, 0, 14, 0}, - {"&Copyright...", 0, (Fl_Callback*)MasterUI::cb_Copyright1, 0, 128, FL_NORMAL_LABEL, 0, 14, 0}, - {"E&xit", 0, (Fl_Callback*)MasterUI::cb_E1, 0, 0, FL_NORMAL_LABEL, 0, 14, 0}, - {0,0,0,0,0,0,0,0,0}, - {"&Instrument", 0, 0, 0, 64, FL_NORMAL_LABEL, 0, 14, 0}, - {"&Open Instrument...", 0, (Fl_Callback*)MasterUI::cb_Open3, 0, 0, FL_NORMAL_LABEL, 0, 14, 0}, - {"Show Instrument &Bank...", 0, (Fl_Callback*)MasterUI::cb_Show3, 0, 128, FL_NORMAL_LABEL, 0, 14, 0}, - {0,0,0,0,0,0,0,0,0}, - {"Misc", 0, 0, 0, 64, FL_NORMAL_LABEL, 0, 14, 0}, - {"Switch User Interface Mode", 0, (Fl_Callback*)MasterUI::cb_Switch1, 0, 0, FL_NORMAL_LABEL, 0, 14, 0}, - {0,0,0,0,0,0,0,0,0}, - {0,0,0,0,0,0,0,0,0} -}; - -void MasterUI::cb_partname1_i(Fl_Button*, void*) { - if ((int)bankui->cbwig->value()!=(npart+1)){ - bankui->cbwig->value(npart+1); - bankui->cbwig->do_callback(); -}; -bankui->show(); -} -void MasterUI::cb_partname1(Fl_Button* o, void* v) { - ((MasterUI*)(o->parent()->parent()->user_data()))->cb_partname1_i(o,v); -} - -void MasterUI::cb_partpanning1_i(Fl_Slider* o, void*) { - master->part[npart]->setPpanning((int) o->value()); -} -void MasterUI::cb_partpanning1(Fl_Slider* o, void* v) { - ((MasterUI*)(o->parent()->parent()->user_data()))->cb_partpanning1_i(o,v); -} - -void MasterUI::cb_partrcv1_i(Fl_Choice* o, void*) { - virkeys->relaseallkeys(0); -master->part[npart]->Prcvchn=(int) o->value(); -virkeys->midich=(int) o->value(); -} -void MasterUI::cb_partrcv1(Fl_Choice* o, void* v) { - ((MasterUI*)(o->parent()->parent()->user_data()))->cb_partrcv1_i(o,v); -} - -void MasterUI::cb_partvolume1_i(WidgetPDial* o, void*) { - master->part[npart]->setPvolume((int) o->value()); -} -void MasterUI::cb_partvolume1(WidgetPDial* o, void* v) { - ((MasterUI*)(o->parent()->parent()->user_data()))->cb_partvolume1_i(o,v); -} - -void MasterUI::cb_simplepartportamento_i(Fl_Check_Button* o, void*) { - master->part[npart]->ctl.portamento.portamento=(int) o->value(); -} -void MasterUI::cb_simplepartportamento(Fl_Check_Button* o, void* v) { - ((MasterUI*)(o->parent()->parent()->user_data()))->cb_simplepartportamento_i(o,v); -} - -void MasterUI::cb_simpleminkcounter_i(Fl_Counter* o, void*) { - master->part[npart]->Pminkey=(int) o->value(); -if (master->part[npart]->Pminkey>master->part[npart]->Pmaxkey) o->textcolor(FL_RED); - else o->textcolor(FL_BLACK); -} -void MasterUI::cb_simpleminkcounter(Fl_Counter* o, void* v) { - ((MasterUI*)(o->parent()->parent()->user_data()))->cb_simpleminkcounter_i(o,v); -} - -void MasterUI::cb_simplemaxkcounter_i(Fl_Counter* o, void*) { - master->part[npart]->Pmaxkey=(int) o->value(); - -if (master->part[npart]->Pminkey>master->part[npart]->Pmaxkey) o->textcolor(FL_RED); - else o->textcolor(FL_BLACK); -} -void MasterUI::cb_simplemaxkcounter(Fl_Counter* o, void* v) { - ((MasterUI*)(o->parent()->parent()->user_data()))->cb_simplemaxkcounter_i(o,v); -} - -void MasterUI::cb_m_i(Fl_Button*, void*) { - if (master->part[npart]->lastnote>=0) simpleminkcounter->value(master->part[npart]->lastnote); -simpleminkcounter->do_callback(); -simplemaxkcounter->do_callback(); -} -void MasterUI::cb_m(Fl_Button* o, void* v) { - ((MasterUI*)(o->parent()->parent()->user_data()))->cb_m_i(o,v); -} - -void MasterUI::cb_M_i(Fl_Button*, void*) { - if (master->part[npart]->lastnote>=0) simplemaxkcounter->value(master->part[npart]->lastnote); -simplemaxkcounter->do_callback(); -simpleminkcounter->do_callback(); -} -void MasterUI::cb_M(Fl_Button* o, void* v) { - ((MasterUI*)(o->parent()->parent()->user_data()))->cb_M_i(o,v); -} - -void MasterUI::cb_R1_i(Fl_Button*, void*) { - simpleminkcounter->value(0); -simpleminkcounter->do_callback(); -simplemaxkcounter->value(127); -simplemaxkcounter->do_callback(); -} -void MasterUI::cb_R1(Fl_Button* o, void* v) { - ((MasterUI*)(o->parent()->parent()->user_data()))->cb_R1_i(o,v); -} - -void MasterUI::cb_simplepartkeyshiftcounter_i(Fl_Counter* o, void*) { - master->part[npart]->Pkeyshift=(int) o->value()+64; -} -void MasterUI::cb_simplepartkeyshiftcounter(Fl_Counter* o, void* v) { - ((MasterUI*)(o->parent()->parent()->user_data()))->cb_simplepartkeyshiftcounter_i(o,v); -} - -void MasterUI::cb_simplesyseffsend_i(WidgetPDial* o, void*) { - master->setPsysefxvol(npart,nsyseff,(int) o->value()); -} -void MasterUI::cb_simplesyseffsend(WidgetPDial* o, void* v) { - ((MasterUI*)(o->parent()->parent()->user_data()))->cb_simplesyseffsend_i(o,v); -} - -void MasterUI::cb_partenabled1_i(Fl_Check_Button* o, void*) { - pthread_mutex_lock(&master->mutex); - master->partonoff(npart,(int) o->value()); -pthread_mutex_unlock(&master->mutex); - -if ((int) o->value()==0) simplelistitemgroup->deactivate(); - else { - simplelistitemgroup->activate(); - if ((int)bankui->cbwig->value()!=(npart+1)){ - bankui->cbwig->value(npart+1); - bankui->cbwig->do_callback(); - }; -}; - -o->redraw(); -} -void MasterUI::cb_partenabled1(Fl_Check_Button* o, void* v) { - ((MasterUI*)(o->parent()->user_data()))->cb_partenabled1_i(o,v); -} - -void MasterUI::cb_simplesyseffnocounter_i(Fl_Counter* o, void*) { - nsyseff=(int) o->value()-1; -simplesysefftype->value(master->sysefx[nsyseff]->geteffect()); -simplesyseffectui->refresh(master->sysefx[nsyseff]); -simplerefresh(); -} -void MasterUI::cb_simplesyseffnocounter(Fl_Counter* o, void* v) { - ((MasterUI*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_simplesyseffnocounter_i(o,v); -} - -void MasterUI::cb_simplesysefftype_i(Fl_Choice* o, void*) { - pthread_mutex_lock(&master->mutex); -master->sysefx[nsyseff]->changeeffect((int) o->value()); -pthread_mutex_unlock(&master->mutex); -simplesyseffectui->refresh(master->sysefx[nsyseff]); -} -void MasterUI::cb_simplesysefftype(Fl_Choice* o, void* v) { - ((MasterUI*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_simplesysefftype_i(o,v); -} - -Fl_Menu_Item MasterUI::menu_simplesysefftype[] = { - {"No Effect", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {"Reverb", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {"Echo", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {"Chorus", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {"Phaser", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {"AlienWah", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {"Distortion", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {"EQ", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {"DynFilter", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {0,0,0,0,0,0,0,0,0} -}; - -void MasterUI::cb_Send1_i(Fl_Button*, void*) { - syseffsendwindow->show(); -} -void MasterUI::cb_Send1(Fl_Button* o, void* v) { - ((MasterUI*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_Send1_i(o,v); -} - -void MasterUI::cb_P2_i(Fl_Button*, void*) { - pthread_mutex_lock(&master->mutex); -presetsui->paste(master->sysefx[nsyseff],simplesyseffectui); -pthread_mutex_unlock(&master->mutex); -} -void MasterUI::cb_P2(Fl_Button* o, void* v) { - ((MasterUI*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_P2_i(o,v); -} - -void MasterUI::cb_simpleinseffnocounter_i(Fl_Counter* o, void*) { - ninseff=(int) o->value()-1; -simpleinsefftype->value(master->insefx[ninseff]->geteffect()); -simpleinseffpart->value(master->Pinsparts[ninseff]+2); -simpleinseffectui->refresh(master->insefx[ninseff]); - -if (master->Pinsparts[ninseff]!=-1) { - simpleinsefftype->activate(); - simpleinseffectui->activate(); - simpleinseffectuigroup->activate(); -} else { - simpleinsefftype->deactivate(); - simpleinseffectui->deactivate(); - simpleinseffectuigroup->deactivate(); -}; -} -void MasterUI::cb_simpleinseffnocounter(Fl_Counter* o, void* v) { - ((MasterUI*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_simpleinseffnocounter_i(o,v); -} - -void MasterUI::cb_simpleinsefftype_i(Fl_Choice* o, void*) { - pthread_mutex_lock(&master->mutex); -master->insefx[ninseff]->changeeffect((int) o->value()); -pthread_mutex_unlock(&master->mutex); -simpleinseffectui->refresh(master->insefx[ninseff]); -simpleinseffectui->show(); -} -void MasterUI::cb_simpleinsefftype(Fl_Choice* o, void* v) { - ((MasterUI*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_simpleinsefftype_i(o,v); -} - -Fl_Menu_Item MasterUI::menu_simpleinsefftype[] = { - {"No Effect", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {"Reverb", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {"Echo", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {"Chorus", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {"Phaser", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {"AlienWah", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {"Distortion", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {"EQ", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {"DynFilter", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {0,0,0,0,0,0,0,0,0} -}; - -void MasterUI::cb_simpleinseffpart_i(Fl_Choice* o, void*) { - master->Pinsparts[ninseff]=(int) o->value()-2; -if ((int) o->value()==1){ - simpleinseffectuigroup->deactivate(); - simpleinsefftype->deactivate(); - simpleinseffectui->deactivate(); -} else { - simpleinseffectuigroup->activate(); - simpleinsefftype->activate(); - simpleinseffectui->activate(); -}; -master->insefx[ninseff]->cleanup(); -} -void MasterUI::cb_simpleinseffpart(Fl_Choice* o, void* v) { - ((MasterUI*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_simpleinseffpart_i(o,v); -} - -void MasterUI::cb_P3_i(Fl_Button*, void*) { - pthread_mutex_lock(&master->mutex); -presetsui->paste(master->insefx[ninseff],simpleinseffectui); -pthread_mutex_unlock(&master->mutex); -} -void MasterUI::cb_P3(Fl_Button* o, void* v) { - ((MasterUI*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_P3_i(o,v); -} - -void MasterUI::cb_simplemastervolumedial_i(WidgetPDial* o, void*) { - master->setPvolume((int) o->value()); -} -void MasterUI::cb_simplemastervolumedial(WidgetPDial* o, void* v) { - ((MasterUI*)(o->parent()->user_data()))->cb_simplemastervolumedial_i(o,v); -} - -void MasterUI::cb_simplemasterkeyshiftcounter_i(Fl_Counter* o, void*) { - master->setPkeyshift((int) o->value()+64); -} -void MasterUI::cb_simplemasterkeyshiftcounter(Fl_Counter* o, void* v) { - ((MasterUI*)(o->parent()->user_data()))->cb_simplemasterkeyshiftcounter_i(o,v); -} - -void MasterUI::cb_Stop_i(Fl_Button*, void*) { - virkeyboard->relaseallkeys(); -pthread_mutex_lock(&master->mutex); -master->shutup=1; -pthread_mutex_unlock(&master->mutex); -} -void MasterUI::cb_Stop(Fl_Button* o, void* v) { - ((MasterUI*)(o->parent()->user_data()))->cb_Stop_i(o,v); -} - -void MasterUI::cb_Reset_i(Fl_Button*, void*) { - simpleglobalfinedetuneslider->value(64.0); -simpleglobalfinedetuneslider->do_callback(); -} -void MasterUI::cb_Reset(Fl_Button* o, void* v) { - ((MasterUI*)(o->parent()->user_data()))->cb_Reset_i(o,v); -} - -void MasterUI::cb_simpleglobalfinedetuneslider_i(WidgetPDial* o, void*) { - master->microtonal.Pglobalfinedetune=(int) o->value(); -} -void MasterUI::cb_simpleglobalfinedetuneslider(WidgetPDial* o, void* v) { - ((MasterUI*)(o->parent()->user_data()))->cb_simpleglobalfinedetuneslider_i(o,v); -} - -void MasterUI::cb_simplenpartcounter_i(Fl_Counter* o, void*) { - virkeys->relaseallkeys(0); -npartcounter->value(o->value()); -npart=(int) o->value()-1; - -simplerefresh(); -virkeys->midich=master->part[npart]->Prcvchn; -} -void MasterUI::cb_simplenpartcounter(Fl_Counter* o, void* v) { - ((MasterUI*)(o->parent()->user_data()))->cb_simplenpartcounter_i(o,v); -} - -void MasterUI::cb_Keyb_i(Fl_Counter* o, void*) { - virkeys->relaseallkeys(0); -virkeys->midioct=(int) o->value(); -virkeys->take_focus(); -} -void MasterUI::cb_Keyb(Fl_Counter* o, void* v) { - ((MasterUI*)(o->parent()->user_data()))->cb_Keyb_i(o,v); -} - -void MasterUI::cb_selectuiwindow_i(Fl_Double_Window*, void*) { - *exitprogram=1; -} -void MasterUI::cb_selectuiwindow(Fl_Double_Window* o, void* v) { - ((MasterUI*)(o->user_data()))->cb_selectuiwindow_i(o,v); -} - -void MasterUI::cb_Advanced_i(Fl_Button*, void*) { - config.cfg.UserInterfaceMode=1; -masterwindow->show(); -selectuiwindow->hide(); -} -void MasterUI::cb_Advanced(Fl_Button* o, void* v) { - ((MasterUI*)(o->parent()->user_data()))->cb_Advanced_i(o,v); -} - -void MasterUI::cb_Beginner_i(Fl_Button*, void*) { - simplemasterwindow->show(); -selectuiwindow->hide(); -config.cfg.UserInterfaceMode=2; -} -void MasterUI::cb_Beginner(Fl_Button* o, void* v) { - ((MasterUI*)(o->parent()->user_data()))->cb_Beginner_i(o,v); -} - -Fl_Double_Window* MasterUI::make_window() { - { masterwindow = new Fl_Double_Window(390, 465, "zynaddsubfx"); - masterwindow->callback((Fl_Callback*)cb_masterwindow, (void*)(this)); - { mastermenu = new Fl_Menu_Bar(-5, 0, 690, 25); - mastermenu->menu(menu_mastermenu); - } // Fl_Menu_Bar* mastermenu - { WidgetPDial* o = mastervolumedial = new WidgetPDial(5, 30, 30, 30, "M.Vol"); - mastervolumedial->tooltip("Master Volume"); - mastervolumedial->box(FL_ROUND_UP_BOX); - mastervolumedial->color(FL_BACKGROUND_COLOR); - mastervolumedial->selection_color(FL_INACTIVE_COLOR); - mastervolumedial->labeltype(FL_NORMAL_LABEL); - mastervolumedial->labelfont(1); - mastervolumedial->labelsize(11); - mastervolumedial->labelcolor(FL_FOREGROUND_COLOR); - mastervolumedial->maximum(127); - mastervolumedial->step(1); - mastervolumedial->callback((Fl_Callback*)cb_mastervolumedial); - mastervolumedial->align(Fl_Align(130)); - mastervolumedial->when(FL_WHEN_CHANGED); - o->value(master->Pvolume); - } // WidgetPDial* mastervolumedial - { Fl_Counter* o = masterkeyshiftcounter = new Fl_Counter(45, 31, 90, 20, "Master KeyShift"); - masterkeyshiftcounter->labelsize(11); - masterkeyshiftcounter->minimum(-64); - masterkeyshiftcounter->maximum(64); - masterkeyshiftcounter->step(1); - masterkeyshiftcounter->callback((Fl_Callback*)cb_masterkeyshiftcounter); - o->lstep(12); - o->value(master->Pkeyshift-64); - } // Fl_Counter* masterkeyshiftcounter - { Fl_Button* o = new Fl_Button(293, 29, 92, 31, "Panic!"); - o->box(FL_PLASTIC_UP_BOX); - o->color((Fl_Color)231); - o->labelfont(1); - o->callback((Fl_Callback*)cb_Panic); - } // Fl_Button* o - { partuigroup = new Fl_Group(0, 242, 390, 183); - partuigroup->box(FL_ENGRAVED_FRAME); - { PartUI* o = partui = new PartUI(4, 245, 383, 175); - partui->box(FL_FLAT_BOX); - partui->color(FL_BACKGROUND_COLOR); - partui->selection_color(FL_BACKGROUND_COLOR); - partui->labeltype(FL_NORMAL_LABEL); - partui->labelfont(0); - partui->labelsize(14); - partui->labelcolor(FL_FOREGROUND_COLOR); - partui->align(Fl_Align(FL_ALIGN_TOP)); - partui->when(FL_WHEN_RELEASE); - o->init(master->part[0],master,0,bankui); - o->show(); - partui->end(); - } // PartUI* partui - partuigroup->end(); - } // Fl_Group* partuigroup - { Fl_Tabs* o = new Fl_Tabs(0, 80, 390, 160); - { Fl_Group* o = new Fl_Group(0, 100, 390, 140, "System Effects"); - o->box(FL_ENGRAVED_FRAME); - o->labeltype(FL_EMBOSSED_LABEL); - o->labelsize(15); - o->align(Fl_Align(FL_ALIGN_TOP_RIGHT|FL_ALIGN_INSIDE)); - { Fl_Counter* o = syseffnocounter = new Fl_Counter(5, 120, 80, 20, "Sys.Effect No."); - syseffnocounter->type(1); - syseffnocounter->labelfont(1); - syseffnocounter->labelsize(10); - syseffnocounter->minimum(0); - syseffnocounter->maximum(127); - syseffnocounter->step(1); - syseffnocounter->value(1); - syseffnocounter->textfont(1); - syseffnocounter->callback((Fl_Callback*)cb_syseffnocounter); - syseffnocounter->align(Fl_Align(FL_ALIGN_TOP)); - o->bounds(1,NUM_SYS_EFX); - o->value(nsyseff+1); - } // Fl_Counter* syseffnocounter - { Fl_Choice* o = sysefftype = new Fl_Choice(315, 125, 70, 15, "EffType"); - sysefftype->down_box(FL_BORDER_BOX); - sysefftype->labelsize(10); - sysefftype->callback((Fl_Callback*)cb_sysefftype); - sysefftype->menu(menu_sysefftype); - o->value(master->sysefx[nsyseff]->geteffect()); - } // Fl_Choice* sysefftype - { syseffectuigroup = new Fl_Group(5, 140, 380, 95); - syseffectuigroup->box(FL_FLAT_BOX); - syseffectuigroup->color((Fl_Color)48); - { EffUI* o = syseffectui = new EffUI(5, 140, 380, 95); - syseffectui->box(FL_NO_BOX); - syseffectui->color(FL_BACKGROUND_COLOR); - syseffectui->selection_color(FL_BACKGROUND_COLOR); - syseffectui->labeltype(FL_NORMAL_LABEL); - syseffectui->labelfont(0); - syseffectui->labelsize(14); - syseffectui->labelcolor(FL_FOREGROUND_COLOR); - syseffectui->align(Fl_Align(FL_ALIGN_TOP)); - syseffectui->when(FL_WHEN_RELEASE); - o->init(master->sysefx[nsyseff]); - syseffectui->end(); - } // EffUI* syseffectui - syseffectuigroup->end(); - } // Fl_Group* syseffectuigroup - { Fl_Button* o = new Fl_Button(95, 120, 75, 20, "Send to..."); - o->box(FL_THIN_UP_BOX); - o->labelfont(1); - o->labelsize(11); - o->callback((Fl_Callback*)cb_Send); - } // Fl_Button* o - { Fl_Button* o = new Fl_Button(215, 124, 25, 15, "C"); - o->box(FL_THIN_UP_BOX); - o->color((Fl_Color)179); - o->labelfont(1); - o->labelsize(11); - o->labelcolor(FL_BACKGROUND2_COLOR); - o->callback((Fl_Callback*)cb_C); - } // Fl_Button* o - { Fl_Button* o = new Fl_Button(245, 124, 25, 15, "P"); - o->box(FL_THIN_UP_BOX); - o->color((Fl_Color)179); - o->labelfont(1); - o->labelsize(11); - o->labelcolor(FL_BACKGROUND2_COLOR); - o->callback((Fl_Callback*)cb_P); - } // Fl_Button* o - o->end(); - } // Fl_Group* o - { Fl_Group* o = new Fl_Group(0, 100, 390, 140, "Insertion Effects"); - o->box(FL_ENGRAVED_FRAME); - o->labeltype(FL_EMBOSSED_LABEL); - o->labelsize(15); - o->align(Fl_Align(FL_ALIGN_TOP_RIGHT|FL_ALIGN_INSIDE)); - o->hide(); - { Fl_Counter* o = inseffnocounter = new Fl_Counter(5, 120, 80, 20, "Ins.Effect No."); - inseffnocounter->type(1); - inseffnocounter->labelfont(1); - inseffnocounter->labelsize(10); - inseffnocounter->minimum(0); - inseffnocounter->maximum(127); - inseffnocounter->step(1); - inseffnocounter->value(1); - inseffnocounter->textfont(1); - inseffnocounter->callback((Fl_Callback*)cb_inseffnocounter); - inseffnocounter->align(Fl_Align(FL_ALIGN_TOP)); - o->bounds(1,NUM_INS_EFX); - o->value(ninseff+1); - } // Fl_Counter* inseffnocounter - { Fl_Choice* o = insefftype = new Fl_Choice(315, 125, 70, 15, "EffType"); - insefftype->down_box(FL_BORDER_BOX); - insefftype->labelsize(10); - insefftype->callback((Fl_Callback*)cb_insefftype); - insefftype->menu(menu_insefftype); - o->value(master->insefx[ninseff]->geteffect()); - if (master->Pinsparts[ninseff]== -1) o->deactivate(); - } // Fl_Choice* insefftype - { inseffectuigroup = new Fl_Group(5, 140, 380, 95); - inseffectuigroup->box(FL_FLAT_BOX); - inseffectuigroup->color((Fl_Color)48); - { EffUI* o = inseffectui = new EffUI(5, 140, 380, 95); - inseffectui->box(FL_NO_BOX); - inseffectui->color(FL_BACKGROUND_COLOR); - inseffectui->selection_color(FL_BACKGROUND_COLOR); - inseffectui->labeltype(FL_NORMAL_LABEL); - inseffectui->labelfont(0); - inseffectui->labelsize(14); - inseffectui->labelcolor(FL_FOREGROUND_COLOR); - inseffectui->align(Fl_Align(FL_ALIGN_TOP)); - inseffectui->when(FL_WHEN_RELEASE); - o->init(master->insefx[ninseff]); - if (master->Pinsparts[ninseff]== -1) o->deactivate(); - inseffectui->end(); - } // EffUI* inseffectui - inseffectuigroup->end(); - } // Fl_Group* inseffectuigroup - { Fl_Choice* o = inseffpart = new Fl_Choice(95, 120, 80, 20, "Insert To."); - inseffpart->down_box(FL_BORDER_BOX); - inseffpart->labelfont(1); - inseffpart->labelsize(10); - inseffpart->textsize(10); - inseffpart->callback((Fl_Callback*)cb_inseffpart); - inseffpart->align(Fl_Align(FL_ALIGN_TOP_LEFT)); - o->add("Master Out");o->add("Off"); - char tmp[50]; for (int i=0;iadd(tmp);}; - o->value(master->Pinsparts[ninseff]+2); - } // Fl_Choice* inseffpart - { Fl_Button* o = new Fl_Button(215, 124, 25, 15, "C"); - o->box(FL_THIN_UP_BOX); - o->color((Fl_Color)179); - o->labelfont(1); - o->labelsize(11); - o->labelcolor(FL_BACKGROUND2_COLOR); - o->callback((Fl_Callback*)cb_C1); - } // Fl_Button* o - { Fl_Button* o = new Fl_Button(245, 124, 25, 15, "P"); - o->box(FL_THIN_UP_BOX); - o->color((Fl_Color)179); - o->labelfont(1); - o->labelsize(11); - o->labelcolor(FL_BACKGROUND2_COLOR); - o->callback((Fl_Callback*)cb_P1); - } // Fl_Button* o - o->end(); - } // Fl_Group* o - o->end(); - } // Fl_Tabs* o - { Fl_Button* o = new Fl_Button(330, 80, 56, 19, "Scales"); - o->box(FL_PLASTIC_UP_BOX); - o->color((Fl_Color)231); - o->labeltype(FL_ENGRAVED_LABEL); - o->labelfont(1); - o->callback((Fl_Callback*)cb_Scales); - } // Fl_Button* o - { Fl_Group* o = new Fl_Group(172, 30, 117, 45); - o->box(FL_ENGRAVED_BOX); - { recordbutton = new Fl_Button(181, 36, 21, 21, "Rec."); - recordbutton->tooltip("Start Recording"); - recordbutton->box(FL_ROUND_UP_BOX); - recordbutton->color(FL_RED); - recordbutton->labelfont(1); - recordbutton->labelsize(10); - recordbutton->callback((Fl_Callback*)cb_recordbutton); - recordbutton->align(Fl_Align(FL_ALIGN_BOTTOM)); - recordbutton->deactivate(); - } // Fl_Button* recordbutton - { stopbutton = new Fl_Button(259, 36, 21, 21, "Stop"); - stopbutton->tooltip("Stop Recording and close the audio file"); - stopbutton->box(FL_THIN_UP_BOX); - stopbutton->color((Fl_Color)4); - stopbutton->labelfont(1); - stopbutton->labelsize(10); - stopbutton->callback((Fl_Callback*)cb_stopbutton); - stopbutton->align(Fl_Align(FL_ALIGN_BOTTOM)); - stopbutton->deactivate(); - } // Fl_Button* stopbutton - { pausebutton = new Fl_Button(220, 36, 21, 21, "@||"); - pausebutton->tooltip("Pause Recording"); - pausebutton->box(FL_THIN_UP_BOX); - pausebutton->color((Fl_Color)4); - pausebutton->selection_color((Fl_Color)4); - pausebutton->labelfont(1); - pausebutton->labelcolor((Fl_Color)3); - pausebutton->callback((Fl_Callback*)cb_pausebutton); - pausebutton->align(Fl_Align(FL_ALIGN_CENTER|FL_ALIGN_INSIDE)); - pausebutton->deactivate(); - } // Fl_Button* pausebutton - { pauselabel = new Fl_Box(214, 56, 30, 15, "Pause"); - pauselabel->labelfont(1); - pauselabel->labelsize(10); - pauselabel->deactivate(); - } // Fl_Box* pauselabel - o->end(); - } // Fl_Group* o - { Fl_Group* o = new Fl_Group(1, 427, 389, 33); - o->box(FL_ENGRAVED_FRAME); - { VUMeter* o = new VUMeter(4, 430, 384, 30, "VU-Meter"); - o->box(FL_FLAT_BOX); - o->color((Fl_Color)48); - o->selection_color((Fl_Color)75); - o->labeltype(FL_NORMAL_LABEL); - o->labelfont(0); - o->labelsize(14); - o->labelcolor(FL_FOREGROUND_COLOR); - o->align(Fl_Align(FL_ALIGN_CENTER)); - o->when(FL_WHEN_RELEASE); - o->init(master,-1); - } // VUMeter* o - o->end(); - } // Fl_Group* o - { Fl_Check_Button* o = nrpnbutton = new Fl_Check_Button(45, 65, 47, 10, "NRPN"); - nrpnbutton->tooltip("Receive NRPNs"); - nrpnbutton->down_box(FL_DOWN_BOX); - nrpnbutton->labelsize(10); - nrpnbutton->callback((Fl_Callback*)cb_nrpnbutton); - o->value(master->ctl.NRPN.receive); - } // Fl_Check_Button* nrpnbutton - { Fl_Counter* o = npartcounter = new Fl_Counter(5, 247, 70, 23); - npartcounter->tooltip("The part number"); - npartcounter->type(1); - npartcounter->labelfont(1); - npartcounter->minimum(0); - npartcounter->maximum(127); - npartcounter->step(1); - npartcounter->value(1); - npartcounter->textfont(1); - npartcounter->callback((Fl_Callback*)cb_npartcounter); - o->bounds(1,NUM_MIDI_PARTS); - bankui->init(o); - } // Fl_Counter* npartcounter - { Fl_Button* o = new Fl_Button(292, 80, 35, 19, "vK"); - o->tooltip("Virtual Keyboard"); - o->box(FL_PLASTIC_UP_BOX); - o->color((Fl_Color)231); - o->labeltype(FL_ENGRAVED_LABEL); - o->labelfont(1); - o->callback((Fl_Callback*)cb_vK); - } // Fl_Button* o - { Fl_Button* o = new Fl_Button(140, 65, 30, 10, "R.D."); - o->tooltip("Master fine detune reset"); - o->box(FL_THIN_UP_BOX); - o->labelfont(1); - o->labelsize(10); - o->callback((Fl_Callback*)cb_R); - } // Fl_Button* o - { WidgetPDial* o = globalfinedetuneslider = new WidgetPDial(143, 30, 20, 20, "F.Det."); - globalfinedetuneslider->tooltip("global fine detune"); - globalfinedetuneslider->box(FL_ROUND_UP_BOX); - globalfinedetuneslider->color(FL_BACKGROUND_COLOR); - globalfinedetuneslider->selection_color(FL_INACTIVE_COLOR); - globalfinedetuneslider->labeltype(FL_NORMAL_LABEL); - globalfinedetuneslider->labelfont(0); - globalfinedetuneslider->labelsize(10); - globalfinedetuneslider->labelcolor(FL_FOREGROUND_COLOR); - globalfinedetuneslider->maximum(127); - globalfinedetuneslider->step(1); - globalfinedetuneslider->value(64); - globalfinedetuneslider->callback((Fl_Callback*)cb_globalfinedetuneslider); - globalfinedetuneslider->align(Fl_Align(130)); - globalfinedetuneslider->when(FL_WHEN_CHANGED); - o->value(master->microtonal.Pglobalfinedetune); - } // WidgetPDial* globalfinedetuneslider - { Fl_Button* o = new Fl_Button(293, 62, 92, 16, "Panel Window"); - o->tooltip("Panel Window"); - o->box(FL_PLASTIC_UP_BOX); - o->color((Fl_Color)183); - o->labelfont(1); - o->labelsize(10); - o->callback((Fl_Callback*)cb_Panel); - } // Fl_Button* o - masterwindow->xclass("zynaddsubfx"); - masterwindow->end(); - } // Fl_Double_Window* masterwindow - { aboutwindow = new Fl_Double_Window(365, 280, "Copyright..."); - aboutwindow->user_data((void*)(this)); - { Fl_Box* o = new Fl_Box(15, 35, 335, 55, "Copyright (c) 2002-2009 Nasca O. PAUL and others. Please read AUTHORS.txt"); - o->labeltype(FL_EMBOSSED_LABEL); - o->labelsize(15); - o->align(Fl_Align(192|FL_ALIGN_INSIDE)); - } // Fl_Box* o - { Fl_Box* o = new Fl_Box(15, 90, 335, 145, "This is free software; you may redistribute it and/or modify it under the ter\ -ms of the \nversion 2 (or any later version) of the GNU General Public License\ - as published by the Free Software Fundation.\n This program comes with\n ABS\ -OLUTELY NO WARRANTY. \n See the version 2 (or any later version) of the \nGNU \ -General Public License for details."); - o->labelfont(1); - o->labelsize(11); - o->align(Fl_Align(FL_ALIGN_WRAP|FL_ALIGN_INSIDE)); - } // Fl_Box* o - { Fl_Button* o = new Fl_Button(80, 245, 190, 25, "Close this window"); - o->box(FL_THIN_UP_BOX); - o->labelsize(11); - o->callback((Fl_Callback*)cb_Close); - } // Fl_Button* o - { Fl_Box* o = new Fl_Box(15, 5, 335, 30, "ZynAddSubFX"); - o->labeltype(FL_EMBOSSED_LABEL); - o->labelfont(1); - o->labelsize(20); - o->align(Fl_Align(FL_ALIGN_CENTER|FL_ALIGN_INSIDE)); - } // Fl_Box* o - aboutwindow->end(); - } // Fl_Double_Window* aboutwindow - { syseffsendwindow = new Fl_Double_Window(120, 250, "System Effects Send"); - syseffsendwindow->user_data((void*)(this)); - { Fl_Scroll* o = new Fl_Scroll(0, 45, 120, 170); - o->box(FL_FLAT_BOX); - for (int neff1=0;neff1x()+(neff2-1)*35,o->y()+15+neff1*50,30,30);syseffsend[neff1][neff2]->label("aaa");syseffsend[neff1][neff2]->init(master,neff1,neff2);}; - o->end(); - Fl_Group::current()->resizable(o); - } // Fl_Scroll* o - { Fl_Button* o = new Fl_Button(25, 220, 80, 25, "Close"); - o->box(FL_THIN_UP_BOX); - o->callback((Fl_Callback*)cb_Close1); - } // Fl_Button* o - { Fl_Box* o = new Fl_Box(5, 5, 110, 35, "Send system effect\'s output to other system effects"); - o->labelsize(10); - o->align(Fl_Align(192)); - } // Fl_Box* o - syseffsendwindow->end(); - } // Fl_Double_Window* syseffsendwindow - { panelwindow = new Fl_Double_Window(630, 635, "ZynAddSubFX Panel"); - panelwindow->user_data((void*)(this)); - { Fl_Scroll* o = new Fl_Scroll(0, 5, 570, 310); - o->type(1); - o->box(FL_THIN_UP_BOX); - { Fl_Pack* o = new Fl_Pack(5, 10, 560, 285); - o->type(1); - for (int i=0;iinit(master,i,bankui);} - o->end(); - } // Fl_Pack* o - o->end(); - } // Fl_Scroll* o - { Fl_Scroll* o = new Fl_Scroll(0, 320, 570, 310); - o->type(1); - o->box(FL_THIN_UP_BOX); - { Fl_Pack* o = new Fl_Pack(5, 325, 560, 285); - o->type(1); - for (int i=NUM_MIDI_PARTS/2;iinit(master,i,bankui);} - o->end(); - } // Fl_Pack* o - o->end(); - } // Fl_Scroll* o - { Fl_Button* o = new Fl_Button(575, 605, 50, 25, "Close"); - o->box(FL_THIN_UP_BOX); - o->labelsize(13); - o->callback((Fl_Callback*)cb_Close2); - } // Fl_Button* o - { Fl_Button* o = new Fl_Button(575, 570, 55, 25, "Refresh"); - o->box(FL_THIN_UP_BOX); - o->labelsize(13); - o->callback((Fl_Callback*)cb_Refresh); - } // Fl_Button* o - panelwindow->end(); - } // Fl_Double_Window* panelwindow - { simplemasterwindow = new Fl_Double_Window(600, 335, "ZynAddSubFX"); - simplemasterwindow->callback((Fl_Callback*)cb_simplemasterwindow, (void*)(this)); - { Fl_Menu_Bar* o = new Fl_Menu_Bar(0, 0, 690, 25); - o->menu(menu_); - } // Fl_Menu_Bar* o - { Fl_Group* o = simplelistitemgroup = new Fl_Group(125, 65, 215, 150); - simplelistitemgroup->box(FL_ENGRAVED_BOX); - { partname = new Fl_Button(130, 72, 205, 18); - partname->box(FL_PLASTIC_THIN_DOWN_BOX); - partname->down_box(FL_FLAT_BOX); - partname->color((Fl_Color)247); - partname->labelfont(1); - partname->labelsize(11); - partname->callback((Fl_Callback*)cb_partname1); - partname->align(Fl_Align(192|FL_ALIGN_INSIDE)); - } // Fl_Button* partname - { Fl_Slider* o = partpanning = new Fl_Slider(185, 95, 70, 15, "Pan"); - partpanning->type(5); - partpanning->box(FL_FLAT_BOX); - partpanning->maximum(127); - partpanning->step(1); - partpanning->value(64); - partpanning->callback((Fl_Callback*)cb_partpanning1); - o->value(master->part[npart]->Ppanning); - } // Fl_Slider* partpanning - { Fl_Choice* o = partrcv = new Fl_Choice(140, 157, 65, 18, "Midi Channel Receive"); - partrcv->tooltip("receive from Midi channel"); - partrcv->down_box(FL_BORDER_BOX); - partrcv->labelsize(10); - partrcv->textfont(1); - partrcv->callback((Fl_Callback*)cb_partrcv1); - partrcv->align(Fl_Align(130)); - char nrstr[10]; for(int i=0;iadd(nrstr); else o->add("Dr10");}; - o->value(master->part[npart]->Prcvchn); - } // Fl_Choice* partrcv - { WidgetPDial* o = partvolume = new WidgetPDial(145, 95, 30, 30); - partvolume->box(FL_OVAL_BOX); - partvolume->color(FL_BACKGROUND_COLOR); - partvolume->selection_color(FL_INACTIVE_COLOR); - partvolume->labeltype(FL_NORMAL_LABEL); - partvolume->labelfont(0); - partvolume->labelsize(14); - partvolume->labelcolor(FL_FOREGROUND_COLOR); - partvolume->maximum(127); - partvolume->step(1); - partvolume->callback((Fl_Callback*)cb_partvolume1); - partvolume->align(Fl_Align(FL_ALIGN_BOTTOM)); - partvolume->when(FL_WHEN_CHANGED); - o->value(master->part[npart]->Pvolume); - } // WidgetPDial* partvolume - { new Fl_Box(130, 125, 60, 15, "Volume"); - } // Fl_Box* o - { Fl_Check_Button* o = simplepartportamento = new Fl_Check_Button(260, 95, 75, 20, "Portamento"); - simplepartportamento->tooltip("Enable/Disable the portamento"); - simplepartportamento->down_box(FL_DOWN_BOX); - simplepartportamento->labelfont(1); - simplepartportamento->labelsize(10); - simplepartportamento->callback((Fl_Callback*)cb_simplepartportamento); - o->value(master->part[npart]->ctl.portamento.portamento); - } // Fl_Check_Button* simplepartportamento - { Fl_Counter* o = simpleminkcounter = new Fl_Counter(210, 158, 40, 15, "Min.key"); - simpleminkcounter->tooltip("Minimum key (that the part receives NoteOn messages)"); - simpleminkcounter->type(1); - simpleminkcounter->labelfont(1); - simpleminkcounter->labelsize(10); - simpleminkcounter->minimum(0); - simpleminkcounter->maximum(127); - simpleminkcounter->step(1); - simpleminkcounter->textsize(10); - simpleminkcounter->callback((Fl_Callback*)cb_simpleminkcounter); - o->value(master->part[npart]->Pminkey); - } // Fl_Counter* simpleminkcounter - { Fl_Counter* o = simplemaxkcounter = new Fl_Counter(255, 158, 40, 15, "Max.key"); - simplemaxkcounter->tooltip("Maximum key (that the part receives NoteOn messages)"); - simplemaxkcounter->type(1); - simplemaxkcounter->labelfont(1); - simplemaxkcounter->labelsize(10); - simplemaxkcounter->minimum(0); - simplemaxkcounter->maximum(127); - simplemaxkcounter->step(1); - simplemaxkcounter->textsize(10); - simplemaxkcounter->callback((Fl_Callback*)cb_simplemaxkcounter); - o->value(master->part[npart]->Pmaxkey); - } // Fl_Counter* simplemaxkcounter - { Fl_Button* o = new Fl_Button(230, 188, 15, 12, "m"); - o->tooltip("set the minimum key to the last pressed key"); - o->box(FL_THIN_UP_BOX); - o->labelsize(10); - o->callback((Fl_Callback*)cb_m); - } // Fl_Button* o - { Fl_Button* o = new Fl_Button(260, 188, 15, 12, "M"); - o->tooltip("set the maximum key to the last pressed key"); - o->box(FL_THIN_UP_BOX); - o->labelsize(10); - o->callback((Fl_Callback*)cb_M); - } // Fl_Button* o - { Fl_Button* o = new Fl_Button(245, 188, 15, 12, "R"); - o->tooltip("reset the minimum key to 0 and maximum key to 127"); - o->box(FL_THIN_UP_BOX); - o->labelfont(1); - o->labelsize(10); - o->callback((Fl_Callback*)cb_R1); - } // Fl_Button* o - { Fl_Counter* o = simplepartkeyshiftcounter = new Fl_Counter(240, 120, 90, 20, "KeyShift"); - simplepartkeyshiftcounter->labelsize(11); - simplepartkeyshiftcounter->minimum(-64); - simplepartkeyshiftcounter->maximum(64); - simplepartkeyshiftcounter->step(1); - simplepartkeyshiftcounter->callback((Fl_Callback*)cb_simplepartkeyshiftcounter); - o->lstep(12); - o->value(master->part[npart]->Pkeyshift-64); - } // Fl_Counter* simplepartkeyshiftcounter - { simplesyseffsend = new WidgetPDial(300, 160, 30, 30); - simplesyseffsend->box(FL_OVAL_BOX); - simplesyseffsend->color(FL_BACKGROUND_COLOR); - simplesyseffsend->selection_color(FL_INACTIVE_COLOR); - simplesyseffsend->labeltype(FL_NORMAL_LABEL); - simplesyseffsend->labelfont(0); - simplesyseffsend->labelsize(14); - simplesyseffsend->labelcolor(FL_FOREGROUND_COLOR); - simplesyseffsend->maximum(127); - simplesyseffsend->step(1); - simplesyseffsend->callback((Fl_Callback*)cb_simplesyseffsend); - simplesyseffsend->align(Fl_Align(FL_ALIGN_BOTTOM)); - simplesyseffsend->when(FL_WHEN_CHANGED); - } // WidgetPDial* simplesyseffsend - { new Fl_Box(295, 190, 40, 15, "Effect"); - } // Fl_Box* o - if (master->part[npart]->Penabled==0) o->deactivate(); - simplelistitemgroup->end(); - } // Fl_Group* simplelistitemgroup - { Fl_Check_Button* o = partenabled = new Fl_Check_Button(250, 40, 85, 20, "Enabled"); - partenabled->down_box(FL_DOWN_BOX); - partenabled->labeltype(FL_EMBOSSED_LABEL); - partenabled->labelfont(1); - partenabled->labelsize(13); - partenabled->callback((Fl_Callback*)cb_partenabled1); - partenabled->align(Fl_Align(FL_ALIGN_RIGHT|FL_ALIGN_INSIDE)); - //char tmp[10];snprintf(tmp,10,"%d",npart+1);o->copy_label(tmp); - o->value(master->part[npart]->Penabled); - } // Fl_Check_Button* partenabled - { VirKeys* o = virkeys = new VirKeys(5, 215, 590, 80, "Keyboard"); - virkeys->box(FL_BORDER_BOX); - virkeys->color((Fl_Color)17); - virkeys->selection_color(FL_BACKGROUND_COLOR); - virkeys->labeltype(FL_NORMAL_LABEL); - virkeys->labelfont(0); - virkeys->labelsize(14); - virkeys->labelcolor(FL_FOREGROUND_COLOR); - virkeys->align(Fl_Align(FL_ALIGN_CENTER)); - virkeys->when(FL_WHEN_RELEASE); - o->init(master); - } // VirKeys* virkeys - { Fl_Group* o = new Fl_Group(340, 30, 255, 185); - o->box(FL_ENGRAVED_BOX); - { Fl_Tabs* o = new Fl_Tabs(345, 35, 245, 175); - o->align(Fl_Align(FL_ALIGN_BOTTOM|FL_ALIGN_INSIDE)); - { Fl_Group* o = new Fl_Group(345, 55, 245, 155, "System Effects"); - o->box(FL_ENGRAVED_FRAME); - o->labelfont(1); - o->labelsize(12); - o->align(Fl_Align(FL_ALIGN_BOTTOM|FL_ALIGN_INSIDE)); - o->hide(); - { Fl_Counter* o = simplesyseffnocounter = new Fl_Counter(350, 75, 80, 20, "Sys.Effect No."); - simplesyseffnocounter->type(1); - simplesyseffnocounter->labelfont(1); - simplesyseffnocounter->labelsize(10); - simplesyseffnocounter->minimum(0); - simplesyseffnocounter->maximum(127); - simplesyseffnocounter->step(1); - simplesyseffnocounter->value(1); - simplesyseffnocounter->textfont(1); - simplesyseffnocounter->callback((Fl_Callback*)cb_simplesyseffnocounter); - simplesyseffnocounter->align(Fl_Align(FL_ALIGN_TOP)); - o->bounds(1,NUM_SYS_EFX); - o->value(nsyseff+1); - } // Fl_Counter* simplesyseffnocounter - { Fl_Choice* o = simplesysefftype = new Fl_Choice(515, 80, 70, 15, "EffType"); - simplesysefftype->down_box(FL_BORDER_BOX); - simplesysefftype->labelsize(10); - simplesysefftype->callback((Fl_Callback*)cb_simplesysefftype); - simplesysefftype->align(Fl_Align(FL_ALIGN_TOP_LEFT)); - simplesysefftype->menu(menu_simplesysefftype); - o->value(master->sysefx[nsyseff]->geteffect()); - } // Fl_Choice* simplesysefftype - { simplesyseffectuigroup = new Fl_Group(350, 95, 235, 95); - simplesyseffectuigroup->box(FL_FLAT_BOX); - simplesyseffectuigroup->color((Fl_Color)48); - { SimpleEffUI* o = simplesyseffectui = new SimpleEffUI(350, 95, 234, 95); - simplesyseffectui->box(FL_NO_BOX); - simplesyseffectui->color(FL_BACKGROUND_COLOR); - simplesyseffectui->selection_color(FL_BACKGROUND_COLOR); - simplesyseffectui->labeltype(FL_NORMAL_LABEL); - simplesyseffectui->labelfont(0); - simplesyseffectui->labelsize(14); - simplesyseffectui->labelcolor(FL_FOREGROUND_COLOR); - simplesyseffectui->align(Fl_Align(FL_ALIGN_TOP)); - simplesyseffectui->when(FL_WHEN_RELEASE); - o->init(master->sysefx[nsyseff]); - simplesyseffectui->end(); - } // SimpleEffUI* simplesyseffectui - simplesyseffectuigroup->end(); - } // Fl_Group* simplesyseffectuigroup - { Fl_Button* o = new Fl_Button(435, 75, 75, 20, "Send to..."); - o->box(FL_THIN_UP_BOX); - o->labelfont(1); - o->labelsize(11); - o->callback((Fl_Callback*)cb_Send1); - } // Fl_Button* o - { Fl_Button* o = new Fl_Button(560, 65, 25, 15, "P"); - o->box(FL_THIN_UP_BOX); - o->color((Fl_Color)179); - o->labelfont(1); - o->labelsize(11); - o->labelcolor(FL_BACKGROUND2_COLOR); - o->callback((Fl_Callback*)cb_P2); - } // Fl_Button* o - o->end(); - } // Fl_Group* o - { Fl_Group* o = new Fl_Group(345, 55, 245, 155, "Insertion Effects"); - o->box(FL_ENGRAVED_FRAME); - o->labelfont(1); - o->labelsize(12); - o->align(Fl_Align(FL_ALIGN_BOTTOM|FL_ALIGN_INSIDE)); - { Fl_Counter* o = simpleinseffnocounter = new Fl_Counter(350, 75, 80, 20, "Ins.Effect No."); - simpleinseffnocounter->type(1); - simpleinseffnocounter->labelfont(1); - simpleinseffnocounter->labelsize(10); - simpleinseffnocounter->minimum(0); - simpleinseffnocounter->maximum(127); - simpleinseffnocounter->step(1); - simpleinseffnocounter->value(1); - simpleinseffnocounter->textfont(1); - simpleinseffnocounter->callback((Fl_Callback*)cb_simpleinseffnocounter); - simpleinseffnocounter->align(Fl_Align(FL_ALIGN_TOP)); - o->bounds(1,NUM_INS_EFX); - o->value(ninseff+1); - } // Fl_Counter* simpleinseffnocounter - { Fl_Choice* o = simpleinsefftype = new Fl_Choice(515, 80, 70, 15, "EffType"); - simpleinsefftype->down_box(FL_BORDER_BOX); - simpleinsefftype->labelsize(10); - simpleinsefftype->callback((Fl_Callback*)cb_simpleinsefftype); - simpleinsefftype->align(Fl_Align(FL_ALIGN_TOP_LEFT)); - simpleinsefftype->menu(menu_simpleinsefftype); - o->value(master->insefx[ninseff]->geteffect()); - if (master->Pinsparts[ninseff]== -1) o->deactivate(); - } // Fl_Choice* simpleinsefftype - { simpleinseffectuigroup = new Fl_Group(350, 95, 234, 95); - simpleinseffectuigroup->box(FL_FLAT_BOX); - simpleinseffectuigroup->color((Fl_Color)48); - { SimpleEffUI* o = simpleinseffectui = new SimpleEffUI(350, 95, 234, 95); - simpleinseffectui->box(FL_NO_BOX); - simpleinseffectui->color(FL_BACKGROUND_COLOR); - simpleinseffectui->selection_color(FL_BACKGROUND_COLOR); - simpleinseffectui->labeltype(FL_NORMAL_LABEL); - simpleinseffectui->labelfont(0); - simpleinseffectui->labelsize(14); - simpleinseffectui->labelcolor(FL_FOREGROUND_COLOR); - simpleinseffectui->align(Fl_Align(FL_ALIGN_TOP)); - simpleinseffectui->when(FL_WHEN_RELEASE); - o->init(master->insefx[ninseff]); - if (master->Pinsparts[ninseff]== -1) o->deactivate(); - simpleinseffectui->end(); - } // SimpleEffUI* simpleinseffectui - simpleinseffectuigroup->end(); - } // Fl_Group* simpleinseffectuigroup - { Fl_Choice* o = simpleinseffpart = new Fl_Choice(435, 75, 80, 20, "Insert To."); - simpleinseffpart->down_box(FL_BORDER_BOX); - simpleinseffpart->labelfont(1); - simpleinseffpart->labelsize(10); - simpleinseffpart->textsize(10); - simpleinseffpart->callback((Fl_Callback*)cb_simpleinseffpart); - simpleinseffpart->align(Fl_Align(FL_ALIGN_TOP_LEFT)); - o->add("Master Out");o->add("Off"); - char tmp[50]; for (int i=0;iadd(tmp);}; - o->value(master->Pinsparts[ninseff]+2); - } // Fl_Choice* simpleinseffpart - { Fl_Button* o = new Fl_Button(560, 65, 25, 15, "P"); - o->box(FL_THIN_UP_BOX); - o->color((Fl_Color)179); - o->labelfont(1); - o->labelsize(11); - o->labelcolor(FL_BACKGROUND2_COLOR); - o->callback((Fl_Callback*)cb_P3); - } // Fl_Button* o - o->end(); - } // Fl_Group* o - o->end(); - } // Fl_Tabs* o - o->end(); - } // Fl_Group* o - { Fl_Group* o = new Fl_Group(5, 300, 590, 30); - o->box(FL_ENGRAVED_FRAME); - { VUMeter* o = new VUMeter(5, 300, 590, 30, "VU-Meter"); - o->box(FL_FLAT_BOX); - o->color((Fl_Color)41); - o->selection_color((Fl_Color)75); - o->labeltype(FL_NORMAL_LABEL); - o->labelfont(0); - o->labelsize(14); - o->labelcolor(FL_FOREGROUND_COLOR); - o->align(Fl_Align(FL_ALIGN_CENTER)); - o->when(FL_WHEN_RELEASE); - o->init(master,-1); - } // VUMeter* o - o->end(); - } // Fl_Group* o - { WidgetPDial* o = simplemastervolumedial = new WidgetPDial(10, 35, 40, 40, "Master Volume"); - simplemastervolumedial->tooltip("Master Volume"); - simplemastervolumedial->box(FL_ROUND_UP_BOX); - simplemastervolumedial->color(FL_BACKGROUND_COLOR); - simplemastervolumedial->selection_color(FL_INACTIVE_COLOR); - simplemastervolumedial->labeltype(FL_NORMAL_LABEL); - simplemastervolumedial->labelfont(1); - simplemastervolumedial->labelsize(11); - simplemastervolumedial->labelcolor(FL_FOREGROUND_COLOR); - simplemastervolumedial->maximum(127); - simplemastervolumedial->step(1); - simplemastervolumedial->callback((Fl_Callback*)cb_simplemastervolumedial); - simplemastervolumedial->align(Fl_Align(130)); - simplemastervolumedial->when(FL_WHEN_CHANGED); - o->value(master->Pvolume); - } // WidgetPDial* simplemastervolumedial - { Fl_Counter* o = simplemasterkeyshiftcounter = new Fl_Counter(25, 110, 90, 20, "Master KeyShift"); - simplemasterkeyshiftcounter->labelsize(11); - simplemasterkeyshiftcounter->minimum(-64); - simplemasterkeyshiftcounter->maximum(64); - simplemasterkeyshiftcounter->step(1); - simplemasterkeyshiftcounter->callback((Fl_Callback*)cb_simplemasterkeyshiftcounter); - o->lstep(12); - o->value(master->Pkeyshift-64); - } // Fl_Counter* simplemasterkeyshiftcounter - { Fl_Button* o = new Fl_Button(5, 149, 115, 31, "Stop ALL sounds!"); - o->box(FL_PLASTIC_UP_BOX); - o->color((Fl_Color)231); - o->labelfont(1); - o->labelsize(11); - o->callback((Fl_Callback*)cb_Stop); - } // Fl_Button* o - { Fl_Button* o = new Fl_Button(70, 32, 50, 10, "Reset"); - o->tooltip("Master fine detune reset"); - o->box(FL_THIN_UP_BOX); - o->labelfont(1); - o->labelsize(11); - o->callback((Fl_Callback*)cb_Reset); - o->align(Fl_Align(FL_ALIGN_WRAP)); - } // Fl_Button* o - { WidgetPDial* o = simpleglobalfinedetuneslider = new WidgetPDial(80, 45, 30, 30, "Fine Detune"); - simpleglobalfinedetuneslider->tooltip("global fine detune"); - simpleglobalfinedetuneslider->box(FL_ROUND_UP_BOX); - simpleglobalfinedetuneslider->color(FL_BACKGROUND_COLOR); - simpleglobalfinedetuneslider->selection_color(FL_INACTIVE_COLOR); - simpleglobalfinedetuneslider->labeltype(FL_NORMAL_LABEL); - simpleglobalfinedetuneslider->labelfont(0); - simpleglobalfinedetuneslider->labelsize(11); - simpleglobalfinedetuneslider->labelcolor(FL_FOREGROUND_COLOR); - simpleglobalfinedetuneslider->maximum(127); - simpleglobalfinedetuneslider->step(1); - simpleglobalfinedetuneslider->value(64); - simpleglobalfinedetuneslider->callback((Fl_Callback*)cb_simpleglobalfinedetuneslider); - simpleglobalfinedetuneslider->align(Fl_Align(130)); - simpleglobalfinedetuneslider->when(FL_WHEN_CHANGED); - o->value(master->microtonal.Pglobalfinedetune); - } // WidgetPDial* simpleglobalfinedetuneslider - { Fl_Counter* o = simplenpartcounter = new Fl_Counter(170, 40, 70, 20, "Part"); - simplenpartcounter->tooltip("The part number"); - simplenpartcounter->type(1); - simplenpartcounter->labelfont(1); - simplenpartcounter->minimum(0); - simplenpartcounter->maximum(127); - simplenpartcounter->step(1); - simplenpartcounter->value(1); - simplenpartcounter->textfont(1); - simplenpartcounter->callback((Fl_Callback*)cb_simplenpartcounter); - simplenpartcounter->align(Fl_Align(FL_ALIGN_LEFT)); - o->bounds(1,NUM_MIDI_PARTS); - } // Fl_Counter* simplenpartcounter - { Fl_Counter* o = new Fl_Counter(5, 195, 55, 20, "Keyb.Oct."); - o->tooltip("Midi Octave"); - o->type(1); - o->labelsize(11); - o->minimum(0); - o->maximum(5); - o->step(1); - o->textfont(1); - o->textsize(11); - o->callback((Fl_Callback*)cb_Keyb); - o->align(Fl_Align(FL_ALIGN_RIGHT)); - o->when(FL_WHEN_RELEASE_ALWAYS); - o->value(virkeys->midioct); - } // Fl_Counter* o - simplemasterwindow->end(); - } // Fl_Double_Window* simplemasterwindow - { selectuiwindow = new Fl_Double_Window(430, 250, "User Interface mode"); - selectuiwindow->callback((Fl_Callback*)cb_selectuiwindow, (void*)(this)); - { Fl_Box* o = new Fl_Box(5, 5, 425, 40, "Welcome to ZynAddSubFX"); - o->labeltype(FL_SHADOW_LABEL); - o->labelfont(1); - o->labelsize(26); - } // Fl_Box* o - { Fl_Box* o = new Fl_Box(10, 50, 265, 25, "Please choose the interface mode:"); - o->labelfont(1); - o->labelsize(13); - } // Fl_Box* o - { Fl_Button* o = new Fl_Button(10, 165, 100, 35, "Advanced"); - o->box(FL_PLASTIC_UP_BOX); - o->color((Fl_Color)229); - o->labelfont(1); - o->labelsize(16); - o->callback((Fl_Callback*)cb_Advanced); - } // Fl_Button* o - { Fl_Box* o = new Fl_Box(110, 165, 310, 35, ".. if you have used ZynAddSubFX before, or you like to have full controll to \ -all parameters."); - o->labelfont(1); - o->labelsize(11); - o->align(Fl_Align(FL_ALIGN_WRAP|FL_ALIGN_INSIDE)); - } // Fl_Box* o - { Fl_Button* o = new Fl_Button(10, 80, 100, 65, "Beginner"); - o->box(FL_PLASTIC_UP_BOX); - o->color((Fl_Color)238); - o->labelfont(1); - o->labelsize(16); - o->callback((Fl_Callback*)cb_Beginner); - } // Fl_Button* o - { Fl_Box* o = new Fl_Box(110, 75, 320, 75, "..if you are a beginner, you prefer using presets or you prefer to use simple\ -r user interfaces. Most functionality of ZynAddSubFX will be hidden in this mo\ -de to make simple the learning/using it."); - o->labelfont(1); - o->labelsize(11); - o->align(Fl_Align(FL_ALIGN_WRAP|FL_ALIGN_INSIDE)); - } // Fl_Box* o - { Fl_Box* o = new Fl_Box(30, 215, 360, 25, "You can switch the interface modes anytime you want."); - o->box(FL_BORDER_BOX); - o->color((Fl_Color)51); - o->labelfont(1); - o->labelsize(11); - o->align(Fl_Align(FL_ALIGN_WRAP|FL_ALIGN_INSIDE)); - } // Fl_Box* o - selectuiwindow->set_non_modal(); - selectuiwindow->end(); - } // Fl_Double_Window* selectuiwindow - return selectuiwindow; -} - -void MasterUI::updatesendwindow() { - for (int neff1=0;neff1value(master->Psysefxsend[neff1][neff2]); -} - -void MasterUI::updatepanel() { - for (int npart=0;npartrefresh(); - }; -} - -void MasterUI::setfilelabel(const char *filename) { - if (filename!=NULL) snprintf(&masterwindowlabel[0],100,"%s - ZynAddSubFX",fl_filename_name(filename)); - else snprintf(&masterwindowlabel[0],100,"%s","ZynAddSubFX"); - masterwindowlabel[99]='\0'; - masterwindow->label(&masterwindowlabel[0]); - simplemasterwindow->label(&masterwindowlabel[0]); -} - -MasterUI::MasterUI(Master *master_,int *exitprogram_) { - master=master_; - exitprogram=exitprogram_; - ninseff=0; - nsyseff=0; - npart=0; - - for (int i=0;imicrotonal); - virkeyboard=new VirKeyboard(master); - bankui=new BankUI(master,&npart); - configui=new ConfigUI(); - sequi=new SeqUI(master); - - make_window(); - #ifdef OS_WINDOWS - masterwindow->icon((char *)LoadIcon(GetModuleHandle(NULL), "zynaddsubfx_icon")); - #endif - presetsui=new PresetsUI(); - setfilelabel(NULL); - swapefftype=0; - simplerefresh(); -} - -MasterUI::~MasterUI() { - masterwindow->hide(); - delete masterwindow; - simplemasterwindow->hide(); - delete simplemasterwindow; - aboutwindow->hide(); - delete aboutwindow; - syseffsendwindow->hide(); - delete syseffsendwindow; - - delete virkeyboard; - delete microtonalui; - delete bankui; - delete configui; - delete sequi; - - delete presetsui; - delete panelwindow; - delete selectuiwindow; -} - -void MasterUI::showUI() { - switch (config.cfg.UserInterfaceMode){ - case 0:selectuiwindow->show(); - break; - case 1:masterwindow->show(); - break; - case 2:simplemasterwindow->show(); - break; - }; -} - -void MasterUI::simplerefresh() { - partenabled->value(master->part[npart]->Penabled); - if (master->part[npart]->Penabled!=0) simplelistitemgroup->activate(); - else simplelistitemgroup->deactivate(); - - partvolume->value(master->part[npart]->Pvolume); - partpanning->value(master->part[npart]->Ppanning); - partrcv->value(master->part[npart]->Prcvchn); - - if (master->part[npart]->Pname[0]!=0) partname->label((char *)master->part[npart]->Pname); - else partname->label("Click here to load a instrument"); - - simplelistitemgroup->redraw(); - simplepartportamento->value(master->part[npart]->ctl.portamento.portamento); - simpleminkcounter->value(master->part[npart]->Pminkey); - simplemaxkcounter->value(master->part[npart]->Pmaxkey); - - simplepartkeyshiftcounter->value(master->part[npart]->Pkeyshift-64); - simplesyseffsend->value(master->Psysefxvol[nsyseff][npart]); -} - -void MasterUI::do_new_master() { - if (fl_choice("Clear *ALL* the parameters ?","No","Yes",NULL)){ - delete microtonalui; - - pthread_mutex_lock(&master->mutex); - master->defaults(); - pthread_mutex_unlock(&master->mutex); - - npartcounter->value(1); - refresh_master_ui(); - - }; - - updatepanel(); -} - -void MasterUI::do_load_master(const char* file ) { - const char *filename; - if (file == NULL) { - filename=fl_file_chooser("Open:","({*.xmz})",NULL,0); - if (filename==NULL) return; - } - else { - filename = file; - } - - - pthread_mutex_lock(&master->mutex); - //clear all parameters - master->defaults(); - - //load the data - int result=master->loadXML(filename); - pthread_mutex_unlock(&master->mutex); - master->applyparameters(); - - npartcounter->value(1); - refresh_master_ui(); - updatepanel(); - if (result>=0) setfilelabel(filename); - - - if (result==-10) fl_alert("Error: Could not load the file\nbecause it is not a zynaddsubfx parameters file."); - else if (result<0) fl_alert("Error: Could not load the file."); -} - -void MasterUI::do_save_master(const char* file ) { - const char *filename; - char *tmp; - int result=0; - if (file == NULL) { - tmp=fl_file_chooser("Save:","({*.xmz})",NULL,0); - if (tmp==NULL) return; - tmp=fl_filename_setext(tmp,".xmz"); - filename=tmp; - result=fileexists(tmp); - if (result) { - result=0; - if (!fl_choice("The file exists. Overwrite it?","No","Yes",NULL)) return; - - } - } - else { - filename = file; - } - - - pthread_mutex_lock(&master->mutex); - result=master->saveXML(filename); - pthread_mutex_unlock(&master->mutex); - - if (result<0) fl_alert("Error: Could not save the file."); - else setfilelabel(filename); - - updatepanel(); -} - -void MasterUI::refresh_master_ui() { - ninseff=0; - nsyseff=0; - npart=0; - - //the Master UI - npartcounter->do_callback(); - syseffnocounter->do_callback(); - inseffnocounter->do_callback(); - masterkeyshiftcounter->value(master->Pkeyshift-64); - mastervolumedial->value(master->Pvolume); - globalfinedetuneslider->value(master->microtonal.Pglobalfinedetune); - microtonalui=new MicrotonalUI(&master->microtonal); - nrpnbutton->value(master->ctl.NRPN.receive); - updatesendwindow(); - updatepanel(); - - //the simle MasterUI - simplenpartcounter->value(1); - simplesyseffnocounter->value(1); - simpleinseffnocounter->value(1); - simplenpartcounter->do_callback(); - simplesyseffnocounter->do_callback(); - simpleinseffnocounter->do_callback(); - simplemasterkeyshiftcounter->value(master->Pkeyshift-64); - simplemastervolumedial->value(master->Pvolume); - simpleglobalfinedetuneslider->value(master->microtonal.Pglobalfinedetune); - virkeys->midich=master->part[npart]->Prcvchn; - - simplerefresh(); - bankui->hide(); -} diff --git a/plugins/zynaddsubfx/src/UI/MasterUI.fl b/plugins/zynaddsubfx/src/UI/MasterUI.fl deleted file mode 100644 index b97b77326..000000000 --- a/plugins/zynaddsubfx/src/UI/MasterUI.fl +++ /dev/null @@ -1,1815 +0,0 @@ -# data file for the Fltk User Interface Designer (fluid) -version 1.0110 -header_name {.h} -code_name {.cc} -decl {//Copyright (c) 2002-2009 Nasca Octavian Paul} {} - -decl {//License: GNU GPL version 2 or later} {} - -decl {\#include } {public -} - -decl {\#include } {public -} - -decl {\#include } {public -} - -decl {\#include "WidgetPDial.h"} {public -} - -decl {\#include "ADnoteUI.h"} {public -} - -decl {\#include "SUBnoteUI.h"} {public -} - -decl {\#include "EffUI.h"} {public -} - -decl {\#include "VirKeyboard.h"} {public -} - -decl {\#include "ConfigUI.h"} {public -} - -decl {\#include "BankUI.h"} {public -} - -decl {\#include "PartUI.h"} {public -} - -decl {\#include "MicrotonalUI.h"} {public -} - -decl {\#include "SeqUI.h"} {public -} - -decl {\#include "PresetsUI.h"} {public -} - -decl {\#include "../Misc/Master.h"} {public -} - -decl {\#include "../Misc/Part.h"} {public -} - -decl {\#include "../Misc/Util.h"} {public -} - -decl {\#include "../globals.h"} {public -} - -class VUMeter {: {public Fl_Box} -} { - Function {VUMeter(int x,int y, int w, int h, const char *label=0):Fl_Box(x,y,w,h,label)} {} { - code {master=NULL; -npart=-1;} {} - } - Function {init(Master *master_,int part_)} {} { - code {//the "part_" parameters sets the part (if it is >=0), else it sets the master -master=master_; -label(NULL); -npart=part_; -olddbl=0.0; -olddbr=0.0; -oldrmsdbl=0.0; -oldrmsdbr=0.0;} {} - } - Function {draw_master()} {} { - code {\#define MIN_DB (-48) - -int ox=x(); int oy=y(); int lx=w(); int ly=h(); - -pthread_mutex_lock(&master->mutex); -REALTYPE dbl=rap2dB(master->vuoutpeakl); -REALTYPE dbr=rap2dB(master->vuoutpeakr); -REALTYPE rmsdbl=rap2dB(master->vurmspeakl); -REALTYPE rmsdbr=rap2dB(master->vurmspeakr); -REALTYPE maxdbl=rap2dB(master->vumaxoutpeakl); -REALTYPE maxdbr=rap2dB(master->vumaxoutpeakr); -int clipped=master->vuclipped; -pthread_mutex_unlock(&master->mutex); - -dbl=(MIN_DB-dbl)/MIN_DB; -if (dbl<0.0) dbl=0.0; - else if (dbl>1.0)dbl=1.0; - -dbr=(MIN_DB-dbr)/MIN_DB; -if (dbr<0.0) dbr=0.0; - else if (dbr>1.0) dbr=1.0; - -dbl=dbl*0.4+olddbl*0.6; -dbr=dbr*0.4+olddbr*0.6; - -olddbl=dbl; -olddbr=dbr; - -\#define VULENX (lx-35) -\#define VULENY (ly/2-3) - -dbl*=VULENX;dbr*=VULENX; - -int idbl=(int) dbl; -int idbr=(int) dbr; - -//compute RMS - start -rmsdbl=(MIN_DB-rmsdbl)/MIN_DB; -if (rmsdbl<0.0) rmsdbl=0.0; - else if (rmsdbl>1.0) rmsdbl=1.0; - -rmsdbr=(MIN_DB-rmsdbr)/MIN_DB; -if (rmsdbr<0.0) rmsdbr=0.0; - else if (rmsdbr>1.0) rmsdbr=1.0; - -rmsdbl=rmsdbl*0.4+oldrmsdbl*0.6; -rmsdbr=rmsdbr*0.4+oldrmsdbr*0.6; - -oldrmsdbl=rmsdbl; -oldrmsdbr=rmsdbr; - - -rmsdbl*=VULENX;rmsdbr*=VULENX; - -int irmsdbl=(int) rmsdbl; -int irmsdbr=(int) rmsdbr; -//compute RMS - end - - - -//draw the vu-meter lines -//db -fl_rectf(ox,oy,idbr,VULENY,0,200,255); -fl_rectf(ox,oy+ly/2,idbl,VULENY,0,200,255); -//black -fl_rectf(ox+idbr,oy,VULENX-idbr,VULENY,0,0,0); -fl_rectf(ox+idbl,oy+ly/2,VULENX-idbl,VULENY,0,0,0); - -//draw the scales -REALTYPE tmp=VULENX*1.0/MIN_DB; -for (int i=1;i<1-MIN_DB;i++){ - int tx=VULENX+(int) (tmp*i); - fl_rectf(ox+tx,oy,1,VULENY+ly/2,0,160,200); - if (i%5==0) fl_rectf(ox+tx,oy,1,VULENY+ly/2,0,230,240); - if (i%10==0) fl_rectf(ox+tx-1,oy,2,VULENY+ly/2,0,225,255); -}; - -//rms -if (irmsdbr>2) fl_rectf(ox+irmsdbr-1,oy,3,VULENY,255,255,0); -if (irmsdbl>2) fl_rectf(ox+irmsdbl-1,oy+ly/2,3,VULENY,255,255,0); - - -//draw the red box if clipping has occured -if (clipped==0) fl_rectf(ox+VULENX+2,oy+1,lx-VULENX-3,ly-4,0,0,10); - else fl_rectf(ox+VULENX+2,oy+1,lx-VULENX-3,ly-4,250,10,10); - -//draw the maxdB -fl_font(FL_HELVETICA|FL_BOLD,10); -fl_color(255,255,255); -char tmpstr[10]; -if ((maxdbl>MIN_DB-20)){ - snprintf((char *)&tmpstr,10,"%ddB",(int)maxdbr); - fl_draw(tmpstr,ox+VULENX+1,oy+1,lx-VULENX-1,VULENY,FL_ALIGN_RIGHT,NULL,0); -}; -if ((maxdbr>MIN_DB-20)){ - snprintf((char *)&tmpstr,10,"%ddB",(int)maxdbl); - fl_draw(tmpstr,ox+VULENX+1,oy+ly/2+1,lx-VULENX-1,VULENY,FL_ALIGN_RIGHT,NULL,0); -};} {} - } - Function {draw_part()} {} { - code {\#define MIN_DB (-48) -int ox=x(); int oy=y(); int lx=w(); int ly=h(); - -if (!active_r()){ - pthread_mutex_lock(&master->mutex); - int fakedb=master->fakepeakpart[npart]; - pthread_mutex_unlock(&master->mutex); - fl_rectf(ox,oy,lx,ly,140,140,140); - if (fakedb>0){ - fakedb=(int)(fakedb/255.0*ly)+4; - fl_rectf(ox+2,oy+ly-fakedb,lx-4,fakedb,0,0,0); - }; - - return; -}; - -//draw the vu lines -pthread_mutex_lock(&master->mutex); - REALTYPE db=rap2dB(master->vuoutpeakpart[npart]); -pthread_mutex_unlock(&master->mutex); - -db=(MIN_DB-db)/MIN_DB; -if (db<0.0) db=0.0; - else if (db>1.0) db=1.0; - -db*=ly-2; - -int idb=(int) db; - -fl_rectf(ox,oy+ly-idb,lx,idb,0,200,255); -fl_rectf(ox,oy,lx,ly-idb,0,0,0); - - -//draw the scales -REALTYPE tmp=ly*1.0/MIN_DB; - for (int i=1;i<1-MIN_DB;i++){ - int ty=ly+(int) (tmp*i); - if (i%5==0) fl_rectf(ox,oy+ly-ty,lx,1,0,160,200); - if (i%10==0) fl_rectf(ox,oy+ly-ty,lx,1,0,230,240); -};} {} - } - Function {draw()} {} { - code {if (npart>=0) draw_part(); - else draw_master();} {} - } - Function {tickdraw(VUMeter *o)} {return_type {static void} - } { - code {o->redraw();} {} - } - Function {tick(void *v)} {return_type {static void} - } { - code {tickdraw((VUMeter *) v); -Fl::add_timeout(1.0/25.0,tick,v);//25 fps} {} - } - Function {handle(int event)} {return_type int - } { - code {switch(event){ - case FL_SHOW: - tick(this); - break; - case FL_HIDE: - Fl::remove_timeout(tick,this); - break; - case FL_PUSH: - if (npart>=0) break; - pthread_mutex_lock(&master->mutex); - master->vuresetpeaks(); - pthread_mutex_unlock(&master->mutex); - break; -}; -return(1);} {} - } - decl {Master *master;} {} - decl {int npart;} {} - decl {float olddbl,olddbr;} {} - decl {float oldrmsdbl,oldrmsdbr;} {} -} - -class SysEffSend {: {public WidgetPDial} -} { - Function {SysEffSend(int x,int y, int w, int h, const char *label=0):WidgetPDial(x,y,w,h,label)} {} { - code {master=NULL; -neff1=0; -neff2=0;} {} - } - Function {init(Master *master_,int neff1_,int neff2_)} {} { - code {neff1=neff1_; -neff2=neff2_; -master=master_; -minimum(0); -maximum(127); -step(1); -labelfont(1); -labelsize(10); -align(FL_ALIGN_TOP); - -value(master->Psysefxsend[neff1][neff2]); -char tmp[20];snprintf(tmp,20,"%d->%d",neff1+1,neff2+1); -this->copy_label(tmp);} {} - } - Function {~SysEffSend()} {} { - code {hide();} {} - } - Function {handle(int event)} {return_type int - } { - code {if ((event==FL_PUSH) || (event==FL_DRAG)){ - master->setPsysefxsend(neff1,neff2,(int) value()); -}; - -return(WidgetPDial::handle(event));} {} - } - decl {Master *master;} {} - decl {int neff1;} {} - decl {int neff2;} {} -} - -class Panellistitem {: {public Fl_Group} -} { - Function {make_window()} {private - } { - Fl_Window panellistitem { - private xywh {315 213 70 260} type Double hide - class Fl_Group - } { - Fl_Group panellistitemgroup { - private xywh {0 20 70 240} box PLASTIC_THIN_UP_BOX - code0 {if (master->part[npart]->Penabled==0) o->deactivate();} - } { - Fl_Group {} { - xywh {45 65 15 110} box ENGRAVED_FRAME - } { - Fl_Box {} { - label {V U} - xywh {45 65 15 110} box FLAT_BOX color 0 selection_color 75 labelcolor 55 align 128 - code0 {o->init(master,npart);} - class VUMeter - } - } - Fl_Button partname { - label { } - callback {if ((int)bankui->cbwig->value()!=(npart+1)){ - bankui->cbwig->value(npart+1); - bankui->cbwig->do_callback(); -}; -bankui->show();} - xywh {5 27 60 30} box THIN_DOWN_BOX down_box FLAT_BOX labelfont 1 labelsize 10 align 208 - } - Fl_Slider partvolume { - callback {master->part[npart]->setPvolume((int) o->value());} - xywh {10 65 30 110} type {Vert Knob} box FLAT_BOX minimum 127 maximum 0 step 1 value 127 - code0 {o->value(master->part[npart]->Pvolume);} - } - Fl_Dial partpanning { - callback {master->part[npart]->setPpanning((int) o->value());} - xywh {20 180 30 30} maximum 127 step 1 - code0 {o->value(master->part[npart]->Ppanning);} - class WidgetPDial - } - Fl_Button {} { - label edit - callback {if ((int)bankui->cbwig->value()!=(npart+1)){ - bankui->cbwig->value(npart+1); - bankui->cbwig->do_callback(); -};} - xywh {15 235 40 20} box PLASTIC_UP_BOX labelsize 10 - } - Fl_Choice partrcv { - callback {master->part[npart]->Prcvchn=(int) o->value();} - tooltip {receive from Midi channel} xywh {10 213 50 15} down_box BORDER_BOX labelsize 10 align 5 textfont 1 textsize 10 - code0 {char nrstr[10]; for(int i=0;iadd(nrstr); else o->add("Dr10");};} - code1 {o->value(master->part[npart]->Prcvchn);} - } {} - } - Fl_Check_Button partenabled { - label 01 - callback {pthread_mutex_lock(&master->mutex); - master->partonoff(npart,(int) o->value()); -pthread_mutex_unlock(&master->mutex); - -if ((int) o->value()==0) panellistitemgroup->deactivate(); - else { - panellistitemgroup->activate(); - if ((int)bankui->cbwig->value()!=(npart+1)){ - bankui->cbwig->value(npart+1); - bankui->cbwig->do_callback(); - }; -}; - -o->redraw();} - private xywh {5 0 45 20} down_box DOWN_BOX labeltype EMBOSSED_LABEL labelfont 1 labelsize 13 align 24 - code0 {char tmp[10];snprintf(tmp,10,"%d",npart+1);o->copy_label(tmp);} - code1 {o->value(master->part[npart]->Penabled);} - } - } - } - Function {Panellistitem(int x,int y, int w, int h, const char *label=0):Fl_Group(x,y,w,h,label)} {} { - code {npart=0; -master=NULL; -bankui=NULL;} {} - } - Function {init(Master *master_, int npart_,BankUI *bankui_)} {} { - code {npart=npart_; -master=master_; -bankui=bankui_; - -make_window(); -panellistitem->show(); -end();} {} - } - Function {refresh()} {} { - code {partenabled->value(master->part[npart]->Penabled); -if (master->part[npart]->Penabled!=0) panellistitemgroup->activate(); - else panellistitemgroup->deactivate(); - -partvolume->value(master->part[npart]->Pvolume); -partpanning->value(master->part[npart]->Ppanning); -partrcv->value(master->part[npart]->Prcvchn); - -partname->label((char *)master->part[npart]->Pname); - -if ((int)bankui->cbwig->value()!=(npart+1)) - panellistitemgroup->color(fl_rgb_color(160,160,160)); -else - panellistitemgroup->color(fl_rgb_color(50,190,240)); - -panellistitemgroup->redraw();} {} - } - Function {~Panellistitem()} {} { - code {panellistitem->hide(); -//delete(panellistitem);} {} - } - decl {int npart;} {} - decl {Master *master;} {} - decl {BankUI *bankui;} {} -} - -class MasterUI {} { - Function {make_window()} {} { - Fl_Window masterwindow { - label zynaddsubfx - callback {\#ifdef VSTAUDIOOUT -fl_alert("ZynAddSubFX could not be closed this way, because it's a VST plugin. Please use the host aplication to close it."); -\#else -//if (fl_choice("Exit and leave the unsaved data?","No","Yes",NULL)) { - config.save(); - *exitprogram=1; -//}; -\#endif} - xywh {585 104 390 465} type Double xclass zynaddsubfx visible - } { - Fl_Menu_Bar mastermenu { - xywh {-5 0 690 25} - } { - Submenu {} { - label {&File} - xywh {0 0 100 20} - } { - MenuItem {} { - label {&New (erase all)...} - callback {do_new_master();} - xywh {20 20 100 20} - } - MenuItem {} { - label {&Open Parameters...} - callback {do_load_master();} - xywh {20 20 100 20} - } - MenuItem {} { - label {&Save All Parameters...} - callback {do_save_master();} - xywh {10 10 100 20} divider - } - MenuItem {} { - label {&Load Scale Settings...} - callback {char *filename; -filename=fl_file_chooser("Open:","({*.xsz})",NULL,0); -if (filename==NULL) return; - -pthread_mutex_lock(&master->mutex); - //clear all parameters - master->microtonal.defaults(); - - //load the data - int result=master->microtonal.loadXML(filename); -pthread_mutex_unlock(&master->mutex); - - - delete microtonalui; - microtonalui=new MicrotonalUI(&master->microtonal); - -if (result==-10) fl_alert("Error: Could not load the file\\nbecause it is not a scale file."); - else if (result<0) fl_alert("Error: Could not load the file.");} - xywh {35 35 100 20} - } - MenuItem {} { - label {Save Sc&ale Settings ..} - callback {char *filename; -int result=0; - -filename=fl_file_chooser("Save:","({*.xsz})",NULL,0); -if (filename==NULL) return; -filename=fl_filename_setext(filename,".xsz"); - -result=fileexists(filename); -if (result) { - result=0; - if (!fl_choice("The file exists. \\nOverwrite it?","No","Yes",NULL)) return; - -}; - - -pthread_mutex_lock(&master->mutex); -result=master->microtonal.saveXML(filename); -pthread_mutex_unlock(&master->mutex); - -if (result<0) fl_alert("Error: Could not save the file."); - - -updatepanel();} - xywh {25 25 100 20} - } - MenuItem {} { - label {Show Scale Settings...} - callback {microtonalui->show();} - xywh {0 0 100 20} divider - } - MenuItem {} { - label {&Settings...} - callback {configui->show();} - xywh {25 25 100 20} divider - } - MenuItem {} { - label {&Copyright...} - callback {aboutwindow->show();} - xywh {15 15 100 20} divider - } - MenuItem {} { - label {E&xit} - callback {masterwindow->do_callback();} - xywh {10 10 100 20} - } - } - Submenu {} { - label {&Instrument} - xywh {10 10 100 20} - } { - MenuItem {} { - label {&Clear Instrument...} - callback {if (fl_choice("Clear instrument's parameters ?","No","Yes",NULL)){ -// int npart=(int)npartcounter->value()-1; - pthread_mutex_lock(&master->mutex); - master->part[npart]->defaultsinstrument(); - pthread_mutex_unlock(&master->mutex); - - npartcounter->do_callback(); -}; - -updatepanel();} - xywh {35 35 100 20} - } - MenuItem {} { - label {&Open Instrument...} - callback {const char *filename; -filename=fl_file_chooser("Load:","({*.xiz})",NULL,0); -if (filename==NULL) return; - - -pthread_mutex_lock(&master->mutex); -// int npart=(int)npartcounter->value()-1; - - //clear all instrument parameters, first - master->part[npart]->defaultsinstrument(); - - //load the instr. parameters - int result=master->part[npart]->loadXMLinstrument(filename); - -pthread_mutex_unlock(&master->mutex); -master->part[npart]->applyparameters(); - -npartcounter->do_callback(); -updatepanel(); - -if (result==-10) fl_alert("Error: Could not load the file\\nbecause it is not an instrument file."); - else if (result<0) fl_alert("Error: Could not load the file.");} - xywh {30 30 100 20} - } - MenuItem {} { - label {&Save Instrument ...} - callback {char *filename; - -filename=fl_file_chooser("Save:","({*.xiz})",NULL,0); -if (filename==NULL) return; -filename=fl_filename_setext(filename,".xiz"); - -int result=fileexists(filename); -if (result) { - result=0; - if (!fl_choice("The file exists. \\nOverwrite it?","No","Yes",NULL)) return; - -}; - - -pthread_mutex_lock(&master->mutex); -result=master->part[npart]->saveXML(filename); -pthread_mutex_unlock(&master->mutex); - -if (result<0) fl_alert("Error: Could not save the file."); - -updatepanel();} - xywh {20 20 100 20} divider - } - MenuItem {} { - label {Show Instrument &Bank...} - callback {bankui->show();} - xywh {0 0 100 20} divider - } - MenuItem {} { - label {&Virtual Keyboard...} - callback {virkeyboard->show();} - xywh {10 10 100 20} - } - } - Submenu recordmenu { - label {&Record} - xywh {0 0 100 20} - } { - MenuItem {} { - label {&Choose WAV file...} - callback {char *filename; -recordbutton->deactivate(); -pausebutton->deactivate(); -pauselabel->deactivate(); -stopbutton->deactivate(); -filename=fl_file_chooser("Record to audio file:","(*.wav)",NULL,0); -if (filename==NULL) return; -fl_filename_setext(filename,".wav"); - -int result=master->HDDRecorder.preparefile(filename,0); -if (result==1) { - result=0; - if (fl_choice("The file exists. \\nOverwrite it?","No","Yes",NULL)) - master->HDDRecorder.preparefile(filename,1); -}; -if (result==0) recordbutton->activate(); - -if (result!=0) fl_alert("Error: Could not save the file.");} - xywh {0 0 100 20} - } - } - Submenu {} { - label {&Sequencer} - xywh {0 0 100 20} hide - } { - MenuItem {} { - label {Show &Sequencer...} - callback {sequi->show();} - xywh {0 0 100 20} - } - } - Submenu {} { - label Misc - xywh {10 10 100 20} - } { - MenuItem {} { - label {Switch User Interface Mode} - callback {if (fl_choice("Switch the User Interface to Beginner mode ?","No","Yes",NULL)){ - masterwindow->hide(); - refresh_master_ui(); - simplemasterwindow->show(); - config.cfg.UserInterfaceMode=2; -};} - xywh {10 10 100 20} - } - } - } - Fl_Dial mastervolumedial { - label {M.Vol} - callback {master->setPvolume((int) o->value());} - tooltip {Master Volume} xywh {5 30 30 30} box ROUND_UP_BOX labelfont 1 labelsize 11 align 130 maximum 127 step 1 - code0 {o->value(master->Pvolume);} - class WidgetPDial - } - Fl_Counter masterkeyshiftcounter { - label {Master KeyShift} - callback {master->setPkeyshift((int) o->value()+64);} - xywh {45 31 90 20} labelsize 11 minimum -64 maximum 64 step 1 - code0 {o->lstep(12);} - code1 {o->value(master->Pkeyshift-64);} - } - Fl_Button {} { - label {Panic!} - callback {virkeyboard->relaseallkeys(); -pthread_mutex_lock(&master->mutex); -master->shutup=1; -pthread_mutex_unlock(&master->mutex);} - xywh {293 29 92 31} box PLASTIC_UP_BOX color 231 labelfont 1 - } - Fl_Group partuigroup { - xywh {0 242 390 183} box ENGRAVED_FRAME - } { - Fl_Group partui { - xywh {4 245 383 175} box FLAT_BOX - code0 {o->init(master->part[0],master,0,bankui);} - code1 {o->show();} - class PartUI - } {} - } - Fl_Tabs {} { - xywh {0 80 390 160} - } { - Fl_Group {} { - label {System Effects} - xywh {0 100 390 140} box ENGRAVED_FRAME labeltype EMBOSSED_LABEL labelsize 15 align 25 - } { - Fl_Counter syseffnocounter { - label {Sys.Effect No.} - callback {nsyseff=(int) o->value()-1; -sysefftype->value(master->sysefx[nsyseff]->geteffect()); -syseffectui->refresh(master->sysefx[nsyseff]);} - xywh {5 120 80 20} type Simple labelfont 1 labelsize 10 align 1 minimum 0 maximum 127 step 1 value 1 textfont 1 - code0 {o->bounds(1,NUM_SYS_EFX);} - code1 {o->value(nsyseff+1);} - } - Fl_Choice sysefftype { - label EffType - callback {pthread_mutex_lock(&master->mutex); -master->sysefx[nsyseff]->changeeffect((int) o->value()); -pthread_mutex_unlock(&master->mutex); -syseffectui->refresh(master->sysefx[nsyseff]);} - xywh {315 125 70 15} down_box BORDER_BOX labelsize 10 - code0 {o->value(master->sysefx[nsyseff]->geteffect());} - } { - MenuItem {} { - label {No Effect} - xywh {10 10 100 20} labelfont 1 labelsize 10 - } - MenuItem {} { - label Reverb - xywh {20 20 100 20} labelfont 1 labelsize 10 - } - MenuItem {} { - label Echo - xywh {30 30 100 20} labelfont 1 labelsize 10 - } - MenuItem {} { - label Chorus - xywh {40 40 100 20} labelfont 1 labelsize 10 - } - MenuItem {} { - label Phaser - xywh {50 50 100 20} labelfont 1 labelsize 10 - } - MenuItem {} { - label AlienWah - xywh {60 60 100 20} labelfont 1 labelsize 10 - } - MenuItem {} { - label Distortion - xywh {70 70 100 20} labelfont 1 labelsize 10 - } - MenuItem {} { - label EQ - xywh {80 80 100 20} labelfont 1 labelsize 10 - } - MenuItem {} { - label DynFilter - xywh {90 90 100 20} labelfont 1 labelsize 10 - } - } - Fl_Group syseffectuigroup { - xywh {5 140 380 95} box FLAT_BOX color 48 - } { - Fl_Group syseffectui { - xywh {5 140 380 95} - code0 {o->init(master->sysefx[nsyseff]);} - class EffUI - } {} - } - Fl_Button {} { - label {Send to...} - callback {syseffsendwindow->show();} - xywh {95 120 75 20} box THIN_UP_BOX labelfont 1 labelsize 11 - } - Fl_Button {} { - label C - callback {presetsui->copy(master->sysefx[nsyseff]);} - xywh {215 124 25 15} box THIN_UP_BOX color 179 labelfont 1 labelsize 11 labelcolor 7 - } - Fl_Button {} { - label P - callback {pthread_mutex_lock(&master->mutex); -presetsui->paste(master->sysefx[nsyseff],syseffectui); -pthread_mutex_unlock(&master->mutex);} - xywh {245 124 25 15} box THIN_UP_BOX color 179 labelfont 1 labelsize 11 labelcolor 7 - } - } - Fl_Group {} { - label {Insertion Effects} - xywh {0 100 390 140} box ENGRAVED_FRAME labeltype EMBOSSED_LABEL labelsize 15 align 25 hide - } { - Fl_Counter inseffnocounter { - label {Ins.Effect No.} - callback {ninseff=(int) o->value()-1; -insefftype->value(master->insefx[ninseff]->geteffect()); -inseffpart->value(master->Pinsparts[ninseff]+2); -inseffectui->refresh(master->insefx[ninseff]); - -if (master->Pinsparts[ninseff]!=-1) { - insefftype->activate(); - inseffectui->activate(); - inseffectuigroup->activate(); -} else { - insefftype->deactivate(); - inseffectui->deactivate(); - inseffectuigroup->deactivate(); -};} - xywh {5 120 80 20} type Simple labelfont 1 labelsize 10 align 1 minimum 0 maximum 127 step 1 value 1 textfont 1 - code0 {o->bounds(1,NUM_INS_EFX);} - code1 {o->value(ninseff+1);} - } - Fl_Choice insefftype { - label EffType - callback {pthread_mutex_lock(&master->mutex); -master->insefx[ninseff]->changeeffect((int) o->value()); -pthread_mutex_unlock(&master->mutex); -inseffectui->refresh(master->insefx[ninseff]); -inseffectui->show();} - xywh {315 125 70 15} down_box BORDER_BOX labelsize 10 - code0 {o->value(master->insefx[ninseff]->geteffect());} - code1 {if (master->Pinsparts[ninseff]== -1) o->deactivate();} - } { - MenuItem {} { - label {No Effect} - xywh {25 25 100 20} labelfont 1 labelsize 10 - } - MenuItem {} { - label Reverb - xywh {35 35 100 20} labelfont 1 labelsize 10 - } - MenuItem {} { - label Echo - xywh {45 45 100 20} labelfont 1 labelsize 10 - } - MenuItem {} { - label Chorus - xywh {55 55 100 20} labelfont 1 labelsize 10 - } - MenuItem {} { - label Phaser - xywh {60 60 100 20} labelfont 1 labelsize 10 - } - MenuItem {} { - label AlienWah - xywh {70 70 100 20} labelfont 1 labelsize 10 - } - MenuItem {} { - label Distortion - xywh {80 80 100 20} labelfont 1 labelsize 10 - } - MenuItem {} { - label EQ - xywh {90 90 100 20} labelfont 1 labelsize 10 - } - MenuItem {} { - label DynFilter - xywh {100 100 100 20} labelfont 1 labelsize 10 - } - } - Fl_Group inseffectuigroup { - xywh {5 140 380 95} box FLAT_BOX color 48 - } { - Fl_Group inseffectui { - xywh {5 140 380 95} - code0 {o->init(master->insefx[ninseff]);} - code1 {if (master->Pinsparts[ninseff]== -1) o->deactivate();} - class EffUI - } {} - } - Fl_Choice inseffpart { - label {Insert To.} - callback {master->Pinsparts[ninseff]=(int) o->value()-2; -if ((int) o->value()==1){ - inseffectuigroup->deactivate(); - insefftype->deactivate(); - inseffectui->deactivate(); -} else { - inseffectuigroup->activate(); - insefftype->activate(); - inseffectui->activate(); -}; -master->insefx[ninseff]->cleanup();} open - xywh {95 120 80 20} down_box BORDER_BOX labelfont 1 labelsize 10 align 5 textsize 10 - code0 {o->add("Master Out");o->add("Off");} - code1 {char tmp[50]; for (int i=0;iadd(tmp);};} - code3 {o->value(master->Pinsparts[ninseff]+2);} - } {} - Fl_Button {} { - label C - callback {presetsui->copy(master->insefx[ninseff]);} - xywh {215 124 25 15} box THIN_UP_BOX color 179 labelfont 1 labelsize 11 labelcolor 7 - } - Fl_Button {} { - label P - callback {pthread_mutex_lock(&master->mutex); -presetsui->paste(master->insefx[ninseff],inseffectui); -pthread_mutex_unlock(&master->mutex);} - xywh {245 124 25 15} box THIN_UP_BOX color 179 labelfont 1 labelsize 11 labelcolor 7 - } - } - } - Fl_Button {} { - label Scales - callback {microtonalui->show();} - xywh {330 80 56 19} box PLASTIC_UP_BOX color 231 labeltype ENGRAVED_LABEL labelfont 1 - } - Fl_Group {} { - xywh {172 30 117 45} box ENGRAVED_BOX - } { - Fl_Button recordbutton { - label {Rec.} - callback {o->deactivate(); -recordmenu->deactivate(); -recordmenu->label("&Record(*)"); -stopbutton->activate(); -pausebutton->activate(); -pauselabel->activate(); -master->HDDRecorder.start(); -master->vuresetpeaks(); -mastermenu->redraw();} - tooltip {Start Recording} xywh {181 36 21 21} box ROUND_UP_BOX color 88 labelfont 1 labelsize 10 align 2 deactivate - } - Fl_Button stopbutton { - label Stop - callback {o->deactivate(); -master->HDDRecorder.stop(); -recordbutton->deactivate(); -pausebutton->deactivate(); -pauselabel->deactivate(); -recordmenu->activate(); -recordmenu->label("&Record"); -mastermenu->redraw();} - tooltip {Stop Recording and close the audio file} xywh {259 36 21 21} box THIN_UP_BOX color 4 labelfont 1 labelsize 10 align 2 deactivate - } - Fl_Button pausebutton { - label {@||} - callback {o->deactivate(); -master->HDDRecorder.pause(); -recordbutton->activate(); -mastermenu->redraw();} - tooltip {Pause Recording} xywh {220 36 21 21} box THIN_UP_BOX color 4 selection_color 4 labelfont 1 labelcolor 3 align 16 deactivate - } - Fl_Box pauselabel { - label Pause - xywh {214 56 30 15} labelfont 1 labelsize 10 deactivate - } - } - Fl_Group {} { - xywh {1 427 389 33} box ENGRAVED_FRAME - } { - Fl_Box {} { - label {VU-Meter} - xywh {4 430 384 30} box FLAT_BOX color 48 selection_color 75 - code0 {o->init(master,-1);} - class VUMeter - } - } - Fl_Check_Button nrpnbutton { - label NRPN - callback {master->ctl.NRPN.receive=(int) o->value();} - tooltip {Receive NRPNs} xywh {45 65 47 10} down_box DOWN_BOX labelsize 10 - code0 {o->value(master->ctl.NRPN.receive);} - } - Fl_Counter npartcounter { - callback {int nval=(int) o->value()-1; -partuigroup->remove(partui); -delete partui; -partui=new PartUI(0,0,765,525); -partuigroup->add(partui); -partui->init(master->part[nval],master,nval,bankui); -partui->redraw(); -o->redraw(); -npart=nval; - -updatepanel(); -simplenpartcounter->value(nval+1); -simplenpartcounter->do_callback();} - tooltip {The part number} xywh {5 247 70 23} type Simple labelfont 1 minimum 0 maximum 127 step 1 value 1 textfont 1 - code0 {o->bounds(1,NUM_MIDI_PARTS);} - code1 {bankui->init(o);} - } - Fl_Button {} { - label vK - callback {virkeyboard->show();} - tooltip {Virtual Keyboard} xywh {292 80 35 19} box PLASTIC_UP_BOX color 231 labeltype ENGRAVED_LABEL labelfont 1 - } - Fl_Button {} { - label {R.D.} - callback {globalfinedetuneslider->value(64.0); -globalfinedetuneslider->do_callback();} - tooltip {Master fine detune reset} xywh {140 65 30 10} box THIN_UP_BOX labelfont 1 labelsize 10 - } - Fl_Dial globalfinedetuneslider { - label {F.Det.} - callback {master->microtonal.Pglobalfinedetune=(int) o->value();} - tooltip {global fine detune} xywh {143 30 20 20} box ROUND_UP_BOX labelsize 10 align 130 maximum 127 step 1 value 64 - code0 {o->value(master->microtonal.Pglobalfinedetune);} - class WidgetPDial - } - Fl_Button {} { - label {Panel Window} - callback {updatepanel(); -panelwindow->show();} - tooltip {Panel Window} xywh {293 62 92 16} box PLASTIC_UP_BOX color 183 labelfont 1 labelsize 10 - } - } - Fl_Window aboutwindow { - label {Copyright...} - xywh {411 344 365 280} type Double hide - } { - Fl_Box {} { - label {Copyright (c) 2002-2009 Nasca O. PAUL and others. Please read AUTHORS.txt} - xywh {15 35 335 55} labeltype EMBOSSED_LABEL labelsize 15 align 208 - } - Fl_Box {} { - label {This is free software; you may redistribute it and/or modify it under the terms of the -version 2 (or any later version) of the GNU General Public License as published by the Free Software Fundation. - This program comes with - ABSOLUTELY NO WARRANTY. - See the version 2 (or any later version) of the -GNU General Public License for details.} - xywh {15 90 335 145} labelfont 1 labelsize 11 align 144 - } - Fl_Button {} { - label {Close this window} - callback {aboutwindow->hide();} - xywh {80 245 190 25} box THIN_UP_BOX labelsize 11 - } - Fl_Box {} { - label ZynAddSubFX - xywh {15 5 335 30} labeltype EMBOSSED_LABEL labelfont 1 labelsize 20 align 16 - } - } - Fl_Window syseffsendwindow { - label {System Effects Send} - xywh {171 234 120 250} type Double hide resizable - } { - Fl_Scroll {} {open - xywh {0 45 120 170} box FLAT_BOX resizable - code0 {for (int neff1=0;neff1x()+(neff2-1)*35,o->y()+15+neff1*50,30,30);syseffsend[neff1][neff2]->label("aaa");syseffsend[neff1][neff2]->init(master,neff1,neff2);};} - } {} - Fl_Button {} { - label Close - callback {syseffsendwindow->hide();} - xywh {25 220 80 25} box THIN_UP_BOX - } - Fl_Box {} { - label {Send system effect's output to other system effects} - xywh {5 5 110 35} labelsize 10 align 192 - } - } - Fl_Window panelwindow { - label {ZynAddSubFX Panel} - xywh {89 59 630 635} type Double hide - } { - Fl_Scroll {} { - xywh {0 5 570 310} type HORIZONTAL box THIN_UP_BOX - } { - Fl_Pack {} { - xywh {5 10 560 285} type HORIZONTAL - code0 {for (int i=0;iinit(master,i,bankui);}} - } {} - } - Fl_Scroll {} { - xywh {0 320 570 310} type HORIZONTAL box THIN_UP_BOX - } { - Fl_Pack {} { - xywh {5 325 560 285} type HORIZONTAL - code0 {for (int i=NUM_MIDI_PARTS/2;iinit(master,i,bankui);}} - } {} - } - Fl_Button {} { - label Close - callback {panelwindow->hide(); -updatepanel();} - xywh {575 605 50 25} box THIN_UP_BOX labelsize 13 - } - Fl_Button {} { - label Refresh - callback {updatepanel();} - xywh {575 570 55 25} box THIN_UP_BOX labelsize 13 - } - } - Fl_Window simplemasterwindow { - label ZynAddSubFX - callback {\#ifdef VSTAUDIOOUT -fl_alert("ZynAddSubFX could not be closed this way, because it's a VST plugin. Please use the host aplication to close it."); -\#else -//if (fl_choice("Exit and leave the unsaved data?","No","Yes",NULL)) { - config.save(); - *exitprogram=1; -//}; -\#endif} - xywh {400 405 600 335} type Double hide - } { - Fl_Menu_Bar {} { - xywh {0 0 690 25} - } { - Submenu {} { - label {&File} - xywh {10 10 100 20} - } { - MenuItem {} { - label {&New (erase all)...} - callback {do_new_master();} - xywh {30 30 100 20} - } - MenuItem {} { - label {&Open Parameters...} - callback {do_load_master();} - xywh {30 30 100 20} - } - MenuItem {} { - label {&Save All Parameters...} - callback {do_save_master();} - xywh {20 20 100 20} divider - } - MenuItem {} { - label {&Settings...} - callback {configui->show();} - xywh {35 35 100 20} divider - } - MenuItem {} { - label {&Copyright...} - callback {aboutwindow->show();} - xywh {25 25 100 20} divider - } - MenuItem {} { - label {E&xit} - callback {masterwindow->do_callback();} - xywh {20 20 100 20} - } - } - Submenu {} { - label {&Instrument} - xywh {20 20 100 20} - } { - MenuItem {} { - label {&Open Instrument...} - callback {const char *filename; -filename=fl_file_chooser("Load:","({*.xiz})",NULL,0); -if (filename==NULL) return; - - -pthread_mutex_lock(&master->mutex); -// int npart=(int)npartcounter->value()-1; - - //clear all instrument parameters, first - master->part[npart]->defaultsinstrument(); - - //load the instr. parameters - int result=master->part[npart]->loadXMLinstrument(filename); - -pthread_mutex_unlock(&master->mutex); -master->part[npart]->applyparameters(); - -simplenpartcounter->do_callback(); - -if (result==-10) fl_alert("Error: Could not load the file\\nbecause it is not an instrument file."); - else if (result<0) fl_alert("Error: Could not load the file.");} - xywh {40 40 100 20} - } - MenuItem {} { - label {Show Instrument &Bank...} - callback {bankui->show();} - xywh {10 10 100 20} divider - } - } - Submenu {} { - label Misc - xywh {0 0 100 20} - } { - MenuItem {} { - label {Switch User Interface Mode} - callback {if (fl_choice("Switch the User Interface to Advanced mode ?","No","Yes",NULL)){ - simplemasterwindow->hide(); - refresh_master_ui(); - masterwindow->show(); - config.cfg.UserInterfaceMode=1; -};} - xywh {0 0 100 20} - } - } - } - Fl_Group simplelistitemgroup { - private xywh {125 65 215 150} box ENGRAVED_BOX - code0 {if (master->part[npart]->Penabled==0) o->deactivate();} - } { - Fl_Button partname { - callback {if ((int)bankui->cbwig->value()!=(npart+1)){ - bankui->cbwig->value(npart+1); - bankui->cbwig->do_callback(); -}; -bankui->show();} - xywh {130 72 205 18} box PLASTIC_THIN_DOWN_BOX down_box FLAT_BOX color 247 labelfont 1 labelsize 11 align 208 - } - Fl_Slider partpanning { - label Pan - callback {master->part[npart]->setPpanning((int) o->value());} - xywh {185 95 70 15} type {Horz Knob} box FLAT_BOX maximum 127 step 1 value 64 - code0 {o->value(master->part[npart]->Ppanning);} - } - Fl_Choice partrcv { - label {Midi Channel Receive} - callback {virkeys->relaseallkeys(0); -master->part[npart]->Prcvchn=(int) o->value(); -virkeys->midich=(int) o->value();} open - tooltip {receive from Midi channel} xywh {140 157 65 18} down_box BORDER_BOX labelsize 10 align 130 textfont 1 - code0 {char nrstr[10]; for(int i=0;iadd(nrstr); else o->add("Dr10");};} - code1 {o->value(master->part[npart]->Prcvchn);} - } {} - Fl_Dial partvolume { - callback {master->part[npart]->setPvolume((int) o->value());} - xywh {145 95 30 30} maximum 127 step 1 - code0 {o->value(master->part[npart]->Pvolume);} - class WidgetPDial - } - Fl_Box {} { - label Volume - xywh {130 125 60 15} - } - Fl_Check_Button simplepartportamento { - label Portamento - callback {master->part[npart]->ctl.portamento.portamento=(int) o->value();} - tooltip {Enable/Disable the portamento} xywh {260 95 75 20} down_box DOWN_BOX labelfont 1 labelsize 10 - code0 {o->value(master->part[npart]->ctl.portamento.portamento);} - } - Fl_Counter simpleminkcounter { - label {Min.key} - callback {master->part[npart]->Pminkey=(int) o->value(); -if (master->part[npart]->Pminkey>master->part[npart]->Pmaxkey) o->textcolor(FL_RED); - else o->textcolor(FL_BLACK);} - tooltip {Minimum key (that the part receives NoteOn messages)} xywh {210 158 40 15} type Simple labelfont 1 labelsize 10 minimum 0 maximum 127 step 1 textsize 10 - code0 {o->value(master->part[npart]->Pminkey);} - } - Fl_Counter simplemaxkcounter { - label {Max.key} - callback {master->part[npart]->Pmaxkey=(int) o->value(); - -if (master->part[npart]->Pminkey>master->part[npart]->Pmaxkey) o->textcolor(FL_RED); - else o->textcolor(FL_BLACK);} - tooltip {Maximum key (that the part receives NoteOn messages)} xywh {255 158 40 15} type Simple labelfont 1 labelsize 10 minimum 0 maximum 127 step 1 textsize 10 - code0 {o->value(master->part[npart]->Pmaxkey);} - } - Fl_Button {} { - label m - callback {if (master->part[npart]->lastnote>=0) simpleminkcounter->value(master->part[npart]->lastnote); -simpleminkcounter->do_callback(); -simplemaxkcounter->do_callback();} - tooltip {set the minimum key to the last pressed key} xywh {230 188 15 12} box THIN_UP_BOX labelsize 10 - } - Fl_Button {} { - label M - callback {if (master->part[npart]->lastnote>=0) simplemaxkcounter->value(master->part[npart]->lastnote); -simplemaxkcounter->do_callback(); -simpleminkcounter->do_callback();} - tooltip {set the maximum key to the last pressed key} xywh {260 188 15 12} box THIN_UP_BOX labelsize 10 - } - Fl_Button {} { - label R - callback {simpleminkcounter->value(0); -simpleminkcounter->do_callback(); -simplemaxkcounter->value(127); -simplemaxkcounter->do_callback();} - tooltip {reset the minimum key to 0 and maximum key to 127} xywh {245 188 15 12} box THIN_UP_BOX labelfont 1 labelsize 10 - } - Fl_Counter simplepartkeyshiftcounter { - label KeyShift - callback {master->part[npart]->Pkeyshift=(int) o->value()+64;} - xywh {240 120 90 20} labelsize 11 minimum -64 maximum 64 step 1 - code0 {o->lstep(12);} - code1 {o->value(master->part[npart]->Pkeyshift-64);} - } - Fl_Dial simplesyseffsend { - callback {master->setPsysefxvol(npart,nsyseff,(int) o->value());} - xywh {300 160 30 30} maximum 127 step 1 - class WidgetPDial - } - Fl_Box {} { - label Effect - xywh {295 190 40 15} - } - } - Fl_Check_Button partenabled { - label Enabled - callback {pthread_mutex_lock(&master->mutex); - master->partonoff(npart,(int) o->value()); -pthread_mutex_unlock(&master->mutex); - -if ((int) o->value()==0) simplelistitemgroup->deactivate(); - else { - simplelistitemgroup->activate(); - if ((int)bankui->cbwig->value()!=(npart+1)){ - bankui->cbwig->value(npart+1); - bankui->cbwig->do_callback(); - }; -}; - -o->redraw();} - private xywh {250 40 85 20} down_box DOWN_BOX labeltype EMBOSSED_LABEL labelfont 1 labelsize 13 align 24 - code0 {//char tmp[10];snprintf(tmp,10,"%d",npart+1);o->copy_label(tmp);} - code1 {o->value(master->part[npart]->Penabled);} - } - Fl_Box virkeys { - label Keyboard - xywh {5 215 590 80} box BORDER_BOX color 17 - code0 {o->init(master);} - class VirKeys - } - Fl_Group {} { - xywh {340 30 255 185} box ENGRAVED_BOX - } { - Fl_Tabs {} { - xywh {345 35 245 175} align 18 - } { - Fl_Group {} { - label {System Effects} - xywh {345 55 245 155} box ENGRAVED_FRAME labelfont 1 labelsize 12 align 18 hide - } { - Fl_Counter simplesyseffnocounter { - label {Sys.Effect No.} - callback {nsyseff=(int) o->value()-1; -simplesysefftype->value(master->sysefx[nsyseff]->geteffect()); -simplesyseffectui->refresh(master->sysefx[nsyseff]); -simplerefresh();} - xywh {350 75 80 20} type Simple labelfont 1 labelsize 10 align 1 minimum 0 maximum 127 step 1 value 1 textfont 1 - code0 {o->bounds(1,NUM_SYS_EFX);} - code1 {o->value(nsyseff+1);} - } - Fl_Choice simplesysefftype { - label EffType - callback {pthread_mutex_lock(&master->mutex); -master->sysefx[nsyseff]->changeeffect((int) o->value()); -pthread_mutex_unlock(&master->mutex); -simplesyseffectui->refresh(master->sysefx[nsyseff]);} - xywh {515 80 70 15} down_box BORDER_BOX labelsize 10 align 5 - code0 {o->value(master->sysefx[nsyseff]->geteffect());} - } { - MenuItem {} { - label {No Effect} - xywh {20 20 100 20} labelfont 1 labelsize 10 - } - MenuItem {} { - label Reverb - xywh {30 30 100 20} labelfont 1 labelsize 10 - } - MenuItem {} { - label Echo - xywh {40 40 100 20} labelfont 1 labelsize 10 - } - MenuItem {} { - label Chorus - xywh {50 50 100 20} labelfont 1 labelsize 10 - } - MenuItem {} { - label Phaser - xywh {60 60 100 20} labelfont 1 labelsize 10 - } - MenuItem {} { - label AlienWah - xywh {70 70 100 20} labelfont 1 labelsize 10 - } - MenuItem {} { - label Distortion - xywh {80 80 100 20} labelfont 1 labelsize 10 - } - MenuItem {} { - label EQ - xywh {90 90 100 20} labelfont 1 labelsize 10 - } - MenuItem {} { - label DynFilter - xywh {100 100 100 20} labelfont 1 labelsize 10 - } - } - Fl_Group simplesyseffectuigroup { - xywh {350 95 235 95} box FLAT_BOX color 48 - } { - Fl_Group simplesyseffectui { - xywh {350 95 234 95} - code0 {o->init(master->sysefx[nsyseff]);} - class SimpleEffUI - } {} - } - Fl_Button {} { - label {Send to...} - callback {syseffsendwindow->show();} - xywh {435 75 75 20} box THIN_UP_BOX labelfont 1 labelsize 11 - } - Fl_Button {} { - label P - callback {pthread_mutex_lock(&master->mutex); -presetsui->paste(master->sysefx[nsyseff],simplesyseffectui); -pthread_mutex_unlock(&master->mutex);} - xywh {560 65 25 15} box THIN_UP_BOX color 179 labelfont 1 labelsize 11 labelcolor 7 - } - } - Fl_Group {} { - label {Insertion Effects} - xywh {345 55 245 155} box ENGRAVED_FRAME labelfont 1 labelsize 12 align 18 - } { - Fl_Counter simpleinseffnocounter { - label {Ins.Effect No.} - callback {ninseff=(int) o->value()-1; -simpleinsefftype->value(master->insefx[ninseff]->geteffect()); -simpleinseffpart->value(master->Pinsparts[ninseff]+2); -simpleinseffectui->refresh(master->insefx[ninseff]); - -if (master->Pinsparts[ninseff]!=-1) { - simpleinsefftype->activate(); - simpleinseffectui->activate(); - simpleinseffectuigroup->activate(); -} else { - simpleinsefftype->deactivate(); - simpleinseffectui->deactivate(); - simpleinseffectuigroup->deactivate(); -};} - xywh {350 75 80 20} type Simple labelfont 1 labelsize 10 align 1 minimum 0 maximum 127 step 1 value 1 textfont 1 - code0 {o->bounds(1,NUM_INS_EFX);} - code1 {o->value(ninseff+1);} - } - Fl_Choice simpleinsefftype { - label EffType - callback {pthread_mutex_lock(&master->mutex); -master->insefx[ninseff]->changeeffect((int) o->value()); -pthread_mutex_unlock(&master->mutex); -simpleinseffectui->refresh(master->insefx[ninseff]); -simpleinseffectui->show();} selected - xywh {515 80 70 15} down_box BORDER_BOX labelsize 10 align 5 - code0 {o->value(master->insefx[ninseff]->geteffect());} - code1 {if (master->Pinsparts[ninseff]== -1) o->deactivate();} - } { - MenuItem {} { - label {No Effect} - xywh {35 35 100 20} labelfont 1 labelsize 10 - } - MenuItem {} { - label Reverb - xywh {45 45 100 20} labelfont 1 labelsize 10 - } - MenuItem {} { - label Echo - xywh {55 55 100 20} labelfont 1 labelsize 10 - } - MenuItem {} { - label Chorus - xywh {65 65 100 20} labelfont 1 labelsize 10 - } - MenuItem {} { - label Phaser - xywh {70 70 100 20} labelfont 1 labelsize 10 - } - MenuItem {} { - label AlienWah - xywh {80 80 100 20} labelfont 1 labelsize 10 - } - MenuItem {} { - label Distortion - xywh {90 90 100 20} labelfont 1 labelsize 10 - } - MenuItem {} { - label EQ - xywh {100 100 100 20} labelfont 1 labelsize 10 - } - MenuItem {} { - label DynFilter - xywh {110 110 100 20} labelfont 1 labelsize 10 - } - } - Fl_Group simpleinseffectuigroup { - xywh {350 95 234 95} box FLAT_BOX color 48 - } { - Fl_Group simpleinseffectui { - xywh {350 95 234 95} - code0 {o->init(master->insefx[ninseff]);} - code1 {if (master->Pinsparts[ninseff]== -1) o->deactivate();} - class SimpleEffUI - } {} - } - Fl_Choice simpleinseffpart { - label {Insert To.} - callback {master->Pinsparts[ninseff]=(int) o->value()-2; -if ((int) o->value()==1){ - simpleinseffectuigroup->deactivate(); - simpleinsefftype->deactivate(); - simpleinseffectui->deactivate(); -} else { - simpleinseffectuigroup->activate(); - simpleinsefftype->activate(); - simpleinseffectui->activate(); -}; -master->insefx[ninseff]->cleanup();} open - xywh {435 75 80 20} down_box BORDER_BOX labelfont 1 labelsize 10 align 5 textsize 10 - code0 {o->add("Master Out");o->add("Off");} - code1 {char tmp[50]; for (int i=0;iadd(tmp);};} - code3 {o->value(master->Pinsparts[ninseff]+2);} - } {} - Fl_Button {} { - label P - callback {pthread_mutex_lock(&master->mutex); -presetsui->paste(master->insefx[ninseff],simpleinseffectui); -pthread_mutex_unlock(&master->mutex);} - xywh {560 65 25 15} box THIN_UP_BOX color 179 labelfont 1 labelsize 11 labelcolor 7 - } - } - } - } - Fl_Group {} { - xywh {5 300 590 30} box ENGRAVED_FRAME - } { - Fl_Box {} { - label {VU-Meter} - xywh {5 300 590 30} box FLAT_BOX color 41 selection_color 75 - code0 {o->init(master,-1);} - class VUMeter - } - } - Fl_Dial simplemastervolumedial { - label {Master Volume} - callback {master->setPvolume((int) o->value());} - tooltip {Master Volume} xywh {10 35 40 40} box ROUND_UP_BOX labelfont 1 labelsize 11 align 130 maximum 127 step 1 - code0 {o->value(master->Pvolume);} - class WidgetPDial - } - Fl_Counter simplemasterkeyshiftcounter { - label {Master KeyShift} - callback {master->setPkeyshift((int) o->value()+64);} - xywh {25 110 90 20} labelsize 11 minimum -64 maximum 64 step 1 - code0 {o->lstep(12);} - code1 {o->value(master->Pkeyshift-64);} - } - Fl_Button {} { - label {Stop ALL sounds!} - callback {virkeyboard->relaseallkeys(); -pthread_mutex_lock(&master->mutex); -master->shutup=1; -pthread_mutex_unlock(&master->mutex);} - xywh {5 149 115 31} box PLASTIC_UP_BOX color 231 labelfont 1 labelsize 11 - } - Fl_Button {} { - label Reset - callback {simpleglobalfinedetuneslider->value(64.0); -simpleglobalfinedetuneslider->do_callback();} - tooltip {Master fine detune reset} xywh {70 32 50 10} box THIN_UP_BOX labelfont 1 labelsize 11 align 128 - } - Fl_Dial simpleglobalfinedetuneslider { - label {Fine Detune} - callback {master->microtonal.Pglobalfinedetune=(int) o->value();} - tooltip {global fine detune} xywh {80 45 30 30} box ROUND_UP_BOX labelsize 11 align 130 maximum 127 step 1 value 64 - code0 {o->value(master->microtonal.Pglobalfinedetune);} - class WidgetPDial - } - Fl_Counter simplenpartcounter { - label Part - callback {virkeys->relaseallkeys(0); -npartcounter->value(o->value()); -npart=(int) o->value()-1; - -simplerefresh(); -virkeys->midich=master->part[npart]->Prcvchn;} - tooltip {The part number} xywh {170 40 70 20} type Simple labelfont 1 align 4 minimum 0 maximum 127 step 1 value 1 textfont 1 - code0 {o->bounds(1,NUM_MIDI_PARTS);} - } - Fl_Counter {} { - label {Keyb.Oct.} - callback {virkeys->relaseallkeys(0); -virkeys->midioct=(int) o->value(); -virkeys->take_focus();} - tooltip {Midi Octave} xywh {5 195 55 20} type Simple labelsize 11 align 8 when 6 minimum 0 maximum 5 step 1 textfont 1 textsize 11 - code0 {o->value(virkeys->midioct);} - } - } - Fl_Window selectuiwindow { - label {User Interface mode} - callback {*exitprogram=1;} - xywh {342 246 430 250} type Double hide non_modal - } { - Fl_Box {} { - label {Welcome to ZynAddSubFX} - xywh {5 5 425 40} labeltype SHADOW_LABEL labelfont 1 labelsize 26 - } - Fl_Box {} { - label {Please choose the interface mode:} - xywh {10 50 265 25} labelfont 1 labelsize 13 - } - Fl_Button {} { - label Advanced - callback {config.cfg.UserInterfaceMode=1; -masterwindow->show(); -selectuiwindow->hide();} - xywh {10 165 100 35} box PLASTIC_UP_BOX color 229 labelfont 1 labelsize 16 - } - Fl_Box {} { - label {.. if you have used ZynAddSubFX before, or you like to have full controll to all parameters.} - xywh {110 165 310 35} labelfont 1 labelsize 11 align 144 - } - Fl_Button {} { - label Beginner - callback {simplemasterwindow->show(); -selectuiwindow->hide(); -config.cfg.UserInterfaceMode=2;} - xywh {10 80 100 65} box PLASTIC_UP_BOX color 238 labelfont 1 labelsize 16 - } - Fl_Box {} { - label {..if you are a beginner, you prefer using presets or you prefer to use simpler user interfaces. Most functionality of ZynAddSubFX will be hidden in this mode to make simple the learning/using it.} - xywh {110 75 320 75} labelfont 1 labelsize 11 align 144 - } - Fl_Box {} { - label {You can switch the interface modes anytime you want.} - xywh {30 215 360 25} box BORDER_BOX color 51 labelfont 1 labelsize 11 align 144 - } - } - } - Function {updatesendwindow()} {} { - code {for (int neff1=0;neff1value(master->Psysefxsend[neff1][neff2]);} {} - } - Function {updatepanel()} {} { - code {for (int npart=0;npartrefresh(); -};} {} - } - Function {setfilelabel(const char *filename)} {} { - code {if (filename!=NULL) snprintf(&masterwindowlabel[0],100,"%s - ZynAddSubFX",fl_filename_name(filename)); - else snprintf(&masterwindowlabel[0],100,"%s","ZynAddSubFX"); -masterwindowlabel[99]='\\0'; -masterwindow->label(&masterwindowlabel[0]); -simplemasterwindow->label(&masterwindowlabel[0]);} {} - } - Function {MasterUI(Master *master_,int *exitprogram_)} {} { - code {master=master_; -exitprogram=exitprogram_; -ninseff=0; -nsyseff=0; -npart=0; - -for (int i=0;imicrotonal); -virkeyboard=new VirKeyboard(master); -bankui=new BankUI(master,&npart); -configui=new ConfigUI(); -sequi=new SeqUI(master); - -make_window(); -\#ifdef OS_WINDOWS -masterwindow->icon((char *)LoadIcon(GetModuleHandle(NULL), "zynaddsubfx_icon")); -\#endif -presetsui=new PresetsUI(); -setfilelabel(NULL); -swapefftype=0; -simplerefresh();} {} - } - Function {~MasterUI()} {} { - code {masterwindow->hide(); -delete masterwindow; -simplemasterwindow->hide(); -delete simplemasterwindow; -aboutwindow->hide(); -delete aboutwindow; -syseffsendwindow->hide(); -delete syseffsendwindow; - -delete virkeyboard; -delete microtonalui; -delete bankui; -delete configui; -delete sequi; - -delete presetsui; -delete panelwindow; -delete selectuiwindow;} {} - } - Function {showUI()} {} { - code {switch (config.cfg.UserInterfaceMode){ - case 0:selectuiwindow->show(); - break; - case 1:masterwindow->show(); - break; - case 2:simplemasterwindow->show(); - break; -};} {} - } - Function {simplerefresh()} {} { - code {partenabled->value(master->part[npart]->Penabled); -if (master->part[npart]->Penabled!=0) simplelistitemgroup->activate(); - else simplelistitemgroup->deactivate(); - -partvolume->value(master->part[npart]->Pvolume); -partpanning->value(master->part[npart]->Ppanning); -partrcv->value(master->part[npart]->Prcvchn); - -if (master->part[npart]->Pname[0]!=0) partname->label((char *)master->part[npart]->Pname); - else partname->label("Click here to load a instrument"); - -simplelistitemgroup->redraw(); -simplepartportamento->value(master->part[npart]->ctl.portamento.portamento); -simpleminkcounter->value(master->part[npart]->Pminkey); -simplemaxkcounter->value(master->part[npart]->Pmaxkey); - -simplepartkeyshiftcounter->value(master->part[npart]->Pkeyshift-64); -simplesyseffsend->value(master->Psysefxvol[nsyseff][npart]);} {} - } - Function {do_new_master()} {} { - code {if (fl_choice("Clear *ALL* the parameters ?","No","Yes",NULL)){ - delete microtonalui; - - pthread_mutex_lock(&master->mutex); - master->defaults(); - pthread_mutex_unlock(&master->mutex); - - npartcounter->value(1); - refresh_master_ui(); - -}; - -updatepanel();} {} - } - Function {do_load_master(const char* file = NULL)} {} { - code {const char *filename; - if (file == NULL) { - filename=fl_file_chooser("Open:","({*.xmz})",NULL,0); - if (filename==NULL) return; - } - else { - filename = file; - } - - -pthread_mutex_lock(&master->mutex); - //clear all parameters - master->defaults(); - - //load the data - int result=master->loadXML(filename); -pthread_mutex_unlock(&master->mutex); -master->applyparameters(); - -npartcounter->value(1); -refresh_master_ui(); -updatepanel(); -if (result>=0) setfilelabel(filename); - - -if (result==-10) fl_alert("Error: Could not load the file\\nbecause it is not a zynaddsubfx parameters file."); - else if (result<0) fl_alert("Error: Could not load the file.");} {} - } - Function {do_save_master(const char* file = NULL)} {} { - code {const char *filename; -char *tmp; - int result=0; - if (file == NULL) { - tmp=fl_file_chooser("Save:","({*.xmz})",NULL,0); - if (tmp==NULL) return; - tmp=fl_filename_setext(tmp,".xmz"); - filename=tmp; - result=fileexists(tmp); - if (result) { - result=0; - if (!fl_choice("The file exists. Overwrite it?","No","Yes",NULL)) return; - - } - } - else { - filename = file; - } - - -pthread_mutex_lock(&master->mutex); -result=master->saveXML(filename); -pthread_mutex_unlock(&master->mutex); - -if (result<0) fl_alert("Error: Could not save the file."); - else setfilelabel(filename); - -updatepanel();} {} - } - Function {refresh_master_ui()} {} { - code {ninseff=0; -nsyseff=0; -npart=0; - -//the Master UI -npartcounter->do_callback(); -syseffnocounter->do_callback(); -inseffnocounter->do_callback(); -masterkeyshiftcounter->value(master->Pkeyshift-64); -mastervolumedial->value(master->Pvolume); -globalfinedetuneslider->value(master->microtonal.Pglobalfinedetune); -microtonalui=new MicrotonalUI(&master->microtonal); -nrpnbutton->value(master->ctl.NRPN.receive); -updatesendwindow(); -updatepanel(); - -//the simle MasterUI -simplenpartcounter->value(1); -simplesyseffnocounter->value(1); -simpleinseffnocounter->value(1); -simplenpartcounter->do_callback(); -simplesyseffnocounter->do_callback(); -simpleinseffnocounter->do_callback(); -simplemasterkeyshiftcounter->value(master->Pkeyshift-64); -simplemastervolumedial->value(master->Pvolume); -simpleglobalfinedetuneslider->value(master->microtonal.Pglobalfinedetune); -virkeys->midich=master->part[npart]->Prcvchn; - -simplerefresh(); -bankui->hide();} {} - } - decl {Master *master;} {} - decl {MicrotonalUI *microtonalui;} {} - decl {SeqUI *sequi;} {} - decl {BankUI *bankui;} {} - decl {int ninseff,npart;} {} - decl {int nsyseff;} {} - decl {int *exitprogram;} {} - decl {SysEffSend *syseffsend[NUM_SYS_EFX][NUM_SYS_EFX];} {} - decl {VirKeyboard *virkeyboard;} {} - decl {ConfigUI *configui;} {} - decl {int swapefftype;} {} - decl {char masterwindowlabel[100];} {} - decl {Panellistitem *panellistitem[NUM_MIDI_PARTS];} {} -} diff --git a/plugins/zynaddsubfx/src/UI/MasterUI.h b/plugins/zynaddsubfx/src/UI/MasterUI.h deleted file mode 100644 index fc1db4b59..000000000 --- a/plugins/zynaddsubfx/src/UI/MasterUI.h +++ /dev/null @@ -1,448 +0,0 @@ -// generated by Fast Light User Interface Designer (fluid) version 1.0300 - -#ifndef MasterUI_h -#define MasterUI_h -#include -#include -#include -#include -#include "WidgetPDial.h" -#include "ADnoteUI.h" -#include "SUBnoteUI.h" -#include "EffUI.h" -#include "VirKeyboard.h" -#include "ConfigUI.h" -#include "BankUI.h" -#include "PartUI.h" -#include "MicrotonalUI.h" -#include "SeqUI.h" -#include "PresetsUI.h" -#include "../Misc/Master.h" -#include "../Misc/Part.h" -#include "../Misc/Util.h" -#include "../globals.h" - -class VUMeter : public Fl_Box { -public: - VUMeter(int x,int y, int w, int h, const char *label=0); - void init(Master *master_,int part_); - void draw_master(); - void draw_part(); - void draw(); - static void tickdraw(VUMeter *o); - static void tick(void *v); - int handle(int event); -private: - Master *master; - int npart; - float olddbl,olddbr; - float oldrmsdbl,oldrmsdbr; -}; - -class SysEffSend : public WidgetPDial { -public: - SysEffSend(int x,int y, int w, int h, const char *label=0); - void init(Master *master_,int neff1_,int neff2_); - ~SysEffSend(); - int handle(int event); -private: - Master *master; - int neff1; - int neff2; -}; -#include -#include -#include -#include -#include - -class Panellistitem : public Fl_Group { - Fl_Group* make_window(); - Fl_Group *panellistitem; - Fl_Group *panellistitemgroup; -public: - Fl_Button *partname; -private: - void cb_partname_i(Fl_Button*, void*); - static void cb_partname(Fl_Button*, void*); -public: - Fl_Slider *partvolume; -private: - void cb_partvolume_i(Fl_Slider*, void*); - static void cb_partvolume(Fl_Slider*, void*); -public: - WidgetPDial *partpanning; -private: - void cb_partpanning_i(WidgetPDial*, void*); - static void cb_partpanning(WidgetPDial*, void*); - void cb_edit_i(Fl_Button*, void*); - static void cb_edit(Fl_Button*, void*); -public: - Fl_Choice *partrcv; -private: - void cb_partrcv_i(Fl_Choice*, void*); - static void cb_partrcv(Fl_Choice*, void*); - Fl_Check_Button *partenabled; - void cb_partenabled_i(Fl_Check_Button*, void*); - static void cb_partenabled(Fl_Check_Button*, void*); -public: - Panellistitem(int x,int y, int w, int h, const char *label=0); - void init(Master *master_, int npart_,BankUI *bankui_); - void refresh(); - ~Panellistitem(); -private: - int npart; - Master *master; - BankUI *bankui; -}; -#include -#include -#include -#include -#include -#include -#include - -class MasterUI { -public: - Fl_Double_Window* make_window(); - Fl_Double_Window *masterwindow; -private: - void cb_masterwindow_i(Fl_Double_Window*, void*); - static void cb_masterwindow(Fl_Double_Window*, void*); -public: - Fl_Menu_Bar *mastermenu; - static Fl_Menu_Item menu_mastermenu[]; -private: - void cb_New_i(Fl_Menu_*, void*); - static void cb_New(Fl_Menu_*, void*); - void cb_Open_i(Fl_Menu_*, void*); - static void cb_Open(Fl_Menu_*, void*); - void cb_Save_i(Fl_Menu_*, void*); - static void cb_Save(Fl_Menu_*, void*); - void cb_Load_i(Fl_Menu_*, void*); - static void cb_Load(Fl_Menu_*, void*); - void cb_Save1_i(Fl_Menu_*, void*); - static void cb_Save1(Fl_Menu_*, void*); - void cb_Show_i(Fl_Menu_*, void*); - static void cb_Show(Fl_Menu_*, void*); - void cb_Settings_i(Fl_Menu_*, void*); - static void cb_Settings(Fl_Menu_*, void*); - void cb_Copyright_i(Fl_Menu_*, void*); - static void cb_Copyright(Fl_Menu_*, void*); - void cb_E_i(Fl_Menu_*, void*); - static void cb_E(Fl_Menu_*, void*); - void cb_Clear_i(Fl_Menu_*, void*); - static void cb_Clear(Fl_Menu_*, void*); - void cb_Open1_i(Fl_Menu_*, void*); - static void cb_Open1(Fl_Menu_*, void*); - void cb_Save2_i(Fl_Menu_*, void*); - static void cb_Save2(Fl_Menu_*, void*); - void cb_Show1_i(Fl_Menu_*, void*); - static void cb_Show1(Fl_Menu_*, void*); - void cb_Virtual_i(Fl_Menu_*, void*); - static void cb_Virtual(Fl_Menu_*, void*); -public: - static Fl_Menu_Item *recordmenu; -private: - void cb_Choose_i(Fl_Menu_*, void*); - static void cb_Choose(Fl_Menu_*, void*); - void cb_Show2_i(Fl_Menu_*, void*); - static void cb_Show2(Fl_Menu_*, void*); - void cb_Switch_i(Fl_Menu_*, void*); - static void cb_Switch(Fl_Menu_*, void*); -public: - WidgetPDial *mastervolumedial; -private: - void cb_mastervolumedial_i(WidgetPDial*, void*); - static void cb_mastervolumedial(WidgetPDial*, void*); -public: - Fl_Counter *masterkeyshiftcounter; -private: - void cb_masterkeyshiftcounter_i(Fl_Counter*, void*); - static void cb_masterkeyshiftcounter(Fl_Counter*, void*); - void cb_Panic_i(Fl_Button*, void*); - static void cb_Panic(Fl_Button*, void*); -public: - Fl_Group *partuigroup; - PartUI *partui; - Fl_Counter *syseffnocounter; -private: - void cb_syseffnocounter_i(Fl_Counter*, void*); - static void cb_syseffnocounter(Fl_Counter*, void*); -public: - Fl_Choice *sysefftype; -private: - void cb_sysefftype_i(Fl_Choice*, void*); - static void cb_sysefftype(Fl_Choice*, void*); - static Fl_Menu_Item menu_sysefftype[]; -public: - Fl_Group *syseffectuigroup; - EffUI *syseffectui; -private: - void cb_Send_i(Fl_Button*, void*); - static void cb_Send(Fl_Button*, void*); - void cb_C_i(Fl_Button*, void*); - static void cb_C(Fl_Button*, void*); - void cb_P_i(Fl_Button*, void*); - static void cb_P(Fl_Button*, void*); -public: - Fl_Counter *inseffnocounter; -private: - void cb_inseffnocounter_i(Fl_Counter*, void*); - static void cb_inseffnocounter(Fl_Counter*, void*); -public: - Fl_Choice *insefftype; -private: - void cb_insefftype_i(Fl_Choice*, void*); - static void cb_insefftype(Fl_Choice*, void*); - static Fl_Menu_Item menu_insefftype[]; -public: - Fl_Group *inseffectuigroup; - EffUI *inseffectui; - Fl_Choice *inseffpart; -private: - void cb_inseffpart_i(Fl_Choice*, void*); - static void cb_inseffpart(Fl_Choice*, void*); - void cb_C1_i(Fl_Button*, void*); - static void cb_C1(Fl_Button*, void*); - void cb_P1_i(Fl_Button*, void*); - static void cb_P1(Fl_Button*, void*); - void cb_Scales_i(Fl_Button*, void*); - static void cb_Scales(Fl_Button*, void*); -public: - Fl_Button *recordbutton; -private: - void cb_recordbutton_i(Fl_Button*, void*); - static void cb_recordbutton(Fl_Button*, void*); -public: - Fl_Button *stopbutton; -private: - void cb_stopbutton_i(Fl_Button*, void*); - static void cb_stopbutton(Fl_Button*, void*); -public: - Fl_Button *pausebutton; -private: - void cb_pausebutton_i(Fl_Button*, void*); - static void cb_pausebutton(Fl_Button*, void*); -public: - Fl_Box *pauselabel; - Fl_Check_Button *nrpnbutton; -private: - void cb_nrpnbutton_i(Fl_Check_Button*, void*); - static void cb_nrpnbutton(Fl_Check_Button*, void*); -public: - Fl_Counter *npartcounter; -private: - void cb_npartcounter_i(Fl_Counter*, void*); - static void cb_npartcounter(Fl_Counter*, void*); - void cb_vK_i(Fl_Button*, void*); - static void cb_vK(Fl_Button*, void*); - void cb_R_i(Fl_Button*, void*); - static void cb_R(Fl_Button*, void*); -public: - WidgetPDial *globalfinedetuneslider; -private: - void cb_globalfinedetuneslider_i(WidgetPDial*, void*); - static void cb_globalfinedetuneslider(WidgetPDial*, void*); - void cb_Panel_i(Fl_Button*, void*); - static void cb_Panel(Fl_Button*, void*); -public: - Fl_Double_Window *aboutwindow; -private: - void cb_Close_i(Fl_Button*, void*); - static void cb_Close(Fl_Button*, void*); -public: - Fl_Double_Window *syseffsendwindow; -private: - void cb_Close1_i(Fl_Button*, void*); - static void cb_Close1(Fl_Button*, void*); -public: - Fl_Double_Window *panelwindow; -private: - void cb_Close2_i(Fl_Button*, void*); - static void cb_Close2(Fl_Button*, void*); - void cb_Refresh_i(Fl_Button*, void*); - static void cb_Refresh(Fl_Button*, void*); -public: - Fl_Double_Window *simplemasterwindow; -private: - void cb_simplemasterwindow_i(Fl_Double_Window*, void*); - static void cb_simplemasterwindow(Fl_Double_Window*, void*); - static Fl_Menu_Item menu_[]; - void cb_New1_i(Fl_Menu_*, void*); - static void cb_New1(Fl_Menu_*, void*); - void cb_Open2_i(Fl_Menu_*, void*); - static void cb_Open2(Fl_Menu_*, void*); - void cb_Save3_i(Fl_Menu_*, void*); - static void cb_Save3(Fl_Menu_*, void*); - void cb_Settings1_i(Fl_Menu_*, void*); - static void cb_Settings1(Fl_Menu_*, void*); - void cb_Copyright1_i(Fl_Menu_*, void*); - static void cb_Copyright1(Fl_Menu_*, void*); - void cb_E1_i(Fl_Menu_*, void*); - static void cb_E1(Fl_Menu_*, void*); - void cb_Open3_i(Fl_Menu_*, void*); - static void cb_Open3(Fl_Menu_*, void*); - void cb_Show3_i(Fl_Menu_*, void*); - static void cb_Show3(Fl_Menu_*, void*); - void cb_Switch1_i(Fl_Menu_*, void*); - static void cb_Switch1(Fl_Menu_*, void*); - Fl_Group *simplelistitemgroup; -public: - Fl_Button *partname; -private: - void cb_partname1_i(Fl_Button*, void*); - static void cb_partname1(Fl_Button*, void*); -public: - Fl_Slider *partpanning; -private: - void cb_partpanning1_i(Fl_Slider*, void*); - static void cb_partpanning1(Fl_Slider*, void*); -public: - Fl_Choice *partrcv; -private: - void cb_partrcv1_i(Fl_Choice*, void*); - static void cb_partrcv1(Fl_Choice*, void*); -public: - WidgetPDial *partvolume; -private: - void cb_partvolume1_i(WidgetPDial*, void*); - static void cb_partvolume1(WidgetPDial*, void*); -public: - Fl_Check_Button *simplepartportamento; -private: - void cb_simplepartportamento_i(Fl_Check_Button*, void*); - static void cb_simplepartportamento(Fl_Check_Button*, void*); -public: - Fl_Counter *simpleminkcounter; -private: - void cb_simpleminkcounter_i(Fl_Counter*, void*); - static void cb_simpleminkcounter(Fl_Counter*, void*); -public: - Fl_Counter *simplemaxkcounter; -private: - void cb_simplemaxkcounter_i(Fl_Counter*, void*); - static void cb_simplemaxkcounter(Fl_Counter*, void*); - void cb_m_i(Fl_Button*, void*); - static void cb_m(Fl_Button*, void*); - void cb_M_i(Fl_Button*, void*); - static void cb_M(Fl_Button*, void*); - void cb_R1_i(Fl_Button*, void*); - static void cb_R1(Fl_Button*, void*); -public: - Fl_Counter *simplepartkeyshiftcounter; -private: - void cb_simplepartkeyshiftcounter_i(Fl_Counter*, void*); - static void cb_simplepartkeyshiftcounter(Fl_Counter*, void*); -public: - WidgetPDial *simplesyseffsend; -private: - void cb_simplesyseffsend_i(WidgetPDial*, void*); - static void cb_simplesyseffsend(WidgetPDial*, void*); - Fl_Check_Button *partenabled; - void cb_partenabled1_i(Fl_Check_Button*, void*); - static void cb_partenabled1(Fl_Check_Button*, void*); -public: - VirKeys *virkeys; - Fl_Counter *simplesyseffnocounter; -private: - void cb_simplesyseffnocounter_i(Fl_Counter*, void*); - static void cb_simplesyseffnocounter(Fl_Counter*, void*); -public: - Fl_Choice *simplesysefftype; -private: - void cb_simplesysefftype_i(Fl_Choice*, void*); - static void cb_simplesysefftype(Fl_Choice*, void*); - static Fl_Menu_Item menu_simplesysefftype[]; -public: - Fl_Group *simplesyseffectuigroup; - SimpleEffUI *simplesyseffectui; -private: - void cb_Send1_i(Fl_Button*, void*); - static void cb_Send1(Fl_Button*, void*); - void cb_P2_i(Fl_Button*, void*); - static void cb_P2(Fl_Button*, void*); -public: - Fl_Counter *simpleinseffnocounter; -private: - void cb_simpleinseffnocounter_i(Fl_Counter*, void*); - static void cb_simpleinseffnocounter(Fl_Counter*, void*); -public: - Fl_Choice *simpleinsefftype; -private: - void cb_simpleinsefftype_i(Fl_Choice*, void*); - static void cb_simpleinsefftype(Fl_Choice*, void*); - static Fl_Menu_Item menu_simpleinsefftype[]; -public: - Fl_Group *simpleinseffectuigroup; - SimpleEffUI *simpleinseffectui; - Fl_Choice *simpleinseffpart; -private: - void cb_simpleinseffpart_i(Fl_Choice*, void*); - static void cb_simpleinseffpart(Fl_Choice*, void*); - void cb_P3_i(Fl_Button*, void*); - static void cb_P3(Fl_Button*, void*); -public: - WidgetPDial *simplemastervolumedial; -private: - void cb_simplemastervolumedial_i(WidgetPDial*, void*); - static void cb_simplemastervolumedial(WidgetPDial*, void*); -public: - Fl_Counter *simplemasterkeyshiftcounter; -private: - void cb_simplemasterkeyshiftcounter_i(Fl_Counter*, void*); - static void cb_simplemasterkeyshiftcounter(Fl_Counter*, void*); - void cb_Stop_i(Fl_Button*, void*); - static void cb_Stop(Fl_Button*, void*); - void cb_Reset_i(Fl_Button*, void*); - static void cb_Reset(Fl_Button*, void*); -public: - WidgetPDial *simpleglobalfinedetuneslider; -private: - void cb_simpleglobalfinedetuneslider_i(WidgetPDial*, void*); - static void cb_simpleglobalfinedetuneslider(WidgetPDial*, void*); -public: - Fl_Counter *simplenpartcounter; -private: - void cb_simplenpartcounter_i(Fl_Counter*, void*); - static void cb_simplenpartcounter(Fl_Counter*, void*); - void cb_Keyb_i(Fl_Counter*, void*); - static void cb_Keyb(Fl_Counter*, void*); -public: - Fl_Double_Window *selectuiwindow; -private: - void cb_selectuiwindow_i(Fl_Double_Window*, void*); - static void cb_selectuiwindow(Fl_Double_Window*, void*); - void cb_Advanced_i(Fl_Button*, void*); - static void cb_Advanced(Fl_Button*, void*); - void cb_Beginner_i(Fl_Button*, void*); - static void cb_Beginner(Fl_Button*, void*); -public: - void updatesendwindow(); - void updatepanel(); - void setfilelabel(const char *filename); - MasterUI(Master *master_,int *exitprogram_); - ~MasterUI(); - void showUI(); - void simplerefresh(); - void do_new_master(); - void do_load_master(const char* file = NULL); - void do_save_master(const char* file = NULL); - void refresh_master_ui(); -private: - Master *master; - MicrotonalUI *microtonalui; - SeqUI *sequi; - BankUI *bankui; - int ninseff,npart; - int nsyseff; - int *exitprogram; - SysEffSend *syseffsend[NUM_SYS_EFX][NUM_SYS_EFX]; - VirKeyboard *virkeyboard; - ConfigUI *configui; - int swapefftype; - char masterwindowlabel[100]; - Panellistitem *panellistitem[NUM_MIDI_PARTS]; -}; -#endif diff --git a/plugins/zynaddsubfx/src/UI/MicrotonalUI.cc b/plugins/zynaddsubfx/src/UI/MicrotonalUI.cc deleted file mode 100644 index a58bbf021..000000000 --- a/plugins/zynaddsubfx/src/UI/MicrotonalUI.cc +++ /dev/null @@ -1,463 +0,0 @@ -// generated by Fast Light User Interface Designer (fluid) version 1.0300 - -#include "MicrotonalUI.h" -//Copyright (c) 2002-2005 Nasca Octavian Paul -//License: GNU GPL version 2 or later - -void MicrotonalUI::cb_Invert_i(Fl_Check_Button* o, void*) { - microtonal->Pinvertupdown=(int) o->value(); -if (microtonal->Pinvertupdown==0) centerinvertcounter->deactivate(); - else centerinvertcounter->activate(); -} -void MicrotonalUI::cb_Invert(Fl_Check_Button* o, void* v) { - ((MicrotonalUI*)(o->parent()->parent()->user_data()))->cb_Invert_i(o,v); -} - -void MicrotonalUI::cb_centerinvertcounter_i(Fl_Counter* o, void*) { - microtonal->Pinvertupdowncenter=(int) o->value(); -} -void MicrotonalUI::cb_centerinvertcounter(Fl_Counter* o, void* v) { - ((MicrotonalUI*)(o->parent()->parent()->user_data()))->cb_centerinvertcounter_i(o,v); -} - -void MicrotonalUI::cb_applybutton_i(Fl_Button*, void*) { - apply(); -} -void MicrotonalUI::cb_applybutton(Fl_Button* o, void* v) { - ((MicrotonalUI*)(o->parent()->parent()->user_data()))->cb_applybutton_i(o,v); -} - -void MicrotonalUI::cb_octavesizeoutput_i(Fl_Value_Output* o, void*) { - o->value(microtonal->getoctavesize()); -} -void MicrotonalUI::cb_octavesizeoutput(Fl_Value_Output* o, void* v) { - ((MicrotonalUI*)(o->parent()->parent()->user_data()))->cb_octavesizeoutput_i(o,v); -} - -void MicrotonalUI::cb_nameinput_i(Fl_Input* o, void*) { - snprintf((char *)microtonal->Pname,MICROTONAL_MAX_NAME_LEN,"%s",o->value()); -} -void MicrotonalUI::cb_nameinput(Fl_Input* o, void* v) { - ((MicrotonalUI*)(o->parent()->parent()->user_data()))->cb_nameinput_i(o,v); -} - -void MicrotonalUI::cb_commentinput_i(Fl_Input* o, void*) { - snprintf((char *)microtonal->Pcomment,MICROTONAL_MAX_NAME_LEN,"%s",o->value()); -} -void MicrotonalUI::cb_commentinput(Fl_Input* o, void* v) { - ((MicrotonalUI*)(o->parent()->parent()->user_data()))->cb_commentinput_i(o,v); -} - -void MicrotonalUI::cb_Shift_i(Fl_Counter* o, void*) { - microtonal->Pscaleshift=(int) o->value()+64; -} -void MicrotonalUI::cb_Shift(Fl_Counter* o, void* v) { - ((MicrotonalUI*)(o->parent()->parent()->user_data()))->cb_Shift_i(o,v); -} - -void MicrotonalUI::cb_Import_i(Fl_Button*, void*) { - const char *filename; -filename=fl_file_chooser("Open:","(*.scl)",NULL,0); -if (filename==NULL) return; -int result=microtonal->loadscl(filename); -if (result==0) { - updateTuningsInput(); - nameinput->cut(0,nameinput->maximum_size()); - nameinput->insert((char *)microtonal->Pname); - nameinput->position(0); - commentinput->cut(0,commentinput->maximum_size()); - commentinput->insert((char *)microtonal->Pname); - commentinput->position(0); - tuningsinput->position(0); - octavesizeoutput->do_callback(); - } else { - fl_alert("Error: Could not load the file."); - }; -} -void MicrotonalUI::cb_Import(Fl_Button* o, void* v) { - ((MicrotonalUI*)(o->parent()->parent()->user_data()))->cb_Import_i(o,v); -} - -void MicrotonalUI::cb_firstnotecounter_i(Fl_Counter* o, void*) { - microtonal->Pfirstkey=(int) o->value(); -} -void MicrotonalUI::cb_firstnotecounter(Fl_Counter* o, void* v) { - ((MicrotonalUI*)(o->parent()->parent()->parent()->user_data()))->cb_firstnotecounter_i(o,v); -} - -void MicrotonalUI::cb_lastnotecounter_i(Fl_Counter* o, void*) { - microtonal->Plastkey=(int) o->value(); -} -void MicrotonalUI::cb_lastnotecounter(Fl_Counter* o, void* v) { - ((MicrotonalUI*)(o->parent()->parent()->parent()->user_data()))->cb_lastnotecounter_i(o,v); -} - -void MicrotonalUI::cb_middlenotecounter_i(Fl_Counter* o, void*) { - microtonal->Pmiddlenote=(int) o->value(); -} -void MicrotonalUI::cb_middlenotecounter(Fl_Counter* o, void* v) { - ((MicrotonalUI*)(o->parent()->parent()->parent()->user_data()))->cb_middlenotecounter_i(o,v); -} - -void MicrotonalUI::cb_mapsizeoutput_i(Fl_Value_Output* o, void*) { - o->value(microtonal->Pmapsize); -} -void MicrotonalUI::cb_mapsizeoutput(Fl_Value_Output* o, void* v) { - ((MicrotonalUI*)(o->parent()->parent()->parent()->user_data()))->cb_mapsizeoutput_i(o,v); -} - -void MicrotonalUI::cb_mappingenabledbutton_i(Fl_Check_Button* o, void*) { - int x=(int) o->value(); -microtonal->Pmappingenabled=x; -if (x==0) keymappinggroup->deactivate(); - else keymappinggroup->activate(); -o->show(); -} -void MicrotonalUI::cb_mappingenabledbutton(Fl_Check_Button* o, void* v) { - ((MicrotonalUI*)(o->parent()->parent()->user_data()))->cb_mappingenabledbutton_i(o,v); -} - -void MicrotonalUI::cb_Import1_i(Fl_Button*, void*) { - const char *filename; -filename=fl_file_chooser("Open:","(*.kbm)",NULL,0); -if (filename==NULL) return; -int result=microtonal->loadkbm(filename); -if (result==0) { - updateMappingInput(); - mappinginput->position(0); - mapsizeoutput->do_callback(); - firstnotecounter->value(microtonal->Pfirstkey); - lastnotecounter->value(microtonal->Plastkey); - middlenotecounter->value(microtonal->Pmiddlenote); - mapsizeoutput->do_callback(); - mappingenabledbutton->value(microtonal->Pmappingenabled); - mappingenabledbutton->do_callback(); - afreqinput->value(microtonal->PAfreq); - anotecounter->value(microtonal->PAnote); - anotecounter->do_callback(); - } else { - fl_alert("Error: Could not load the file."); - }; -} -void MicrotonalUI::cb_Import1(Fl_Button* o, void* v) { - ((MicrotonalUI*)(o->parent()->parent()->user_data()))->cb_Import1_i(o,v); -} - -void MicrotonalUI::cb_anotecounter_i(Fl_Counter* o, void*) { - microtonal->PAnote=(int) o->value(); -if (microtonal->getnotefreq(microtonal->PAnote,0)<0.0) o->textcolor(FL_RED); - else o->textcolor(FL_BLACK); - -o->redraw(); -} -void MicrotonalUI::cb_anotecounter(Fl_Counter* o, void* v) { - ((MicrotonalUI*)(o->parent()->parent()->user_data()))->cb_anotecounter_i(o,v); -} - -void MicrotonalUI::cb_afreqinput_i(Fl_Value_Input* o, void*) { - microtonal->PAfreq=o->value(); -} -void MicrotonalUI::cb_afreqinput(Fl_Value_Input* o, void* v) { - ((MicrotonalUI*)(o->parent()->parent()->user_data()))->cb_afreqinput_i(o,v); -} - -void MicrotonalUI::cb_Close_i(Fl_Button*, void*) { - microtonaluiwindow->hide(); -} -void MicrotonalUI::cb_Close(Fl_Button* o, void* v) { - ((MicrotonalUI*)(o->parent()->user_data()))->cb_Close_i(o,v); -} - -void MicrotonalUI::cb_Enable_i(Fl_Check_Button* o, void*) { - microtonal->Penabled=(int) o->value(); -if (microtonal->Penabled==0) microtonalgroup->deactivate(); - else microtonalgroup->activate(); -} -void MicrotonalUI::cb_Enable(Fl_Check_Button* o, void* v) { - ((MicrotonalUI*)(o->parent()->user_data()))->cb_Enable_i(o,v); -} - -Fl_Double_Window* MicrotonalUI::make_window() { - { microtonaluiwindow = new Fl_Double_Window(405, 450, "Scales"); - microtonaluiwindow->user_data((void*)(this)); - { Fl_Group* o = new Fl_Group(249, 2, 155, 45); - o->tooltip("Center where the note\'s freqs. are turned upside-down"); - o->box(FL_ENGRAVED_FRAME); - { Fl_Check_Button* o = new Fl_Check_Button(254, 13, 55, 30, "Invert keys"); - o->tooltip("Turn upside-down the note frequencies"); - o->down_box(FL_DOWN_BOX); - o->labelfont(1); - o->labelsize(11); - o->callback((Fl_Callback*)cb_Invert); - o->align(Fl_Align(132|FL_ALIGN_INSIDE)); - o->value(microtonal->Pinvertupdown); - } // Fl_Check_Button* o - { Fl_Counter* o = centerinvertcounter = new Fl_Counter(319, 13, 80, 20, "Center"); - centerinvertcounter->labelfont(1); - centerinvertcounter->labelsize(11); - centerinvertcounter->minimum(0); - centerinvertcounter->maximum(127); - centerinvertcounter->step(1); - centerinvertcounter->textfont(1); - centerinvertcounter->callback((Fl_Callback*)cb_centerinvertcounter); - centerinvertcounter->align(Fl_Align(130)); - o->lstep(microtonal->getoctavesize()); - o->value(microtonal->Pinvertupdowncenter); - if (microtonal->Pinvertupdown==0) o->deactivate(); - } // Fl_Counter* centerinvertcounter - o->end(); - } // Fl_Group* o - { Fl_Group* o = microtonalgroup = new Fl_Group(3, 49, 402, 398); - microtonalgroup->box(FL_ENGRAVED_FRAME); - { applybutton = new Fl_Button(8, 413, 107, 28, "Retune"); - applybutton->tooltip("Retune the synth accorging to the inputs from \"Tunnings\" and \"Keyboard Map\ -pings\""); - applybutton->box(FL_THIN_UP_BOX); - applybutton->labeltype(FL_EMBOSSED_LABEL); - applybutton->labelfont(1); - applybutton->labelsize(13); - applybutton->callback((Fl_Callback*)cb_applybutton); - } // Fl_Button* applybutton - { Fl_Value_Output* o = octavesizeoutput = new Fl_Value_Output(150, 423, 35, 17, "nts./oct."); - octavesizeoutput->tooltip("Notes/Octave"); - octavesizeoutput->labelsize(10); - octavesizeoutput->maximum(500); - octavesizeoutput->step(1); - octavesizeoutput->value(12); - octavesizeoutput->textfont(1); - octavesizeoutput->callback((Fl_Callback*)cb_octavesizeoutput); - octavesizeoutput->align(Fl_Align(FL_ALIGN_TOP_LEFT)); - o->value(microtonal->getoctavesize()); - } // Fl_Value_Output* octavesizeoutput - { Fl_Input* o = nameinput = new Fl_Input(8, 64, 285, 25, "Name:"); - nameinput->labelfont(1); - nameinput->labelsize(11); - nameinput->callback((Fl_Callback*)cb_nameinput); - nameinput->align(Fl_Align(FL_ALIGN_TOP_LEFT)); - o->insert((char *)microtonal->Pname); - } // Fl_Input* nameinput - { tuningsinput = new Fl_Input(8, 144, 182, 264, "Tunings:"); - tuningsinput->type(4); - tuningsinput->labelfont(1); - tuningsinput->labelsize(11); - tuningsinput->align(Fl_Align(FL_ALIGN_TOP_LEFT)); - tuningsinput->when(FL_WHEN_NEVER); - updateTuningsInput(); - } // Fl_Input* tuningsinput - { Fl_Input* o = commentinput = new Fl_Input(8, 104, 391, 25, "Comment:"); - commentinput->labelfont(1); - commentinput->labelsize(11); - commentinput->callback((Fl_Callback*)cb_commentinput); - commentinput->align(Fl_Align(FL_ALIGN_TOP_LEFT)); - o->insert((char *)microtonal->Pcomment); - } // Fl_Input* commentinput - { Fl_Counter* o = new Fl_Counter(313, 69, 70, 20, "Shift"); - o->type(1); - o->labelsize(11); - o->minimum(-63); - o->maximum(64); - o->step(1); - o->textfont(1); - o->callback((Fl_Callback*)cb_Shift); - o->align(Fl_Align(FL_ALIGN_TOP)); - o->value(microtonal->Pscaleshift-64); - } // Fl_Counter* o - { Fl_Button* o = new Fl_Button(243, 411, 84, 15, "Import .SCL file"); - o->tooltip("Inport Scala .scl file (tunnings)"); - o->box(FL_THIN_UP_BOX); - o->labelfont(1); - o->labelsize(10); - o->callback((Fl_Callback*)cb_Import); - } // Fl_Button* o - { keymappinggroup = new Fl_Group(193, 144, 206, 264, "Keyboard Mapping"); - keymappinggroup->box(FL_ENGRAVED_BOX); - keymappinggroup->labelfont(1); - keymappinggroup->labelsize(11); - { mappinginput = new Fl_Input(250, 147, 146, 258); - mappinginput->type(4); - mappinginput->labelfont(1); - mappinginput->labelsize(11); - mappinginput->align(Fl_Align(FL_ALIGN_TOP_LEFT)); - mappinginput->when(FL_WHEN_NEVER); - updateMappingInput(); - } // Fl_Input* mappinginput - { Fl_Counter* o = firstnotecounter = new Fl_Counter(199, 195, 42, 18, "First note"); - firstnotecounter->tooltip("First MIDI note number"); - firstnotecounter->type(1); - firstnotecounter->labelsize(10); - firstnotecounter->minimum(0); - firstnotecounter->maximum(127); - firstnotecounter->step(1); - firstnotecounter->textfont(1); - firstnotecounter->textsize(11); - firstnotecounter->callback((Fl_Callback*)cb_firstnotecounter); - firstnotecounter->align(Fl_Align(FL_ALIGN_TOP_LEFT)); - o->value(microtonal->Pfirstkey); - } // Fl_Counter* firstnotecounter - { Fl_Counter* o = lastnotecounter = new Fl_Counter(199, 225, 42, 18, "Last note"); - lastnotecounter->tooltip("Last MIDI note number"); - lastnotecounter->type(1); - lastnotecounter->labelsize(10); - lastnotecounter->minimum(0); - lastnotecounter->maximum(127); - lastnotecounter->step(1); - lastnotecounter->value(127); - lastnotecounter->textfont(1); - lastnotecounter->textsize(11); - lastnotecounter->callback((Fl_Callback*)cb_lastnotecounter); - lastnotecounter->align(Fl_Align(FL_ALIGN_TOP_LEFT)); - o->value(microtonal->Plastkey); - } // Fl_Counter* lastnotecounter - { Fl_Counter* o = middlenotecounter = new Fl_Counter(199, 267, 42, 18, "Midle note"); - middlenotecounter->tooltip("Midle note (where scale degree 0 is mapped to)"); - middlenotecounter->type(1); - middlenotecounter->labelsize(10); - middlenotecounter->minimum(0); - middlenotecounter->maximum(127); - middlenotecounter->step(1); - middlenotecounter->value(60); - middlenotecounter->textfont(1); - middlenotecounter->textsize(11); - middlenotecounter->callback((Fl_Callback*)cb_middlenotecounter); - middlenotecounter->align(Fl_Align(FL_ALIGN_TOP_LEFT)); - o->value(microtonal->Pmiddlenote); - } // Fl_Counter* middlenotecounter - { Fl_Value_Output* o = mapsizeoutput = new Fl_Value_Output(201, 382, 44, 20, "Map Size"); - mapsizeoutput->labelsize(10); - mapsizeoutput->maximum(500); - mapsizeoutput->step(1); - mapsizeoutput->value(12); - mapsizeoutput->textfont(1); - mapsizeoutput->callback((Fl_Callback*)cb_mapsizeoutput); - mapsizeoutput->align(Fl_Align(FL_ALIGN_TOP_LEFT)); - o->value(microtonal->Pmapsize); - } // Fl_Value_Output* mapsizeoutput - keymappinggroup->end(); - } // Fl_Group* keymappinggroup - { Fl_Check_Button* o = mappingenabledbutton = new Fl_Check_Button(198, 150, 48, 21, "ON"); - mappingenabledbutton->tooltip("Enable the Mapping (otherwise the mapping is linear)"); - mappingenabledbutton->box(FL_FLAT_BOX); - mappingenabledbutton->down_box(FL_DOWN_BOX); - mappingenabledbutton->labelfont(1); - mappingenabledbutton->callback((Fl_Callback*)cb_mappingenabledbutton); - o->value(microtonal->Pmappingenabled); - if (microtonal->Pmappingenabled==0) keymappinggroup->deactivate(); - } // Fl_Check_Button* mappingenabledbutton - { Fl_Button* o = new Fl_Button(243, 428, 84, 16, "Import .kbm file"); - o->tooltip("Inport Scala .kbm file (keyboard mapping)"); - o->box(FL_THIN_UP_BOX); - o->labelfont(1); - o->labelsize(10); - o->callback((Fl_Callback*)cb_Import1); - } // Fl_Button* o - if (microtonal->Penabled==0) o->deactivate(); - microtonalgroup->end(); - } // Fl_Group* microtonalgroup - { Fl_Group* o = new Fl_Group(108, 2, 140, 45); - o->box(FL_ENGRAVED_FRAME); - { Fl_Counter* o = anotecounter = new Fl_Counter(173, 17, 65, 20, "\"A\" Note"); - anotecounter->tooltip("The \"A\" note (the reference note for which freq. (\"A\" freq) is given)"); - anotecounter->labelfont(1); - anotecounter->labelsize(10); - anotecounter->minimum(0); - anotecounter->maximum(127); - anotecounter->step(1); - anotecounter->value(69); - anotecounter->textfont(1); - anotecounter->textsize(10); - anotecounter->callback((Fl_Callback*)cb_anotecounter); - anotecounter->align(Fl_Align(129)); - o->lstep(12); - o->value(microtonal->PAnote); - } // Fl_Counter* anotecounter - { Fl_Value_Input* o = afreqinput = new Fl_Value_Input(118, 17, 45, 20, "\"A\" Freq."); - afreqinput->tooltip("The freq. of \"A\" note (default=440.0)"); - afreqinput->labelfont(1); - afreqinput->labelsize(10); - afreqinput->minimum(1); - afreqinput->maximum(20000); - afreqinput->step(0.001); - afreqinput->value(440); - afreqinput->textfont(1); - afreqinput->textsize(10); - afreqinput->callback((Fl_Callback*)cb_afreqinput); - afreqinput->align(Fl_Align(FL_ALIGN_TOP)); - o->value(microtonal->PAfreq); - } // Fl_Value_Input* afreqinput - o->end(); - } // Fl_Group* o - { Fl_Button* o = new Fl_Button(333, 413, 67, 28, "Close"); - o->box(FL_THIN_UP_BOX); - o->callback((Fl_Callback*)cb_Close); - } // Fl_Button* o - { Fl_Check_Button* o = new Fl_Check_Button(3, 3, 102, 45, "Enable Microtonal"); - o->box(FL_PLASTIC_UP_BOX); - o->down_box(FL_DOWN_BOX); - o->labelfont(1); - o->labelsize(11); - o->callback((Fl_Callback*)cb_Enable); - o->align(Fl_Align(132|FL_ALIGN_INSIDE)); - o->value(microtonal->Penabled); - } // Fl_Check_Button* o - microtonaluiwindow->end(); - } // Fl_Double_Window* microtonaluiwindow - return microtonaluiwindow; -} - -void MicrotonalUI::updateTuningsInput() { - char *tmpbuf=new char[100]; - - tuningsinput->cut(0,tuningsinput->maximum_size()); - - for (int i=0;igetoctavesize();i++){ - if (i!=0) tuningsinput->insert("\n"); - microtonal->tuningtoline(i,tmpbuf,100); - tuningsinput->insert(tmpbuf); - }; - - delete []tmpbuf; -} - -void MicrotonalUI::updateMappingInput() { - char *tmpbuf=new char[100]; - - mappinginput->cut(0,tuningsinput->maximum_size()); - - for (int i=0;iPmapsize;i++){ - if (i!=0) mappinginput->insert("\n"); - if ((microtonal->Pmapping[i])==-1) - snprintf(tmpbuf,100,"x"); - else snprintf(tmpbuf,100,"%d",microtonal->Pmapping[i]); - mappinginput->insert(tmpbuf); - }; - - delete []tmpbuf; -} - -MicrotonalUI::MicrotonalUI(Microtonal *microtonal_) { - microtonal=microtonal_; - - make_window(); -} - -MicrotonalUI::~MicrotonalUI() { - microtonaluiwindow->hide(); - delete(microtonaluiwindow); -} - -void MicrotonalUI::show() { - microtonaluiwindow->show(); -} - -void MicrotonalUI::apply() { - int err=microtonal->texttotunings(tuningsinput->value()); - if (err>=0) fl_alert("Parse Error: The input may contain only numbers (like 232.59)\n or divisions (like 121/64)."); - if (err==-2) fl_alert("Parse Error: The input is empty."); - octavesizeoutput->do_callback(); - - microtonal->texttomapping(mappinginput->value()); - mapsizeoutput->do_callback(); - anotecounter->do_callback(); - - //applybutton->color(FL_GRAY); -} diff --git a/plugins/zynaddsubfx/src/UI/MicrotonalUI.fl b/plugins/zynaddsubfx/src/UI/MicrotonalUI.fl deleted file mode 100644 index adc08b551..000000000 --- a/plugins/zynaddsubfx/src/UI/MicrotonalUI.fl +++ /dev/null @@ -1,270 +0,0 @@ -# data file for the Fltk User Interface Designer (fluid) -version 1.0106 -header_name {.h} -code_name {.cc} -decl {//Copyright (c) 2002-2005 Nasca Octavian Paul} {} - -decl {//License: GNU GPL version 2 or later} {} - -decl {\#include } {public -} - -decl {\#include } {public -} - -decl {\#include } {public -} - -decl {\#include } {public -} - -decl {\#include } {public -} - -decl {\#include "../Misc/Microtonal.h"} {public -} - -class MicrotonalUI {} { - Function {make_window()} {} { - Fl_Window microtonaluiwindow { - label Scales - xywh {99 164 405 450} type Double hide - } { - Fl_Group {} { - tooltip {Center where the note's freqs. are turned upside-down} xywh {249 2 155 45} box ENGRAVED_FRAME - } { - Fl_Check_Button {} { - label {Invert keys} - callback {microtonal->Pinvertupdown=(int) o->value(); -if (microtonal->Pinvertupdown==0) centerinvertcounter->deactivate(); - else centerinvertcounter->activate();} - tooltip {Turn upside-down the note frequencies} xywh {254 13 55 30} down_box DOWN_BOX labelfont 1 labelsize 11 align 148 - code0 {o->value(microtonal->Pinvertupdown);} - } - Fl_Counter centerinvertcounter { - label Center - callback {microtonal->Pinvertupdowncenter=(int) o->value();} - xywh {319 13 80 20} labelfont 1 labelsize 11 align 130 minimum 0 maximum 127 step 1 textfont 1 - code0 {o->lstep(microtonal->getoctavesize());} - code1 {o->value(microtonal->Pinvertupdowncenter);} - code2 {if (microtonal->Pinvertupdown==0) o->deactivate();} - } - } - Fl_Group microtonalgroup {selected - xywh {3 49 402 398} box ENGRAVED_FRAME - code0 {if (microtonal->Penabled==0) o->deactivate();} - } { - Fl_Button applybutton { - label Retune - callback {apply();} - tooltip {Retune the synth accorging to the inputs from "Tunnings" and "Keyboard Mappings"} xywh {8 413 107 28} box THIN_UP_BOX labeltype EMBOSSED_LABEL labelfont 1 labelsize 13 - } - Fl_Value_Output octavesizeoutput { - label {nts./oct.} - callback {o->value(microtonal->getoctavesize());} - tooltip {Notes/Octave} xywh {150 423 35 17} labelsize 10 align 5 maximum 500 step 1 value 12 textfont 1 - code0 {o->value(microtonal->getoctavesize());} - } - Fl_Input nameinput { - label {Name:} - callback {snprintf((char *)microtonal->Pname,MICROTONAL_MAX_NAME_LEN,"%s",o->value());} - xywh {8 64 285 25} labelfont 1 labelsize 11 align 5 - code0 {o->insert((char *)microtonal->Pname);} - } - Fl_Input tuningsinput { - label {Tunings:} - xywh {8 144 182 264} type Multiline labelfont 1 labelsize 11 align 5 when 2 - code0 {updateTuningsInput();} - } - Fl_Input commentinput { - label {Comment:} - callback {snprintf((char *)microtonal->Pcomment,MICROTONAL_MAX_NAME_LEN,"%s",o->value());} - xywh {8 104 391 25} labelfont 1 labelsize 11 align 5 - code0 {o->insert((char *)microtonal->Pcomment);} - } - Fl_Counter {} { - label Shift - callback {microtonal->Pscaleshift=(int) o->value()+64;} - xywh {313 69 70 20} type Simple labelsize 11 align 1 minimum -63 maximum 64 step 1 textfont 1 - code0 {o->value(microtonal->Pscaleshift-64);} - } - Fl_Button {} { - label {Import .SCL file} - callback {const char *filename; -filename=fl_file_chooser("Open:","(*.scl)",NULL,0); -if (filename==NULL) return; -int result=microtonal->loadscl(filename); -if (result==0) { - updateTuningsInput(); - nameinput->cut(0,nameinput->maximum_size()); - nameinput->insert((char *)microtonal->Pname); - nameinput->position(0); - commentinput->cut(0,commentinput->maximum_size()); - commentinput->insert((char *)microtonal->Pname); - commentinput->position(0); - tuningsinput->position(0); - octavesizeoutput->do_callback(); - } else { - fl_alert("Error: Could not load the file."); - };} - tooltip {Inport Scala .scl file (tunnings)} xywh {243 411 84 15} box THIN_UP_BOX labelfont 1 labelsize 10 - } - Fl_Group keymappinggroup { - label {Keyboard Mapping} open - xywh {193 144 206 264} box ENGRAVED_BOX labelfont 1 labelsize 11 - } { - Fl_Input mappinginput { - xywh {250 147 146 258} type Multiline labelfont 1 labelsize 11 align 5 when 2 - code0 {updateMappingInput();} - } - Fl_Counter firstnotecounter { - label {First note} - callback {microtonal->Pfirstkey=(int) o->value();} - tooltip {First MIDI note number} xywh {199 195 42 18} type Simple labelsize 10 align 5 minimum 0 maximum 127 step 1 textfont 1 textsize 11 - code0 {o->value(microtonal->Pfirstkey);} - } - Fl_Counter lastnotecounter { - label {Last note} - callback {microtonal->Plastkey=(int) o->value();} - tooltip {Last MIDI note number} xywh {199 225 42 18} type Simple labelsize 10 align 5 minimum 0 maximum 127 step 1 value 127 textfont 1 textsize 11 - code0 {o->value(microtonal->Plastkey);} - } - Fl_Counter middlenotecounter { - label {Midle note} - callback {microtonal->Pmiddlenote=(int) o->value();} - tooltip {Midle note (where scale degree 0 is mapped to)} xywh {199 267 42 18} type Simple labelsize 10 align 5 minimum 0 maximum 127 step 1 value 60 textfont 1 textsize 11 - code0 {o->value(microtonal->Pmiddlenote);} - } - Fl_Value_Output mapsizeoutput { - label {Map Size} - callback {o->value(microtonal->Pmapsize);} - xywh {201 382 44 20} labelsize 10 align 5 maximum 500 step 1 value 12 textfont 1 - code0 {o->value(microtonal->Pmapsize);} - } - } - Fl_Check_Button mappingenabledbutton { - label ON - callback {int x=(int) o->value(); -microtonal->Pmappingenabled=x; -if (x==0) keymappinggroup->deactivate(); - else keymappinggroup->activate(); -o->show();} - tooltip {Enable the Mapping (otherwise the mapping is linear)} xywh {198 150 48 21} box FLAT_BOX down_box DOWN_BOX labelfont 1 - code0 {o->value(microtonal->Pmappingenabled);} - code1 {if (microtonal->Pmappingenabled==0) keymappinggroup->deactivate();} - } - Fl_Button {} { - label {Import .kbm file} - callback {const char *filename; -filename=fl_file_chooser("Open:","(*.kbm)",NULL,0); -if (filename==NULL) return; -int result=microtonal->loadkbm(filename); -if (result==0) { - updateMappingInput(); - mappinginput->position(0); - mapsizeoutput->do_callback(); - firstnotecounter->value(microtonal->Pfirstkey); - lastnotecounter->value(microtonal->Plastkey); - middlenotecounter->value(microtonal->Pmiddlenote); - mapsizeoutput->do_callback(); - mappingenabledbutton->value(microtonal->Pmappingenabled); - mappingenabledbutton->do_callback(); - afreqinput->value(microtonal->PAfreq); - anotecounter->value(microtonal->PAnote); - anotecounter->do_callback(); - } else { - fl_alert("Error: Could not load the file."); - };} - tooltip {Inport Scala .kbm file (keyboard mapping)} xywh {243 428 84 16} box THIN_UP_BOX labelfont 1 labelsize 10 - } - } - Fl_Group {} { - xywh {108 2 140 45} box ENGRAVED_FRAME - } { - Fl_Counter anotecounter { - label {"A" Note} - callback {microtonal->PAnote=(int) o->value(); -if (microtonal->getnotefreq(microtonal->PAnote,0)<0.0) o->textcolor(FL_RED); - else o->textcolor(FL_BLACK); - -o->redraw();} - tooltip {The "A" note (the reference note for which freq. ("A" freq) is given)} xywh {173 17 65 20} labelfont 1 labelsize 10 align 129 minimum 0 maximum 127 step 1 value 69 textfont 1 textsize 10 - code0 {o->lstep(12);} - code1 {o->value(microtonal->PAnote);} - } - Fl_Value_Input afreqinput { - label {"A" Freq.} - callback {microtonal->PAfreq=o->value();} - tooltip {The freq. of "A" note (default=440.0)} xywh {118 17 45 20} labelfont 1 labelsize 10 align 1 minimum 1 maximum 20000 step 0.001 value 440 textfont 1 textsize 10 - code0 {o->value(microtonal->PAfreq);} - } - } - Fl_Button {} { - label Close - callback {microtonaluiwindow->hide();} - xywh {333 413 67 28} box THIN_UP_BOX - } - Fl_Check_Button {} { - label {Enable Microtonal} - callback {microtonal->Penabled=(int) o->value(); -if (microtonal->Penabled==0) microtonalgroup->deactivate(); - else microtonalgroup->activate();} - xywh {3 3 102 45} box PLASTIC_UP_BOX down_box DOWN_BOX labelfont 1 labelsize 11 align 148 - code0 {o->value(microtonal->Penabled);} - } - } - } - Function {updateTuningsInput()} {} { - code {char *tmpbuf=new char[100]; - -tuningsinput->cut(0,tuningsinput->maximum_size()); - -for (int i=0;igetoctavesize();i++){ - if (i!=0) tuningsinput->insert("\\n"); - microtonal->tuningtoline(i,tmpbuf,100); - tuningsinput->insert(tmpbuf); -}; - -delete []tmpbuf;} {} - } - Function {updateMappingInput()} {} { - code {char *tmpbuf=new char[100]; - -mappinginput->cut(0,tuningsinput->maximum_size()); - -for (int i=0;iPmapsize;i++){ - if (i!=0) mappinginput->insert("\\n"); - if ((microtonal->Pmapping[i])==-1) - snprintf(tmpbuf,100,"x"); - else snprintf(tmpbuf,100,"%d",microtonal->Pmapping[i]); - mappinginput->insert(tmpbuf); -}; - -delete []tmpbuf;} {} - } - Function {MicrotonalUI(Microtonal *microtonal_)} {} { - code {microtonal=microtonal_; - -make_window();} {} - } - Function {~MicrotonalUI()} {} { - code {microtonaluiwindow->hide(); -delete(microtonaluiwindow);} {} - } - Function {show()} {} { - code {microtonaluiwindow->show();} {} - } - Function {apply()} {} { - code {int err=microtonal->texttotunings(tuningsinput->value()); -if (err>=0) fl_alert("Parse Error: The input may contain only numbers (like 232.59)\\n or divisions (like 121/64)."); -if (err==-2) fl_alert("Parse Error: The input is empty."); -octavesizeoutput->do_callback(); - -microtonal->texttomapping(mappinginput->value()); -mapsizeoutput->do_callback(); -anotecounter->do_callback(); - -//applybutton->color(FL_GRAY);} {} - } - decl {Microtonal *microtonal;} {} -} diff --git a/plugins/zynaddsubfx/src/UI/MicrotonalUI.h b/plugins/zynaddsubfx/src/UI/MicrotonalUI.h deleted file mode 100644 index 3668b41e5..000000000 --- a/plugins/zynaddsubfx/src/UI/MicrotonalUI.h +++ /dev/null @@ -1,112 +0,0 @@ -// generated by Fast Light User Interface Designer (fluid) version 1.0300 - -#ifndef MicrotonalUI_h -#define MicrotonalUI_h -#include -#include -#include -#include -#include -#include -#include "../Misc/Microtonal.h" -#include -#include -#include -#include -#include -#include -#include -#include - -class MicrotonalUI { -public: - Fl_Double_Window* make_window(); - Fl_Double_Window *microtonaluiwindow; -private: - void cb_Invert_i(Fl_Check_Button*, void*); - static void cb_Invert(Fl_Check_Button*, void*); -public: - Fl_Counter *centerinvertcounter; -private: - void cb_centerinvertcounter_i(Fl_Counter*, void*); - static void cb_centerinvertcounter(Fl_Counter*, void*); -public: - Fl_Group *microtonalgroup; - Fl_Button *applybutton; -private: - void cb_applybutton_i(Fl_Button*, void*); - static void cb_applybutton(Fl_Button*, void*); -public: - Fl_Value_Output *octavesizeoutput; -private: - void cb_octavesizeoutput_i(Fl_Value_Output*, void*); - static void cb_octavesizeoutput(Fl_Value_Output*, void*); -public: - Fl_Input *nameinput; -private: - void cb_nameinput_i(Fl_Input*, void*); - static void cb_nameinput(Fl_Input*, void*); -public: - Fl_Input *tuningsinput; - Fl_Input *commentinput; -private: - void cb_commentinput_i(Fl_Input*, void*); - static void cb_commentinput(Fl_Input*, void*); - void cb_Shift_i(Fl_Counter*, void*); - static void cb_Shift(Fl_Counter*, void*); - void cb_Import_i(Fl_Button*, void*); - static void cb_Import(Fl_Button*, void*); -public: - Fl_Group *keymappinggroup; - Fl_Input *mappinginput; - Fl_Counter *firstnotecounter; -private: - void cb_firstnotecounter_i(Fl_Counter*, void*); - static void cb_firstnotecounter(Fl_Counter*, void*); -public: - Fl_Counter *lastnotecounter; -private: - void cb_lastnotecounter_i(Fl_Counter*, void*); - static void cb_lastnotecounter(Fl_Counter*, void*); -public: - Fl_Counter *middlenotecounter; -private: - void cb_middlenotecounter_i(Fl_Counter*, void*); - static void cb_middlenotecounter(Fl_Counter*, void*); -public: - Fl_Value_Output *mapsizeoutput; -private: - void cb_mapsizeoutput_i(Fl_Value_Output*, void*); - static void cb_mapsizeoutput(Fl_Value_Output*, void*); -public: - Fl_Check_Button *mappingenabledbutton; -private: - void cb_mappingenabledbutton_i(Fl_Check_Button*, void*); - static void cb_mappingenabledbutton(Fl_Check_Button*, void*); - void cb_Import1_i(Fl_Button*, void*); - static void cb_Import1(Fl_Button*, void*); -public: - Fl_Counter *anotecounter; -private: - void cb_anotecounter_i(Fl_Counter*, void*); - static void cb_anotecounter(Fl_Counter*, void*); -public: - Fl_Value_Input *afreqinput; -private: - void cb_afreqinput_i(Fl_Value_Input*, void*); - static void cb_afreqinput(Fl_Value_Input*, void*); - void cb_Close_i(Fl_Button*, void*); - static void cb_Close(Fl_Button*, void*); - void cb_Enable_i(Fl_Check_Button*, void*); - static void cb_Enable(Fl_Check_Button*, void*); -public: - void updateTuningsInput(); - void updateMappingInput(); - MicrotonalUI(Microtonal *microtonal_); - ~MicrotonalUI(); - void show(); - void apply(); -private: - Microtonal *microtonal; -}; -#endif diff --git a/plugins/zynaddsubfx/src/UI/OscilGenUI.cc b/plugins/zynaddsubfx/src/UI/OscilGenUI.cc deleted file mode 100644 index 2925a1e14..000000000 --- a/plugins/zynaddsubfx/src/UI/OscilGenUI.cc +++ /dev/null @@ -1,1410 +0,0 @@ -// generated by Fast Light User Interface Designer (fluid) version 1.0300 - -#include "OscilGenUI.h" -//Copyright (c) 2002-2005 Nasca Octavian Paul -//License: GNU GPL version 2 or later -#include -#include -#include -#include - -OscilSpectrum::OscilSpectrum(int x,int y, int w, int h, const char *label):Fl_Box(x,y,w,h,label) { - oscil=NULL; -} - -void OscilSpectrum::init(OscilGen *oscil_,int oscbase_,Master *master_) { - oscil=oscil_; - oscbase=oscbase_; - master=master_; -} - -void OscilSpectrum::draw() { - int ox=x(),oy=y(),lx=w(),ly=h(),i; - const int maxdb=60;//must be multiple of 10 - int GX=2; - int n=lx/GX-1; - if (n>OSCIL_SIZE/2) n=OSCIL_SIZE/2; - - REALTYPE x; - REALTYPE* spc=new REALTYPE[n]; - for (i=0;imutex); - if (oscbase==0) oscil->getspectrum(n,spc,0); - else oscil->getspectrum(n,spc,1); - pthread_mutex_unlock(&master->mutex); - - //normalize - REALTYPE max=0; - for (i=0;iactive_r()) fl_color(this->parent()->selection_color()); - else fl_color(this->parent()->color()); - fl_line_style(FL_DOT); - - for (i=1;iactive_r()) fl_color(this->parent()->labelcolor()); - else fl_color(this->parent()->color()); - fl_line_style(0); - - //draws the spectrum - for (i=0;idB2rap(-maxdb)) x=rap2dB(x)/maxdb+1; - else x=0; - - int val=(int) ((ly-2)*x); - if (val>0) fl_line(ox+tmp,oy+ly-2-val,ox+tmp,oy+ly-2); - } - delete [] spc; -} - -PSlider::PSlider(int x,int y, int w, int h, const char *label):Fl_Slider(x,y,w,h,label) { - ; -} - -int PSlider::handle(int event) { - int X=x(),Y=y(),W=w(),H=h(); - - if ((!Fl::event_buttons())|| (event==0)||(Fl::event_shift()==0)) return(Fl_Slider::handle(event)); - - if (!Fl::event_inside(X,Y,W,H)) { - if (event==FL_DRAG){ - Fl_Slider::handle(FL_RELEASE); - Fl_Slider::handle(FL_LEAVE); - deactivate(); - activate(); - return(1); - }else{ - return(Fl_Slider::handle(event)); - }; - } else { - //Fl_Slider::handle(FL_FOCUS); - Fl_Slider::handle(FL_PUSH); - }; - - return(1); -} - -Oscilloscope::Oscilloscope(int x,int y, int w, int h, const char *label):Fl_Box(x,y,w,h,label) { - oscil=NULL; - phase=64; - oscbase=0; -} - -void Oscilloscope::init(OscilGen *oscil_,Master *master_) { - oscil=oscil_; - master=master_; -} - -void Oscilloscope::init(OscilGen *oscil_,int oscbase_,Master *master_) { - oscil=oscil_; - oscbase=oscbase_; - master=master_; -} - -void Oscilloscope::init(OscilGen *oscil_,int oscbase_,int phase_,Master *master_) { - oscil=oscil_; - oscbase=oscbase_; - phase=phase_; - master=master_; -} - -void Oscilloscope::draw() { - int ox=x(),oy=y(),lx=w(),ly=h()-1,i; - REALTYPE smps[OSCIL_SIZE]; - pthread_mutex_lock(&master->mutex); - if (oscbase==0) oscil->get(smps,-1.0); - else oscil->getcurrentbasefunction(smps); - pthread_mutex_unlock(&master->mutex); - - if (damage()!=1){ - fl_color(0,0,0); - fl_rectf(ox,oy,lx,ly); - }; - - //normalize - REALTYPE max=0; - for (i=0;iactive_r()) fl_color(this->parent()->labelcolor()); - else fl_color(this->parent()->color()); - int GX=16;if (lxactive_r()) fl_color(this->parent()->selection_color()); - else fl_color(this->parent()->labelcolor()); - int lw=1; - //if ((lx<135)||(ly<135)) lw=1; - fl_line_style(0,lw); - int ph=(int)((phase-64.0)/128.0*OSCIL_SIZE+OSCIL_SIZE); - for (i=1;ivalue(x); - else x=127-(int)o->value(); -if (x==64) o->selection_color(0); - else o->selection_color(222); - -pthread_mutex_lock(&master->mutex); - oscil->Phmag[n]=x; - if (x==64) { - oscil->Phphase[n]=64; - phase->value(64); - }; - oscil->prepare(); -pthread_mutex_unlock(&master->mutex); - -display->redraw(); -oldosc->redraw(); -if (cbwidget!=NULL) { - cbwidget->do_callback(); - applybutton->color(FL_RED); - applybutton->redraw(); -}; -} -void Oscilharmonic::cb_mag(PSlider* o, void* v) { - ((Oscilharmonic*)(o->parent()->user_data()))->cb_mag_i(o,v); -} - -void Oscilharmonic::cb_phase_i(PSlider* o, void*) { - int x=64; -if (Fl::event_button3()) o->value(x); - else x=(int)o->value(); - -pthread_mutex_lock(&master->mutex); - oscil->Phphase[n]=x; - oscil->prepare(); -pthread_mutex_unlock(&master->mutex); - -display->redraw(); -oldosc->redraw(); -if (cbwidget!=NULL) { - cbwidget->do_callback(); - applybutton->color(FL_RED); - applybutton->redraw(); -}; -} -void Oscilharmonic::cb_phase(PSlider* o, void* v) { - ((Oscilharmonic*)(o->parent()->user_data()))->cb_phase_i(o,v); -} - -Fl_Group* Oscilharmonic::make_window() { - { harmonic = new Fl_Group(0, 0, 90, 225); - harmonic->box(FL_FLAT_BOX); - harmonic->color(FL_BACKGROUND_COLOR); - harmonic->selection_color(FL_BACKGROUND_COLOR); - harmonic->labeltype(FL_NO_LABEL); - harmonic->labelfont(0); - harmonic->labelsize(14); - harmonic->labelcolor(FL_FOREGROUND_COLOR); - harmonic->user_data((void*)(this)); - harmonic->align(Fl_Align(FL_ALIGN_TOP)); - harmonic->when(FL_WHEN_RELEASE); - { PSlider* o = mag = new PSlider(0, 15, 15, 115); - mag->type(4); - mag->box(FL_FLAT_BOX); - mag->color(FL_BACKGROUND_COLOR); - mag->selection_color((Fl_Color)222); - mag->labeltype(FL_NORMAL_LABEL); - mag->labelfont(0); - mag->labelsize(14); - mag->labelcolor(FL_FOREGROUND_COLOR); - mag->maximum(127); - mag->step(1); - mag->value(64); - mag->callback((Fl_Callback*)cb_mag); - mag->align(Fl_Align(FL_ALIGN_BOTTOM)); - mag->when(FL_WHEN_CHANGED); - o->value(127-oscil->Phmag[n]); - if (oscil->Phmag[n]==64) o->selection_color(0); - } // PSlider* mag - { PSlider* o = phase = new PSlider(0, 135, 15, 75); - phase->type(4); - phase->box(FL_FLAT_BOX); - phase->color(FL_BACKGROUND_COLOR); - phase->selection_color((Fl_Color)222); - phase->labeltype(FL_NORMAL_LABEL); - phase->labelfont(0); - phase->labelsize(14); - phase->labelcolor(FL_FOREGROUND_COLOR); - phase->maximum(127); - phase->step(1); - phase->value(64); - phase->callback((Fl_Callback*)cb_phase); - phase->align(Fl_Align(FL_ALIGN_BOTTOM)); - phase->when(FL_WHEN_CHANGED); - o->value(oscil->Phphase[n]); - } // PSlider* phase - { Fl_Box* o = new Fl_Box(15, 70, 5, 5); - o->box(FL_FLAT_BOX); - o->color(FL_DARK2); - } // Fl_Box* o - { Fl_Box* o = new Fl_Box(15, 170, 5, 5); - o->box(FL_FLAT_BOX); - o->color(FL_DARK2); - } // Fl_Box* o - { Fl_Box* o = new Fl_Box(0, 210, 20, 15, "01"); - o->labelfont(1); - o->labelsize(9); - o->align(Fl_Align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE)); - char tmp[10];snprintf(tmp,10,"%d",n+1);o->label(strdup(tmp)); - } // Fl_Box* o - { Fl_Box* o = new Fl_Box(0, 0, 20, 15, "01"); - o->labelfont(1); - o->labelsize(9); - o->align(Fl_Align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE)); - char tmp[10];snprintf(tmp,10,"%d",n+1);o->label(strdup(tmp)); - } // Fl_Box* o - harmonic->end(); - } // Fl_Group* harmonic - return harmonic; -} - -Oscilharmonic::Oscilharmonic(int x,int y, int w, int h, const char *label):Fl_Group(x,y,w,h,label) { - n=0; - oscil=NULL; - display=NULL; - applybutton=NULL; - cbwidget=NULL; -} - -void Oscilharmonic::init(OscilGen *oscil_,int n_,Fl_Group *display_,Fl_Widget *oldosc_,Fl_Widget *cbwidget_,Fl_Widget *applybutton_, Master *master_) { - oscil=oscil_; - n=n_; - display=display_; - master=master_; - oldosc=oldosc_; - cbwidget=cbwidget_; - applybutton=applybutton_; - make_window(); - end(); - harmonic->show(); -} - -void Oscilharmonic::refresh() { - mag->value(127-oscil->Phmag[n]); - phase->value(oscil->Phphase[n]); - - if (oscil->Phmag[n]==64) mag->selection_color(0); - else mag->selection_color(222); -} - -Oscilharmonic::~Oscilharmonic() { - harmonic->hide(); - //delete(harmonic); -} - -void OscilEditor::cb_applybutton_i(Fl_Button*, void*) { - applybutton->color(FL_GRAY); -applybutton->redraw(); -if (cbapplywidget!=NULL) { - cbapplywidget->do_callback(); - cbapplywidget->color(FL_GRAY); - cbapplywidget->redraw(); -}; -} -void OscilEditor::cb_applybutton(Fl_Button* o, void* v) { - ((OscilEditor*)(o->parent()->user_data()))->cb_applybutton_i(o,v); -} - -void OscilEditor::cb_rndslider_i(Fl_Value_Slider* o, void*) { - oscil->Prand=(int)o->value()+64; -oscildisplaygroup->redraw(); -oldosc->redraw(); -} -void OscilEditor::cb_rndslider(Fl_Value_Slider* o, void* v) { - ((OscilEditor*)(o->parent()->parent()->user_data()))->cb_rndslider_i(o,v); -} - -void OscilEditor::cb_hrndtype_i(Fl_Choice* o, void*) { - oscil->Pamprandtype=(int) o->value(); -} -void OscilEditor::cb_hrndtype(Fl_Choice* o, void* v) { - ((OscilEditor*)(o->parent()->parent()->parent()->user_data()))->cb_hrndtype_i(o,v); -} - -Fl_Menu_Item OscilEditor::menu_hrndtype[] = { - {"None", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {"Pow", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {"Sin", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {0,0,0,0,0,0,0,0,0} -}; - -void OscilEditor::cb_hrnddial_i(WidgetPDial* o, void*) { - oscil->Pamprandpower=(int) o->value(); -} -void OscilEditor::cb_hrnddial(WidgetPDial* o, void* v) { - ((OscilEditor*)(o->parent()->parent()->parent()->user_data()))->cb_hrnddial_i(o,v); -} - -void OscilEditor::cb_bfslider_i(WidgetPDial* o, void*) { - oscil->Pbasefuncpar=(int)o->value()+64; -basefuncdisplaygroup->redraw(); -bfparval->value(oscil->Pbasefuncpar-64); - -redrawoscil(); -} -void OscilEditor::cb_bfslider(WidgetPDial* o, void* v) { - ((OscilEditor*)(o->parent()->parent()->user_data()))->cb_bfslider_i(o,v); -} - -void OscilEditor::cb_bftype_i(Fl_Choice* o, void*) { - oscil->Pcurrentbasefunc=(int) o->value(); - -basefuncdisplaygroup->redraw(); -redrawoscil(); - -if ((oscil->Pcurrentbasefunc==0)||(oscil->Pcurrentbasefunc==127)) basefuncmodulation->deactivate(); - else basefuncmodulation->activate(); -} -void OscilEditor::cb_bftype(Fl_Choice* o, void* v) { - ((OscilEditor*)(o->parent()->parent()->user_data()))->cb_bftype_i(o,v); -} - -Fl_Menu_Item OscilEditor::menu_bftype[] = { - {"Sine", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 11, 0}, - {"Triangle", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 11, 0}, - {"Pulse", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 11, 0}, - {"Saw", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 11, 0}, - {"Power", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 11, 0}, - {"Gauss", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 11, 0}, - {"Diode", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 11, 0}, - {"AbsSine", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 11, 0}, - {"PulseSine", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 11, 0}, - {"StrchSine", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 11, 0}, - {"Chirp", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 11, 0}, - {"AbsStrSine", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 11, 0}, - {"Chebyshev", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 11, 0}, - {"Sqr", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 11, 0}, - {0,0,0,0,0,0,0,0,0} -}; - -void OscilEditor::cb_bfmodtype_i(Fl_Choice* o, void*) { - oscil->Pbasefuncmodulation=(int) o->value(); -basefuncdisplaygroup->redraw(); -redrawoscil(); -} -void OscilEditor::cb_bfmodtype(Fl_Choice* o, void* v) { - ((OscilEditor*)(o->parent()->parent()->parent()->user_data()))->cb_bfmodtype_i(o,v); -} - -Fl_Menu_Item OscilEditor::menu_bfmodtype[] = { - {"None", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {"Rev", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {"Sine", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {"Pow", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {0,0,0,0,0,0,0,0,0} -}; - -void OscilEditor::cb_bfmodpar1_i(WidgetPDial* o, void*) { - oscil->Pbasefuncmodulationpar1=(int)o->value(); -basefuncdisplaygroup->redraw(); -redrawoscil(); -} -void OscilEditor::cb_bfmodpar1(WidgetPDial* o, void* v) { - ((OscilEditor*)(o->parent()->parent()->parent()->user_data()))->cb_bfmodpar1_i(o,v); -} - -void OscilEditor::cb_bfmodpar2_i(WidgetPDial* o, void*) { - oscil->Pbasefuncmodulationpar2=(int)o->value(); -basefuncdisplaygroup->redraw(); -redrawoscil(); -} -void OscilEditor::cb_bfmodpar2(WidgetPDial* o, void* v) { - ((OscilEditor*)(o->parent()->parent()->parent()->user_data()))->cb_bfmodpar2_i(o,v); -} - -void OscilEditor::cb_bfmodpar3_i(WidgetPDial* o, void*) { - oscil->Pbasefuncmodulationpar3=(int)o->value(); -basefuncdisplaygroup->redraw(); -redrawoscil(); -} -void OscilEditor::cb_bfmodpar3(WidgetPDial* o, void* v) { - ((OscilEditor*)(o->parent()->parent()->parent()->user_data()))->cb_bfmodpar3_i(o,v); -} - -void OscilEditor::cb_magtype_i(Fl_Choice* o, void*) { - oscil->Phmagtype=(int) o->value(); -basefuncdisplaygroup->redraw(); - -redrawoscil(); -} -void OscilEditor::cb_magtype(Fl_Choice* o, void* v) { - ((OscilEditor*)(o->parent()->user_data()))->cb_magtype_i(o,v); -} - -Fl_Menu_Item OscilEditor::menu_magtype[] = { - {"Linear", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 11, 0}, - {"-40dB", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 11, 0}, - {"-60dB", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 11, 0}, - {"-80dB", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 11, 0}, - {"-100dB", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 11, 0}, - {0,0,0,0,0,0,0,0,0} -}; - -void OscilEditor::cb_Use_i(Fl_Button*, void*) { - oscil->useasbase(); -if (autoclearbutton->value()){ - for (int i=0;imag->value(64); - oscil->Phmag[i]=64; - h[i]->phase->value(64); - oscil->Phphase[i]=64; - }; - oscil->Phmag[0]=127; - - oscil->Pharmonicshift=0; - harmonicshiftcounter->value(0); - - h[0]->mag->value(0); - wshbutton->value(0); - wshbutton->do_callback(); - fltbutton->value(0); - fltbutton->do_callback(); - sabutton->value(0); - sabutton->do_callback(); -}; - -pthread_mutex_lock(&master->mutex); - for (int i=0;iPhmag[i]==64) h[i]->mag->selection_color(0); - else h[i]->mag->selection_color(222); - }; - oscil->prepare(); -pthread_mutex_unlock(&master->mutex); - -basefuncdisplaygroup->redraw(); -redrawoscil(); -} -void OscilEditor::cb_Use(Fl_Button* o, void* v) { - ((OscilEditor*)(o->parent()->user_data()))->cb_Use_i(o,v); -} - -void OscilEditor::cb_Close_i(Fl_Button*, void*) { - osceditUI->hide(); -} -void OscilEditor::cb_Close(Fl_Button* o, void* v) { - ((OscilEditor*)(o->parent()->user_data()))->cb_Close_i(o,v); -} - -void OscilEditor::cb_Clear_i(Fl_Button*, void*) { - if (!fl_choice("Clear the harmonics settings?","No","Yes",NULL)) return; - -for (int i=0;imag->value(64); - oscil->Phmag[i]=64; - h[i]->phase->value(64); - oscil->Phphase[i]=64; -}; -oscil->Phmag[0]=127; -h[0]->mag->value(0); - -for (int i=0;iPhmag[i]==64) h[i]->mag->selection_color(0); - else h[i]->mag->selection_color(222); -}; - -//harmonics->redraw(); - -pthread_mutex_lock(&master->mutex); - oscil->prepare(); -pthread_mutex_unlock(&master->mutex); - -redrawoscil(); -} -void OscilEditor::cb_Clear(Fl_Button* o, void* v) { - ((OscilEditor*)(o->parent()->user_data()))->cb_Clear_i(o,v); -} - -void OscilEditor::cb_wshbutton_i(Fl_Choice* o, void*) { - oscil->Pwaveshapingfunction=(int) o->value(); -basefuncdisplaygroup->redraw(); -redrawoscil(); -} -void OscilEditor::cb_wshbutton(Fl_Choice* o, void* v) { - ((OscilEditor*)(o->parent()->parent()->user_data()))->cb_wshbutton_i(o,v); -} - -Fl_Menu_Item OscilEditor::menu_wshbutton[] = { - {"None", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {"Atan", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {"Asym1", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {"Pow", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {"Sine", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {"Qnts", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {"Zigzg", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {"Lmt", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {"LmtU", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {"LmtL", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {"ILmt", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {"Clip", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {"Asym2", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {"Pow2", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {"Sgm", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {0,0,0,0,0,0,0,0,0} -}; - -void OscilEditor::cb_wshpar_i(WidgetPDial* o, void*) { - oscil->Pwaveshaping=(int)o->value()+64; -wsparval->value(oscil->Pwaveshaping-64); -redrawoscil(); -} -void OscilEditor::cb_wshpar(WidgetPDial* o, void* v) { - ((OscilEditor*)(o->parent()->parent()->user_data()))->cb_wshpar_i(o,v); -} - -void OscilEditor::cb_fltbutton_i(Fl_Choice* o, void*) { - oscil->Pfiltertype=(int) o->value(); - -redrawoscil(); -} -void OscilEditor::cb_fltbutton(Fl_Choice* o, void* v) { - ((OscilEditor*)(o->parent()->parent()->user_data()))->cb_fltbutton_i(o,v); -} - -Fl_Menu_Item OscilEditor::menu_fltbutton[] = { - {"None", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {"LP1", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {"HP1a", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {"HP1b", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {"BP1", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {"BS1", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {"LP2", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {"HP2", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {"BP2", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {"BS2", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {"Cos", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {"Sin", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {"LSh", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {"S", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {0,0,0,0,0,0,0,0,0} -}; - -void OscilEditor::cb_filtervalue1_i(WidgetPDial* o, void*) { - oscil->Pfilterpar1=(int)o->value(); - -redrawoscil(); -} -void OscilEditor::cb_filtervalue1(WidgetPDial* o, void* v) { - ((OscilEditor*)(o->parent()->parent()->user_data()))->cb_filtervalue1_i(o,v); -} - -void OscilEditor::cb_filterpref_i(Fl_Check_Button* o, void*) { - oscil->Pfilterbeforews=(int)o->value(); - -redrawoscil(); -} -void OscilEditor::cb_filterpref(Fl_Check_Button* o, void* v) { - ((OscilEditor*)(o->parent()->parent()->user_data()))->cb_filterpref_i(o,v); -} - -void OscilEditor::cb_filtervalue2_i(WidgetPDial* o, void*) { - oscil->Pfilterpar2=(int)o->value(); - -redrawoscil(); -} -void OscilEditor::cb_filtervalue2(WidgetPDial* o, void* v) { - ((OscilEditor*)(o->parent()->parent()->user_data()))->cb_filtervalue2_i(o,v); -} - -void OscilEditor::cb_sabutton_i(Fl_Choice* o, void*) { - oscil->Psatype=(int) o->value(); -redrawoscil(); -} -void OscilEditor::cb_sabutton(Fl_Choice* o, void* v) { - ((OscilEditor*)(o->parent()->parent()->user_data()))->cb_sabutton_i(o,v); -} - -Fl_Menu_Item OscilEditor::menu_sabutton[] = { - {"None", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {"Pow", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {"ThrsD", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {"ThrsU", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {0,0,0,0,0,0,0,0,0} -}; - -void OscilEditor::cb_sadjpar_i(WidgetPDial* o, void*) { - oscil->Psapar=(int)o->value(); -redrawoscil(); -} -void OscilEditor::cb_sadjpar(WidgetPDial* o, void* v) { - ((OscilEditor*)(o->parent()->parent()->user_data()))->cb_sadjpar_i(o,v); -} - -void OscilEditor::cb_harmonicshiftcounter_i(Fl_Counter* o, void*) { - oscil->Pharmonicshift=(int)o->value(); -redrawoscil(); -} -void OscilEditor::cb_harmonicshiftcounter(Fl_Counter* o, void* v) { - ((OscilEditor*)(o->parent()->parent()->user_data()))->cb_harmonicshiftcounter_i(o,v); -} - -void OscilEditor::cb_harmonicshiftpre_i(Fl_Check_Button* o, void*) { - oscil->Pharmonicshiftfirst=(int)o->value(); -redrawoscil(); -} -void OscilEditor::cb_harmonicshiftpre(Fl_Check_Button* o, void* v) { - ((OscilEditor*)(o->parent()->parent()->user_data()))->cb_harmonicshiftpre_i(o,v); -} - -void OscilEditor::cb_R_i(Fl_Button*, void*) { - oscil->Pharmonicshift=0; -harmonicshiftcounter->value(0); -redrawoscil(); -} -void OscilEditor::cb_R(Fl_Button* o, void* v) { - ((OscilEditor*)(o->parent()->parent()->user_data()))->cb_R_i(o,v); -} - -void OscilEditor::cb_adhrtype_i(Fl_Choice* o, void*) { - oscil->Padaptiveharmonics=(int) o->value(); -redrawoscil(); -} -void OscilEditor::cb_adhrtype(Fl_Choice* o, void* v) { - ((OscilEditor*)(o->parent()->parent()->user_data()))->cb_adhrtype_i(o,v); -} - -Fl_Menu_Item OscilEditor::menu_adhrtype[] = { - {"OFF", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {"ON", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {"Square", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {"2xSub", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {"2xAdd", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {"3xSub", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {"3xAdd", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {"4xSub", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {"4xAdd", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {0,0,0,0,0,0,0,0,0} -}; - -void OscilEditor::cb_adhrpow_i(WidgetPDial* o, void*) { - oscil->Padaptiveharmonicspower=(int)o->value(); -redrawoscil(); -} -void OscilEditor::cb_adhrpow(WidgetPDial* o, void* v) { - ((OscilEditor*)(o->parent()->parent()->user_data()))->cb_adhrpow_i(o,v); -} - -void OscilEditor::cb_adhrbf_i(WidgetPDial* o, void*) { - oscil->Padaptiveharmonicsbasefreq=(int)o->value(); -redrawoscil(); -} -void OscilEditor::cb_adhrbf(WidgetPDial* o, void* v) { - ((OscilEditor*)(o->parent()->parent()->user_data()))->cb_adhrbf_i(o,v); -} - -void OscilEditor::cb_adhrpar_i(Fl_Slider* o, void*) { - oscil->Padaptiveharmonicspar=(int)o->value(); -redrawoscil(); -} -void OscilEditor::cb_adhrpar(Fl_Slider* o, void* v) { - ((OscilEditor*)(o->parent()->parent()->user_data()))->cb_adhrpar_i(o,v); -} - -void OscilEditor::cb_modtype_i(Fl_Choice* o, void*) { - oscil->Pmodulation=(int) o->value(); - -redrawoscil(); -} -void OscilEditor::cb_modtype(Fl_Choice* o, void* v) { - ((OscilEditor*)(o->parent()->parent()->user_data()))->cb_modtype_i(o,v); -} - -Fl_Menu_Item OscilEditor::menu_modtype[] = { - {"None", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {"Rev", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {"Sine", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {"Pow", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {0,0,0,0,0,0,0,0,0} -}; - -void OscilEditor::cb_modpar1_i(WidgetPDial* o, void*) { - oscil->Pmodulationpar1=(int)o->value(); - -redrawoscil(); -} -void OscilEditor::cb_modpar1(WidgetPDial* o, void* v) { - ((OscilEditor*)(o->parent()->parent()->user_data()))->cb_modpar1_i(o,v); -} - -void OscilEditor::cb_modpar2_i(WidgetPDial* o, void*) { - oscil->Pmodulationpar2=(int)o->value(); - -redrawoscil(); -} -void OscilEditor::cb_modpar2(WidgetPDial* o, void* v) { - ((OscilEditor*)(o->parent()->parent()->user_data()))->cb_modpar2_i(o,v); -} - -void OscilEditor::cb_modpar3_i(WidgetPDial* o, void*) { - oscil->Pmodulationpar3=(int)o->value(); -redrawoscil(); -} -void OscilEditor::cb_modpar3(WidgetPDial* o, void* v) { - ((OscilEditor*)(o->parent()->parent()->user_data()))->cb_modpar3_i(o,v); -} - -void OscilEditor::cb_Sine_i(Fl_Button*, void*) { - if (!fl_choice("Convert to SINE?","No","Yes",NULL)) return; - -pthread_mutex_lock(&master->mutex); - oscil->convert2sine(0); -pthread_mutex_unlock(&master->mutex); - -redrawoscil(); -refresh(); -} -void OscilEditor::cb_Sine(Fl_Button* o, void* v) { - ((OscilEditor*)(o->parent()->user_data()))->cb_Sine_i(o,v); -} - -void OscilEditor::cb_C_i(Fl_Button*, void*) { - presetsui->copy(oscil); -} -void OscilEditor::cb_C(Fl_Button* o, void* v) { - ((OscilEditor*)(o->parent()->user_data()))->cb_C_i(o,v); -} - -void OscilEditor::cb_P_i(Fl_Button*, void*) { - presetsui->paste(oscil,this); -} -void OscilEditor::cb_P(Fl_Button* o, void* v) { - ((OscilEditor*)(o->parent()->user_data()))->cb_P_i(o,v); -} - -Fl_Double_Window* OscilEditor::make_window() { - { Fl_Double_Window* o = osceditUI = new Fl_Double_Window(735, 595, "ADsynth Oscillator Editor"); - osceditUI->user_data((void*)(this)); - { Fl_Button* o = applybutton = new Fl_Button(300, 280, 60, 20, "Apply"); - applybutton->box(FL_THIN_UP_BOX); - applybutton->labelfont(1); - applybutton->callback((Fl_Callback*)cb_applybutton); - if (!oscil->ADvsPAD) o->hide(); - } // Fl_Button* applybutton - { oscildisplaygroup = new Fl_Group(5, 5, 360, 300); - oscildisplaygroup->box(FL_ENGRAVED_FRAME); - { Fl_Group* o = new Fl_Group(10, 85, 350, 190); - o->box(FL_THIN_DOWN_BOX); - o->color(FL_GRAY0); - o->selection_color((Fl_Color)71); - o->labelcolor((Fl_Color)179); - Oscilloscope *osc=new Oscilloscope(o->x(),o->y(),o->w(),o->h(),""); - osc->init(oscil,master); - o->end(); - } // Fl_Group* o - { Fl_Box* o = new Fl_Box(120, 10, 110, 20, "Oscillator"); - o->box(FL_FLAT_BOX); - o->labelfont(1); - } // Fl_Box* o - { Fl_Value_Slider* o = rndslider = new Fl_Value_Slider(140, 285, 100, 10, "rnd"); - rndslider->tooltip("Oscilator Phase Randomness: smaller than 0 is \"group\", larger than 0 is for\ - each harmonic"); - rndslider->type(5); - rndslider->box(FL_FLAT_BOX); - rndslider->labelsize(10); - rndslider->minimum(-64); - rndslider->maximum(63); - rndslider->step(1); - rndslider->callback((Fl_Callback*)cb_rndslider); - rndslider->align(Fl_Align(FL_ALIGN_TOP_LEFT)); - if (oscil->ADvsPAD) o->hide(); - } // Fl_Value_Slider* rndslider - { Fl_Group* o = new Fl_Group(10, 30, 350, 50); - o->box(FL_THIN_DOWN_BOX); - o->color(FL_GRAY0); - o->selection_color((Fl_Color)218); - o->labelcolor(FL_GREEN); - OscilSpectrum *spc=new OscilSpectrum(o->x(),o->y(),o->w(),o->h(),""); - spc->init(oscil,0,master); - o->end(); - } // Fl_Group* o - { Fl_Group* o = new Fl_Group(246, 277, 115, 25); - o->box(FL_ENGRAVED_BOX); - { hrndtype = new Fl_Choice(281, 282, 50, 15, "H.rnd"); - hrndtype->tooltip("Harmonic Amplitude Randomness"); - hrndtype->down_box(FL_BORDER_BOX); - hrndtype->labelsize(10); - hrndtype->textsize(10); - hrndtype->callback((Fl_Callback*)cb_hrndtype); - hrndtype->menu(menu_hrndtype); - } // Fl_Choice* hrndtype - { hrnddial = new WidgetPDial(338, 280, 18, 18); - hrnddial->tooltip("Oscillator\'s spectrum adjust parameter"); - hrnddial->box(FL_OVAL_BOX); - hrnddial->color(FL_BACKGROUND_COLOR); - hrnddial->selection_color(FL_INACTIVE_COLOR); - hrnddial->labeltype(FL_NORMAL_LABEL); - hrnddial->labelfont(0); - hrnddial->labelsize(14); - hrnddial->labelcolor(FL_FOREGROUND_COLOR); - hrnddial->maximum(127); - hrnddial->step(1); - hrnddial->callback((Fl_Callback*)cb_hrnddial); - hrnddial->align(Fl_Align(FL_ALIGN_BOTTOM)); - hrnddial->when(FL_WHEN_CHANGED); - } // WidgetPDial* hrnddial - if (oscil->ADvsPAD) o->hide(); - o->end(); - } // Fl_Group* o - oscildisplaygroup->end(); - } // Fl_Group* oscildisplaygroup - { Fl_Box* o = new Fl_Box(495, 15, 110, 20, "Base Func."); - o->box(FL_FLAT_BOX); - o->labelfont(1); - } // Fl_Box* o - { basefuncdisplaygroup = new Fl_Group(365, 5, 360, 300); - basefuncdisplaygroup->box(FL_ENGRAVED_FRAME); - { Fl_Group* o = new Fl_Group(370, 85, 350, 190); - o->box(FL_THIN_DOWN_BOX); - o->color(FL_GRAY0); - o->selection_color((Fl_Color)71); - o->labelcolor((Fl_Color)179); - Oscilloscope *osc=new Oscilloscope(o->x(),o->y(),o->w(),o->h(),""); - osc->init(oscil,1,master); - o->end(); - } // Fl_Group* o - { bfslider = new WidgetPDial(520, 280, 20, 20); - bfslider->tooltip("Base Function Parameter"); - bfslider->box(FL_OVAL_BOX); - bfslider->color(FL_BACKGROUND_COLOR); - bfslider->selection_color(FL_INACTIVE_COLOR); - bfslider->labeltype(FL_NORMAL_LABEL); - bfslider->labelfont(0); - bfslider->labelsize(14); - bfslider->labelcolor(FL_FOREGROUND_COLOR); - bfslider->minimum(-64); - bfslider->maximum(63); - bfslider->step(1); - bfslider->callback((Fl_Callback*)cb_bfslider); - bfslider->align(Fl_Align(FL_ALIGN_BOTTOM)); - bfslider->when(FL_WHEN_CHANGED); - } // WidgetPDial* bfslider - { bftype = new Fl_Choice(370, 285, 90, 15, "Base.F.."); - bftype->down_box(FL_BORDER_BOX); - bftype->labelsize(10); - bftype->textsize(11); - bftype->callback((Fl_Callback*)cb_bftype); - bftype->align(Fl_Align(FL_ALIGN_TOP_LEFT)); - bftype->menu(menu_bftype); - } // Fl_Choice* bftype - { Fl_Box* o = new Fl_Box(480, 10, 110, 20, "Base Func."); - o->box(FL_FLAT_BOX); - o->labelfont(1); - } // Fl_Box* o - { Fl_Group* o = new Fl_Group(370, 30, 350, 50); - o->box(FL_THIN_DOWN_BOX); - o->color(FL_GRAY0); - o->selection_color((Fl_Color)218); - o->labelcolor(FL_GREEN); - OscilSpectrum *spc=new OscilSpectrum (o->x(),o->y(),o->w(),o->h(),""); - spc->init(oscil,1,master); - o->end(); - } // Fl_Group* o - { bfparval = new Fl_Value_Output(490, 285, 25, 15, "Par."); - bfparval->labelsize(12); - bfparval->minimum(-63); - bfparval->maximum(63); - bfparval->step(1); - } // Fl_Value_Output* bfparval - { basefuncmodulation = new Fl_Group(550, 276, 169, 25); - basefuncmodulation->box(FL_ENGRAVED_BOX); - { bfmodtype = new Fl_Choice(599, 281, 50, 15, "B.F.Mod."); - bfmodtype->tooltip("Base function modulation"); - bfmodtype->down_box(FL_BORDER_BOX); - bfmodtype->labelsize(10); - bfmodtype->textsize(10); - bfmodtype->callback((Fl_Callback*)cb_bfmodtype); - bfmodtype->menu(menu_bfmodtype); - } // Fl_Choice* bfmodtype - { bfmodpar1 = new WidgetPDial(659, 281, 15, 15); - bfmodpar1->tooltip("Oscillator\'s modulation parameter 1"); - bfmodpar1->box(FL_OVAL_BOX); - bfmodpar1->color(FL_BACKGROUND_COLOR); - bfmodpar1->selection_color(FL_INACTIVE_COLOR); - bfmodpar1->labeltype(FL_NORMAL_LABEL); - bfmodpar1->labelfont(0); - bfmodpar1->labelsize(14); - bfmodpar1->labelcolor(FL_FOREGROUND_COLOR); - bfmodpar1->maximum(127); - bfmodpar1->step(1); - bfmodpar1->callback((Fl_Callback*)cb_bfmodpar1); - bfmodpar1->align(Fl_Align(FL_ALIGN_BOTTOM)); - bfmodpar1->when(FL_WHEN_CHANGED); - } // WidgetPDial* bfmodpar1 - { bfmodpar2 = new WidgetPDial(679, 281, 15, 15); - bfmodpar2->tooltip("Oscillator\'s modulation parameter 2"); - bfmodpar2->box(FL_OVAL_BOX); - bfmodpar2->color(FL_BACKGROUND_COLOR); - bfmodpar2->selection_color(FL_INACTIVE_COLOR); - bfmodpar2->labeltype(FL_NORMAL_LABEL); - bfmodpar2->labelfont(0); - bfmodpar2->labelsize(14); - bfmodpar2->labelcolor(FL_FOREGROUND_COLOR); - bfmodpar2->maximum(127); - bfmodpar2->step(1); - bfmodpar2->callback((Fl_Callback*)cb_bfmodpar2); - bfmodpar2->align(Fl_Align(FL_ALIGN_BOTTOM)); - bfmodpar2->when(FL_WHEN_CHANGED); - } // WidgetPDial* bfmodpar2 - { bfmodpar3 = new WidgetPDial(699, 281, 15, 15); - bfmodpar3->tooltip("Oscillator\'s modulation parameter 3"); - bfmodpar3->box(FL_OVAL_BOX); - bfmodpar3->color(FL_BACKGROUND_COLOR); - bfmodpar3->selection_color(FL_INACTIVE_COLOR); - bfmodpar3->labeltype(FL_NORMAL_LABEL); - bfmodpar3->labelfont(0); - bfmodpar3->labelsize(14); - bfmodpar3->labelcolor(FL_FOREGROUND_COLOR); - bfmodpar3->maximum(127); - bfmodpar3->step(1); - bfmodpar3->callback((Fl_Callback*)cb_bfmodpar3); - bfmodpar3->align(Fl_Align(FL_ALIGN_BOTTOM)); - bfmodpar3->when(FL_WHEN_CHANGED); - } // WidgetPDial* bfmodpar3 - if ((oscil->Pcurrentbasefunc==0)||(oscil->Pcurrentbasefunc==127)) basefuncmodulation->deactivate(); - basefuncmodulation->end(); - } // Fl_Group* basefuncmodulation - basefuncdisplaygroup->end(); - } // Fl_Group* basefuncdisplaygroup - { magtype = new Fl_Choice(70, 280, 65, 20, "Mag.Type"); - magtype->down_box(FL_BORDER_BOX); - magtype->labelsize(11); - magtype->textsize(11); - magtype->callback((Fl_Callback*)cb_magtype); - magtype->menu(menu_magtype); - } // Fl_Choice* magtype - { Fl_Button* o = new Fl_Button(5, 313, 85, 20, "Use as base"); - o->tooltip("Use this Oscillator as base function"); - o->box(FL_THIN_UP_BOX); - o->labelfont(1); - o->labelsize(11); - o->callback((Fl_Callback*)cb_Use); - } // Fl_Button* o - { Fl_Button* o = new Fl_Button(668, 565, 62, 25, "Close"); - o->box(FL_THIN_UP_BOX); - o->callback((Fl_Callback*)cb_Close); - } // Fl_Button* o - { Fl_Button* o = new Fl_Button(670, 505, 55, 15, "Clear"); - o->box(FL_THIN_UP_BOX); - o->labelfont(1); - o->labelsize(11); - o->callback((Fl_Callback*)cb_Clear); - } // Fl_Button* o - { Fl_Group* o = new Fl_Group(135, 308, 150, 30); - o->box(FL_ENGRAVED_BOX); - { wshbutton = new Fl_Choice(165, 313, 55, 20, "Wsh."); - wshbutton->tooltip("Waveshaping function"); - wshbutton->down_box(FL_BORDER_BOX); - wshbutton->labelsize(10); - wshbutton->textsize(10); - wshbutton->callback((Fl_Callback*)cb_wshbutton); - wshbutton->menu(menu_wshbutton); - } // Fl_Choice* wshbutton - { wshpar = new WidgetPDial(260, 313, 20, 20); - wshpar->tooltip("Waveshaping Parameter"); - wshpar->box(FL_OVAL_BOX); - wshpar->color(FL_BACKGROUND_COLOR); - wshpar->selection_color(FL_INACTIVE_COLOR); - wshpar->labeltype(FL_NORMAL_LABEL); - wshpar->labelfont(0); - wshpar->labelsize(14); - wshpar->labelcolor(FL_FOREGROUND_COLOR); - wshpar->minimum(-64); - wshpar->maximum(63); - wshpar->step(1); - wshpar->callback((Fl_Callback*)cb_wshpar); - wshpar->align(Fl_Align(FL_ALIGN_BOTTOM)); - wshpar->when(FL_WHEN_CHANGED); - } // WidgetPDial* wshpar - { wsparval = new Fl_Value_Output(228, 316, 25, 15); - wsparval->labelsize(12); - wsparval->minimum(-63); - wsparval->maximum(63); - wsparval->step(1); - } // Fl_Value_Output* wsparval - o->end(); - } // Fl_Group* o - { autoclearbutton = new Fl_Light_Button(95, 313, 35, 20, "Clr."); - autoclearbutton->tooltip("Auto clear when using the oscillator as base function"); - autoclearbutton->box(FL_THIN_UP_BOX); - autoclearbutton->value(1); - autoclearbutton->labelfont(1); - autoclearbutton->labelsize(10); - } // Fl_Light_Button* autoclearbutton - { Fl_Group* o = new Fl_Group(285, 308, 155, 30); - o->box(FL_ENGRAVED_BOX); - { fltbutton = new Fl_Choice(315, 313, 50, 20, "Filter"); - fltbutton->tooltip("Oscillator\'s filter type"); - fltbutton->down_box(FL_BORDER_BOX); - fltbutton->labelsize(10); - fltbutton->textsize(10); - fltbutton->callback((Fl_Callback*)cb_fltbutton); - fltbutton->menu(menu_fltbutton); - } // Fl_Choice* fltbutton - { filtervalue1 = new WidgetPDial(367, 313, 20, 20); - filtervalue1->tooltip("Oscillator\'s filter parameter1"); - filtervalue1->box(FL_OVAL_BOX); - filtervalue1->color(FL_BACKGROUND_COLOR); - filtervalue1->selection_color(FL_INACTIVE_COLOR); - filtervalue1->labeltype(FL_NORMAL_LABEL); - filtervalue1->labelfont(0); - filtervalue1->labelsize(14); - filtervalue1->labelcolor(FL_FOREGROUND_COLOR); - filtervalue1->maximum(127); - filtervalue1->step(1); - filtervalue1->callback((Fl_Callback*)cb_filtervalue1); - filtervalue1->align(Fl_Align(FL_ALIGN_BOTTOM)); - filtervalue1->when(FL_WHEN_CHANGED); - } // WidgetPDial* filtervalue1 - { filterpref = new Fl_Check_Button(415, 313, 20, 20, "p"); - filterpref->tooltip("Apply the filter before the waveshaping"); - filterpref->down_box(FL_DOWN_BOX); - filterpref->labelsize(10); - filterpref->callback((Fl_Callback*)cb_filterpref); - filterpref->align(Fl_Align(FL_ALIGN_RIGHT|FL_ALIGN_INSIDE)); - } // Fl_Check_Button* filterpref - { filtervalue2 = new WidgetPDial(392, 313, 20, 20); - filtervalue2->tooltip("Oscillator\'s filter parameter2"); - filtervalue2->box(FL_OVAL_BOX); - filtervalue2->color(FL_BACKGROUND_COLOR); - filtervalue2->selection_color(FL_INACTIVE_COLOR); - filtervalue2->labeltype(FL_NORMAL_LABEL); - filtervalue2->labelfont(0); - filtervalue2->labelsize(14); - filtervalue2->labelcolor(FL_FOREGROUND_COLOR); - filtervalue2->maximum(127); - filtervalue2->step(1); - filtervalue2->callback((Fl_Callback*)cb_filtervalue2); - filtervalue2->align(Fl_Align(FL_ALIGN_BOTTOM)); - filtervalue2->when(FL_WHEN_CHANGED); - } // WidgetPDial* filtervalue2 - o->end(); - } // Fl_Group* o - { Fl_Group* o = new Fl_Group(590, 308, 135, 30); - o->box(FL_ENGRAVED_BOX); - { sabutton = new Fl_Choice(630, 313, 60, 20, "Sp.adj."); - sabutton->tooltip("Oscillator\'s spectrum adjust"); - sabutton->down_box(FL_BORDER_BOX); - sabutton->labelsize(10); - sabutton->textsize(10); - sabutton->callback((Fl_Callback*)cb_sabutton); - sabutton->menu(menu_sabutton); - } // Fl_Choice* sabutton - { sadjpar = new WidgetPDial(695, 313, 20, 20); - sadjpar->tooltip("Oscillator\'s spectrum adjust parameter"); - sadjpar->box(FL_OVAL_BOX); - sadjpar->color(FL_BACKGROUND_COLOR); - sadjpar->selection_color(FL_INACTIVE_COLOR); - sadjpar->labeltype(FL_NORMAL_LABEL); - sadjpar->labelfont(0); - sadjpar->labelsize(14); - sadjpar->labelcolor(FL_FOREGROUND_COLOR); - sadjpar->maximum(127); - sadjpar->step(1); - sadjpar->callback((Fl_Callback*)cb_sadjpar); - sadjpar->align(Fl_Align(FL_ALIGN_BOTTOM)); - sadjpar->when(FL_WHEN_CHANGED); - } // WidgetPDial* sadjpar - o->end(); - } // Fl_Group* o - { Fl_Group* o = new Fl_Group(665, 340, 65, 65); - o->box(FL_ENGRAVED_BOX); - { harmonicshiftcounter = new Fl_Counter(670, 365, 55, 15, "Harmonic Shift"); - harmonicshiftcounter->type(1); - harmonicshiftcounter->labelsize(10); - harmonicshiftcounter->minimum(-64); - harmonicshiftcounter->maximum(64); - harmonicshiftcounter->step(1); - harmonicshiftcounter->textfont(1); - harmonicshiftcounter->textsize(10); - harmonicshiftcounter->callback((Fl_Callback*)cb_harmonicshiftcounter); - harmonicshiftcounter->align(Fl_Align(129)); - } // Fl_Counter* harmonicshiftcounter - { harmonicshiftpre = new Fl_Check_Button(690, 385, 34, 15, "preH"); - harmonicshiftpre->tooltip("Apply the harmonic shift before the waveshaping and filtering"); - harmonicshiftpre->down_box(FL_DOWN_BOX); - harmonicshiftpre->labelsize(10); - harmonicshiftpre->callback((Fl_Callback*)cb_harmonicshiftpre); - harmonicshiftpre->align(Fl_Align(FL_ALIGN_RIGHT|FL_ALIGN_INSIDE)); - } // Fl_Check_Button* harmonicshiftpre - { Fl_Button* o = new Fl_Button(670, 385, 20, 15, "R"); - o->box(FL_THIN_UP_BOX); - o->labelfont(1); - o->labelsize(10); - o->callback((Fl_Callback*)cb_R); - } // Fl_Button* o - o->end(); - } // Fl_Group* o - { Fl_Group* o = new Fl_Group(665, 410, 65, 90); - o->box(FL_ENGRAVED_FRAME); - { adhrtype = new Fl_Choice(670, 425, 55, 15, "Adpt.Harm."); - adhrtype->tooltip("The type of the addaptive harmonics"); - adhrtype->down_box(FL_BORDER_BOX); - adhrtype->labelsize(10); - adhrtype->textsize(10); - adhrtype->callback((Fl_Callback*)cb_adhrtype); - adhrtype->align(Fl_Align(129)); - adhrtype->when(FL_WHEN_RELEASE_ALWAYS); - adhrtype->menu(menu_adhrtype); - } // Fl_Choice* adhrtype - { adhrpow = new WidgetPDial(700, 460, 25, 25, "pow"); - adhrpow->tooltip("Adaptive harmonics power"); - adhrpow->box(FL_OVAL_BOX); - adhrpow->color(FL_BACKGROUND_COLOR); - adhrpow->selection_color(FL_INACTIVE_COLOR); - adhrpow->labeltype(FL_NORMAL_LABEL); - adhrpow->labelfont(0); - adhrpow->labelsize(10); - adhrpow->labelcolor(FL_FOREGROUND_COLOR); - adhrpow->maximum(200); - adhrpow->step(1); - adhrpow->callback((Fl_Callback*)cb_adhrpow); - adhrpow->align(Fl_Align(FL_ALIGN_BOTTOM)); - adhrpow->when(FL_WHEN_CHANGED); - } // WidgetPDial* adhrpow - { adhrbf = new WidgetPDial(670, 460, 25, 25, "baseF"); - adhrbf->tooltip("Adaptive harmonics base frequency"); - adhrbf->box(FL_OVAL_BOX); - adhrbf->color(FL_BACKGROUND_COLOR); - adhrbf->selection_color(FL_INACTIVE_COLOR); - adhrbf->labeltype(FL_NORMAL_LABEL); - adhrbf->labelfont(0); - adhrbf->labelsize(10); - adhrbf->labelcolor(FL_FOREGROUND_COLOR); - adhrbf->maximum(255); - adhrbf->step(1); - adhrbf->callback((Fl_Callback*)cb_adhrbf); - adhrbf->align(Fl_Align(FL_ALIGN_BOTTOM)); - adhrbf->when(FL_WHEN_CHANGED); - } // WidgetPDial* adhrbf - { adhrpar = new Fl_Slider(670, 445, 55, 10); - adhrpar->type(5); - adhrpar->box(FL_FLAT_BOX); - adhrpar->maximum(100); - adhrpar->step(1); - adhrpar->value(50); - adhrpar->callback((Fl_Callback*)cb_adhrpar); - } // Fl_Slider* adhrpar - o->end(); - } // Fl_Group* o - { Fl_Group* o = new Fl_Group(440, 308, 150, 30); - o->box(FL_ENGRAVED_BOX); - { modtype = new Fl_Choice(470, 315, 50, 15, "Mod."); - modtype->tooltip("modulation"); - modtype->down_box(FL_BORDER_BOX); - modtype->labelsize(10); - modtype->textsize(10); - modtype->callback((Fl_Callback*)cb_modtype); - modtype->menu(menu_modtype); - } // Fl_Choice* modtype - { modpar1 = new WidgetPDial(530, 315, 15, 15); - modpar1->tooltip("Oscillator\'s modulation parameter 1"); - modpar1->box(FL_OVAL_BOX); - modpar1->color(FL_BACKGROUND_COLOR); - modpar1->selection_color(FL_INACTIVE_COLOR); - modpar1->labeltype(FL_NORMAL_LABEL); - modpar1->labelfont(0); - modpar1->labelsize(14); - modpar1->labelcolor(FL_FOREGROUND_COLOR); - modpar1->maximum(127); - modpar1->step(1); - modpar1->callback((Fl_Callback*)cb_modpar1); - modpar1->align(Fl_Align(FL_ALIGN_BOTTOM)); - modpar1->when(FL_WHEN_CHANGED); - } // WidgetPDial* modpar1 - { modpar2 = new WidgetPDial(550, 315, 15, 15); - modpar2->tooltip("Oscillator\'s modulation parameter 2"); - modpar2->box(FL_OVAL_BOX); - modpar2->color(FL_BACKGROUND_COLOR); - modpar2->selection_color(FL_INACTIVE_COLOR); - modpar2->labeltype(FL_NORMAL_LABEL); - modpar2->labelfont(0); - modpar2->labelsize(14); - modpar2->labelcolor(FL_FOREGROUND_COLOR); - modpar2->maximum(127); - modpar2->step(1); - modpar2->callback((Fl_Callback*)cb_modpar2); - modpar2->align(Fl_Align(FL_ALIGN_BOTTOM)); - modpar2->when(FL_WHEN_CHANGED); - } // WidgetPDial* modpar2 - { modpar3 = new WidgetPDial(570, 315, 15, 15); - modpar3->tooltip("Oscillator\'s modulation parameter 3"); - modpar3->box(FL_OVAL_BOX); - modpar3->color(FL_BACKGROUND_COLOR); - modpar3->selection_color(FL_INACTIVE_COLOR); - modpar3->labeltype(FL_NORMAL_LABEL); - modpar3->labelfont(0); - modpar3->labelsize(14); - modpar3->labelcolor(FL_FOREGROUND_COLOR); - modpar3->maximum(127); - modpar3->step(1); - modpar3->callback((Fl_Callback*)cb_modpar3); - modpar3->align(Fl_Align(FL_ALIGN_BOTTOM)); - modpar3->when(FL_WHEN_CHANGED); - } // WidgetPDial* modpar3 - o->end(); - } // Fl_Group* o - { Fl_Button* o = new Fl_Button(670, 525, 55, 15, "Sine"); - o->box(FL_THIN_UP_BOX); - o->labelfont(1); - o->labelsize(11); - o->callback((Fl_Callback*)cb_Sine); - } // Fl_Button* o - { Fl_Button* o = new Fl_Button(670, 545, 25, 15, "C"); - o->box(FL_THIN_UP_BOX); - o->color((Fl_Color)179); - o->labelfont(1); - o->labelsize(11); - o->labelcolor(FL_BACKGROUND2_COLOR); - o->callback((Fl_Callback*)cb_C); - } // Fl_Button* o - { Fl_Button* o = new Fl_Button(700, 545, 25, 15, "P"); - o->box(FL_THIN_UP_BOX); - o->color((Fl_Color)179); - o->labelfont(1); - o->labelsize(11); - o->labelcolor(FL_BACKGROUND2_COLOR); - o->callback((Fl_Callback*)cb_P); - } // Fl_Button* o - { _this_has_to_be_the_last = new Fl_Scroll(5, 340, 660, 250); - _this_has_to_be_the_last->type(1); - _this_has_to_be_the_last->box(FL_ENGRAVED_BOX); - { Fl_Pack* o = harmonics = new Fl_Pack(10, 345, 650, 225); - harmonics->type(1); - for (int i=0;ih(),"");h[i]->init(oscil,i,oscildisplaygroup,oldosc,cbwidget,applybutton,master);} - harmonics->end(); - } // Fl_Pack* harmonics - _this_has_to_be_the_last->end(); - } // Fl_Scroll* _this_has_to_be_the_last - if (oscil->ADvsPAD) o->label("PADsynth Harmonic Content Editor"); - osceditUI->end(); - } // Fl_Double_Window* osceditUI - return osceditUI; -} - -OscilEditor::OscilEditor(OscilGen *oscil_,Fl_Widget *oldosc_,Fl_Widget *cbwidget_,Fl_Widget *cbapplywidget_,Master *master_) { - oscil=oscil_; - oldosc=oldosc_; - cbwidget=cbwidget_; - cbapplywidget=cbapplywidget_; - master=master_; - - make_window(); - - refresh(); - osceditUI->show(); -} - -OscilEditor::~OscilEditor() { - osceditUI->hide(); - //for (int i=0;ivalue(oscil->Phmagtype); - rndslider->value(oscil->Prand-64); - - hrndtype->value(oscil->Pamprandtype); - hrnddial->value(oscil->Pamprandpower); - - bftype->value(oscil->Pcurrentbasefunc); - bfparval->value(oscil->Pbasefuncpar-64); - bfslider->value(oscil->Pbasefuncpar-64); - - bfmodtype->value(oscil->Pbasefuncmodulation); - bfmodpar1->value(oscil->Pbasefuncmodulationpar1); - bfmodpar2->value(oscil->Pbasefuncmodulationpar2); - bfmodpar3->value(oscil->Pbasefuncmodulationpar3); - - wshbutton->value(oscil->Pwaveshapingfunction); - wsparval->value(oscil->Pwaveshaping-64); - wshpar->value(oscil->Pwaveshaping-64); - - fltbutton->value(oscil->Pfiltertype); - filtervalue1->value(oscil->Pfilterpar1); - filtervalue2->value(oscil->Pfilterpar2); - filterpref->value(oscil->Pfilterbeforews); - - modtype->value(oscil->Pmodulation); - modpar1->value(oscil->Pmodulationpar1); - modpar2->value(oscil->Pmodulationpar2); - modpar3->value(oscil->Pmodulationpar3); - - sabutton->value(oscil->Psatype); - sadjpar->value(oscil->Psapar); - - harmonicshiftcounter->value(oscil->Pharmonicshift); - harmonicshiftpre->value(oscil->Pharmonicshiftfirst); - - adhrtype->value(oscil->Padaptiveharmonics); - adhrbf->value(oscil->Padaptiveharmonicsbasefreq); - adhrpow->value(oscil->Padaptiveharmonicspower); - adhrtype->value(oscil->Padaptiveharmonicspar); - - for (int i=0;irefresh(); - - pthread_mutex_lock(&master->mutex); - oscil->prepare(); - pthread_mutex_unlock(&master->mutex); - - basefuncdisplaygroup->redraw(); - redrawoscil(); -} - -void OscilEditor::redrawoscil() { - oscildisplaygroup->redraw(); - oldosc->redraw(); - if (cbwidget!=NULL) { - cbwidget->do_callback(); - applybutton->color(FL_RED); - applybutton->redraw(); - }; -} diff --git a/plugins/zynaddsubfx/src/UI/OscilGenUI.fl b/plugins/zynaddsubfx/src/UI/OscilGenUI.fl deleted file mode 100644 index d686b2ecb..000000000 --- a/plugins/zynaddsubfx/src/UI/OscilGenUI.fl +++ /dev/null @@ -1,1133 +0,0 @@ -# data file for the Fltk User Interface Designer (fluid) -version 1.0109 -header_name {.h} -code_name {.cc} -decl {//Copyright (c) 2002-2005 Nasca Octavian Paul} {} - -decl {//License: GNU GPL version 2 or later} {} - -decl {\#include "../Synth/OscilGen.h"} {public -} - -decl {\#include "../Misc/Util.h"} {public -} - -decl {\#include "../Misc/Master.h"} {public -} - -decl {\#include "ResonanceUI.h"} {public -} - -decl {\#include } {public -} - -decl {\#include } {public -} - -decl {\#include } {public -} - -decl {\#include } {} - -decl {\#include } {} - -decl {\#include } {} - -decl {\#include } {} - -decl {\#include "WidgetPDial.h"} {public -} - -decl {\#include "EnvelopeUI.h"} {public -} - -decl {\#include "LFOUI.h"} {public -} - -decl {\#include "FilterUI.h"} {public -} - -decl {\#include "PresetsUI.h"} {public -} - -class OscilSpectrum {: {public Fl_Box} -} { - Function {OscilSpectrum(int x,int y, int w, int h, const char *label=0):Fl_Box(x,y,w,h,label)} {} { - code {oscil=NULL;} {} - } - Function {init(OscilGen *oscil_,int oscbase_,Master *master_)} {} { - code {oscil=oscil_; -oscbase=oscbase_; -master=master_;} {} - } - Function {draw()} {} { - code {int ox=x(),oy=y(),lx=w(),ly=h(),i; -const int maxdb=60;//must be multiple of 10 -int GX=2; -int n=lx/GX-1; -if (n>OSCIL_SIZE/2) n=OSCIL_SIZE/2; - -REALTYPE x; -REALTYPE* spc=new REALTYPE[n]; -for (i=0;imutex); -if (oscbase==0) oscil->getspectrum(n,spc,0); - else oscil->getspectrum(n,spc,1); -pthread_mutex_unlock(&master->mutex); - -//normalize -REALTYPE max=0; -for (i=0;iactive_r()) fl_color(this->parent()->selection_color()); - else fl_color(this->parent()->color()); -fl_line_style(FL_DOT); - -for (i=1;iactive_r()) fl_color(this->parent()->labelcolor()); - else fl_color(this->parent()->color()); -fl_line_style(0); - -//draws the spectrum -for (i=0;idB2rap(-maxdb)) x=rap2dB(x)/maxdb+1; - else x=0; - - int val=(int) ((ly-2)*x); - if (val>0) fl_line(ox+tmp,oy+ly-2-val,ox+tmp,oy+ly-2); -} -delete [] spc;} {selected - } - } - decl {OscilGen *oscil;} {} - decl {int oscbase;} {} - decl {Master *master;} {} -} - -class PSlider {: {public Fl_Slider} -} { - Function {PSlider(int x,int y, int w, int h, const char *label=0):Fl_Slider(x,y,w,h,label)} {} {code{;}} - Function {handle(int event)} {return_type int - } { - code {int X=x(),Y=y(),W=w(),H=h(); - -if ((!Fl::event_buttons())|| (event==0)||(Fl::event_shift()==0)) return(Fl_Slider::handle(event)); - -if (!Fl::event_inside(X,Y,W,H)) { - if (event==FL_DRAG){ - Fl_Slider::handle(FL_RELEASE); - Fl_Slider::handle(FL_LEAVE); - deactivate(); - activate(); - return(1); - }else{ - return(Fl_Slider::handle(event)); - }; -} else { - //Fl_Slider::handle(FL_FOCUS); - Fl_Slider::handle(FL_PUSH); -}; - -return(1);} {} - } -} - -class Oscilloscope {: {public Fl_Box} -} { - Function {Oscilloscope(int x,int y, int w, int h, const char *label=0):Fl_Box(x,y,w,h,label)} {} { - code {oscil=NULL; -phase=64; -oscbase=0;} {} - } - Function {init(OscilGen *oscil_,Master *master_)} {} { - code {oscil=oscil_; -master=master_;} {} - } - Function {init(OscilGen *oscil_,int oscbase_,Master *master_)} {} { - code {oscil=oscil_; -oscbase=oscbase_; -master=master_;} {} - } - Function {init(OscilGen *oscil_,int oscbase_,int phase_,Master *master_)} {} { - code {oscil=oscil_; -oscbase=oscbase_; -phase=phase_; -master=master_;} {} - } - Function {draw()} {} { - code {int ox=x(),oy=y(),lx=w(),ly=h()-1,i; -REALTYPE smps[OSCIL_SIZE]; -pthread_mutex_lock(&master->mutex); -if (oscbase==0) oscil->get(smps,-1.0); - else oscil->getcurrentbasefunction(smps); -pthread_mutex_unlock(&master->mutex); - -if (damage()!=1){ - fl_color(0,0,0); - fl_rectf(ox,oy,lx,ly); -}; - -//normalize -REALTYPE max=0; -for (i=0;iactive_r()) fl_color(this->parent()->labelcolor()); - else fl_color(this->parent()->color()); -int GX=16;if (lxactive_r()) fl_color(this->parent()->selection_color()); - else fl_color(this->parent()->labelcolor()); -int lw=1; -//if ((lx<135)||(ly<135)) lw=1; -fl_line_style(0,lw); -int ph=(int)((phase-64.0)/128.0*OSCIL_SIZE+OSCIL_SIZE); -for (i=1;ivalue(x); - else x=127-(int)o->value(); -if (x==64) o->selection_color(0); - else o->selection_color(222); - -pthread_mutex_lock(&master->mutex); - oscil->Phmag[n]=x; - if (x==64) { - oscil->Phphase[n]=64; - phase->value(64); - }; - oscil->prepare(); -pthread_mutex_unlock(&master->mutex); - -display->redraw(); -oldosc->redraw(); -if (cbwidget!=NULL) { - cbwidget->do_callback(); - applybutton->color(FL_RED); - applybutton->redraw(); -};} - xywh {0 15 15 115} type {Vert Knob} box FLAT_BOX selection_color 222 maximum 127 step 1 value 64 - code0 {o->value(127-oscil->Phmag[n]);} - code1 {if (oscil->Phmag[n]==64) o->selection_color(0);} - class PSlider - } - Fl_Slider phase { - callback {int x=64; -if (Fl::event_button3()) o->value(x); - else x=(int)o->value(); - -pthread_mutex_lock(&master->mutex); - oscil->Phphase[n]=x; - oscil->prepare(); -pthread_mutex_unlock(&master->mutex); - -display->redraw(); -oldosc->redraw(); -if (cbwidget!=NULL) { - cbwidget->do_callback(); - applybutton->color(FL_RED); - applybutton->redraw(); -};} - xywh {0 135 15 75} type {Vert Knob} box FLAT_BOX selection_color 222 maximum 127 step 1 value 64 - code0 {o->value(oscil->Phphase[n]);} - class PSlider - } - Fl_Box {} { - xywh {15 70 5 5} box FLAT_BOX color 45 - } - Fl_Box {} { - xywh {15 170 5 5} box FLAT_BOX color 45 - } - Fl_Box {} { - label 01 - xywh {0 210 20 15} labelfont 1 labelsize 9 align 20 - code0 {char tmp[10];snprintf(tmp,10,"%d",n+1);o->label(strdup(tmp));} - } - Fl_Box {} { - label 01 - xywh {0 0 20 15} labelfont 1 labelsize 9 align 20 - code0 {char tmp[10];snprintf(tmp,10,"%d",n+1);o->label(strdup(tmp));} - } - } - } - Function {Oscilharmonic(int x,int y, int w, int h, const char *label=0):Fl_Group(x,y,w,h,label)} {} { - code {n=0; -oscil=NULL; -display=NULL; -applybutton=NULL; -cbwidget=NULL;} {} - } - Function {init(OscilGen *oscil_,int n_,Fl_Group *display_,Fl_Widget *oldosc_,Fl_Widget *cbwidget_,Fl_Widget *applybutton_, Master *master_)} {} { - code {oscil=oscil_; -n=n_; -display=display_; -master=master_; -oldosc=oldosc_; -cbwidget=cbwidget_; -applybutton=applybutton_; -make_window(); -end(); -harmonic->show();} {} - } - Function {refresh()} {} { - code {mag->value(127-oscil->Phmag[n]); -phase->value(oscil->Phphase[n]); - -if (oscil->Phmag[n]==64) mag->selection_color(0); - else mag->selection_color(222);} {} - } - Function {~Oscilharmonic()} {} { - code {harmonic->hide(); -//delete(harmonic);} {} - } - decl {OscilGen *oscil;} {} - decl {Fl_Group *display;} {} - decl {int n;} {} - decl {Fl_Widget *oldosc,*cbwidget,*applybutton;} {} - decl {Master *master;} {} -} - -class OscilEditor {: {public PresetsUI_} -} { - Function {make_window()} {} { - Fl_Window osceditUI { - label {ADsynth Oscillator Editor} - xywh {131 90 735 595} type Double hide - code0 {if (oscil->ADvsPAD) o->label("PADsynth Harmonic Content Editor");} - } { - Fl_Button applybutton { - label Apply - callback {applybutton->color(FL_GRAY); -applybutton->redraw(); -if (cbapplywidget!=NULL) { - cbapplywidget->do_callback(); - cbapplywidget->color(FL_GRAY); - cbapplywidget->redraw(); -};} - xywh {300 280 60 20} box THIN_UP_BOX labelfont 1 - code0 {if (!oscil->ADvsPAD) o->hide();} - } - Fl_Group oscildisplaygroup { - xywh {5 5 360 300} box ENGRAVED_FRAME - } { - Fl_Group {} {open - xywh {10 85 350 190} box THIN_DOWN_BOX color 32 selection_color 71 labelcolor 179 - code0 {Oscilloscope *osc=new Oscilloscope(o->x(),o->y(),o->w(),o->h(),"");} - code1 {osc->init(oscil,master);} - } {} - Fl_Box {} { - label Oscillator - xywh {120 10 110 20} box FLAT_BOX labelfont 1 - } - Fl_Value_Slider rndslider { - label rnd - callback {oscil->Prand=(int)o->value()+64; -oscildisplaygroup->redraw(); -oldosc->redraw();} - tooltip {Oscilator Phase Randomness: smaller than 0 is "group", larger than 0 is for each harmonic} xywh {140 285 100 10} type {Horz Knob} box FLAT_BOX labelsize 10 align 5 minimum -64 maximum 63 step 1 - code0 {if (oscil->ADvsPAD) o->hide();} - } - Fl_Group {} {open - xywh {10 30 350 50} box THIN_DOWN_BOX color 32 selection_color 218 labelcolor 63 - code0 {OscilSpectrum *spc=new OscilSpectrum(o->x(),o->y(),o->w(),o->h(),"");} - code1 {spc->init(oscil,0,master);} - } {} - Fl_Group {} { - xywh {246 277 115 25} box ENGRAVED_BOX - code0 {if (oscil->ADvsPAD) o->hide();} - } { - Fl_Choice hrndtype { - label {H.rnd} - callback {oscil->Pamprandtype=(int) o->value();} - tooltip {Harmonic Amplitude Randomness} xywh {281 282 50 15} down_box BORDER_BOX labelsize 10 textsize 10 - } { - MenuItem {} { - label None - xywh {60 60 100 20} labelfont 1 labelsize 10 - } - MenuItem {} { - label Pow - xywh {70 70 100 20} labelfont 1 labelsize 10 - } - MenuItem {} { - label Sin - xywh {80 80 100 20} labelfont 1 labelsize 10 - } - } - Fl_Dial hrnddial { - callback {oscil->Pamprandpower=(int) o->value();} - tooltip {Oscillator's spectrum adjust parameter} xywh {338 280 18 18} maximum 127 step 1 - class WidgetPDial - } - } - } - Fl_Box {} { - label {Base Func.} - xywh {495 15 110 20} box FLAT_BOX labelfont 1 - } - Fl_Group basefuncdisplaygroup { - xywh {365 5 360 300} box ENGRAVED_FRAME - } { - Fl_Group {} { - xywh {370 85 350 190} box THIN_DOWN_BOX color 32 selection_color 71 labelcolor 179 - code0 {Oscilloscope *osc=new Oscilloscope(o->x(),o->y(),o->w(),o->h(),"");} - code1 {osc->init(oscil,1,master);} - } {} - Fl_Dial bfslider { - callback {oscil->Pbasefuncpar=(int)o->value()+64; -basefuncdisplaygroup->redraw(); -bfparval->value(oscil->Pbasefuncpar-64); - -redrawoscil();} - tooltip {Base Function Parameter} xywh {520 280 20 20} minimum -64 maximum 63 step 1 - class WidgetPDial - } - Fl_Choice bftype { - label {Base.F..} - callback {oscil->Pcurrentbasefunc=(int) o->value(); - -basefuncdisplaygroup->redraw(); -redrawoscil(); - -if ((oscil->Pcurrentbasefunc==0)||(oscil->Pcurrentbasefunc==127)) basefuncmodulation->deactivate(); - else basefuncmodulation->activate();} - xywh {370 285 90 15} down_box BORDER_BOX labelsize 10 align 5 textsize 11 - } { - MenuItem {} { - label Sine - xywh {10 10 100 20} labelfont 1 labelsize 11 - } - MenuItem {} { - label Triangle - xywh {20 20 100 20} labelfont 1 labelsize 11 - } - MenuItem {} { - label Pulse - xywh {30 30 100 20} labelfont 1 labelsize 11 - } - MenuItem {} { - label Saw - xywh {40 40 100 20} labelfont 1 labelsize 11 - } - MenuItem {} { - label Power - xywh {50 50 100 20} labelfont 1 labelsize 11 - } - MenuItem {} { - label Gauss - xywh {50 50 100 20} labelfont 1 labelsize 11 - } - MenuItem {} { - label Diode - xywh {60 60 100 20} labelfont 1 labelsize 11 - } - MenuItem {} { - label AbsSine - xywh {70 70 100 20} labelfont 1 labelsize 11 - } - MenuItem {} { - label PulseSine - xywh {80 80 100 20} labelfont 1 labelsize 11 - } - MenuItem {} { - label StrchSine - xywh {90 90 100 20} labelfont 1 labelsize 11 - } - MenuItem {} { - label Chirp - xywh {100 100 100 20} labelfont 1 labelsize 11 - } - MenuItem {} { - label AbsStrSine - xywh {102 102 100 20} labelfont 1 labelsize 11 - } - MenuItem {} { - label Chebyshev - xywh {112 112 100 20} labelfont 1 labelsize 11 - } - MenuItem {} { - label Sqr - xywh {122 122 100 20} labelfont 1 labelsize 11 - } - } - Fl_Box {} { - label {Base Func.} - xywh {480 10 110 20} box FLAT_BOX labelfont 1 - } - Fl_Group {} {open - xywh {370 30 350 50} box THIN_DOWN_BOX color 32 selection_color 218 labelcolor 63 - code0 {OscilSpectrum *spc=new OscilSpectrum (o->x(),o->y(),o->w(),o->h(),"");} - code1 {spc->init(oscil,1,master);} - } {} - Fl_Value_Output bfparval { - label {Par.} - xywh {490 285 25 15} labelsize 12 minimum -63 maximum 63 step 1 - } - Fl_Group basefuncmodulation { - xywh {550 276 169 25} box ENGRAVED_BOX - code0 {if ((oscil->Pcurrentbasefunc==0)||(oscil->Pcurrentbasefunc==127)) basefuncmodulation->deactivate();} - } { - Fl_Choice bfmodtype { - label {B.F.Mod.} - callback {oscil->Pbasefuncmodulation=(int) o->value(); -basefuncdisplaygroup->redraw(); -redrawoscil();} - tooltip {Base function modulation} xywh {599 281 50 15} down_box BORDER_BOX labelsize 10 textsize 10 - } { - MenuItem {} { - label None - xywh {50 50 100 20} labelfont 1 labelsize 10 - } - MenuItem {} { - label Rev - xywh {60 60 100 20} labelfont 1 labelsize 10 - } - MenuItem {} { - label Sine - xywh {70 70 100 20} labelfont 1 labelsize 10 - } - MenuItem {} { - label Pow - xywh {80 80 100 20} labelfont 1 labelsize 10 - } - } - Fl_Dial bfmodpar1 { - callback {oscil->Pbasefuncmodulationpar1=(int)o->value(); -basefuncdisplaygroup->redraw(); -redrawoscil();} - tooltip {Oscillator's modulation parameter 1} xywh {659 281 15 15} maximum 127 step 1 - class WidgetPDial - } - Fl_Dial bfmodpar2 { - callback {oscil->Pbasefuncmodulationpar2=(int)o->value(); -basefuncdisplaygroup->redraw(); -redrawoscil();} - tooltip {Oscillator's modulation parameter 2} xywh {679 281 15 15} maximum 127 step 1 - class WidgetPDial - } - Fl_Dial bfmodpar3 { - callback {oscil->Pbasefuncmodulationpar3=(int)o->value(); -basefuncdisplaygroup->redraw(); -redrawoscil();} - tooltip {Oscillator's modulation parameter 3} xywh {699 281 15 15} maximum 127 step 1 - class WidgetPDial - } - } - } - Fl_Choice magtype { - label {Mag.Type} - callback {oscil->Phmagtype=(int) o->value(); -basefuncdisplaygroup->redraw(); - -redrawoscil();} - xywh {70 280 65 20} down_box BORDER_BOX labelsize 11 textsize 11 - } { - MenuItem {} { - label Linear - xywh {0 0 100 20} labelfont 1 labelsize 11 - } - MenuItem {} { - label {-40dB} - xywh {10 10 100 20} labelfont 1 labelsize 11 - } - MenuItem {} { - label {-60dB} - xywh {20 20 100 20} labelfont 1 labelsize 11 - } - MenuItem {} { - label {-80dB} - xywh {30 30 100 20} labelfont 1 labelsize 11 - } - MenuItem {} { - label {-100dB} - xywh {40 40 100 20} labelfont 1 labelsize 11 - } - } - Fl_Button {} { - label {Use as base} - callback {oscil->useasbase(); -if (autoclearbutton->value()){ - for (int i=0;imag->value(64); - oscil->Phmag[i]=64; - h[i]->phase->value(64); - oscil->Phphase[i]=64; - }; - oscil->Phmag[0]=127; - - oscil->Pharmonicshift=0; - harmonicshiftcounter->value(0); - - h[0]->mag->value(0); - wshbutton->value(0); - wshbutton->do_callback(); - fltbutton->value(0); - fltbutton->do_callback(); - sabutton->value(0); - sabutton->do_callback(); -}; - -pthread_mutex_lock(&master->mutex); - for (int i=0;iPhmag[i]==64) h[i]->mag->selection_color(0); - else h[i]->mag->selection_color(222); - }; - oscil->prepare(); -pthread_mutex_unlock(&master->mutex); - -basefuncdisplaygroup->redraw(); -redrawoscil();} - tooltip {Use this Oscillator as base function} xywh {5 313 85 20} box THIN_UP_BOX labelfont 1 labelsize 11 - } - Fl_Button {} { - label Close - callback {osceditUI->hide();} - xywh {668 565 62 25} box THIN_UP_BOX - } - Fl_Button {} { - label Clear - callback {if (!fl_choice("Clear the harmonics settings?","No","Yes",NULL)) return; - -for (int i=0;imag->value(64); - oscil->Phmag[i]=64; - h[i]->phase->value(64); - oscil->Phphase[i]=64; -}; -oscil->Phmag[0]=127; -h[0]->mag->value(0); - -for (int i=0;iPhmag[i]==64) h[i]->mag->selection_color(0); - else h[i]->mag->selection_color(222); -}; - -//harmonics->redraw(); - -pthread_mutex_lock(&master->mutex); - oscil->prepare(); -pthread_mutex_unlock(&master->mutex); - -redrawoscil();} - xywh {670 505 55 15} box THIN_UP_BOX labelfont 1 labelsize 11 - } - Fl_Group {} { - xywh {135 308 150 30} box ENGRAVED_BOX - } { - Fl_Choice wshbutton { - label {Wsh.} - callback {oscil->Pwaveshapingfunction=(int) o->value(); -basefuncdisplaygroup->redraw(); -redrawoscil();} open - tooltip {Waveshaping function} xywh {165 313 55 20} down_box BORDER_BOX labelsize 10 textsize 10 - } { - MenuItem {} { - label None - xywh {25 25 100 20} labelfont 1 labelsize 10 - } - MenuItem {} { - label Atan - xywh {35 35 100 20} labelfont 1 labelsize 10 - } - MenuItem {} { - label Asym1 - xywh {45 45 100 20} labelfont 1 labelsize 10 - } - MenuItem {} { - label Pow - xywh {55 55 100 20} labelfont 1 labelsize 10 - } - MenuItem {} { - label Sine - xywh {65 65 100 20} labelfont 1 labelsize 10 - } - MenuItem {} { - label Qnts - xywh {75 75 100 20} labelfont 1 labelsize 10 - } - MenuItem {} { - label Zigzg - xywh {85 85 100 20} labelfont 1 labelsize 10 - } - MenuItem {} { - label Lmt - xywh {95 95 100 20} labelfont 1 labelsize 10 - } - MenuItem {} { - label LmtU - xywh {105 105 100 20} labelfont 1 labelsize 10 - } - MenuItem {} { - label LmtL - xywh {115 115 100 20} labelfont 1 labelsize 10 - } - MenuItem {} { - label ILmt - xywh {127 127 100 20} labelfont 1 labelsize 10 - } - MenuItem {} { - label Clip - xywh {137 137 100 20} labelfont 1 labelsize 10 - } - MenuItem {} { - label Asym2 - xywh {85 85 100 20} labelfont 1 labelsize 10 - } - MenuItem {} { - label Pow2 - xywh {95 95 100 20} labelfont 1 labelsize 10 - } - MenuItem {} { - label Sgm - xywh {90 90 100 20} labelfont 1 labelsize 10 - } - } - Fl_Dial wshpar { - callback {oscil->Pwaveshaping=(int)o->value()+64; -wsparval->value(oscil->Pwaveshaping-64); -redrawoscil();} - tooltip {Waveshaping Parameter} xywh {260 313 20 20} minimum -64 maximum 63 step 1 - class WidgetPDial - } - Fl_Value_Output wsparval { - xywh {228 316 25 15} labelsize 12 minimum -63 maximum 63 step 1 - } - } - Fl_Light_Button autoclearbutton { - label {Clr.} - tooltip {Auto clear when using the oscillator as base function} xywh {95 313 35 20} box THIN_UP_BOX value 1 labelfont 1 labelsize 10 - } - Fl_Group {} { - xywh {285 308 155 30} box ENGRAVED_BOX - } { - Fl_Choice fltbutton { - label Filter - callback {oscil->Pfiltertype=(int) o->value(); - -redrawoscil();} - tooltip {Oscillator's filter type} xywh {315 313 50 20} down_box BORDER_BOX labelsize 10 textsize 10 - } { - MenuItem {} { - label None - xywh {35 35 100 20} labelfont 1 labelsize 10 - } - MenuItem {} { - label LP1 - xywh {45 45 100 20} labelfont 1 labelsize 10 - } - MenuItem {} { - label HP1a - xywh {55 55 100 20} labelfont 1 labelsize 10 - } - MenuItem {} { - label HP1b - xywh {65 65 100 20} labelfont 1 labelsize 10 - } - MenuItem {} { - label BP1 - xywh {75 75 100 20} labelfont 1 labelsize 10 - } - MenuItem {} { - label BS1 - xywh {85 85 100 20} labelfont 1 labelsize 10 - } - MenuItem {} { - label LP2 - xywh {55 55 100 20} labelfont 1 labelsize 10 - } - MenuItem {} { - label HP2 - xywh {65 65 100 20} labelfont 1 labelsize 10 - } - MenuItem {} { - label BP2 - xywh {65 65 100 20} labelfont 1 labelsize 10 - } - MenuItem {} { - label BS2 - xywh {75 75 100 20} labelfont 1 labelsize 10 - } - MenuItem {} { - label Cos - xywh {75 75 100 20} labelfont 1 labelsize 10 - } - MenuItem {} { - label Sin - xywh {85 85 100 20} labelfont 1 labelsize 10 - } - MenuItem {} { - label LSh - xywh {95 95 100 20} labelfont 1 labelsize 10 - } - MenuItem {} { - label S - xywh {105 105 100 20} labelfont 1 labelsize 10 - } - } - Fl_Dial filtervalue1 { - callback {oscil->Pfilterpar1=(int)o->value(); - -redrawoscil();} - tooltip {Oscillator's filter parameter1} xywh {367 313 20 20} maximum 127 step 1 - class WidgetPDial - } - Fl_Check_Button filterpref { - label p - callback {oscil->Pfilterbeforews=(int)o->value(); - -redrawoscil();} - tooltip {Apply the filter before the waveshaping} xywh {415 313 20 20} down_box DOWN_BOX labelsize 10 align 24 - } - Fl_Dial filtervalue2 { - callback {oscil->Pfilterpar2=(int)o->value(); - -redrawoscil();} - tooltip {Oscillator's filter parameter2} xywh {392 313 20 20} maximum 127 step 1 - class WidgetPDial - } - } - Fl_Group {} { - xywh {590 308 135 30} box ENGRAVED_BOX - } { - Fl_Choice sabutton { - label {Sp.adj.} - callback {oscil->Psatype=(int) o->value(); -redrawoscil();} - tooltip {Oscillator's spectrum adjust} xywh {630 313 60 20} down_box BORDER_BOX labelsize 10 textsize 10 - } { - MenuItem {} { - label None - xywh {55 55 100 20} labelfont 1 labelsize 10 - } - MenuItem {} { - label Pow - xywh {65 65 100 20} labelfont 1 labelsize 10 - } - MenuItem {} { - label ThrsD - xywh {75 75 100 20} labelfont 1 labelsize 10 - } - MenuItem {} { - label ThrsU - xywh {85 85 100 20} labelfont 1 labelsize 10 - } - } - Fl_Dial sadjpar { - callback {oscil->Psapar=(int)o->value(); -redrawoscil();} - tooltip {Oscillator's spectrum adjust parameter} xywh {695 313 20 20} maximum 127 step 1 - class WidgetPDial - } - } - Fl_Group {} { - xywh {665 340 65 65} box ENGRAVED_BOX - } { - Fl_Counter harmonicshiftcounter { - label {Harmonic Shift} - callback {oscil->Pharmonicshift=(int)o->value(); -redrawoscil();} - xywh {670 365 55 15} type Simple labelsize 10 align 129 minimum -64 maximum 64 step 1 textfont 1 textsize 10 - } - Fl_Check_Button harmonicshiftpre { - label preH - callback {oscil->Pharmonicshiftfirst=(int)o->value(); -redrawoscil();} - tooltip {Apply the harmonic shift before the waveshaping and filtering} xywh {690 385 34 15} down_box DOWN_BOX labelsize 10 align 24 - } - Fl_Button {} { - label R - callback {oscil->Pharmonicshift=0; -harmonicshiftcounter->value(0); -redrawoscil();} - xywh {670 385 20 15} box THIN_UP_BOX labelfont 1 labelsize 10 - } - } - Fl_Group {} { - xywh {665 410 65 90} box ENGRAVED_FRAME - } { - Fl_Choice adhrtype { - label {Adpt.Harm.} - callback {oscil->Padaptiveharmonics=(int) o->value(); -redrawoscil();} - tooltip {The type of the addaptive harmonics} xywh {670 425 55 15} down_box BORDER_BOX labelsize 10 align 129 when 6 textsize 10 - } { - MenuItem {} { - label OFF - xywh {80 80 100 20} labelfont 1 labelsize 10 - } - MenuItem {} { - label ON - xywh {90 90 100 20} labelfont 1 labelsize 10 - } - MenuItem {} { - label Square - xywh {100 100 100 20} labelfont 1 labelsize 10 - } - MenuItem {} { - label 2xSub - xywh {110 110 100 20} labelfont 1 labelsize 10 - } - MenuItem {} { - label 2xAdd - xywh {120 120 100 20} labelfont 1 labelsize 10 - } - MenuItem {} { - label 3xSub - xywh {120 120 100 20} labelfont 1 labelsize 10 - } - MenuItem {} { - label 3xAdd - xywh {130 130 100 20} labelfont 1 labelsize 10 - } - MenuItem {} { - label 4xSub - xywh {130 130 100 20} labelfont 1 labelsize 10 - } - MenuItem {} { - label 4xAdd - xywh {140 140 100 20} labelfont 1 labelsize 10 - } - } - Fl_Dial adhrpow { - label pow - callback {oscil->Padaptiveharmonicspower=(int)o->value(); -redrawoscil();} - tooltip {Adaptive harmonics power} xywh {700 460 25 25} labelsize 10 maximum 200 step 1 - class WidgetPDial - } - Fl_Dial adhrbf { - label baseF - callback {oscil->Padaptiveharmonicsbasefreq=(int)o->value(); -redrawoscil();} - tooltip {Adaptive harmonics base frequency} xywh {670 460 25 25} labelsize 10 maximum 255 step 1 - class WidgetPDial - } - Fl_Slider adhrpar { - callback {oscil->Padaptiveharmonicspar=(int)o->value(); -redrawoscil();} - xywh {670 445 55 10} type {Horz Knob} box FLAT_BOX maximum 100 step 1 value 50 - } - } - Fl_Group {} { - xywh {440 308 150 30} box ENGRAVED_BOX - } { - Fl_Choice modtype { - label {Mod.} - callback {oscil->Pmodulation=(int) o->value(); - -redrawoscil();} - tooltip modulation xywh {470 315 50 15} down_box BORDER_BOX labelsize 10 textsize 10 - } { - MenuItem {} { - label None - xywh {60 60 100 20} labelfont 1 labelsize 10 - } - MenuItem {} { - label Rev - xywh {70 70 100 20} labelfont 1 labelsize 10 - } - MenuItem {} { - label Sine - xywh {80 80 100 20} labelfont 1 labelsize 10 - } - MenuItem {} { - label Pow - xywh {90 90 100 20} labelfont 1 labelsize 10 - } - } - Fl_Dial modpar1 { - callback {oscil->Pmodulationpar1=(int)o->value(); - -redrawoscil();} - tooltip {Oscillator's modulation parameter 1} xywh {530 315 15 15} maximum 127 step 1 - class WidgetPDial - } - Fl_Dial modpar2 { - callback {oscil->Pmodulationpar2=(int)o->value(); - -redrawoscil();} - tooltip {Oscillator's modulation parameter 2} xywh {550 315 15 15} maximum 127 step 1 - class WidgetPDial - } - Fl_Dial modpar3 { - callback {oscil->Pmodulationpar3=(int)o->value(); -redrawoscil();} - tooltip {Oscillator's modulation parameter 3} xywh {570 315 15 15} maximum 127 step 1 - class WidgetPDial - } - } - Fl_Button {} { - label Sine - callback {if (!fl_choice("Convert to SINE?","No","Yes",NULL)) return; - -pthread_mutex_lock(&master->mutex); - oscil->convert2sine(0); -pthread_mutex_unlock(&master->mutex); - -redrawoscil(); -refresh();} - xywh {670 525 55 15} box THIN_UP_BOX labelfont 1 labelsize 11 - } - Fl_Button {} { - label C - callback {presetsui->copy(oscil);} - xywh {670 545 25 15} box THIN_UP_BOX color 179 labelfont 1 labelsize 11 labelcolor 7 - } - Fl_Button {} { - label P - callback {presetsui->paste(oscil,this);} - xywh {700 545 25 15} box THIN_UP_BOX color 179 labelfont 1 labelsize 11 labelcolor 7 - } - Fl_Scroll _this_has_to_be_the_last { - xywh {5 340 660 250} type HORIZONTAL box ENGRAVED_BOX - } { - Fl_Pack harmonics {open - xywh {10 345 650 225} type HORIZONTAL - code0 {for (int i=0;ih(),"");h[i]->init(oscil,i,oscildisplaygroup,oldosc,cbwidget,applybutton,master);}} - } {} - } - } - } - Function {OscilEditor(OscilGen *oscil_,Fl_Widget *oldosc_,Fl_Widget *cbwidget_,Fl_Widget *cbapplywidget_,Master *master_)} {} { - code {oscil=oscil_; -oldosc=oldosc_; -cbwidget=cbwidget_; -cbapplywidget=cbapplywidget_; -master=master_; - -make_window(); - -refresh(); -osceditUI->show();} {} - } - Function {~OscilEditor()} {} { - code {osceditUI->hide(); -//for (int i=0;ivalue(oscil->Phmagtype); -rndslider->value(oscil->Prand-64); - -hrndtype->value(oscil->Pamprandtype); -hrnddial->value(oscil->Pamprandpower); - -bftype->value(oscil->Pcurrentbasefunc); -bfparval->value(oscil->Pbasefuncpar-64); -bfslider->value(oscil->Pbasefuncpar-64); - -bfmodtype->value(oscil->Pbasefuncmodulation); -bfmodpar1->value(oscil->Pbasefuncmodulationpar1); -bfmodpar2->value(oscil->Pbasefuncmodulationpar2); -bfmodpar3->value(oscil->Pbasefuncmodulationpar3); - -wshbutton->value(oscil->Pwaveshapingfunction); -wsparval->value(oscil->Pwaveshaping-64); -wshpar->value(oscil->Pwaveshaping-64); - -fltbutton->value(oscil->Pfiltertype); -filtervalue1->value(oscil->Pfilterpar1); -filtervalue2->value(oscil->Pfilterpar2); -filterpref->value(oscil->Pfilterbeforews); - -modtype->value(oscil->Pmodulation); -modpar1->value(oscil->Pmodulationpar1); -modpar2->value(oscil->Pmodulationpar2); -modpar3->value(oscil->Pmodulationpar3); - -sabutton->value(oscil->Psatype); -sadjpar->value(oscil->Psapar); - -harmonicshiftcounter->value(oscil->Pharmonicshift); -harmonicshiftpre->value(oscil->Pharmonicshiftfirst); - -adhrtype->value(oscil->Padaptiveharmonics); -adhrbf->value(oscil->Padaptiveharmonicsbasefreq); -adhrpow->value(oscil->Padaptiveharmonicspower); -adhrtype->value(oscil->Padaptiveharmonicspar); - -for (int i=0;irefresh(); - -pthread_mutex_lock(&master->mutex); - oscil->prepare(); -pthread_mutex_unlock(&master->mutex); - -basefuncdisplaygroup->redraw(); -redrawoscil();} {} - } - Function {redrawoscil()} {} { - code {oscildisplaygroup->redraw(); -oldosc->redraw(); -if (cbwidget!=NULL) { - cbwidget->do_callback(); - applybutton->color(FL_RED); - applybutton->redraw(); -};} {} - } - decl {OscilGen *oscil;} {} - decl {Fl_Widget *oldosc,*cbwidget,*cbapplywidget;} {} - decl {Oscilharmonic *h[MAX_AD_HARMONICS];} {} - decl {Master *master;} {} -} diff --git a/plugins/zynaddsubfx/src/UI/OscilGenUI.h b/plugins/zynaddsubfx/src/UI/OscilGenUI.h deleted file mode 100644 index 0cd795bc8..000000000 --- a/plugins/zynaddsubfx/src/UI/OscilGenUI.h +++ /dev/null @@ -1,281 +0,0 @@ -// generated by Fast Light User Interface Designer (fluid) version 1.0300 - -#ifndef OscilGenUI_h -#define OscilGenUI_h -#include -#include "../Synth/OscilGen.h" -#include "../Misc/Util.h" -#include "../Misc/Master.h" -#include "ResonanceUI.h" -#include -#include -#include -#include "WidgetPDial.h" -#include "EnvelopeUI.h" -#include "LFOUI.h" -#include "FilterUI.h" -#include "PresetsUI.h" - -class OscilSpectrum : public Fl_Box { -public: - OscilSpectrum(int x,int y, int w, int h, const char *label=0); - void init(OscilGen *oscil_,int oscbase_,Master *master_); - void draw(); -private: - OscilGen *oscil; - int oscbase; - Master *master; -}; - -class PSlider : public Fl_Slider { -public: - PSlider(int x,int y, int w, int h, const char *label=0); - int handle(int event); -}; - -class Oscilloscope : public Fl_Box { -public: - Oscilloscope(int x,int y, int w, int h, const char *label=0); - void init(OscilGen *oscil_,Master *master_); - void init(OscilGen *oscil_,int oscbase_,Master *master_); - void init(OscilGen *oscil_,int oscbase_,int phase_,Master *master_); - void draw(); -private: - OscilGen *oscil; - int oscbase; -public: - int phase; -private: - Master *master; -}; -#include - -class Oscilharmonic : public Fl_Group { - Fl_Group* make_window(); - Fl_Group *harmonic; -public: - PSlider *mag; -private: - void cb_mag_i(PSlider*, void*); - static void cb_mag(PSlider*, void*); -public: - PSlider *phase; -private: - void cb_phase_i(PSlider*, void*); - static void cb_phase(PSlider*, void*); -public: - Oscilharmonic(int x,int y, int w, int h, const char *label=0); - void init(OscilGen *oscil_,int n_,Fl_Group *display_,Fl_Widget *oldosc_,Fl_Widget *cbwidget_,Fl_Widget *applybutton_, Master *master_); - void refresh(); - ~Oscilharmonic(); -private: - OscilGen *oscil; - Fl_Group *display; - int n; - Fl_Widget *oldosc,*cbwidget,*applybutton; - Master *master; -}; -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -class OscilEditor : public PresetsUI_ { -public: - Fl_Double_Window* make_window(); - Fl_Double_Window *osceditUI; - Fl_Button *applybutton; -private: - void cb_applybutton_i(Fl_Button*, void*); - static void cb_applybutton(Fl_Button*, void*); -public: - Fl_Group *oscildisplaygroup; - Fl_Value_Slider *rndslider; -private: - void cb_rndslider_i(Fl_Value_Slider*, void*); - static void cb_rndslider(Fl_Value_Slider*, void*); -public: - Fl_Choice *hrndtype; -private: - void cb_hrndtype_i(Fl_Choice*, void*); - static void cb_hrndtype(Fl_Choice*, void*); - static Fl_Menu_Item menu_hrndtype[]; -public: - WidgetPDial *hrnddial; -private: - void cb_hrnddial_i(WidgetPDial*, void*); - static void cb_hrnddial(WidgetPDial*, void*); -public: - Fl_Group *basefuncdisplaygroup; - WidgetPDial *bfslider; -private: - void cb_bfslider_i(WidgetPDial*, void*); - static void cb_bfslider(WidgetPDial*, void*); -public: - Fl_Choice *bftype; -private: - void cb_bftype_i(Fl_Choice*, void*); - static void cb_bftype(Fl_Choice*, void*); - static Fl_Menu_Item menu_bftype[]; -public: - Fl_Value_Output *bfparval; - Fl_Group *basefuncmodulation; - Fl_Choice *bfmodtype; -private: - void cb_bfmodtype_i(Fl_Choice*, void*); - static void cb_bfmodtype(Fl_Choice*, void*); - static Fl_Menu_Item menu_bfmodtype[]; -public: - WidgetPDial *bfmodpar1; -private: - void cb_bfmodpar1_i(WidgetPDial*, void*); - static void cb_bfmodpar1(WidgetPDial*, void*); -public: - WidgetPDial *bfmodpar2; -private: - void cb_bfmodpar2_i(WidgetPDial*, void*); - static void cb_bfmodpar2(WidgetPDial*, void*); -public: - WidgetPDial *bfmodpar3; -private: - void cb_bfmodpar3_i(WidgetPDial*, void*); - static void cb_bfmodpar3(WidgetPDial*, void*); -public: - Fl_Choice *magtype; -private: - void cb_magtype_i(Fl_Choice*, void*); - static void cb_magtype(Fl_Choice*, void*); - static Fl_Menu_Item menu_magtype[]; - void cb_Use_i(Fl_Button*, void*); - static void cb_Use(Fl_Button*, void*); - void cb_Close_i(Fl_Button*, void*); - static void cb_Close(Fl_Button*, void*); - void cb_Clear_i(Fl_Button*, void*); - static void cb_Clear(Fl_Button*, void*); -public: - Fl_Choice *wshbutton; -private: - void cb_wshbutton_i(Fl_Choice*, void*); - static void cb_wshbutton(Fl_Choice*, void*); - static Fl_Menu_Item menu_wshbutton[]; -public: - WidgetPDial *wshpar; -private: - void cb_wshpar_i(WidgetPDial*, void*); - static void cb_wshpar(WidgetPDial*, void*); -public: - Fl_Value_Output *wsparval; - Fl_Light_Button *autoclearbutton; - Fl_Choice *fltbutton; -private: - void cb_fltbutton_i(Fl_Choice*, void*); - static void cb_fltbutton(Fl_Choice*, void*); - static Fl_Menu_Item menu_fltbutton[]; -public: - WidgetPDial *filtervalue1; -private: - void cb_filtervalue1_i(WidgetPDial*, void*); - static void cb_filtervalue1(WidgetPDial*, void*); -public: - Fl_Check_Button *filterpref; -private: - void cb_filterpref_i(Fl_Check_Button*, void*); - static void cb_filterpref(Fl_Check_Button*, void*); -public: - WidgetPDial *filtervalue2; -private: - void cb_filtervalue2_i(WidgetPDial*, void*); - static void cb_filtervalue2(WidgetPDial*, void*); -public: - Fl_Choice *sabutton; -private: - void cb_sabutton_i(Fl_Choice*, void*); - static void cb_sabutton(Fl_Choice*, void*); - static Fl_Menu_Item menu_sabutton[]; -public: - WidgetPDial *sadjpar; -private: - void cb_sadjpar_i(WidgetPDial*, void*); - static void cb_sadjpar(WidgetPDial*, void*); -public: - Fl_Counter *harmonicshiftcounter; -private: - void cb_harmonicshiftcounter_i(Fl_Counter*, void*); - static void cb_harmonicshiftcounter(Fl_Counter*, void*); -public: - Fl_Check_Button *harmonicshiftpre; -private: - void cb_harmonicshiftpre_i(Fl_Check_Button*, void*); - static void cb_harmonicshiftpre(Fl_Check_Button*, void*); - void cb_R_i(Fl_Button*, void*); - static void cb_R(Fl_Button*, void*); -public: - Fl_Choice *adhrtype; -private: - void cb_adhrtype_i(Fl_Choice*, void*); - static void cb_adhrtype(Fl_Choice*, void*); - static Fl_Menu_Item menu_adhrtype[]; -public: - WidgetPDial *adhrpow; -private: - void cb_adhrpow_i(WidgetPDial*, void*); - static void cb_adhrpow(WidgetPDial*, void*); -public: - WidgetPDial *adhrbf; -private: - void cb_adhrbf_i(WidgetPDial*, void*); - static void cb_adhrbf(WidgetPDial*, void*); -public: - Fl_Slider *adhrpar; -private: - void cb_adhrpar_i(Fl_Slider*, void*); - static void cb_adhrpar(Fl_Slider*, void*); -public: - Fl_Choice *modtype; -private: - void cb_modtype_i(Fl_Choice*, void*); - static void cb_modtype(Fl_Choice*, void*); - static Fl_Menu_Item menu_modtype[]; -public: - WidgetPDial *modpar1; -private: - void cb_modpar1_i(WidgetPDial*, void*); - static void cb_modpar1(WidgetPDial*, void*); -public: - WidgetPDial *modpar2; -private: - void cb_modpar2_i(WidgetPDial*, void*); - static void cb_modpar2(WidgetPDial*, void*); -public: - WidgetPDial *modpar3; -private: - void cb_modpar3_i(WidgetPDial*, void*); - static void cb_modpar3(WidgetPDial*, void*); - void cb_Sine_i(Fl_Button*, void*); - static void cb_Sine(Fl_Button*, void*); - void cb_C_i(Fl_Button*, void*); - static void cb_C(Fl_Button*, void*); - void cb_P_i(Fl_Button*, void*); - static void cb_P(Fl_Button*, void*); -public: - Fl_Scroll *_this_has_to_be_the_last; - Fl_Pack *harmonics; - OscilEditor(OscilGen *oscil_,Fl_Widget *oldosc_,Fl_Widget *cbwidget_,Fl_Widget *cbapplywidget_,Master *master_); - ~OscilEditor(); - void refresh(); - void redrawoscil(); -private: - OscilGen *oscil; - Fl_Widget *oldosc,*cbwidget,*cbapplywidget; - Oscilharmonic *h[MAX_AD_HARMONICS]; - Master *master; -}; -#endif diff --git a/plugins/zynaddsubfx/src/UI/PADnoteUI.cc b/plugins/zynaddsubfx/src/UI/PADnoteUI.cc deleted file mode 100644 index a2abb9a05..000000000 --- a/plugins/zynaddsubfx/src/UI/PADnoteUI.cc +++ /dev/null @@ -1,1504 +0,0 @@ -// generated by Fast Light User Interface Designer (fluid) version 1.0300 - -#include "PADnoteUI.h" -#include -#include -#include -#include - -PADnoteHarmonicProfile::PADnoteHarmonicProfile(int x,int y, int w, int h, const char *label):Fl_Box(x,y,w,h,label) { - pars=NULL; -} - -void PADnoteHarmonicProfile::init(PADnoteParameters *pars,Master *master_) { - master=master_; - this->pars=pars; -} - -void PADnoteHarmonicProfile::draw() { - int ox=x(),oy=y(),lx=w(),ly=h(); - if (!visible()) return; - REALTYPE smps[lx]; - - REALTYPE realbw=pars->getprofile(smps,lx); - bool active=active_r(); - - //draw the equivalent bandwidth - if (active) fl_color(220,220,220); - else fl_color(160,165,165); - fl_line_style(0); - int rbw=(int)(realbw*(lx-1.0)/2.0); - for (int i=lx/2-rbw;i<(lx/2+rbw);i++) fl_line(ox+i,oy,ox+i,oy+ly-1); - - fl_line_style(0); - if (active) fl_color(200,200,200); - else fl_color(160,160,160); - for (int i=1;i<10;i++){ - int kx=(int)(lx/10.0*i); - fl_line(ox+kx,oy,ox+kx,oy+ly-1); - }; - for (int i=1;i<5;i++){ - int ky=(int)(ly/5.0*i); - fl_line(ox,oy+ly-ky,ox+lx,oy+ly-ky-1); - }; - - - fl_color(120,120,120); - fl_line_style(FL_DOT); - fl_line(ox+lx/2,oy,ox+lx/2,oy+ly); - - //draw the graph - fl_line_style(0); - int old=0; - for (int i=0;i0) fl_line(ox+i-1,oy+ly-2-old,ox+i,oy+ly-2-val); - old=val; - }; - - - fl_line_style(FL_DASH); - if (active) fl_color(0,100,220); - else fl_color(150,160,170); - fl_line(ox+lx/2-rbw,oy,ox+lx/2-rbw,oy+ly-1); - fl_line(ox+lx/2+rbw,oy,ox+lx/2+rbw,oy+ly-1); - - fl_line_style(0); -} - -PADnoteOvertonePosition::PADnoteOvertonePosition(int x,int y, int w, int h, const char *label):Fl_Box(x,y,w,h,label) { - pars=NULL; -} - -void PADnoteOvertonePosition::init(PADnoteParameters *pars,Master *master_) { - master=master_; - this->pars=pars; -} - -void PADnoteOvertonePosition::draw() { - if (!visible()) return; - const int maxdb=60; - - int ox=x(),oy=y(),lx=w(),ly=h(); - const int maxharmonic=64; - - - for (int i=1;imutex); - pars->oscilgen->getspectrum(n,spc,0); - pthread_mutex_unlock(&master->mutex); - - - //normalize - REALTYPE max=0; - for (int i=0;igetNhr(i); - int kx=(int)(lx/(REALTYPE)maxharmonic*nhr); - if ((kx<0)||(kx>lx)) continue; - - spectrum[kx]=spc[i-1]/max+1e-9; - - }; - - fl_color(180,0,0); - fl_line_style(0); - - if (pars->Pmode==2){ - int old=0; - for (int i=1;i1e-10)||(i==(lx-1))){ - int delta=i-old; - REALTYPE val1=spectrum[old]; - REALTYPE val2=spectrum[i]; - - REALTYPE idelta=1.0/delta; - for (int j=0;jdB2rap(-maxdb)) x=rap2dB(x)/maxdb+1; - else continue; - int yy=(int)(x*ly); - fl_line(ox+i,oy+ly-1-yy,ox+i,oy+ly-1); - - }; -} - -void PADnoteUI::cb__i(Fl_Tabs* o, void*) { - if (o->value()!=harmonicstructuregroup) applybutton->hide(); - else applybutton->show(); -} -void PADnoteUI::cb_(Fl_Tabs* o, void* v) { - ((PADnoteUI*)(o->parent()->user_data()))->cb__i(o,v); -} - -void PADnoteUI::cb_hpbasepar1_i(WidgetPDial* o, void*) { - pars->Php.base.par1=(int) o->value(); -hprofile->redraw(); -cbwidget->do_callback(); -} -void PADnoteUI::cb_hpbasepar1(WidgetPDial* o, void* v) { - ((PADnoteUI*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_hpbasepar1_i(o,v); -} - -void PADnoteUI::cb_hpbasetype_i(Fl_Choice* o, void*) { - pars->Php.base.type=o->value(); -hprofile->redraw(); -cbwidget->do_callback(); -} -void PADnoteUI::cb_hpbasetype(Fl_Choice* o, void* v) { - ((PADnoteUI*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_hpbasetype_i(o,v); -} - -Fl_Menu_Item PADnoteUI::menu_hpbasetype[] = { - {"Gauss", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {"Square", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {"DoubleExp", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {0,0,0,0,0,0,0,0,0} -}; - -void PADnoteUI::cb_hpfreqmult_i(WidgetPDial* o, void*) { - pars->Php.freqmult=(int) o->value(); -hprofile->redraw(); -cbwidget->do_callback(); -} -void PADnoteUI::cb_hpfreqmult(WidgetPDial* o, void* v) { - ((PADnoteUI*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_hpfreqmult_i(o,v); -} - -void PADnoteUI::cb_hpmpar1_i(WidgetPDial* o, void*) { - pars->Php.modulator.par1=(int) o->value(); -hprofile->redraw(); -cbwidget->do_callback(); -} -void PADnoteUI::cb_hpmpar1(WidgetPDial* o, void* v) { - ((PADnoteUI*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_hpmpar1_i(o,v); -} - -void PADnoteUI::cb_hpmfreq_i(WidgetPDial* o, void*) { - pars->Php.modulator.freq=(int) o->value(); -hprofile->redraw(); -cbwidget->do_callback(); -} -void PADnoteUI::cb_hpmfreq(WidgetPDial* o, void* v) { - ((PADnoteUI*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_hpmfreq_i(o,v); -} - -void PADnoteUI::cb_hpamptype_i(Fl_Choice* o, void*) { - pars->Php.amp.type=o->value(); -hprofile->redraw(); -cbwidget->do_callback(); -} -void PADnoteUI::cb_hpamptype(Fl_Choice* o, void* v) { - ((PADnoteUI*)(o->parent()->parent()->parent()->parent()->parent()->user_data()))->cb_hpamptype_i(o,v); -} - -Fl_Menu_Item PADnoteUI::menu_hpamptype[] = { - {"OFF", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {"Gauss", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {"Sine", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {"Flat", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {0,0,0,0,0,0,0,0,0} -}; - -void PADnoteUI::cb_hpampmode_i(Fl_Choice* o, void*) { - pars->Php.amp.mode=o->value(); -hprofile->redraw(); -cbwidget->do_callback(); -} -void PADnoteUI::cb_hpampmode(Fl_Choice* o, void* v) { - ((PADnoteUI*)(o->parent()->parent()->parent()->parent()->parent()->user_data()))->cb_hpampmode_i(o,v); -} - -Fl_Menu_Item PADnoteUI::menu_hpampmode[] = { - {"Sum", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {"Mult", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {"Div1", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {"Div2", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {0,0,0,0,0,0,0,0,0} -}; - -void PADnoteUI::cb_hpamppar1_i(WidgetPDial* o, void*) { - pars->Php.amp.par1=(int) o->value(); -hprofile->redraw(); -cbwidget->do_callback(); -} -void PADnoteUI::cb_hpamppar1(WidgetPDial* o, void* v) { - ((PADnoteUI*)(o->parent()->parent()->parent()->parent()->parent()->user_data()))->cb_hpamppar1_i(o,v); -} - -void PADnoteUI::cb_hpamppar2_i(WidgetPDial* o, void*) { - pars->Php.amp.par2=(int) o->value(); -hprofile->redraw(); -cbwidget->do_callback(); -} -void PADnoteUI::cb_hpamppar2(WidgetPDial* o, void* v) { - ((PADnoteUI*)(o->parent()->parent()->parent()->parent()->parent()->user_data()))->cb_hpamppar2_i(o,v); -} - -void PADnoteUI::cb_hpautoscale_i(Fl_Check_Button* o, void*) { - pars->Php.autoscale=(int) o->value(); -hprofile->redraw(); -cbwidget->do_callback(); -} -void PADnoteUI::cb_hpautoscale(Fl_Check_Button* o, void* v) { - ((PADnoteUI*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_hpautoscale_i(o,v); -} - -void PADnoteUI::cb_hponehalf_i(Fl_Choice* o, void*) { - pars->Php.onehalf=o->value(); -hprofile->redraw(); -cbwidget->do_callback(); -} -void PADnoteUI::cb_hponehalf(Fl_Choice* o, void* v) { - ((PADnoteUI*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_hponehalf_i(o,v); -} - -Fl_Menu_Item PADnoteUI::menu_hponehalf[] = { - {"Full", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {"Upper Half", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {"Lower Half", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {0,0,0,0,0,0,0,0,0} -}; - -void PADnoteUI::cb_hpwidth_i(WidgetPDial* o, void*) { - pars->Php.width=(int) o->value(); -hprofile->redraw(); -cbwidget->do_callback(); -} -void PADnoteUI::cb_hpwidth(WidgetPDial* o, void* v) { - ((PADnoteUI*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_hpwidth_i(o,v); -} - -void PADnoteUI::cb_Change_i(Fl_Button*, void*) { - if (oscui!=NULL) delete (oscui); -oscui=new OscilEditor(pars->oscilgen,osc,cbwidget,applybutton,master); -} -void PADnoteUI::cb_Change(Fl_Button* o, void* v) { - ((PADnoteUI*)(o->parent()->parent()->parent()->user_data()))->cb_Change_i(o,v); -} - -void PADnoteUI::cb_cbwidget_i(Fl_Box*, void*) { - overtonepos->redraw(); -applybutton->color(FL_RED); -applybutton->redraw(); -} -void PADnoteUI::cb_cbwidget(Fl_Box* o, void* v) { - ((PADnoteUI*)(o->parent()->parent()->parent()->user_data()))->cb_cbwidget_i(o,v); -} - -void PADnoteUI::cb_Resonance_i(Fl_Button*, void*) { - resui->resonancewindow->redraw(); -resui->resonancewindow->show(); -resui->setcbwidget(cbwidget,applybutton); -} -void PADnoteUI::cb_Resonance(Fl_Button* o, void* v) { - ((PADnoteUI*)(o->parent()->parent()->parent()->user_data()))->cb_Resonance_i(o,v); -} - -void PADnoteUI::cb_bwdial_i(WidgetPDial* o, void*) { - bwcents->value(pars->setPbandwidth((int) o->value())); -cbwidget->do_callback(); -} -void PADnoteUI::cb_bwdial(WidgetPDial* o, void* v) { - ((PADnoteUI*)(o->parent()->parent()->parent()->user_data()))->cb_bwdial_i(o,v); -} - -void PADnoteUI::cb_hrpostype_i(Fl_Choice* o, void*) { - pars->Phrpos.type=o->value(); -overtonepos->redraw(); -cbwidget->do_callback(); -} -void PADnoteUI::cb_hrpostype(Fl_Choice* o, void* v) { - ((PADnoteUI*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_hrpostype_i(o,v); -} - -Fl_Menu_Item PADnoteUI::menu_hrpostype[] = { - {"Harmonic", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 11, 0}, - {"ShiftU", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 11, 0}, - {"ShiftL", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 11, 0}, - {"PowerU", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 11, 0}, - {"PowerL", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 11, 0}, - {"Sine", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 11, 0}, - {"Power", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 11, 0}, - {0,0,0,0,0,0,0,0,0} -}; - -void PADnoteUI::cb_hrpospar1_i(WidgetPDial* o, void*) { - pars->Phrpos.par1=(int) o->value(); -overtonepos->redraw(); -cbwidget->do_callback(); -} -void PADnoteUI::cb_hrpospar1(WidgetPDial* o, void* v) { - ((PADnoteUI*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_hrpospar1_i(o,v); -} - -void PADnoteUI::cb_hrpospar2_i(WidgetPDial* o, void*) { - pars->Phrpos.par2=(int) o->value(); -overtonepos->redraw(); -cbwidget->do_callback(); -} -void PADnoteUI::cb_hrpospar2(WidgetPDial* o, void* v) { - ((PADnoteUI*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_hrpospar2_i(o,v); -} - -void PADnoteUI::cb_hrpospar3_i(WidgetPDial* o, void*) { - pars->Phrpos.par3=(int) o->value(); -overtonepos->redraw(); -cbwidget->do_callback(); -} -void PADnoteUI::cb_hrpospar3(WidgetPDial* o, void* v) { - ((PADnoteUI*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_hrpospar3_i(o,v); -} - -void PADnoteUI::cb_bwscale_i(Fl_Choice* o, void*) { - pars->Pbwscale=(int) o->value(); -cbwidget->do_callback(); -} -void PADnoteUI::cb_bwscale(Fl_Choice* o, void* v) { - ((PADnoteUI*)(o->parent()->parent()->parent()->user_data()))->cb_bwscale_i(o,v); -} - -Fl_Menu_Item PADnoteUI::menu_bwscale[] = { - {"Normal", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 11, 0}, - {"EqualHz", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 11, 0}, - {"Quater", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 11, 0}, - {"Half", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 11, 0}, - {"75%", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 11, 0}, - {"150%", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 11, 0}, - {"Double", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 11, 0}, - {"Inv.Half", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 11, 0}, - {0,0,0,0,0,0,0,0,0} -}; - -void PADnoteUI::cb_qsamplesize_i(Fl_Choice* o, void*) { - pars->Pquality.samplesize=(int) o->value(); -cbwidget->do_callback(); -} -void PADnoteUI::cb_qsamplesize(Fl_Choice* o, void* v) { - ((PADnoteUI*)(o->parent()->parent()->parent()->user_data()))->cb_qsamplesize_i(o,v); -} - -Fl_Menu_Item PADnoteUI::menu_qsamplesize[] = { - {"16k (Tiny)", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 11, 0}, - {"32k", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 11, 0}, - {"64k (Small)", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 11, 0}, - {"128k", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 11, 0}, - {"256k (Normal)", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 11, 0}, - {"512k", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 11, 0}, - {"1M (Big)", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 11, 0}, - {0,0,0,0,0,0,0,0,0} -}; - -void PADnoteUI::cb_qsmpoct_i(Fl_Choice* o, void*) { - pars->Pquality.smpoct=(int) o->value(); -cbwidget->do_callback(); -} -void PADnoteUI::cb_qsmpoct(Fl_Choice* o, void* v) { - ((PADnoteUI*)(o->parent()->parent()->parent()->user_data()))->cb_qsmpoct_i(o,v); -} - -Fl_Menu_Item PADnoteUI::menu_qsmpoct[] = { - {"0.5", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 11, 0}, - {"1", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 11, 0}, - {"2", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 11, 0}, - {"3", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 11, 0}, - {"4", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 11, 0}, - {"6", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 11, 0}, - {"12", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 11, 0}, - {0,0,0,0,0,0,0,0,0} -}; - -void PADnoteUI::cb_qoct_i(Fl_Choice* o, void*) { - pars->Pquality.oct=(int) o->value(); -cbwidget->do_callback(); -} -void PADnoteUI::cb_qoct(Fl_Choice* o, void* v) { - ((PADnoteUI*)(o->parent()->parent()->parent()->user_data()))->cb_qoct_i(o,v); -} - -Fl_Menu_Item PADnoteUI::menu_qoct[] = { - {"1", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 11, 0}, - {"2", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 11, 0}, - {"3", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 11, 0}, - {"4", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 11, 0}, - {"5", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 11, 0}, - {"6", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 11, 0}, - {"7", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 11, 0}, - {"8", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 11, 0}, - {0,0,0,0,0,0,0,0,0} -}; - -void PADnoteUI::cb_qbasenote_i(Fl_Choice* o, void*) { - pars->Pquality.basenote=(int) o->value(); -cbwidget->do_callback(); -} -void PADnoteUI::cb_qbasenote(Fl_Choice* o, void* v) { - ((PADnoteUI*)(o->parent()->parent()->parent()->user_data()))->cb_qbasenote_i(o,v); -} - -Fl_Menu_Item PADnoteUI::menu_qbasenote[] = { - {"C-2", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 14, 0}, - {"G-2", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 14, 0}, - {"C-3", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 14, 0}, - {"G-3", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 14, 0}, - {"C-4", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 14, 0}, - {"G-4", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 14, 0}, - {"C-5", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 14, 0}, - {"G-5", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 14, 0}, - {"G-6", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 14, 0}, - {0,0,0,0,0,0,0,0,0} -}; - -void PADnoteUI::cb_spectrummode_i(Fl_Choice* o, void*) { - pars->Pmode=(int) o->value(); - -if (pars->Pmode==0){ - bwprofilegroup->activate(); - bwdial->activate(); - bwcents->activate(); - hprofile->activate(); - hprofile->color(54); - bwscale->activate(); -} else { - bwprofilegroup->deactivate(); - bwdial->deactivate(); - bwcents->deactivate(); - hprofile->deactivate(); - hprofile->color(48); - bwscale->deactivate(); -}; - -cbwidget->do_callback(); -} -void PADnoteUI::cb_spectrummode(Fl_Choice* o, void* v) { - ((PADnoteUI*)(o->parent()->parent()->parent()->user_data()))->cb_spectrummode_i(o,v); -} - -Fl_Menu_Item PADnoteUI::menu_spectrummode[] = { - {"Bandwidth", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 11, 0}, - {"Discrete", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 11, 0}, - {"Continous", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 11, 0}, - {0,0,0,0,0,0,0,0,0} -}; - -void PADnoteUI::cb_octave_i(Fl_Counter* o, void*) { - int k=(int) o->value(); -if (k<0) k+=16; -pars->PCoarseDetune = k*1024+ - pars->PCoarseDetune%1024; -} -void PADnoteUI::cb_octave(Fl_Counter* o, void* v) { - ((PADnoteUI*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_octave_i(o,v); -} - -void PADnoteUI::cb_coarsedet_i(Fl_Counter* o, void*) { - int k=(int) o->value(); -if (k<0) k+=1024; -pars->PCoarseDetune = k+ - (pars->PCoarseDetune/1024)*1024; -} -void PADnoteUI::cb_coarsedet(Fl_Counter* o, void* v) { - ((PADnoteUI*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_coarsedet_i(o,v); -} - -void PADnoteUI::cb_detune_i(Fl_Slider* o, void*) { - pars->PDetune=(int)o->value()+8192; -detunevalueoutput->do_callback(); -} -void PADnoteUI::cb_detune(Fl_Slider* o, void* v) { - ((PADnoteUI*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_detune_i(o,v); -} - -void PADnoteUI::cb_detunevalueoutput_i(Fl_Value_Output* o, void*) { - o->value(getdetune(pars->PDetuneType,0,pars->PDetune)); -} -void PADnoteUI::cb_detunevalueoutput(Fl_Value_Output* o, void* v) { - ((PADnoteUI*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_detunevalueoutput_i(o,v); -} - -void PADnoteUI::cb_detunetype_i(Fl_Choice* o, void*) { - pars->PDetuneType=(int) o->value()+1; -detunevalueoutput->do_callback(); -} -void PADnoteUI::cb_detunetype(Fl_Choice* o, void* v) { - ((PADnoteUI*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_detunetype_i(o,v); -} - -void PADnoteUI::cb_hz440_i(Fl_Check_Button* o, void*) { - int x=(int) o->value(); -pars->Pfixedfreq=x; -if (x==0) fixedfreqetdial->deactivate(); - else fixedfreqetdial->activate(); -} -void PADnoteUI::cb_hz440(Fl_Check_Button* o, void* v) { - ((PADnoteUI*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_hz440_i(o,v); -} - -void PADnoteUI::cb_fixedfreqetdial_i(WidgetPDial* o, void*) { - pars->PfixedfreqET=(int) o->value(); -} -void PADnoteUI::cb_fixedfreqetdial(WidgetPDial* o, void* v) { - ((PADnoteUI*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_fixedfreqetdial_i(o,v); -} - -void PADnoteUI::cb_volume_i(Fl_Value_Slider* o, void*) { - pars->PVolume=(int)o->value(); -} -void PADnoteUI::cb_volume(Fl_Value_Slider* o, void* v) { - ((PADnoteUI*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_volume_i(o,v); -} - -void PADnoteUI::cb_vsns_i(Fl_Value_Slider* o, void*) { - pars->PAmpVelocityScaleFunction=(int) o->value(); -} -void PADnoteUI::cb_vsns(Fl_Value_Slider* o, void* v) { - ((PADnoteUI*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_vsns_i(o,v); -} - -void PADnoteUI::cb_pan_i(WidgetPDial* o, void*) { - pars->PPanning=(int) o->value(); -} -void PADnoteUI::cb_pan(WidgetPDial* o, void* v) { - ((PADnoteUI*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_pan_i(o,v); -} - -void PADnoteUI::cb_pstr_i(WidgetPDial* o, void*) { - pars->PPunchStrength=(int) o->value(); -} -void PADnoteUI::cb_pstr(WidgetPDial* o, void* v) { - ((PADnoteUI*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_pstr_i(o,v); -} - -void PADnoteUI::cb_pt_i(WidgetPDial* o, void*) { - pars->PPunchTime=(int) o->value(); -} -void PADnoteUI::cb_pt(WidgetPDial* o, void* v) { - ((PADnoteUI*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_pt_i(o,v); -} - -void PADnoteUI::cb_pstc_i(WidgetPDial* o, void*) { - pars->PPunchStretch=(int) o->value(); -} -void PADnoteUI::cb_pstc(WidgetPDial* o, void* v) { - ((PADnoteUI*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_pstc_i(o,v); -} - -void PADnoteUI::cb_pvel_i(WidgetPDial* o, void*) { - pars->PPunchVelocitySensing=(int) o->value(); -} -void PADnoteUI::cb_pvel(WidgetPDial* o, void* v) { - ((PADnoteUI*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_pvel_i(o,v); -} - -void PADnoteUI::cb_stereo_i(Fl_Check_Button* o, void*) { - pars->PStereo=(int) o->value(); -hprofile->redraw(); -} -void PADnoteUI::cb_stereo(Fl_Check_Button* o, void* v) { - ((PADnoteUI*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_stereo_i(o,v); -} - -void PADnoteUI::cb_applybutton_i(Fl_Button* o, void*) { - pars->applyparameters(true); -o->color(FL_GRAY); -if (oscui!=NULL) { - oscui->applybutton->color(FL_GRAY); - oscui->applybutton->redraw(); -}; -if (resui!=NULL) { - resui->applybutton->color(FL_GRAY); - resui->applybutton->redraw(); -}; -} -void PADnoteUI::cb_applybutton(Fl_Button* o, void* v) { - ((PADnoteUI*)(o->parent()->user_data()))->cb_applybutton_i(o,v); -} - -void PADnoteUI::cb_Close_i(Fl_Button*, void*) { - padnotewindow->hide(); -} -void PADnoteUI::cb_Close(Fl_Button* o, void* v) { - ((PADnoteUI*)(o->parent()->user_data()))->cb_Close_i(o,v); -} - -void PADnoteUI::cb_C_i(Fl_Button*, void*) { - presetsui->copy(pars); -} -void PADnoteUI::cb_C(Fl_Button* o, void* v) { - ((PADnoteUI*)(o->parent()->user_data()))->cb_C_i(o,v); -} - -void PADnoteUI::cb_P_i(Fl_Button*, void*) { - presetsui->paste(pars,this); -} -void PADnoteUI::cb_P(Fl_Button* o, void* v) { - ((PADnoteUI*)(o->parent()->user_data()))->cb_P_i(o,v); -} - -void PADnoteUI::cb_export_i(Fl_Button*, void*) { - char *filename; -filename=fl_file_chooser("Export samples:","(*.wav)",NULL,0); -if (filename==NULL) return; -fl_filename_setext(filename,""); - - - -pars->export2wav(filename); -} -void PADnoteUI::cb_export(Fl_Button* o, void* v) { - ((PADnoteUI*)(o->parent()->user_data()))->cb_export_i(o,v); -} - -PADnoteUI::PADnoteUI(PADnoteParameters *parameters,Master *master_) { - pars=parameters; - master=master_; - oscui=NULL; - resui=new ResonanceUI(pars->resonance); - make_window(); -} - -Fl_Double_Window* PADnoteUI::make_window() { - { padnotewindow = new Fl_Double_Window(535, 450, "PAD synth Parameters"); - padnotewindow->user_data((void*)(this)); - { Fl_Tabs* o = new Fl_Tabs(0, 0, 535, 395); - o->callback((Fl_Callback*)cb_); - { harmonicstructuregroup = new Fl_Group(0, 20, 535, 375, "Harmonic Structure"); - harmonicstructuregroup->box(FL_ENGRAVED_BOX); - { Fl_Group* o = bwprofilegroup = new Fl_Group(5, 30, 90, 260); - bwprofilegroup->box(FL_ENGRAVED_BOX); - { WidgetPDial* o = hpbasepar1 = new WidgetPDial(20, 75, 25, 25, "Width"); - hpbasepar1->box(FL_ROUND_UP_BOX); - hpbasepar1->color(FL_BACKGROUND_COLOR); - hpbasepar1->selection_color(FL_INACTIVE_COLOR); - hpbasepar1->labeltype(FL_NORMAL_LABEL); - hpbasepar1->labelfont(0); - hpbasepar1->labelsize(10); - hpbasepar1->labelcolor(FL_FOREGROUND_COLOR); - hpbasepar1->maximum(127); - hpbasepar1->step(1); - hpbasepar1->callback((Fl_Callback*)cb_hpbasepar1); - hpbasepar1->align(Fl_Align(FL_ALIGN_TOP)); - hpbasepar1->when(FL_WHEN_CHANGED); - o->value(pars->Php.base.par1); - } // WidgetPDial* hpbasepar1 - { Fl_Choice* o = hpbasetype = new Fl_Choice(15, 45, 75, 15, "Base Type"); - hpbasetype->down_box(FL_BORDER_BOX); - hpbasetype->labelsize(10); - hpbasetype->textsize(10); - hpbasetype->callback((Fl_Callback*)cb_hpbasetype); - hpbasetype->align(Fl_Align(FL_ALIGN_TOP_LEFT)); - hpbasetype->menu(menu_hpbasetype); - o->value(pars->Php.base.type); - } // Fl_Choice* hpbasetype - { WidgetPDial* o = hpfreqmult = new WidgetPDial(55, 75, 25, 25, "FreqMlt"); - hpfreqmult->box(FL_ROUND_UP_BOX); - hpfreqmult->color(FL_BACKGROUND_COLOR); - hpfreqmult->selection_color(FL_INACTIVE_COLOR); - hpfreqmult->labeltype(FL_NORMAL_LABEL); - hpfreqmult->labelfont(0); - hpfreqmult->labelsize(10); - hpfreqmult->labelcolor(FL_FOREGROUND_COLOR); - hpfreqmult->maximum(127); - hpfreqmult->step(1); - hpfreqmult->callback((Fl_Callback*)cb_hpfreqmult); - hpfreqmult->align(Fl_Align(FL_ALIGN_TOP)); - hpfreqmult->when(FL_WHEN_CHANGED); - o->value(pars->Php.freqmult); - } // WidgetPDial* hpfreqmult - { WidgetPDial* o = hpmpar1 = new WidgetPDial(15, 115, 20, 20, "Str"); - hpmpar1->box(FL_ROUND_UP_BOX); - hpmpar1->color(FL_BACKGROUND_COLOR); - hpmpar1->selection_color(FL_INACTIVE_COLOR); - hpmpar1->labeltype(FL_NORMAL_LABEL); - hpmpar1->labelfont(0); - hpmpar1->labelsize(10); - hpmpar1->labelcolor(FL_FOREGROUND_COLOR); - hpmpar1->maximum(127); - hpmpar1->step(1); - hpmpar1->callback((Fl_Callback*)cb_hpmpar1); - hpmpar1->align(Fl_Align(FL_ALIGN_TOP)); - hpmpar1->when(FL_WHEN_CHANGED); - o->value(pars->Php.modulator.par1); - } // WidgetPDial* hpmpar1 - { WidgetPDial* o = hpmfreq = new WidgetPDial(40, 115, 20, 20, "SFreq"); - hpmfreq->box(FL_ROUND_UP_BOX); - hpmfreq->color(FL_BACKGROUND_COLOR); - hpmfreq->selection_color(FL_INACTIVE_COLOR); - hpmfreq->labeltype(FL_NORMAL_LABEL); - hpmfreq->labelfont(0); - hpmfreq->labelsize(10); - hpmfreq->labelcolor(FL_FOREGROUND_COLOR); - hpmfreq->maximum(127); - hpmfreq->step(1); - hpmfreq->callback((Fl_Callback*)cb_hpmfreq); - hpmfreq->align(Fl_Align(FL_ALIGN_TOP)); - hpmfreq->when(FL_WHEN_CHANGED); - o->value(pars->Php.modulator.freq); - } // WidgetPDial* hpmfreq - { Fl_Group* o = new Fl_Group(10, 160, 80, 105); - o->box(FL_BORDER_BOX); - { Fl_Choice* o = hpamptype = new Fl_Choice(15, 175, 70, 15, "AmpMultiplier"); - hpamptype->down_box(FL_BORDER_BOX); - hpamptype->labelsize(10); - hpamptype->textsize(10); - hpamptype->callback((Fl_Callback*)cb_hpamptype); - hpamptype->align(Fl_Align(FL_ALIGN_TOP_LEFT)); - hpamptype->menu(menu_hpamptype); - o->value(pars->Php.amp.type); - } // Fl_Choice* hpamptype - { Fl_Choice* o = hpampmode = new Fl_Choice(15, 205, 70, 15, "AmpMode"); - hpampmode->down_box(FL_BORDER_BOX); - hpampmode->labelsize(10); - hpampmode->textsize(10); - hpampmode->callback((Fl_Callback*)cb_hpampmode); - hpampmode->align(Fl_Align(FL_ALIGN_TOP_LEFT)); - hpampmode->menu(menu_hpampmode); - o->value(pars->Php.amp.mode); - } // Fl_Choice* hpampmode - { WidgetPDial* o = hpamppar1 = new WidgetPDial(15, 235, 25, 25, "Par1"); - hpamppar1->box(FL_ROUND_UP_BOX); - hpamppar1->color(FL_BACKGROUND_COLOR); - hpamppar1->selection_color(FL_INACTIVE_COLOR); - hpamppar1->labeltype(FL_NORMAL_LABEL); - hpamppar1->labelfont(0); - hpamppar1->labelsize(10); - hpamppar1->labelcolor(FL_FOREGROUND_COLOR); - hpamppar1->maximum(127); - hpamppar1->step(1); - hpamppar1->callback((Fl_Callback*)cb_hpamppar1); - hpamppar1->align(Fl_Align(FL_ALIGN_TOP)); - hpamppar1->when(FL_WHEN_CHANGED); - o->value(pars->Php.amp.par1); - } // WidgetPDial* hpamppar1 - { WidgetPDial* o = hpamppar2 = new WidgetPDial(55, 235, 25, 25, "Par2"); - hpamppar2->box(FL_ROUND_UP_BOX); - hpamppar2->color(FL_BACKGROUND_COLOR); - hpamppar2->selection_color(FL_INACTIVE_COLOR); - hpamppar2->labeltype(FL_NORMAL_LABEL); - hpamppar2->labelfont(0); - hpamppar2->labelsize(10); - hpamppar2->labelcolor(FL_FOREGROUND_COLOR); - hpamppar2->maximum(127); - hpamppar2->step(1); - hpamppar2->callback((Fl_Callback*)cb_hpamppar2); - hpamppar2->align(Fl_Align(FL_ALIGN_TOP)); - hpamppar2->when(FL_WHEN_CHANGED); - o->value(pars->Php.amp.par2); - } // WidgetPDial* hpamppar2 - o->end(); - } // Fl_Group* o - { Fl_Check_Button* o = hpautoscale = new Fl_Check_Button(10, 270, 60, 15, "autoscale"); - hpautoscale->down_box(FL_DOWN_BOX); - hpautoscale->labelsize(10); - hpautoscale->callback((Fl_Callback*)cb_hpautoscale); - o->value(pars->Php.autoscale); - } // Fl_Check_Button* hpautoscale - { Fl_Choice* o = hponehalf = new Fl_Choice(10, 143, 80, 15); - hponehalf->down_box(FL_BORDER_BOX); - hponehalf->labelsize(10); - hponehalf->textsize(10); - hponehalf->callback((Fl_Callback*)cb_hponehalf); - hponehalf->align(Fl_Align(FL_ALIGN_TOP_LEFT)); - hponehalf->menu(menu_hponehalf); - o->value(pars->Php.onehalf); - } // Fl_Choice* hponehalf - { WidgetPDial* o = hpwidth = new WidgetPDial(65, 115, 20, 20, "Size"); - hpwidth->box(FL_ROUND_UP_BOX); - hpwidth->color(FL_BACKGROUND_COLOR); - hpwidth->selection_color(FL_INACTIVE_COLOR); - hpwidth->labeltype(FL_NORMAL_LABEL); - hpwidth->labelfont(0); - hpwidth->labelsize(10); - hpwidth->labelcolor(FL_FOREGROUND_COLOR); - hpwidth->maximum(127); - hpwidth->step(1); - hpwidth->callback((Fl_Callback*)cb_hpwidth); - hpwidth->align(Fl_Align(FL_ALIGN_TOP)); - hpwidth->when(FL_WHEN_CHANGED); - o->value(pars->Php.width); - } // WidgetPDial* hpwidth - if (pars->Pmode!=0) o->deactivate(); - bwprofilegroup->end(); - } // Fl_Group* bwprofilegroup - { Fl_Group* o = new Fl_Group(100, 155, 270, 135); - o->box(FL_THIN_DOWN_BOX); - o->color(FL_GRAY0); - o->selection_color((Fl_Color)71); - o->labelcolor((Fl_Color)179); - o->align(Fl_Align(FL_ALIGN_BOTTOM_LEFT)); - osc=new Oscilloscope(o->x(),o->y(),o->w(),o->h(),""); - osc->init(pars->oscilgen,master); - o->end(); - } // Fl_Group* o - { Fl_Button* o = new Fl_Button(375, 270, 60, 20, "Change"); - o->box(FL_THIN_UP_BOX); - o->labelfont(1); - o->labelsize(11); - o->callback((Fl_Callback*)cb_Change); - } // Fl_Button* o - { cbwidget = new Fl_Box(125, 135, 205, 20, "Harmonic Content"); - cbwidget->callback((Fl_Callback*)cb_cbwidget); - cbwidget->align(Fl_Align(FL_ALIGN_CENTER|FL_ALIGN_INSIDE)); - } // Fl_Box* cbwidget - { Fl_Button* o = new Fl_Button(375, 225, 80, 20, "Resonance"); - o->box(FL_THIN_UP_BOX); - o->callback((Fl_Callback*)cb_Resonance); - } // Fl_Button* o - { WidgetPDial* o = bwdial = new WidgetPDial(15, 295, 35, 35, "BandWidth"); - bwdial->box(FL_ROUND_UP_BOX); - bwdial->color(FL_BACKGROUND_COLOR); - bwdial->selection_color(FL_INACTIVE_COLOR); - bwdial->labeltype(FL_NORMAL_LABEL); - bwdial->labelfont(0); - bwdial->labelsize(10); - bwdial->labelcolor(FL_FOREGROUND_COLOR); - bwdial->maximum(1000); - bwdial->step(1); - bwdial->callback((Fl_Callback*)cb_bwdial); - bwdial->align(Fl_Align(FL_ALIGN_BOTTOM)); - bwdial->when(FL_WHEN_CHANGED); - o->value(pars->Pbandwidth); - if (pars->Pmode!=0) o->deactivate(); - } // WidgetPDial* bwdial - { Fl_Value_Output* o = bwcents = new Fl_Value_Output(55, 305, 55, 15, "cents"); - bwcents->labelsize(10); - bwcents->maximum(10000); - bwcents->step(0.1); - bwcents->align(Fl_Align(FL_ALIGN_BOTTOM_LEFT)); - o->value(pars->setPbandwidth(pars->Pbandwidth)); - if (pars->Pmode!=0) o->deactivate(); - } // Fl_Value_Output* bwcents - { Fl_Group* o = new Fl_Group(315, 295, 215, 45); - o->box(FL_ENGRAVED_BOX); - { Fl_Choice* o = hrpostype = new Fl_Choice(325, 310, 80, 20, "OvertonesPosition"); - hrpostype->down_box(FL_BORDER_BOX); - hrpostype->labelsize(10); - hrpostype->textsize(11); - hrpostype->callback((Fl_Callback*)cb_hrpostype); - hrpostype->align(Fl_Align(FL_ALIGN_TOP_LEFT)); - hrpostype->menu(menu_hrpostype); - o->value(pars->Phrpos.type); - } // Fl_Choice* hrpostype - { WidgetPDial* o = hrpospar1 = new WidgetPDial(425, 310, 25, 25, "Par1"); - hrpospar1->box(FL_ROUND_UP_BOX); - hrpospar1->color(FL_BACKGROUND_COLOR); - hrpospar1->selection_color(FL_INACTIVE_COLOR); - hrpospar1->labeltype(FL_NORMAL_LABEL); - hrpospar1->labelfont(0); - hrpospar1->labelsize(10); - hrpospar1->labelcolor(FL_FOREGROUND_COLOR); - hrpospar1->maximum(255); - hrpospar1->step(1); - hrpospar1->callback((Fl_Callback*)cb_hrpospar1); - hrpospar1->align(Fl_Align(FL_ALIGN_TOP)); - hrpospar1->when(FL_WHEN_CHANGED); - o->value(pars->Phrpos.par1); - } // WidgetPDial* hrpospar1 - { WidgetPDial* o = hrpospar2 = new WidgetPDial(460, 310, 25, 25, "Par2"); - hrpospar2->box(FL_ROUND_UP_BOX); - hrpospar2->color(FL_BACKGROUND_COLOR); - hrpospar2->selection_color(FL_INACTIVE_COLOR); - hrpospar2->labeltype(FL_NORMAL_LABEL); - hrpospar2->labelfont(0); - hrpospar2->labelsize(10); - hrpospar2->labelcolor(FL_FOREGROUND_COLOR); - hrpospar2->maximum(255); - hrpospar2->step(1); - hrpospar2->callback((Fl_Callback*)cb_hrpospar2); - hrpospar2->align(Fl_Align(FL_ALIGN_TOP)); - hrpospar2->when(FL_WHEN_CHANGED); - o->value(pars->Phrpos.par2); - } // WidgetPDial* hrpospar2 - { WidgetPDial* o = hrpospar3 = new WidgetPDial(495, 310, 25, 25, "ForceH"); - hrpospar3->box(FL_ROUND_UP_BOX); - hrpospar3->color(FL_BACKGROUND_COLOR); - hrpospar3->selection_color(FL_INACTIVE_COLOR); - hrpospar3->labeltype(FL_NORMAL_LABEL); - hrpospar3->labelfont(0); - hrpospar3->labelsize(10); - hrpospar3->labelcolor(FL_FOREGROUND_COLOR); - hrpospar3->maximum(255); - hrpospar3->step(1); - hrpospar3->callback((Fl_Callback*)cb_hrpospar3); - hrpospar3->align(Fl_Align(FL_ALIGN_TOP)); - hrpospar3->when(FL_WHEN_CHANGED); - o->value(pars->Phrpos.par3); - } // WidgetPDial* hrpospar3 - o->end(); - } // Fl_Group* o - { Fl_Choice* o = bwscale = new Fl_Choice(120, 305, 80, 20, "Bandwidth Scale"); - bwscale->down_box(FL_BORDER_BOX); - bwscale->labelsize(10); - bwscale->textsize(11); - bwscale->callback((Fl_Callback*)cb_bwscale); - bwscale->align(Fl_Align(FL_ALIGN_TOP_LEFT)); - bwscale->menu(menu_bwscale); - o->value(pars->Pbwscale); - if (pars->Pmode!=0) o->deactivate(); - } // Fl_Choice* bwscale - { Fl_Group* o = overtonepos = new Fl_Group(5, 345, 525, 45); - overtonepos->box(FL_FLAT_BOX); - overtonepos->color(FL_LIGHT3); - overtonepos->selection_color((Fl_Color)218); - overtonepos->labelcolor(FL_GREEN); - PADnoteOvertonePosition *opui=new PADnoteOvertonePosition(o->x(),o->y(),o->w(),o->h(),""); - opui->init(pars,master); - overtonepos->end(); - } // Fl_Group* overtonepos - { Fl_Choice* o = qsamplesize = new Fl_Choice(375, 190, 115, 20, "Sample Size"); - qsamplesize->down_box(FL_BORDER_BOX); - qsamplesize->labelsize(10); - qsamplesize->textsize(11); - qsamplesize->callback((Fl_Callback*)cb_qsamplesize); - qsamplesize->align(Fl_Align(FL_ALIGN_TOP_LEFT)); - qsamplesize->menu(menu_qsamplesize); - o->value(pars->Pquality.samplesize); - } // Fl_Choice* qsamplesize - { Fl_Choice* o = qsmpoct = new Fl_Choice(430, 155, 45, 20, "smp/oct"); - qsmpoct->down_box(FL_BORDER_BOX); - qsmpoct->labelsize(11); - qsmpoct->textsize(11); - qsmpoct->callback((Fl_Callback*)cb_qsmpoct); - qsmpoct->align(Fl_Align(FL_ALIGN_TOP_LEFT)); - qsmpoct->menu(menu_qsmpoct); - o->value(pars->Pquality.smpoct); - } // Fl_Choice* qsmpoct - { Fl_Choice* o = qoct = new Fl_Choice(480, 155, 45, 20, "no.oct"); - qoct->down_box(FL_BORDER_BOX); - qoct->labelsize(11); - qoct->textsize(11); - qoct->callback((Fl_Callback*)cb_qoct); - qoct->align(Fl_Align(FL_ALIGN_TOP_LEFT)); - qoct->menu(menu_qoct); - o->value(pars->Pquality.oct); - } // Fl_Choice* qoct - { Fl_Choice* o = qbasenote = new Fl_Choice(375, 155, 50, 20, "base"); - qbasenote->down_box(FL_BORDER_BOX); - qbasenote->labelsize(11); - qbasenote->textsize(11); - qbasenote->callback((Fl_Callback*)cb_qbasenote); - qbasenote->align(Fl_Align(FL_ALIGN_TOP_LEFT)); - qbasenote->menu(menu_qbasenote); - o->value(pars->Pquality.basenote); - } // Fl_Choice* qbasenote - { Fl_Group* o = hprofile = new Fl_Group(100, 45, 430, 90); - hprofile->box(FL_FLAT_BOX); - hprofile->color(FL_LIGHT3); - hprofile->selection_color((Fl_Color)218); - hprofile->labelcolor(FL_GREEN); - PADnoteHarmonicProfile *hpui=new PADnoteHarmonicProfile(o->x(),o->y(),o->w(),o->h(),""); - hpui->init(pars,master); - if (pars->Pmode!=0) { o->deactivate(); o->color(48);}; - hprofile->end(); - } // Fl_Group* hprofile - { new Fl_Box(160, 25, 315, 20, "Profile of One Harmonic (Frequency Distribution)"); - } // Fl_Box* o - { Fl_Choice* o = spectrummode = new Fl_Choice(220, 305, 90, 20, "Spectrum Mode"); - spectrummode->down_box(FL_BORDER_BOX); - spectrummode->labelfont(1); - spectrummode->labelsize(10); - spectrummode->textsize(11); - spectrummode->callback((Fl_Callback*)cb_spectrummode); - spectrummode->align(Fl_Align(FL_ALIGN_TOP_LEFT)); - spectrummode->menu(menu_spectrummode); - o->value(pars->Pmode); - } // Fl_Choice* spectrummode - harmonicstructuregroup->end(); - } // Fl_Group* harmonicstructuregroup - { Fl_Group* o = new Fl_Group(0, 20, 535, 375, "Envelopes&LFOs"); - o->box(FL_ENGRAVED_BOX); - o->hide(); - { Fl_Group* o = new Fl_Group(5, 275, 525, 115, "FREQUENCY"); - o->box(FL_THIN_UP_BOX); - o->labeltype(FL_EMBOSSED_LABEL); - o->labelfont(1); - o->labelsize(13); - o->align(Fl_Align(FL_ALIGN_TOP|FL_ALIGN_INSIDE)); - { EnvelopeUI* o = freqenv = new EnvelopeUI(10, 315, 205, 70, "PADSynth - Frequency Envelope"); - freqenv->box(FL_FLAT_BOX); - freqenv->color((Fl_Color)51); - freqenv->selection_color(FL_BACKGROUND_COLOR); - freqenv->labeltype(FL_NORMAL_LABEL); - freqenv->labelfont(0); - freqenv->labelsize(14); - freqenv->labelcolor(FL_FOREGROUND_COLOR); - freqenv->align(Fl_Align(FL_ALIGN_WRAP|FL_ALIGN_INSIDE)); - freqenv->when(FL_WHEN_RELEASE); - o->init(pars->FreqEnvelope); - freqenv->end(); - } // EnvelopeUI* freqenv - { Fl_Counter* o = octave = new Fl_Counter(470, 295, 45, 15, "Octave"); - octave->tooltip("Octave"); - octave->type(1); - octave->labelsize(10); - octave->minimum(-8); - octave->maximum(7); - octave->step(1); - octave->textfont(1); - octave->textsize(11); - octave->callback((Fl_Callback*)cb_octave); - octave->align(Fl_Align(FL_ALIGN_TOP)); - int k=pars->PCoarseDetune/1024; - if (k>=8) k-=16; - o->value(k); - } // Fl_Counter* octave - { Fl_Counter* o = coarsedet = new Fl_Counter(455, 365, 60, 20, "Coarse det."); - coarsedet->tooltip("Coarse Detune"); - coarsedet->labelsize(10); - coarsedet->minimum(-64); - coarsedet->maximum(63); - coarsedet->step(1); - coarsedet->textfont(1); - coarsedet->textsize(11); - coarsedet->callback((Fl_Callback*)cb_coarsedet); - coarsedet->align(Fl_Align(FL_ALIGN_TOP_LEFT)); - int k=pars->PCoarseDetune%1024; - if (k>=512) k-=1024; - o->value(k); - o->lstep(10); - } // Fl_Counter* coarsedet - { LFOUI* o = freqlfo = new LFOUI(215, 315, 230, 70, "Frequency LFO "); - freqlfo->box(FL_FLAT_BOX); - freqlfo->color(FL_DARK1); - freqlfo->selection_color(FL_BACKGROUND_COLOR); - freqlfo->labeltype(FL_NORMAL_LABEL); - freqlfo->labelfont(0); - freqlfo->labelsize(14); - freqlfo->labelcolor(FL_FOREGROUND_COLOR); - freqlfo->align(Fl_Align(FL_ALIGN_WRAP|FL_ALIGN_INSIDE)); - freqlfo->when(FL_WHEN_RELEASE); - o->init(pars->FreqLfo); - freqlfo->end(); - } // LFOUI* freqlfo - { Fl_Slider* o = detune = new Fl_Slider(60, 295, 295, 15); - detune->tooltip("Fine Detune (cents)"); - detune->type(5); - detune->box(FL_FLAT_BOX); - detune->minimum(-8192); - detune->maximum(8191); - detune->step(1); - detune->callback((Fl_Callback*)cb_detune); - o->value(pars->PDetune-8192); - } // Fl_Slider* detune - { Fl_Value_Output* o = detunevalueoutput = new Fl_Value_Output(12, 295, 45, 15, "Detune"); - detunevalueoutput->labelsize(10); - detunevalueoutput->minimum(-5000); - detunevalueoutput->maximum(5000); - detunevalueoutput->step(0.01); - detunevalueoutput->textfont(1); - detunevalueoutput->textsize(10); - detunevalueoutput->callback((Fl_Callback*)cb_detunevalueoutput); - detunevalueoutput->align(Fl_Align(FL_ALIGN_TOP_LEFT)); - o->value(getdetune(pars->PDetuneType,0,pars->PDetune)); - } // Fl_Value_Output* detunevalueoutput - { Fl_Choice* o = detunetype = new Fl_Choice(450, 335, 75, 15, "Detune Type"); - detunetype->down_box(FL_BORDER_BOX); - detunetype->labelsize(10); - detunetype->textfont(1); - detunetype->textsize(10); - detunetype->callback((Fl_Callback*)cb_detunetype); - detunetype->align(Fl_Align(FL_ALIGN_TOP_LEFT)); - o->add("L35cents");o->add("L10cents");o->add("E100cents");o->add("E1200cents"); - o->value(pars->PDetuneType-1); - } // Fl_Choice* detunetype - { Fl_Check_Button* o = hz440 = new Fl_Check_Button(365, 295, 50, 15, "440Hz"); - hz440->tooltip("set the base frequency to 440Hz"); - hz440->down_box(FL_DOWN_BOX); - hz440->labelfont(1); - hz440->labelsize(10); - hz440->callback((Fl_Callback*)cb_hz440); - o->value(pars->Pfixedfreq); - } // Fl_Check_Button* hz440 - { WidgetPDial* o = fixedfreqetdial = new WidgetPDial(420, 295, 15, 15, "Eq.T."); - fixedfreqetdial->tooltip("How the frequency varies acording to the keyboard (leftmost for fixed frequen\ -cy)"); - fixedfreqetdial->box(FL_ROUND_UP_BOX); - fixedfreqetdial->color(FL_BACKGROUND_COLOR); - fixedfreqetdial->selection_color(FL_INACTIVE_COLOR); - fixedfreqetdial->labeltype(FL_NORMAL_LABEL); - fixedfreqetdial->labelfont(0); - fixedfreqetdial->labelsize(10); - fixedfreqetdial->labelcolor(FL_FOREGROUND_COLOR); - fixedfreqetdial->maximum(127); - fixedfreqetdial->step(1); - fixedfreqetdial->callback((Fl_Callback*)cb_fixedfreqetdial); - fixedfreqetdial->align(Fl_Align(FL_ALIGN_RIGHT)); - fixedfreqetdial->when(FL_WHEN_CHANGED); - o->value(pars->PfixedfreqET); - if (pars->Pfixedfreq==0) o->deactivate(); - } // WidgetPDial* fixedfreqetdial - o->end(); - } // Fl_Group* o - { Fl_Group* o = new Fl_Group(5, 25, 240, 250, "AMPLITUDE"); - o->box(FL_THIN_UP_FRAME); - o->labeltype(FL_EMBOSSED_LABEL); - o->labelfont(1); - o->labelsize(13); - o->align(Fl_Align(FL_ALIGN_TOP|FL_ALIGN_INSIDE)); - { Fl_Value_Slider* o = volume = new Fl_Value_Slider(10, 50, 160, 15, "Vol"); - volume->tooltip("Volume"); - volume->type(5); - volume->box(FL_FLAT_BOX); - volume->labelsize(11); - volume->maximum(127); - volume->step(1); - volume->callback((Fl_Callback*)cb_volume); - volume->align(Fl_Align(FL_ALIGN_RIGHT)); - o->value(pars->PVolume); - } // Fl_Value_Slider* volume - { Fl_Value_Slider* o = vsns = new Fl_Value_Slider(10, 70, 160, 15, "V.Sns"); - vsns->tooltip("Velocity Sensing Function (rightmost to disable)"); - vsns->type(5); - vsns->box(FL_FLAT_BOX); - vsns->labelsize(11); - vsns->maximum(127); - vsns->step(1); - vsns->callback((Fl_Callback*)cb_vsns); - vsns->align(Fl_Align(FL_ALIGN_RIGHT)); - o->value(pars->PAmpVelocityScaleFunction); - } // Fl_Value_Slider* vsns - { WidgetPDial* o = pan = new WidgetPDial(210, 45, 30, 30, "Pan"); - pan->tooltip("Panning (leftmost is Random)"); - pan->box(FL_ROUND_UP_BOX); - pan->color(FL_BACKGROUND_COLOR); - pan->selection_color(FL_INACTIVE_COLOR); - pan->labeltype(FL_NORMAL_LABEL); - pan->labelfont(0); - pan->labelsize(10); - pan->labelcolor(FL_FOREGROUND_COLOR); - pan->maximum(127); - pan->step(1); - pan->callback((Fl_Callback*)cb_pan); - pan->align(Fl_Align(FL_ALIGN_BOTTOM)); - pan->when(FL_WHEN_CHANGED); - o->value(pars->PPanning); - } // WidgetPDial* pan - { WidgetPDial* o = pstr = new WidgetPDial(125, 247, 25, 25, "P.Str."); - pstr->tooltip("Punch Strength"); - pstr->box(FL_ROUND_UP_BOX); - pstr->color(FL_BACKGROUND_COLOR); - pstr->selection_color(FL_INACTIVE_COLOR); - pstr->labeltype(FL_NORMAL_LABEL); - pstr->labelfont(0); - pstr->labelsize(10); - pstr->labelcolor(FL_FOREGROUND_COLOR); - pstr->maximum(127); - pstr->step(1); - pstr->callback((Fl_Callback*)cb_pstr); - pstr->align(Fl_Align(FL_ALIGN_TOP)); - pstr->when(FL_WHEN_CHANGED); - o->value(pars->PPunchStrength); - } // WidgetPDial* pstr - { WidgetPDial* o = pt = new WidgetPDial(155, 247, 25, 25, "P.t."); - pt->tooltip("Punch Time (duration)"); - pt->box(FL_ROUND_UP_BOX); - pt->color(FL_BACKGROUND_COLOR); - pt->selection_color(FL_INACTIVE_COLOR); - pt->labeltype(FL_NORMAL_LABEL); - pt->labelfont(0); - pt->labelsize(10); - pt->labelcolor(FL_FOREGROUND_COLOR); - pt->maximum(127); - pt->step(1); - pt->callback((Fl_Callback*)cb_pt); - pt->align(Fl_Align(FL_ALIGN_TOP)); - pt->when(FL_WHEN_CHANGED); - o->value(pars->PPunchTime); - } // WidgetPDial* pt - { WidgetPDial* o = pstc = new WidgetPDial(185, 247, 25, 25, "P.Stc."); - pstc->tooltip("Punch Stretch"); - pstc->box(FL_ROUND_UP_BOX); - pstc->color(FL_BACKGROUND_COLOR); - pstc->selection_color(FL_INACTIVE_COLOR); - pstc->labeltype(FL_NORMAL_LABEL); - pstc->labelfont(0); - pstc->labelsize(10); - pstc->labelcolor(FL_FOREGROUND_COLOR); - pstc->maximum(127); - pstc->step(1); - pstc->callback((Fl_Callback*)cb_pstc); - pstc->align(Fl_Align(FL_ALIGN_TOP)); - pstc->when(FL_WHEN_CHANGED); - o->value(pars->PPunchStretch); - } // WidgetPDial* pstc - { WidgetPDial* o = pvel = new WidgetPDial(215, 247, 25, 25, "P.Vel."); - pvel->tooltip("Punch Velocity Sensing"); - pvel->box(FL_ROUND_UP_BOX); - pvel->color(FL_BACKGROUND_COLOR); - pvel->selection_color(FL_INACTIVE_COLOR); - pvel->labeltype(FL_NORMAL_LABEL); - pvel->labelfont(0); - pvel->labelsize(10); - pvel->labelcolor(FL_FOREGROUND_COLOR); - pvel->maximum(127); - pvel->step(1); - pvel->callback((Fl_Callback*)cb_pvel); - pvel->align(Fl_Align(FL_ALIGN_TOP)); - pvel->when(FL_WHEN_CHANGED); - o->value(pars->PPunchVelocitySensing); - } // WidgetPDial* pvel - { EnvelopeUI* o = ampenv = new EnvelopeUI(10, 95, 205, 70, "PADSynth - Amplitude Envelope"); - ampenv->box(FL_FLAT_BOX); - ampenv->color((Fl_Color)51); - ampenv->selection_color(FL_BACKGROUND_COLOR); - ampenv->labeltype(FL_NORMAL_LABEL); - ampenv->labelfont(0); - ampenv->labelsize(14); - ampenv->labelcolor(FL_FOREGROUND_COLOR); - ampenv->align(Fl_Align(FL_ALIGN_WRAP|FL_ALIGN_INSIDE)); - ampenv->when(FL_WHEN_RELEASE); - o->init(pars->AmpEnvelope); - ampenv->end(); - } // EnvelopeUI* ampenv - { LFOUI* o = amplfo = new LFOUI(10, 165, 230, 70, "Amplitude LFO "); - amplfo->box(FL_FLAT_BOX); - amplfo->color(FL_DARK1); - amplfo->selection_color(FL_BACKGROUND_COLOR); - amplfo->labeltype(FL_NORMAL_LABEL); - amplfo->labelfont(0); - amplfo->labelsize(14); - amplfo->labelcolor(FL_FOREGROUND_COLOR); - amplfo->align(Fl_Align(FL_ALIGN_WRAP|FL_ALIGN_INSIDE)); - amplfo->when(FL_WHEN_RELEASE); - o->init(pars->AmpLfo); - amplfo->end(); - } // LFOUI* amplfo - { Fl_Check_Button* o = stereo = new Fl_Check_Button(15, 245, 70, 25, "Stereo"); - stereo->down_box(FL_DOWN_BOX); - stereo->callback((Fl_Callback*)cb_stereo); - o->value(pars->PStereo); - } // Fl_Check_Button* stereo - o->end(); - } // Fl_Group* o - { Fl_Group* o = new Fl_Group(245, 25, 285, 250, "FILTER"); - o->box(FL_THIN_UP_BOX); - o->labeltype(FL_EMBOSSED_LABEL); - o->labelfont(1); - o->labelsize(13); - o->align(Fl_Align(FL_ALIGN_TOP|FL_ALIGN_INSIDE)); - { EnvelopeUI* o = filterenv = new EnvelopeUI(250, 130, 275, 70, "PADSynth - Filter Envelope"); - filterenv->box(FL_FLAT_BOX); - filterenv->color((Fl_Color)51); - filterenv->selection_color(FL_BACKGROUND_COLOR); - filterenv->labeltype(FL_NORMAL_LABEL); - filterenv->labelfont(0); - filterenv->labelsize(14); - filterenv->labelcolor(FL_FOREGROUND_COLOR); - filterenv->align(Fl_Align(FL_ALIGN_WRAP|FL_ALIGN_INSIDE)); - filterenv->when(FL_WHEN_RELEASE); - o->init(pars->FilterEnvelope); - filterenv->end(); - } // EnvelopeUI* filterenv - { LFOUI* o = filterlfo = new LFOUI(250, 200, 230, 70, "Filter LFO "); - filterlfo->box(FL_FLAT_BOX); - filterlfo->color(FL_DARK1); - filterlfo->selection_color(FL_BACKGROUND_COLOR); - filterlfo->labeltype(FL_NORMAL_LABEL); - filterlfo->labelfont(0); - filterlfo->labelsize(14); - filterlfo->labelcolor(FL_FOREGROUND_COLOR); - filterlfo->align(Fl_Align(FL_ALIGN_WRAP|FL_ALIGN_INSIDE)); - filterlfo->when(FL_WHEN_RELEASE); - o->init(pars->FilterLfo); - filterlfo->end(); - } // LFOUI* filterlfo - { FilterUI* o = filterui = new FilterUI(250, 55, 275, 75, "PADsynth - Filter"); - filterui->box(FL_FLAT_BOX); - filterui->color(FL_LIGHT1); - filterui->selection_color(FL_BACKGROUND_COLOR); - filterui->labeltype(FL_NORMAL_LABEL); - filterui->labelfont(0); - filterui->labelsize(14); - filterui->labelcolor(FL_FOREGROUND_COLOR); - filterui->align(Fl_Align(FL_ALIGN_WRAP|FL_ALIGN_INSIDE)); - filterui->when(FL_WHEN_RELEASE); - o->init(pars->GlobalFilter,&pars->PFilterVelocityScale,&pars->PFilterVelocityScaleFunction); - filterui->end(); - } // FilterUI* filterui - o->end(); - } // Fl_Group* o - o->end(); - } // Fl_Group* o - o->end(); - } // Fl_Tabs* o - { Fl_Button* o = applybutton = new Fl_Button(45, 405, 185, 40, "Apply Changes"); - applybutton->box(FL_THIN_UP_BOX); - applybutton->labelfont(1); - applybutton->labelsize(16); - applybutton->callback((Fl_Callback*)cb_applybutton); - o->color(FL_RED); - } // Fl_Button* applybutton - { Fl_Button* o = new Fl_Button(320, 405, 175, 40, "Close"); - o->box(FL_THIN_UP_BOX); - o->labelsize(17); - o->callback((Fl_Callback*)cb_Close); - } // Fl_Button* o - { Fl_Button* o = new Fl_Button(240, 430, 25, 15, "C"); - o->box(FL_THIN_UP_BOX); - o->color((Fl_Color)179); - o->labelfont(1); - o->labelsize(11); - o->labelcolor(FL_BACKGROUND2_COLOR); - o->callback((Fl_Callback*)cb_C); - } // Fl_Button* o - { Fl_Button* o = new Fl_Button(270, 430, 25, 15, "P"); - o->box(FL_THIN_UP_BOX); - o->color((Fl_Color)179); - o->labelfont(1); - o->labelsize(11); - o->labelcolor(FL_BACKGROUND2_COLOR); - o->callback((Fl_Callback*)cb_P); - } // Fl_Button* o - { Fl_Button* o = new Fl_Button(240, 405, 55, 15, "export"); - o->tooltip("export samples as wav file"); - o->box(FL_THIN_UP_BOX); - o->color(FL_WHITE); - o->labelsize(11); - o->callback((Fl_Callback*)cb_export); - o->align(Fl_Align(FL_ALIGN_WRAP)); - } // Fl_Button* o - padnotewindow->end(); - } // Fl_Double_Window* padnotewindow - return padnotewindow; -} - -void PADnoteUI::refresh() { - volume->value(pars->PVolume); - vsns->value(pars->PAmpVelocityScaleFunction); - pan->value(pars->PPanning); - - stereo->value(pars->PStereo); - - - pstr->value(pars->PPunchStrength); - pt->value(pars->PPunchTime); - pstc->value(pars->PPunchStretch); - pvel->value(pars->PPunchVelocitySensing); - - detunevalueoutput->value(getdetune(pars->PDetuneType,0,pars->PDetune)); - detune->value(pars->PDetune-8192); - - int k=pars->PCoarseDetune/1024;if (k>=8) k-=16; - octave->value(k); - - detunetype->value(pars->PDetuneType-1); - k=pars->PCoarseDetune%1024;if (k>=512) k-=1024; - coarsedet->value(k); - - hz440->value(pars->Pfixedfreq); - fixedfreqetdial->value(pars->PfixedfreqET); - - amplfo->refresh(); - freqlfo->refresh(); - filterlfo->refresh(); - - ampenv->refresh(); - freqenv->refresh(); - filterenv->refresh(); - filterui->refresh(); - - - /* harmonic structure parametrs */ - - resui->refresh(); - if (oscui!=NULL) oscui->refresh(); - - hpbasetype->value(pars->Php.base.type); - hpbasepar1->value(pars->Php.base.par1); - hpfreqmult->value(pars->Php.freqmult); - - hpmpar1->value(pars->Php.modulator.par1); - hpmfreq->value(pars->Php.modulator.freq); - hpwidth->value(pars->Php.width); - - hponehalf->value(pars->Php.onehalf); - hpamptype->value(pars->Php.amp.type); - hpampmode->value(pars->Php.amp.mode); - hpamppar1->value(pars->Php.amp.par1); - hpamppar2->value(pars->Php.amp.par2); - hpautoscale->value(pars->Php.autoscale); - - bwdial->value(pars->Pbandwidth); - if (pars->Pmode==0){ - bwprofilegroup->activate(); - bwdial->activate(); - bwcents->activate(); - hprofile->activate(); - hprofile->color(54); - bwscale->activate(); - } else { - bwprofilegroup->deactivate(); - bwdial->deactivate(); - bwcents->deactivate(); - hprofile->deactivate(); - hprofile->color(48); - bwscale->activate(); - }; - - spectrummode->value(pars->Pmode); - - qbasenote->value(pars->Pquality.basenote); - qsmpoct->value(pars->Pquality.smpoct); - qoct->value(pars->Pquality.oct); - qsamplesize->value(pars->Pquality.samplesize); - - hrpostype->value(pars->Phrpos.type); - hrpospar1->value(pars->Phrpos.par1); - hrpospar2->value(pars->Phrpos.par2); - hrpospar3->value(pars->Phrpos.par3); - - hprofile->redraw(); - overtonepos->redraw(); - - osc->redraw(); - pars->applyparameters(true); - applybutton->color(FL_GRAY); - applybutton->parent()->redraw(); -} - -PADnoteUI::~PADnoteUI() { - delete(oscui); - delete(resui); - - padnotewindow->hide(); - delete(padnotewindow); -} diff --git a/plugins/zynaddsubfx/src/UI/PADnoteUI.fl b/plugins/zynaddsubfx/src/UI/PADnoteUI.fl deleted file mode 100644 index 74441c199..000000000 --- a/plugins/zynaddsubfx/src/UI/PADnoteUI.fl +++ /dev/null @@ -1,1101 +0,0 @@ -# data file for the Fltk User Interface Designer (fluid) -version 1.0107 -header_name {.h} -code_name {.cc} -decl {\#include "../Params/PADnoteParameters.h"} {public -} - -decl {\#include "../Misc/Util.h"} {public -} - -decl {\#include "../Misc/Master.h"} {public -} - -decl {\#include "ResonanceUI.h"} {public -} - -decl {\#include } {public -} - -decl {\#include } {public -} - -decl {\#include } {public -} - -decl {\#include } {} - -decl {\#include } {} - -decl {\#include } {} - -decl {\#include } {} - -decl {\#include "WidgetPDial.h"} {public -} - -decl {\#include "EnvelopeUI.h"} {public -} - -decl {\#include "LFOUI.h"} {public -} - -decl {\#include "FilterUI.h"} {public -} - -decl {\#include "OscilGenUI.h"} {public -} - -decl {\#include "PresetsUI.h"} {public -} - -class PADnoteHarmonicProfile {: {public Fl_Box} -} { - Function {PADnoteHarmonicProfile(int x,int y, int w, int h, const char *label=0):Fl_Box(x,y,w,h,label)} {} { - code {pars=NULL;} {} - } - Function {init(PADnoteParameters *pars,Master *master_)} {} { - code {master=master_; -this->pars=pars;} {} - } - Function {draw()} {} { - code {int ox=x(),oy=y(),lx=w(),ly=h(); -if (!visible()) return; -REALTYPE smps[lx]; - -REALTYPE realbw=pars->getprofile(smps,lx); -bool active=active_r(); - -//draw the equivalent bandwidth -if (active) fl_color(220,220,220); - else fl_color(160,165,165); -fl_line_style(0); -int rbw=(int)(realbw*(lx-1.0)/2.0); -for (int i=lx/2-rbw;i<(lx/2+rbw);i++) fl_line(ox+i,oy,ox+i,oy+ly-1); - -fl_line_style(0); -if (active) fl_color(200,200,200); - else fl_color(160,160,160); -for (int i=1;i<10;i++){ - int kx=(int)(lx/10.0*i); - fl_line(ox+kx,oy,ox+kx,oy+ly-1); -}; -for (int i=1;i<5;i++){ - int ky=(int)(ly/5.0*i); - fl_line(ox,oy+ly-ky,ox+lx,oy+ly-ky-1); -}; - - -fl_color(120,120,120); -fl_line_style(FL_DOT); -fl_line(ox+lx/2,oy,ox+lx/2,oy+ly); - -//draw the graph -fl_line_style(0); -int old=0; -for (int i=0;i0) fl_line(ox+i-1,oy+ly-2-old,ox+i,oy+ly-2-val); - old=val; -}; - - -fl_line_style(FL_DASH); -if (active) fl_color(0,100,220); - else fl_color(150,160,170); -fl_line(ox+lx/2-rbw,oy,ox+lx/2-rbw,oy+ly-1); -fl_line(ox+lx/2+rbw,oy,ox+lx/2+rbw,oy+ly-1); - -fl_line_style(0);} {} - } - decl {Master *master;} {} - decl {PADnoteParameters *pars;} {public - } -} - -class PADnoteOvertonePosition {: {public Fl_Box} -} { - Function {PADnoteOvertonePosition(int x,int y, int w, int h, const char *label=0):Fl_Box(x,y,w,h,label)} {} { - code {pars=NULL;} {} - } - Function {init(PADnoteParameters *pars,Master *master_)} {} { - code {master=master_; -this->pars=pars;} {} - } - Function {draw()} {} { - code {if (!visible()) return; -const int maxdb=60; - -int ox=x(),oy=y(),lx=w(),ly=h(); -const int maxharmonic=64; - - -for (int i=1;imutex); -pars->oscilgen->getspectrum(n,spc,0); -pthread_mutex_unlock(&master->mutex); - - -//normalize -REALTYPE max=0; -for (int i=0;igetNhr(i); - int kx=(int)(lx/(REALTYPE)maxharmonic*nhr); - if ((kx<0)||(kx>lx)) continue; - - spectrum[kx]=spc[i-1]/max+1e-9; - -}; - -fl_color(180,0,0); -fl_line_style(0); - -if (pars->Pmode==2){ - int old=0; - for (int i=1;i1e-10)||(i==(lx-1))){ - int delta=i-old; - REALTYPE val1=spectrum[old]; - REALTYPE val2=spectrum[i]; - - REALTYPE idelta=1.0/delta; - for (int j=0;jdB2rap(-maxdb)) x=rap2dB(x)/maxdb+1; - else continue; - int yy=(int)(x*ly); - fl_line(ox+i,oy+ly-1-yy,ox+i,oy+ly-1); - -};} {} - } - decl {Master *master;} {} - decl {PADnoteParameters *pars;} {public - } -} - -class PADnoteUI {open : {public PresetsUI_} -} { - Function {PADnoteUI(PADnoteParameters *parameters,Master *master_)} {open - } { - code {pars=parameters; -master=master_; -oscui=NULL; -resui=new ResonanceUI(pars->resonance); -make_window();} {} - } - Function {make_window()} {open - } { - Fl_Window padnotewindow { - label {PAD synth Parameters} open - xywh {281 302 535 450} type Double visible - } { - Fl_Tabs {} { - callback {if (o->value()!=harmonicstructuregroup) applybutton->hide(); - else applybutton->show();} - xywh {0 0 535 395} - } { - Fl_Group harmonicstructuregroup { - label {Harmonic Structure} - xywh {0 20 535 375} box ENGRAVED_BOX - } { - Fl_Group bwprofilegroup { - xywh {5 30 90 260} box ENGRAVED_BOX - code0 {if (pars->Pmode!=0) o->deactivate();} - } { - Fl_Dial hpbasepar1 { - label Width - callback {pars->Php.base.par1=(int) o->value(); -hprofile->redraw(); -cbwidget->do_callback();} - xywh {20 75 25 25} box ROUND_UP_BOX labelsize 10 align 1 maximum 127 step 1 - code0 {o->value(pars->Php.base.par1);} - class WidgetPDial - } - Fl_Choice hpbasetype { - label {Base Type} - callback {pars->Php.base.type=o->value(); -hprofile->redraw(); -cbwidget->do_callback();} - xywh {15 45 75 15} down_box BORDER_BOX labelsize 10 align 5 textsize 10 - code0 {o->value(pars->Php.base.type);} - } { - MenuItem {} { - label Gauss - xywh {15 15 100 20} labelfont 1 labelsize 10 - } - MenuItem {} { - label Square - xywh {25 25 100 20} labelfont 1 labelsize 10 - } - MenuItem {} { - label DoubleExp - xywh {35 35 100 20} labelfont 1 labelsize 10 - } - } - Fl_Dial hpfreqmult { - label FreqMlt - callback {pars->Php.freqmult=(int) o->value(); -hprofile->redraw(); -cbwidget->do_callback();} - xywh {55 75 25 25} box ROUND_UP_BOX labelsize 10 align 1 maximum 127 step 1 - code0 {o->value(pars->Php.freqmult);} - class WidgetPDial - } - Fl_Dial hpmpar1 { - label Str - callback {pars->Php.modulator.par1=(int) o->value(); -hprofile->redraw(); -cbwidget->do_callback();} - xywh {15 115 20 20} box ROUND_UP_BOX labelsize 10 align 1 maximum 127 step 1 - code0 {o->value(pars->Php.modulator.par1);} - class WidgetPDial - } - Fl_Dial hpmfreq { - label SFreq - callback {pars->Php.modulator.freq=(int) o->value(); -hprofile->redraw(); -cbwidget->do_callback();} - xywh {40 115 20 20} box ROUND_UP_BOX labelsize 10 align 1 maximum 127 step 1 - code0 {o->value(pars->Php.modulator.freq);} - class WidgetPDial - } - Fl_Group {} { - xywh {10 160 80 105} box BORDER_BOX - } { - Fl_Choice hpamptype { - label AmpMultiplier - callback {pars->Php.amp.type=o->value(); -hprofile->redraw(); -cbwidget->do_callback();} - xywh {15 175 70 15} down_box BORDER_BOX labelsize 10 align 5 textsize 10 - code0 {o->value(pars->Php.amp.type);} - } { - MenuItem {} { - label OFF - xywh {45 45 100 20} labelfont 1 labelsize 10 - } - MenuItem {} { - label Gauss - xywh {55 55 100 20} labelfont 1 labelsize 10 - } - MenuItem {} { - label Sine - xywh {65 65 100 20} labelfont 1 labelsize 10 - } - MenuItem {} { - label Flat - xywh {75 75 100 20} labelfont 1 labelsize 10 - } - } - Fl_Choice hpampmode { - label AmpMode - callback {pars->Php.amp.mode=o->value(); -hprofile->redraw(); -cbwidget->do_callback();} - xywh {15 205 70 15} down_box BORDER_BOX labelsize 10 align 5 textsize 10 - code0 {o->value(pars->Php.amp.mode);} - } { - MenuItem {} { - label Sum - xywh {60 60 100 20} labelfont 1 labelsize 10 - } - MenuItem {} { - label Mult - xywh {70 70 100 20} labelfont 1 labelsize 10 - } - MenuItem {} { - label Div1 - xywh {80 80 100 20} labelfont 1 labelsize 10 - } - MenuItem {} { - label Div2 - xywh {90 90 100 20} labelfont 1 labelsize 10 - } - } - Fl_Dial hpamppar1 { - label Par1 - callback {pars->Php.amp.par1=(int) o->value(); -hprofile->redraw(); -cbwidget->do_callback();} - xywh {15 235 25 25} box ROUND_UP_BOX labelsize 10 align 1 maximum 127 step 1 - code0 {o->value(pars->Php.amp.par1);} - class WidgetPDial - } - Fl_Dial hpamppar2 { - label Par2 - callback {pars->Php.amp.par2=(int) o->value(); -hprofile->redraw(); -cbwidget->do_callback();} - xywh {55 235 25 25} box ROUND_UP_BOX labelsize 10 align 1 maximum 127 step 1 - code0 {o->value(pars->Php.amp.par2);} - class WidgetPDial - } - } - Fl_Check_Button hpautoscale { - label autoscale - callback {pars->Php.autoscale=(int) o->value(); -hprofile->redraw(); -cbwidget->do_callback();} - xywh {10 270 60 15} down_box DOWN_BOX labelsize 10 - code0 {o->value(pars->Php.autoscale);} - } - Fl_Choice hponehalf { - callback {pars->Php.onehalf=o->value(); -hprofile->redraw(); -cbwidget->do_callback();} - xywh {10 143 80 15} down_box BORDER_BOX labelsize 10 align 5 textsize 10 - code0 {o->value(pars->Php.onehalf);} - } { - MenuItem {} { - label Full - xywh {25 25 100 20} labelfont 1 labelsize 10 - } - MenuItem {} { - label {Upper Half} - xywh {45 45 100 20} labelfont 1 labelsize 10 - } - MenuItem {} { - label {Lower Half} - xywh {35 35 100 20} labelfont 1 labelsize 10 - } - } - Fl_Dial hpwidth { - label Size - callback {pars->Php.width=(int) o->value(); -hprofile->redraw(); -cbwidget->do_callback();} - xywh {65 115 20 20} box ROUND_UP_BOX labelsize 10 align 1 maximum 127 step 1 - code0 {o->value(pars->Php.width);} - class WidgetPDial - } - } - Fl_Group {} { - xywh {100 155 270 135} box THIN_DOWN_BOX color 32 selection_color 71 labelcolor 179 align 6 - code0 {osc=new Oscilloscope(o->x(),o->y(),o->w(),o->h(),"");} - code1 {osc->init(pars->oscilgen,master);} - } {} - Fl_Button {} { - label Change - callback {if (oscui!=NULL) delete (oscui); -oscui=new OscilEditor(pars->oscilgen,osc,cbwidget,applybutton,master);} - xywh {375 270 60 20} box THIN_UP_BOX labelfont 1 labelsize 11 - } - Fl_Box cbwidget { - label {Harmonic Content} - callback {overtonepos->redraw(); -applybutton->color(FL_RED); -applybutton->redraw();} - xywh {125 135 205 20} align 16 - } - Fl_Button {} { - label Resonance - callback {resui->resonancewindow->redraw(); -resui->resonancewindow->show(); -resui->setcbwidget(cbwidget,applybutton);} - xywh {375 225 80 20} box THIN_UP_BOX - } - Fl_Dial bwdial { - label BandWidth - callback {bwcents->value(pars->setPbandwidth((int) o->value())); -cbwidget->do_callback();} - xywh {15 295 35 35} box ROUND_UP_BOX labelsize 10 maximum 1000 step 1 - code0 {o->value(pars->Pbandwidth);} - code1 {if (pars->Pmode!=0) o->deactivate();} - class WidgetPDial - } - Fl_Value_Output bwcents { - label cents - xywh {55 305 55 15} labelsize 10 align 6 maximum 10000 step 0.1 - code0 {o->value(pars->setPbandwidth(pars->Pbandwidth));} - code1 {if (pars->Pmode!=0) o->deactivate();} - } - Fl_Group {} { - xywh {315 295 215 45} box ENGRAVED_BOX - } { - Fl_Choice hrpostype { - label OvertonesPosition - callback {pars->Phrpos.type=o->value(); -overtonepos->redraw(); -cbwidget->do_callback();} - xywh {325 310 80 20} down_box BORDER_BOX labelsize 10 align 5 textsize 11 - code0 {o->value(pars->Phrpos.type);} - } { - MenuItem {} { - label Harmonic - xywh {70 70 100 20} labelfont 1 labelsize 11 - } - MenuItem {} { - label ShiftU - xywh {80 80 100 20} labelfont 1 labelsize 11 - } - MenuItem {} { - label ShiftL - xywh {90 90 100 20} labelfont 1 labelsize 11 - } - MenuItem {} { - label PowerU - xywh {90 90 100 20} labelfont 1 labelsize 11 - } - MenuItem {} { - label PowerL - xywh {100 100 100 20} labelfont 1 labelsize 11 - } - MenuItem {} { - label Sine - xywh {110 110 100 20} labelfont 1 labelsize 11 - } - MenuItem {} { - label Power - xywh {120 120 100 20} labelfont 1 labelsize 11 - } - } - Fl_Dial hrpospar1 { - label Par1 - callback {pars->Phrpos.par1=(int) o->value(); -overtonepos->redraw(); -cbwidget->do_callback();} - xywh {425 310 25 25} box ROUND_UP_BOX labelsize 10 align 1 maximum 255 step 1 - code0 {o->value(pars->Phrpos.par1);} - class WidgetPDial - } - Fl_Dial hrpospar2 { - label Par2 - callback {pars->Phrpos.par2=(int) o->value(); -overtonepos->redraw(); -cbwidget->do_callback();} - xywh {460 310 25 25} box ROUND_UP_BOX labelsize 10 align 1 maximum 255 step 1 - code0 {o->value(pars->Phrpos.par2);} - class WidgetPDial - } - Fl_Dial hrpospar3 { - label ForceH - callback {pars->Phrpos.par3=(int) o->value(); -overtonepos->redraw(); -cbwidget->do_callback();} - xywh {495 310 25 25} box ROUND_UP_BOX labelsize 10 align 1 maximum 255 step 1 - code0 {o->value(pars->Phrpos.par3);} - class WidgetPDial - } - } - Fl_Choice bwscale { - label {Bandwidth Scale} - callback {pars->Pbwscale=(int) o->value(); -cbwidget->do_callback();} - xywh {120 305 80 20} down_box BORDER_BOX labelsize 10 align 5 textsize 11 - code0 {o->value(pars->Pbwscale);} - code1 {if (pars->Pmode!=0) o->deactivate();} - } { - MenuItem {} { - label Normal - xywh {95 95 100 20} labelfont 1 labelsize 11 - } - MenuItem {} { - label EqualHz - xywh {105 105 100 20} labelfont 1 labelsize 11 - } - MenuItem {} { - label Quater - xywh {115 115 100 20} labelfont 1 labelsize 11 - } - MenuItem {} { - label Half - xywh {125 125 100 20} labelfont 1 labelsize 11 - } - MenuItem {} { - label {75%} - xywh {135 135 100 20} labelfont 1 labelsize 11 - } - MenuItem {} { - label {150%} - xywh {145 145 100 20} labelfont 1 labelsize 11 - } - MenuItem {} { - label Double - xywh {145 145 100 20} labelfont 1 labelsize 11 - } - MenuItem {} { - label {Inv.Half} - xywh {155 155 100 20} labelfont 1 labelsize 11 - } - } - Fl_Group overtonepos { - xywh {5 345 525 45} box FLAT_BOX color 54 selection_color 218 labelcolor 63 - code0 {PADnoteOvertonePosition *opui=new PADnoteOvertonePosition(o->x(),o->y(),o->w(),o->h(),"");} - code1 {opui->init(pars,master);} - } {} - Fl_Choice qsamplesize { - label {Sample Size} - callback {pars->Pquality.samplesize=(int) o->value(); -cbwidget->do_callback();} - xywh {375 190 115 20} down_box BORDER_BOX labelsize 10 align 5 textsize 11 - code0 {o->value(pars->Pquality.samplesize);} - } { - MenuItem {} { - label {16k (Tiny)} - xywh {155 155 100 20} labelfont 1 labelsize 11 - } - MenuItem {} { - label 32k - xywh {165 165 100 20} labelfont 1 labelsize 11 - } - MenuItem {} { - label {64k (Small)} - xywh {175 175 100 20} labelfont 1 labelsize 11 - } - MenuItem {} { - label 128k - xywh {185 185 100 20} labelfont 1 labelsize 11 - } - MenuItem {} { - label {256k (Normal)} - xywh {205 205 100 20} labelfont 1 labelsize 11 - } - MenuItem {} { - label 512k - xywh {200 200 100 20} labelfont 1 labelsize 11 - } - MenuItem {} { - label {1M (Big)} - xywh {205 205 100 20} labelfont 1 labelsize 11 - } - } - Fl_Choice qsmpoct { - label {smp/oct} - callback {pars->Pquality.smpoct=(int) o->value(); -cbwidget->do_callback();} - xywh {430 155 45 20} down_box BORDER_BOX labelsize 11 align 5 textsize 11 - code0 {o->value(pars->Pquality.smpoct);} - } { - MenuItem {} { - label {0.5} - xywh {10 10 100 20} labelfont 1 labelsize 11 - } - MenuItem {} { - label 1 - xywh {0 0 100 20} labelfont 1 labelsize 11 - } - MenuItem {} { - label 2 - xywh {10 10 100 20} labelfont 1 labelsize 11 - } - MenuItem {} { - label 3 - xywh {20 20 100 20} labelfont 1 labelsize 11 - } - MenuItem {} { - label 4 - xywh {30 30 100 20} labelfont 1 labelsize 11 - } - MenuItem {} { - label 6 - xywh {40 40 100 20} labelfont 1 labelsize 11 - } - MenuItem {} { - label 12 - xywh {50 50 100 20} labelfont 1 labelsize 11 - } - } - Fl_Choice qoct { - label {no.oct} - callback {pars->Pquality.oct=(int) o->value(); -cbwidget->do_callback();} - xywh {480 155 45 20} down_box BORDER_BOX labelsize 11 align 5 textsize 11 - code0 {o->value(pars->Pquality.oct);} - } { - MenuItem {} { - label 1 - xywh {10 10 100 20} labelfont 1 labelsize 11 - } - MenuItem {} { - label 2 - xywh {20 20 100 20} labelfont 1 labelsize 11 - } - MenuItem {} { - label 3 - xywh {30 30 100 20} labelfont 1 labelsize 11 - } - MenuItem {} { - label 4 - xywh {40 40 100 20} labelfont 1 labelsize 11 - } - MenuItem {} { - label 5 - xywh {50 50 100 20} labelfont 1 labelsize 11 - } - MenuItem {} { - label 6 - xywh {60 60 100 20} labelfont 1 labelsize 11 - } - MenuItem {} { - label 7 - xywh {70 70 100 20} labelfont 1 labelsize 11 - } - MenuItem {} { - label 8 - xywh {80 80 100 20} labelfont 1 labelsize 11 - } - } - Fl_Choice qbasenote { - label base - callback {pars->Pquality.basenote=(int) o->value(); -cbwidget->do_callback();} - xywh {375 155 50 20} down_box BORDER_BOX labelsize 11 align 5 textsize 11 - code0 {o->value(pars->Pquality.basenote);} - } { - MenuItem {} { - label {C-2} - xywh {10 10 100 20} labelfont 1 - } - MenuItem {} { - label {G-2} - xywh {20 20 100 20} labelfont 1 - } - MenuItem {} { - label {C-3} - xywh {20 20 100 20} labelfont 1 - } - MenuItem {} { - label {G-3} - xywh {30 30 100 20} labelfont 1 - } - MenuItem {} { - label {C-4} - xywh {30 30 100 20} labelfont 1 - } - MenuItem {} { - label {G-4} - xywh {40 40 100 20} labelfont 1 - } - MenuItem {} { - label {C-5} - xywh {40 40 100 20} labelfont 1 - } - MenuItem {} { - label {G-5} - xywh {50 50 100 20} labelfont 1 - } - MenuItem {} { - label {G-6} - xywh {60 60 100 20} labelfont 1 - } - } - Fl_Group hprofile { - xywh {100 45 430 90} box FLAT_BOX color 54 selection_color 218 labelcolor 63 - code0 {PADnoteHarmonicProfile *hpui=new PADnoteHarmonicProfile(o->x(),o->y(),o->w(),o->h(),"");} - code1 {hpui->init(pars,master);} - code2 {if (pars->Pmode!=0) { o->deactivate(); o->color(48);};} - } {} - Fl_Box {} { - label {Profile of One Harmonic (Frequency Distribution)} - xywh {160 25 315 20} - } - Fl_Choice spectrummode { - label {Spectrum Mode} - callback {pars->Pmode=(int) o->value(); - -if (pars->Pmode==0){ - bwprofilegroup->activate(); - bwdial->activate(); - bwcents->activate(); - hprofile->activate(); - hprofile->color(54); - bwscale->activate(); -} else { - bwprofilegroup->deactivate(); - bwdial->deactivate(); - bwcents->deactivate(); - hprofile->deactivate(); - hprofile->color(48); - bwscale->deactivate(); -}; - -cbwidget->do_callback();} - xywh {220 305 90 20} down_box BORDER_BOX labelfont 1 labelsize 10 align 5 textsize 11 - code0 {o->value(pars->Pmode);} - } { - MenuItem {} { - label Bandwidth - xywh {105 105 100 20} labelfont 1 labelsize 11 - } - MenuItem {} { - label Discrete - xywh {125 125 100 20} labelfont 1 labelsize 11 - } - MenuItem {} { - label Continous - xywh {115 115 100 20} labelfont 1 labelsize 11 - } - } - } - Fl_Group {} { - label {Envelopes&LFOs} - xywh {0 20 535 375} box ENGRAVED_BOX hide - } { - Fl_Group {} { - label FREQUENCY - xywh {5 275 525 115} box THIN_UP_BOX labeltype EMBOSSED_LABEL labelfont 1 labelsize 13 align 17 - } { - Fl_Group freqenv { - label {PADSynth - Frequency Envelope} open - xywh {10 315 205 70} box FLAT_BOX color 51 align 144 - code0 {o->init(pars->FreqEnvelope);} - class EnvelopeUI - } {} - Fl_Counter octave { - label Octave - callback {int k=(int) o->value(); -if (k<0) k+=16; -pars->PCoarseDetune = k*1024+ - pars->PCoarseDetune%1024;} - tooltip Octave xywh {470 295 45 15} type Simple labelsize 10 align 1 minimum -8 maximum 7 step 1 textfont 1 textsize 11 - code0 {int k=pars->PCoarseDetune/1024;} - code1 {if (k>=8) k-=16;} - code2 {o->value(k);} - } - Fl_Counter coarsedet { - label {Coarse det.} - callback {int k=(int) o->value(); -if (k<0) k+=1024; -pars->PCoarseDetune = k+ - (pars->PCoarseDetune/1024)*1024;} - tooltip {Coarse Detune} xywh {455 365 60 20} labelsize 10 align 5 minimum -64 maximum 63 step 1 textfont 1 textsize 11 - code0 {int k=pars->PCoarseDetune%1024;} - code1 {if (k>=512) k-=1024;} - code2 {o->value(k);} - code3 {o->lstep(10);} - } - Fl_Group freqlfo { - label {Frequency LFO } open - xywh {215 315 230 70} box FLAT_BOX color 47 align 144 - code0 {o->init(pars->FreqLfo);} - class LFOUI - } {} - Fl_Slider detune { - callback {pars->PDetune=(int)o->value()+8192; -detunevalueoutput->do_callback();} - tooltip {Fine Detune (cents)} xywh {60 295 295 15} type {Horz Knob} box FLAT_BOX minimum -8192 maximum 8191 step 1 - code0 {o->value(pars->PDetune-8192);} - } - Fl_Value_Output detunevalueoutput { - label Detune - callback {o->value(getdetune(pars->PDetuneType,0,pars->PDetune));} - xywh {12 295 45 15} labelsize 10 align 5 minimum -5000 maximum 5000 step 0.01 textfont 1 textsize 10 - code0 {o->value(getdetune(pars->PDetuneType,0,pars->PDetune));} - } - Fl_Choice detunetype { - label {Detune Type} - callback {pars->PDetuneType=(int) o->value()+1; -detunevalueoutput->do_callback();} open - xywh {450 335 75 15} down_box BORDER_BOX labelsize 10 align 5 textfont 1 textsize 10 - code0 {o->add("L35cents");o->add("L10cents");o->add("E100cents");o->add("E1200cents");} - code1 {o->value(pars->PDetuneType-1);} - } {} - Fl_Check_Button hz440 { - label 440Hz - callback {int x=(int) o->value(); -pars->Pfixedfreq=x; -if (x==0) fixedfreqetdial->deactivate(); - else fixedfreqetdial->activate();} - tooltip {set the base frequency to 440Hz} xywh {365 295 50 15} down_box DOWN_BOX labelfont 1 labelsize 10 - code0 {o->value(pars->Pfixedfreq);} - } - Fl_Dial fixedfreqetdial { - label {Eq.T.} - callback {pars->PfixedfreqET=(int) o->value();} - tooltip {How the frequency varies acording to the keyboard (leftmost for fixed frequency)} xywh {420 295 15 15} box ROUND_UP_BOX labelsize 10 align 8 maximum 127 step 1 - code0 {o->value(pars->PfixedfreqET);} - code1 {if (pars->Pfixedfreq==0) o->deactivate();} - class WidgetPDial - } - } - Fl_Group {} { - label AMPLITUDE - xywh {5 25 240 250} box THIN_UP_FRAME labeltype EMBOSSED_LABEL labelfont 1 labelsize 13 align 17 - } { - Fl_Value_Slider volume { - label Vol - callback {pars->PVolume=(int)o->value();} - tooltip Volume xywh {10 50 160 15} type {Horz Knob} box FLAT_BOX labelsize 11 align 8 maximum 127 step 1 - code0 {o->value(pars->PVolume);} - } - Fl_Value_Slider vsns { - label {V.Sns} - callback {pars->PAmpVelocityScaleFunction=(int) o->value();} - tooltip {Velocity Sensing Function (rightmost to disable)} xywh {10 70 160 15} type {Horz Knob} box FLAT_BOX labelsize 11 align 8 maximum 127 step 1 - code0 {o->value(pars->PAmpVelocityScaleFunction);} - } - Fl_Dial pan { - label Pan - callback {pars->PPanning=(int) o->value();} - tooltip {Panning (leftmost is Random)} xywh {210 45 30 30} box ROUND_UP_BOX labelsize 10 maximum 127 step 1 - code0 {o->value(pars->PPanning);} - class WidgetPDial - } - Fl_Dial pstr { - label {P.Str.} - callback {pars->PPunchStrength=(int) o->value();} - tooltip {Punch Strength} xywh {125 247 25 25} box ROUND_UP_BOX labelsize 10 align 1 maximum 127 step 1 - code0 {o->value(pars->PPunchStrength);} - class WidgetPDial - } - Fl_Dial pt { - label {P.t.} - callback {pars->PPunchTime=(int) o->value();} - tooltip {Punch Time (duration)} xywh {155 247 25 25} box ROUND_UP_BOX labelsize 10 align 1 maximum 127 step 1 - code0 {o->value(pars->PPunchTime);} - class WidgetPDial - } - Fl_Dial pstc { - label {P.Stc.} - callback {pars->PPunchStretch=(int) o->value();} - tooltip {Punch Stretch} xywh {185 247 25 25} box ROUND_UP_BOX labelsize 10 align 1 maximum 127 step 1 - code0 {o->value(pars->PPunchStretch);} - class WidgetPDial - } - Fl_Dial pvel { - label {P.Vel.} - callback {pars->PPunchVelocitySensing=(int) o->value();} - tooltip {Punch Velocity Sensing} xywh {215 247 25 25} box ROUND_UP_BOX labelsize 10 align 1 maximum 127 step 1 - code0 {o->value(pars->PPunchVelocitySensing);} - class WidgetPDial - } - Fl_Group ampenv { - label {PADSynth - Amplitude Envelope} open - xywh {10 95 205 70} box FLAT_BOX color 51 align 144 - code0 {o->init(pars->AmpEnvelope);} - class EnvelopeUI - } {} - Fl_Group amplfo { - label {Amplitude LFO } open - xywh {10 165 230 70} box FLAT_BOX color 47 align 144 - code0 {o->init(pars->AmpLfo);} - class LFOUI - } {} - Fl_Check_Button stereo { - label Stereo - callback {pars->PStereo=(int) o->value(); -hprofile->redraw();} - xywh {15 245 70 25} down_box DOWN_BOX - code0 {o->value(pars->PStereo);} - } - } - Fl_Group {} { - label FILTER - xywh {245 25 285 250} box THIN_UP_BOX labeltype EMBOSSED_LABEL labelfont 1 labelsize 13 align 17 - } { - Fl_Group filterenv { - label {PADSynth - Filter Envelope} open - xywh {250 130 275 70} box FLAT_BOX color 51 align 144 - code0 {o->init(pars->FilterEnvelope);} - class EnvelopeUI - } {} - Fl_Group filterlfo { - label {Filter LFO } open - xywh {250 200 230 70} box FLAT_BOX color 47 align 144 - code0 {o->init(pars->FilterLfo);} - class LFOUI - } {} - Fl_Group filterui { - label {PADsynth - Filter} open - xywh {250 55 275 75} box FLAT_BOX color 50 align 144 - code0 {o->init(pars->GlobalFilter,&pars->PFilterVelocityScale,&pars->PFilterVelocityScaleFunction);} - class FilterUI - } {} - } - } - } - Fl_Button applybutton { - label {Apply Changes} - callback {pars->applyparameters(true); -o->color(FL_GRAY); -if (oscui!=NULL) { - oscui->applybutton->color(FL_GRAY); - oscui->applybutton->redraw(); -}; -if (resui!=NULL) { - resui->applybutton->color(FL_GRAY); - resui->applybutton->redraw(); -};} - xywh {45 405 185 40} box THIN_UP_BOX labelfont 1 labelsize 16 - code0 {o->color(FL_RED);} - } - Fl_Button {} { - label Close - callback {padnotewindow->hide();} - xywh {320 405 175 40} box THIN_UP_BOX labelsize 17 - } - Fl_Button {} { - label C - callback {presetsui->copy(pars);} - xywh {240 430 25 15} box THIN_UP_BOX color 179 labelfont 1 labelsize 11 labelcolor 7 - } - Fl_Button {} { - label P - callback {presetsui->paste(pars,this);} - xywh {270 430 25 15} box THIN_UP_BOX color 179 labelfont 1 labelsize 11 labelcolor 7 - } - Fl_Button {} { - label export - callback {char *filename; -filename=fl_file_chooser("Export samples:","(*.wav)",NULL,0); -if (filename==NULL) return; -fl_filename_setext(filename,""); - - - -pars->export2wav(filename);} selected - tooltip {export samples as wav file} xywh {240 405 55 15} box THIN_UP_BOX color 255 labelsize 11 align 128 - } - } - } - Function {refresh()} {} { - code {volume->value(pars->PVolume); -vsns->value(pars->PAmpVelocityScaleFunction); -pan->value(pars->PPanning); - -stereo->value(pars->PStereo); - - -pstr->value(pars->PPunchStrength); -pt->value(pars->PPunchTime); -pstc->value(pars->PPunchStretch); -pvel->value(pars->PPunchVelocitySensing); - -detunevalueoutput->value(getdetune(pars->PDetuneType,0,pars->PDetune)); -detune->value(pars->PDetune-8192); - -int k=pars->PCoarseDetune/1024;if (k>=8) k-=16; -octave->value(k); - -detunetype->value(pars->PDetuneType-1); -k=pars->PCoarseDetune%1024;if (k>=512) k-=1024; -coarsedet->value(k); - -hz440->value(pars->Pfixedfreq); -fixedfreqetdial->value(pars->PfixedfreqET); - -amplfo->refresh(); -freqlfo->refresh(); -filterlfo->refresh(); - -ampenv->refresh(); -freqenv->refresh(); -filterenv->refresh(); -filterui->refresh(); - - -/* harmonic structure parametrs */ - -resui->refresh(); -if (oscui!=NULL) oscui->refresh(); - -hpbasetype->value(pars->Php.base.type); -hpbasepar1->value(pars->Php.base.par1); -hpfreqmult->value(pars->Php.freqmult); - -hpmpar1->value(pars->Php.modulator.par1); -hpmfreq->value(pars->Php.modulator.freq); -hpwidth->value(pars->Php.width); - -hponehalf->value(pars->Php.onehalf); -hpamptype->value(pars->Php.amp.type); -hpampmode->value(pars->Php.amp.mode); -hpamppar1->value(pars->Php.amp.par1); -hpamppar2->value(pars->Php.amp.par2); -hpautoscale->value(pars->Php.autoscale); - -bwdial->value(pars->Pbandwidth); -if (pars->Pmode==0){ - bwprofilegroup->activate(); - bwdial->activate(); - bwcents->activate(); - hprofile->activate(); - hprofile->color(54); - bwscale->activate(); -} else { - bwprofilegroup->deactivate(); - bwdial->deactivate(); - bwcents->deactivate(); - hprofile->deactivate(); - hprofile->color(48); - bwscale->activate(); -}; - -spectrummode->value(pars->Pmode); - -qbasenote->value(pars->Pquality.basenote); -qsmpoct->value(pars->Pquality.smpoct); -qoct->value(pars->Pquality.oct); -qsamplesize->value(pars->Pquality.samplesize); - -hrpostype->value(pars->Phrpos.type); -hrpospar1->value(pars->Phrpos.par1); -hrpospar2->value(pars->Phrpos.par2); -hrpospar3->value(pars->Phrpos.par3); - -hprofile->redraw(); -overtonepos->redraw(); - -osc->redraw(); -pars->applyparameters(true); -applybutton->color(FL_GRAY); -applybutton->parent()->redraw();} {} - } - Function {~PADnoteUI()} {} { - code {delete(oscui); -delete(resui); - -padnotewindow->hide(); -delete(padnotewindow);} {} - } - decl {PADnoteParameters *pars;} {public - } - decl {Master *master;} {public - } - decl {OscilEditor *oscui;} {public - } - decl {Oscilloscope *osc;} {public - } - decl {ResonanceUI *resui;} {public - } -} diff --git a/plugins/zynaddsubfx/src/UI/PADnoteUI.h b/plugins/zynaddsubfx/src/UI/PADnoteUI.h deleted file mode 100644 index e21f494de..000000000 --- a/plugins/zynaddsubfx/src/UI/PADnoteUI.h +++ /dev/null @@ -1,305 +0,0 @@ -// generated by Fast Light User Interface Designer (fluid) version 1.0300 - -#ifndef PADnoteUI_h -#define PADnoteUI_h -#include -#include "../Params/PADnoteParameters.h" -#include "../Misc/Util.h" -#include "../Misc/Master.h" -#include "ResonanceUI.h" -#include -#include -#include -#include "WidgetPDial.h" -#include "EnvelopeUI.h" -#include "LFOUI.h" -#include "FilterUI.h" -#include "OscilGenUI.h" -#include "PresetsUI.h" - -class PADnoteHarmonicProfile : public Fl_Box { -public: - PADnoteHarmonicProfile(int x,int y, int w, int h, const char *label=0); - void init(PADnoteParameters *pars,Master *master_); - void draw(); -private: - Master *master; -public: - PADnoteParameters *pars; -}; - -class PADnoteOvertonePosition : public Fl_Box { -public: - PADnoteOvertonePosition(int x,int y, int w, int h, const char *label=0); - void init(PADnoteParameters *pars,Master *master_); - void draw(); -private: - Master *master; -public: - PADnoteParameters *pars; -}; -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -class PADnoteUI : public PresetsUI_ { -public: - PADnoteUI(PADnoteParameters *parameters,Master *master_); - Fl_Double_Window* make_window(); - Fl_Double_Window *padnotewindow; -private: - void cb__i(Fl_Tabs*, void*); - static void cb_(Fl_Tabs*, void*); -public: - Fl_Group *harmonicstructuregroup; - Fl_Group *bwprofilegroup; - WidgetPDial *hpbasepar1; -private: - void cb_hpbasepar1_i(WidgetPDial*, void*); - static void cb_hpbasepar1(WidgetPDial*, void*); -public: - Fl_Choice *hpbasetype; -private: - void cb_hpbasetype_i(Fl_Choice*, void*); - static void cb_hpbasetype(Fl_Choice*, void*); - static Fl_Menu_Item menu_hpbasetype[]; -public: - WidgetPDial *hpfreqmult; -private: - void cb_hpfreqmult_i(WidgetPDial*, void*); - static void cb_hpfreqmult(WidgetPDial*, void*); -public: - WidgetPDial *hpmpar1; -private: - void cb_hpmpar1_i(WidgetPDial*, void*); - static void cb_hpmpar1(WidgetPDial*, void*); -public: - WidgetPDial *hpmfreq; -private: - void cb_hpmfreq_i(WidgetPDial*, void*); - static void cb_hpmfreq(WidgetPDial*, void*); -public: - Fl_Choice *hpamptype; -private: - void cb_hpamptype_i(Fl_Choice*, void*); - static void cb_hpamptype(Fl_Choice*, void*); - static Fl_Menu_Item menu_hpamptype[]; -public: - Fl_Choice *hpampmode; -private: - void cb_hpampmode_i(Fl_Choice*, void*); - static void cb_hpampmode(Fl_Choice*, void*); - static Fl_Menu_Item menu_hpampmode[]; -public: - WidgetPDial *hpamppar1; -private: - void cb_hpamppar1_i(WidgetPDial*, void*); - static void cb_hpamppar1(WidgetPDial*, void*); -public: - WidgetPDial *hpamppar2; -private: - void cb_hpamppar2_i(WidgetPDial*, void*); - static void cb_hpamppar2(WidgetPDial*, void*); -public: - Fl_Check_Button *hpautoscale; -private: - void cb_hpautoscale_i(Fl_Check_Button*, void*); - static void cb_hpautoscale(Fl_Check_Button*, void*); -public: - Fl_Choice *hponehalf; -private: - void cb_hponehalf_i(Fl_Choice*, void*); - static void cb_hponehalf(Fl_Choice*, void*); - static Fl_Menu_Item menu_hponehalf[]; -public: - WidgetPDial *hpwidth; -private: - void cb_hpwidth_i(WidgetPDial*, void*); - static void cb_hpwidth(WidgetPDial*, void*); - void cb_Change_i(Fl_Button*, void*); - static void cb_Change(Fl_Button*, void*); -public: - Fl_Box *cbwidget; -private: - void cb_cbwidget_i(Fl_Box*, void*); - static void cb_cbwidget(Fl_Box*, void*); - void cb_Resonance_i(Fl_Button*, void*); - static void cb_Resonance(Fl_Button*, void*); -public: - WidgetPDial *bwdial; -private: - void cb_bwdial_i(WidgetPDial*, void*); - static void cb_bwdial(WidgetPDial*, void*); -public: - Fl_Value_Output *bwcents; - Fl_Choice *hrpostype; -private: - void cb_hrpostype_i(Fl_Choice*, void*); - static void cb_hrpostype(Fl_Choice*, void*); - static Fl_Menu_Item menu_hrpostype[]; -public: - WidgetPDial *hrpospar1; -private: - void cb_hrpospar1_i(WidgetPDial*, void*); - static void cb_hrpospar1(WidgetPDial*, void*); -public: - WidgetPDial *hrpospar2; -private: - void cb_hrpospar2_i(WidgetPDial*, void*); - static void cb_hrpospar2(WidgetPDial*, void*); -public: - WidgetPDial *hrpospar3; -private: - void cb_hrpospar3_i(WidgetPDial*, void*); - static void cb_hrpospar3(WidgetPDial*, void*); -public: - Fl_Choice *bwscale; -private: - void cb_bwscale_i(Fl_Choice*, void*); - static void cb_bwscale(Fl_Choice*, void*); - static Fl_Menu_Item menu_bwscale[]; -public: - Fl_Group *overtonepos; - Fl_Choice *qsamplesize; -private: - void cb_qsamplesize_i(Fl_Choice*, void*); - static void cb_qsamplesize(Fl_Choice*, void*); - static Fl_Menu_Item menu_qsamplesize[]; -public: - Fl_Choice *qsmpoct; -private: - void cb_qsmpoct_i(Fl_Choice*, void*); - static void cb_qsmpoct(Fl_Choice*, void*); - static Fl_Menu_Item menu_qsmpoct[]; -public: - Fl_Choice *qoct; -private: - void cb_qoct_i(Fl_Choice*, void*); - static void cb_qoct(Fl_Choice*, void*); - static Fl_Menu_Item menu_qoct[]; -public: - Fl_Choice *qbasenote; -private: - void cb_qbasenote_i(Fl_Choice*, void*); - static void cb_qbasenote(Fl_Choice*, void*); - static Fl_Menu_Item menu_qbasenote[]; -public: - Fl_Group *hprofile; - Fl_Choice *spectrummode; -private: - void cb_spectrummode_i(Fl_Choice*, void*); - static void cb_spectrummode(Fl_Choice*, void*); - static Fl_Menu_Item menu_spectrummode[]; -public: - EnvelopeUI *freqenv; - Fl_Counter *octave; -private: - void cb_octave_i(Fl_Counter*, void*); - static void cb_octave(Fl_Counter*, void*); -public: - Fl_Counter *coarsedet; -private: - void cb_coarsedet_i(Fl_Counter*, void*); - static void cb_coarsedet(Fl_Counter*, void*); -public: - LFOUI *freqlfo; - Fl_Slider *detune; -private: - void cb_detune_i(Fl_Slider*, void*); - static void cb_detune(Fl_Slider*, void*); -public: - Fl_Value_Output *detunevalueoutput; -private: - void cb_detunevalueoutput_i(Fl_Value_Output*, void*); - static void cb_detunevalueoutput(Fl_Value_Output*, void*); -public: - Fl_Choice *detunetype; -private: - void cb_detunetype_i(Fl_Choice*, void*); - static void cb_detunetype(Fl_Choice*, void*); -public: - Fl_Check_Button *hz440; -private: - void cb_hz440_i(Fl_Check_Button*, void*); - static void cb_hz440(Fl_Check_Button*, void*); -public: - WidgetPDial *fixedfreqetdial; -private: - void cb_fixedfreqetdial_i(WidgetPDial*, void*); - static void cb_fixedfreqetdial(WidgetPDial*, void*); -public: - Fl_Value_Slider *volume; -private: - void cb_volume_i(Fl_Value_Slider*, void*); - static void cb_volume(Fl_Value_Slider*, void*); -public: - Fl_Value_Slider *vsns; -private: - void cb_vsns_i(Fl_Value_Slider*, void*); - static void cb_vsns(Fl_Value_Slider*, void*); -public: - WidgetPDial *pan; -private: - void cb_pan_i(WidgetPDial*, void*); - static void cb_pan(WidgetPDial*, void*); -public: - WidgetPDial *pstr; -private: - void cb_pstr_i(WidgetPDial*, void*); - static void cb_pstr(WidgetPDial*, void*); -public: - WidgetPDial *pt; -private: - void cb_pt_i(WidgetPDial*, void*); - static void cb_pt(WidgetPDial*, void*); -public: - WidgetPDial *pstc; -private: - void cb_pstc_i(WidgetPDial*, void*); - static void cb_pstc(WidgetPDial*, void*); -public: - WidgetPDial *pvel; -private: - void cb_pvel_i(WidgetPDial*, void*); - static void cb_pvel(WidgetPDial*, void*); -public: - EnvelopeUI *ampenv; - LFOUI *amplfo; - Fl_Check_Button *stereo; -private: - void cb_stereo_i(Fl_Check_Button*, void*); - static void cb_stereo(Fl_Check_Button*, void*); -public: - EnvelopeUI *filterenv; - LFOUI *filterlfo; - FilterUI *filterui; - Fl_Button *applybutton; -private: - void cb_applybutton_i(Fl_Button*, void*); - static void cb_applybutton(Fl_Button*, void*); - void cb_Close_i(Fl_Button*, void*); - static void cb_Close(Fl_Button*, void*); - void cb_C_i(Fl_Button*, void*); - static void cb_C(Fl_Button*, void*); - void cb_P_i(Fl_Button*, void*); - static void cb_P(Fl_Button*, void*); - void cb_export_i(Fl_Button*, void*); - static void cb_export(Fl_Button*, void*); -public: - void refresh(); - ~PADnoteUI(); - PADnoteParameters *pars; - Master *master; - OscilEditor *oscui; - Oscilloscope *osc; - ResonanceUI *resui; -}; -#endif diff --git a/plugins/zynaddsubfx/src/UI/PartUI.cc b/plugins/zynaddsubfx/src/UI/PartUI.cc deleted file mode 100644 index 102edde25..000000000 --- a/plugins/zynaddsubfx/src/UI/PartUI.cc +++ /dev/null @@ -1,1880 +0,0 @@ -// generated by Fast Light User Interface Designer (fluid) version 1.0300 - -#include "PartUI.h" -//Copyright (c) 2002-2005 Nasca Octavian Paul -//License: GNU GPL version 2 or later - -void PartSysEffSend::cb_01_i(WidgetPDial* o, void*) { - master->setPsysefxvol(npart,neff,(int) o->value()); -} -void PartSysEffSend::cb_01(WidgetPDial* o, void* v) { - ((PartSysEffSend*)(o->parent()->user_data()))->cb_01_i(o,v); -} - -Fl_Group* PartSysEffSend::make_window() { - { syseffsend = new Fl_Group(0, 0, 90, 35); - syseffsend->box(FL_FLAT_BOX); - syseffsend->color(FL_BACKGROUND_COLOR); - syseffsend->selection_color(FL_BACKGROUND_COLOR); - syseffsend->labeltype(FL_NO_LABEL); - syseffsend->labelfont(0); - syseffsend->labelsize(14); - syseffsend->labelcolor(FL_FOREGROUND_COLOR); - syseffsend->user_data((void*)(this)); - syseffsend->align(Fl_Align(FL_ALIGN_TOP)); - syseffsend->when(FL_WHEN_RELEASE); - { WidgetPDial* o = new WidgetPDial(0, 0, 25, 25, "01"); - o->box(FL_ROUND_UP_BOX); - o->color(FL_BACKGROUND_COLOR); - o->selection_color(FL_INACTIVE_COLOR); - o->labeltype(FL_NORMAL_LABEL); - o->labelfont(1); - o->labelsize(10); - o->labelcolor(FL_FOREGROUND_COLOR); - o->maximum(127); - o->step(1); - o->callback((Fl_Callback*)cb_01); - o->align(Fl_Align(130)); - o->when(FL_WHEN_CHANGED); - o->size(25,25); - o->value(master->Psysefxvol[neff][npart]); - char tmp[10];snprintf(tmp,10,"%d",neff+1);o->copy_label(tmp); - } // WidgetPDial* o - syseffsend->end(); - } // Fl_Group* syseffsend - return syseffsend; -} - -PartSysEffSend::PartSysEffSend(int x,int y, int w, int h, const char *label):Fl_Group(x,y,w,h,label) { - master=NULL; - neff=0; - npart=0; -} - -void PartSysEffSend::init(Master *master_,int npart_,int neff_) { - npart=npart_; - neff=neff_; - master=master_; - make_window(); - syseffsend->show(); - end(); -} - -PartSysEffSend::~PartSysEffSend() { - syseffsend->hide(); - //delete(syseffsend); -} - -void PartUI_::showparameters(int kititem,int engine) { -} - -void PartKitItem::cb_minkcounter_i(Fl_Counter* o, void*) { - part->kit[n].Pminkey=(int)o->value(); -} -void PartKitItem::cb_minkcounter(Fl_Counter* o, void* v) { - ((PartKitItem*)(o->parent()->parent()->user_data()))->cb_minkcounter_i(o,v); -} - -void PartKitItem::cb_m_i(Fl_Button*, void*) { - if (part->lastnote>=0) minkcounter->value(part->lastnote); -minkcounter->do_callback(); -maxkcounter->do_callback(); -} -void PartKitItem::cb_m(Fl_Button* o, void* v) { - ((PartKitItem*)(o->parent()->parent()->user_data()))->cb_m_i(o,v); -} - -void PartKitItem::cb_M_i(Fl_Button*, void*) { - if (part->lastnote>=0) maxkcounter->value(part->lastnote); -maxkcounter->do_callback(); -minkcounter->do_callback(); -} -void PartKitItem::cb_M(Fl_Button* o, void* v) { - ((PartKitItem*)(o->parent()->parent()->user_data()))->cb_M_i(o,v); -} - -void PartKitItem::cb_R_i(Fl_Button*, void*) { - minkcounter->value(0); -minkcounter->do_callback(); -maxkcounter->value(127); -maxkcounter->do_callback(); -} -void PartKitItem::cb_R(Fl_Button* o, void* v) { - ((PartKitItem*)(o->parent()->parent()->user_data()))->cb_R_i(o,v); -} - -void PartKitItem::cb_adeditbutton_i(Fl_Button*, void*) { - partui->showparameters(n,0); -} -void PartKitItem::cb_adeditbutton(Fl_Button* o, void* v) { - ((PartKitItem*)(o->parent()->parent()->user_data()))->cb_adeditbutton_i(o,v); -} - -void PartKitItem::cb_subeditbutton_i(Fl_Button*, void*) { - partui->showparameters(n,1); -} -void PartKitItem::cb_subeditbutton(Fl_Button* o, void* v) { - ((PartKitItem*)(o->parent()->parent()->user_data()))->cb_subeditbutton_i(o,v); -} - -void PartKitItem::cb_mutedcheck_i(Fl_Check_Button* o, void*) { - part->kit[n].Pmuted=(int)o->value(); -} -void PartKitItem::cb_mutedcheck(Fl_Check_Button* o, void* v) { - ((PartKitItem*)(o->parent()->parent()->user_data()))->cb_mutedcheck_i(o,v); -} - -void PartKitItem::cb_maxkcounter_i(Fl_Counter* o, void*) { - part->kit[n].Pmaxkey=(int)o->value(); -} -void PartKitItem::cb_maxkcounter(Fl_Counter* o, void* v) { - ((PartKitItem*)(o->parent()->parent()->user_data()))->cb_maxkcounter_i(o,v); -} - -void PartKitItem::cb_labelbutton_i(Fl_Button*, void*) { - const char *tmp=fl_input("Kit item name:",(const char *)part->kit[n].Pname); -if (tmp!=NULL) snprintf((char *)part->kit[n].Pname,PART_MAX_NAME_LEN,"%s",tmp); -} -void PartKitItem::cb_labelbutton(Fl_Button* o, void* v) { - ((PartKitItem*)(o->parent()->parent()->user_data()))->cb_labelbutton_i(o,v); -} - -void PartKitItem::cb_adcheck_i(Fl_Check_Button* o, void*) { - part->kit[n].Padenabled=(int)o->value(); -if (part->kit[n].Padenabled!=0) adeditbutton->activate(); - else adeditbutton->deactivate(); -} -void PartKitItem::cb_adcheck(Fl_Check_Button* o, void* v) { - ((PartKitItem*)(o->parent()->parent()->user_data()))->cb_adcheck_i(o,v); -} - -void PartKitItem::cb_subcheck_i(Fl_Check_Button* o, void*) { - part->kit[n].Psubenabled=(int)o->value(); -if (part->kit[n].Psubenabled!=0) subeditbutton->activate(); - else subeditbutton->deactivate(); -} -void PartKitItem::cb_subcheck(Fl_Check_Button* o, void* v) { - ((PartKitItem*)(o->parent()->parent()->user_data()))->cb_subcheck_i(o,v); -} - -void PartKitItem::cb_sendtoeffect_i(Fl_Choice* o, void*) { - if (o->value()!=0) part->kit[n].Psendtoparteffect=(int)o->value()-1; - else part->kit[n].Psendtoparteffect=127; -} -void PartKitItem::cb_sendtoeffect(Fl_Choice* o, void* v) { - ((PartKitItem*)(o->parent()->parent()->user_data()))->cb_sendtoeffect_i(o,v); -} - -void PartKitItem::cb_padeditbutton_i(Fl_Button*, void*) { - partui->showparameters(n,2); -} -void PartKitItem::cb_padeditbutton(Fl_Button* o, void* v) { - ((PartKitItem*)(o->parent()->parent()->user_data()))->cb_padeditbutton_i(o,v); -} - -void PartKitItem::cb_padcheck_i(Fl_Check_Button* o, void*) { - part->kit[n].Ppadenabled=(int)o->value(); -if (part->kit[n].Ppadenabled!=0) padeditbutton->activate(); - else padeditbutton->deactivate(); -} -void PartKitItem::cb_padcheck(Fl_Check_Button* o, void* v) { - ((PartKitItem*)(o->parent()->parent()->user_data()))->cb_padcheck_i(o,v); -} - -void PartKitItem::cb_enabledcheck_i(Fl_Check_Button* o, void*) { - int answer=1; -if (o->value()==0) answer=fl_choice("Delete the item?","No","Yes",NULL); -if (answer!=0){ -pthread_mutex_lock(&master->mutex); - part->setkititemstatus(n,(int) o->value()); -pthread_mutex_unlock(&master->mutex); - -if (o->value()==0) partkititemgroup->deactivate(); -else partkititemgroup->activate(); -o->redraw(); -partui->showparameters(n,-1);//use to delete the ui, if it is not to item 0 -} else o->value(1); -} -void PartKitItem::cb_enabledcheck(Fl_Check_Button* o, void* v) { - ((PartKitItem*)(o->parent()->user_data()))->cb_enabledcheck_i(o,v); -} - -Fl_Group* PartKitItem::make_window() { - { partkititem = new Fl_Group(0, 0, 670, 30); - partkititem->box(FL_FLAT_BOX); - partkititem->color(FL_BACKGROUND_COLOR); - partkititem->selection_color(FL_BACKGROUND_COLOR); - partkititem->labeltype(FL_NO_LABEL); - partkititem->labelfont(0); - partkititem->labelsize(14); - partkititem->labelcolor(FL_FOREGROUND_COLOR); - partkititem->user_data((void*)(this)); - partkititem->align(Fl_Align(FL_ALIGN_TOP)); - partkititem->when(FL_WHEN_RELEASE); - { Fl_Group* o = partkititemgroup = new Fl_Group(55, 0, 605, 20); - partkititemgroup->box(FL_FLAT_BOX); - { Fl_Counter* o = minkcounter = new Fl_Counter(225, 0, 55, 15); - minkcounter->type(1); - minkcounter->minimum(0); - minkcounter->maximum(128); - minkcounter->step(1); - minkcounter->callback((Fl_Callback*)cb_minkcounter); - o->value(part->kit[n].Pminkey); - } // Fl_Counter* minkcounter - { Fl_Button* o = new Fl_Button(285, 3, 15, 12, "m"); - o->tooltip("set the minimum key to the last pressed key"); - o->box(FL_THIN_UP_BOX); - o->labelsize(10); - o->callback((Fl_Callback*)cb_m); - } // Fl_Button* o - { Fl_Button* o = new Fl_Button(315, 3, 15, 12, "M"); - o->tooltip("set the maximum key to the last pressed key"); - o->box(FL_THIN_UP_BOX); - o->labelsize(10); - o->callback((Fl_Callback*)cb_M); - } // Fl_Button* o - { Fl_Button* o = new Fl_Button(300, 3, 15, 12, "R"); - o->tooltip("reset the minimum key to 0 and maximum key to 127"); - o->box(FL_THIN_UP_BOX); - o->labelfont(1); - o->labelsize(10); - o->callback((Fl_Callback*)cb_R); - } // Fl_Button* o - { Fl_Button* o = adeditbutton = new Fl_Button(420, 0, 40, 15, "edit"); - adeditbutton->box(FL_THIN_UP_BOX); - adeditbutton->labelsize(11); - adeditbutton->callback((Fl_Callback*)cb_adeditbutton); - if (part->kit[n].Padenabled==0) o->deactivate(); - if (n==0) o->hide(); - } // Fl_Button* adeditbutton - { Fl_Button* o = subeditbutton = new Fl_Button(490, 0, 40, 15, "edit"); - subeditbutton->box(FL_THIN_UP_BOX); - subeditbutton->labelsize(11); - subeditbutton->callback((Fl_Callback*)cb_subeditbutton); - if (part->kit[n].Psubenabled==0) o->deactivate(); - if (n==0) o->hide(); - } // Fl_Button* subeditbutton - { Fl_Check_Button* o = mutedcheck = new Fl_Check_Button(60, 0, 20, 15); - mutedcheck->down_box(FL_DOWN_BOX); - mutedcheck->labelfont(1); - mutedcheck->labelsize(11); - mutedcheck->callback((Fl_Callback*)cb_mutedcheck); - mutedcheck->align(Fl_Align(FL_ALIGN_LEFT)); - o->value(part->kit[n].Pmuted); - } // Fl_Check_Button* mutedcheck - { Fl_Counter* o = maxkcounter = new Fl_Counter(335, 0, 55, 15); - maxkcounter->type(1); - maxkcounter->minimum(0); - maxkcounter->maximum(128); - maxkcounter->step(1); - maxkcounter->callback((Fl_Callback*)cb_maxkcounter); - o->value(part->kit[n].Pmaxkey); - } // Fl_Counter* maxkcounter - { Fl_Button* o = labelbutton = new Fl_Button(90, 0, 130, 15, "Bass Drum"); - labelbutton->box(FL_THIN_DOWN_BOX); - labelbutton->down_box(FL_FLAT_BOX); - labelbutton->labelfont(1); - labelbutton->labelsize(10); - labelbutton->callback((Fl_Callback*)cb_labelbutton); - labelbutton->align(Fl_Align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE)); - o->label((char *)part->kit[n].Pname); - } // Fl_Button* labelbutton - { Fl_Check_Button* o = adcheck = new Fl_Check_Button(400, 0, 20, 15); - adcheck->down_box(FL_DOWN_BOX); - adcheck->labelfont(1); - adcheck->labelsize(11); - adcheck->callback((Fl_Callback*)cb_adcheck); - adcheck->align(Fl_Align(FL_ALIGN_LEFT)); - o->value(part->kit[n].Padenabled); - if (n==0) o->hide(); - } // Fl_Check_Button* adcheck - { Fl_Check_Button* o = subcheck = new Fl_Check_Button(470, 0, 20, 15); - subcheck->down_box(FL_DOWN_BOX); - subcheck->labelfont(1); - subcheck->labelsize(11); - subcheck->callback((Fl_Callback*)cb_subcheck); - subcheck->align(Fl_Align(FL_ALIGN_LEFT)); - o->value(part->kit[n].Psubenabled); - if (n==0) o->hide(); - } // Fl_Check_Button* subcheck - { Fl_Choice* o = sendtoeffect = new Fl_Choice(615, 0, 45, 15); - sendtoeffect->down_box(FL_BORDER_BOX); - sendtoeffect->labelsize(10); - sendtoeffect->textfont(1); - sendtoeffect->textsize(10); - sendtoeffect->callback((Fl_Callback*)cb_sendtoeffect); - sendtoeffect->align(Fl_Align(FL_ALIGN_TOP_LEFT)); - o->add("OFF");char nrstr[10]; for(int i=0;iadd(nrstr);}; - o->value(part->kit[n].Psendtoparteffect+1);if (part->kit[n].Psendtoparteffect==127) o->value(0); - } // Fl_Choice* sendtoeffect - { Fl_Button* o = padeditbutton = new Fl_Button(560, 0, 40, 15, "edit"); - padeditbutton->box(FL_THIN_UP_BOX); - padeditbutton->labelsize(11); - padeditbutton->callback((Fl_Callback*)cb_padeditbutton); - if (part->kit[n].Ppadenabled==0) o->deactivate(); - if (n==0) o->hide(); - } // Fl_Button* padeditbutton - { Fl_Check_Button* o = padcheck = new Fl_Check_Button(540, 0, 20, 15); - padcheck->down_box(FL_DOWN_BOX); - padcheck->labelfont(1); - padcheck->labelsize(11); - padcheck->callback((Fl_Callback*)cb_padcheck); - padcheck->align(Fl_Align(FL_ALIGN_LEFT)); - o->value(part->kit[n].Ppadenabled); - if (n==0) o->hide(); - } // Fl_Check_Button* padcheck - if (part->kit[n].Penabled==0) o->deactivate(); - partkititemgroup->end(); - } // Fl_Group* partkititemgroup - { Fl_Check_Button* o = enabledcheck = new Fl_Check_Button(30, 0, 20, 15, "01"); - enabledcheck->down_box(FL_DOWN_BOX); - enabledcheck->labeltype(FL_EMBOSSED_LABEL); - enabledcheck->labelfont(1); - enabledcheck->labelsize(13); - enabledcheck->callback((Fl_Callback*)cb_enabledcheck); - enabledcheck->align(Fl_Align(FL_ALIGN_LEFT)); - snprintf(label,10,"%d",n+1);o->label(label); - o->value(part->kit[n].Penabled); - if (n==0) o->deactivate(); - } // Fl_Check_Button* enabledcheck - partkititem->end(); - } // Fl_Group* partkititem - return partkititem; -} - -PartKitItem::PartKitItem(int x,int y, int w, int h, const char *label):Fl_Group(x,y,w,h,label) { - n=0; - part=NULL; -} - -void PartKitItem::refresh() { - enabledcheck->value(part->kit[n].Penabled); - if (part->kit[n].Penabled==0) partkititemgroup->deactivate(); - else partkititemgroup->activate(); - - mutedcheck->value(part->kit[n].Pmuted); - labelbutton->label((char *)part->kit[n].Pname); - minkcounter->value(part->kit[n].Pminkey); - maxkcounter->value(part->kit[n].Pmaxkey); - adcheck->value(part->kit[n].Padenabled); - adcheck->do_callback(); - subcheck->value(part->kit[n].Psubenabled); - subcheck->do_callback(); - - sendtoeffect->value(part->kit[n].Psendtoparteffect+1); - if (part->kit[n].Psendtoparteffect==127) sendtoeffect->value(0); - - this->redraw(); -} - -void PartKitItem::init(Part *part_,int n_,Master *master_,PartUI_ *partui_) { - part=part_; - n=n_; - partui=partui_; - master=master_; - make_window(); - //partkititem->show(); - end(); -} - -PartKitItem::~PartKitItem() { - partkititem->hide(); - //delete(partkititem); -} - -void PartUI::cb_Pan_i(WidgetPDial* o, void*) { - part->setPpanning((int) o->value()); -} -void PartUI::cb_Pan(WidgetPDial* o, void* v) { - ((PartUI*)(o->parent()->parent()->user_data()))->cb_Pan_i(o,v); -} - -void PartUI::cb_KeyShift_i(Fl_Counter* o, void*) { - part->Pkeyshift=(int) o->value()+64; -} -void PartUI::cb_KeyShift(Fl_Counter* o, void* v) { - ((PartUI*)(o->parent()->parent()->user_data()))->cb_KeyShift_i(o,v); -} - -void PartUI::cb_Grand_i(Fl_Button*, void*) { - int event=Fl::event_button(); -if (event==FL_RIGHT_MOUSE){ - const char *tmp=fl_input("Instrument name:",(const char *)part->Pname); - if (tmp!=NULL) snprintf((char *)part->Pname,PART_MAX_NAME_LEN,"%s",tmp); -} else { - if (event==FL_LEFT_MOUSE) bankui->show(); - else instrumenteditwindow->show(); -}; -} -void PartUI::cb_Grand(Fl_Button* o, void* v) { - ((PartUI*)(o->parent()->parent()->user_data()))->cb_Grand_i(o,v); -} - -void PartUI::cb_NoteOn_i(Fl_Check_Button* o, void*) { - part->Pnoteon=(int) o->value(); -} -void PartUI::cb_NoteOn(Fl_Check_Button* o, void* v) { - ((PartUI*)(o->parent()->parent()->user_data()))->cb_NoteOn_i(o,v); -} - -void PartUI::cb_minkcounter1_i(Fl_Counter* o, void*) { - part->Pminkey=(int) o->value(); -if (part->Pminkey>part->Pmaxkey) o->textcolor(FL_RED); - else o->textcolor(FL_BLACK); -} -void PartUI::cb_minkcounter1(Fl_Counter* o, void* v) { - ((PartUI*)(o->parent()->parent()->user_data()))->cb_minkcounter1_i(o,v); -} - -void PartUI::cb_maxkcounter1_i(Fl_Counter* o, void*) { - part->Pmaxkey=(int) o->value(); - -if (part->Pminkey>part->Pmaxkey) o->textcolor(FL_RED); - else o->textcolor(FL_BLACK); -} -void PartUI::cb_maxkcounter1(Fl_Counter* o, void* v) { - ((PartUI*)(o->parent()->parent()->user_data()))->cb_maxkcounter1_i(o,v); -} - -void PartUI::cb_Volume_i(WidgetPDial* o, void*) { - part->setPvolume((int) o->value()); -} -void PartUI::cb_Volume(WidgetPDial* o, void* v) { - ((PartUI*)(o->parent()->parent()->user_data()))->cb_Volume_i(o,v); -} - -void PartUI::cb_Vel_i(WidgetPDial* o, void*) { - part->Pveloffs=(int) o->value(); -} -void PartUI::cb_Vel(WidgetPDial* o, void* v) { - ((PartUI*)(o->parent()->parent()->user_data()))->cb_Vel_i(o,v); -} - -void PartUI::cb_Vel1_i(WidgetPDial* o, void*) { - part->Pvelsns=(int) o->value(); -} -void PartUI::cb_Vel1(WidgetPDial* o, void* v) { - ((PartUI*)(o->parent()->parent()->user_data()))->cb_Vel1_i(o,v); -} - -void PartUI::cb_Controllers_i(Fl_Button*, void*) { - ctlwindow->show(); -} -void PartUI::cb_Controllers(Fl_Button* o, void* v) { - ((PartUI*)(o->parent()->parent()->user_data()))->cb_Controllers_i(o,v); -} - -void PartUI::cb_Portamento_i(Fl_Check_Button* o, void*) { - part->ctl.portamento.portamento=(int) o->value(); -} -void PartUI::cb_Portamento(Fl_Check_Button* o, void* v) { - ((PartUI*)(o->parent()->parent()->user_data()))->cb_Portamento_i(o,v); -} - -void PartUI::cb_Edit_i(Fl_Button*, void*) { - instrumenteditwindow->show(); -} -void PartUI::cb_Edit(Fl_Button* o, void* v) { - ((PartUI*)(o->parent()->parent()->user_data()))->cb_Edit_i(o,v); -} - -void PartUI::cb_m1_i(Fl_Button*, void*) { - if (part->lastnote>=0) minkcounter->value(part->lastnote); -minkcounter->do_callback(); -maxkcounter->do_callback(); -} -void PartUI::cb_m1(Fl_Button* o, void* v) { - ((PartUI*)(o->parent()->parent()->user_data()))->cb_m1_i(o,v); -} - -void PartUI::cb_M1_i(Fl_Button*, void*) { - if (part->lastnote>=0) maxkcounter->value(part->lastnote); -maxkcounter->do_callback(); -minkcounter->do_callback(); -} -void PartUI::cb_M1(Fl_Button* o, void* v) { - ((PartUI*)(o->parent()->parent()->user_data()))->cb_M1_i(o,v); -} - -void PartUI::cb_R1_i(Fl_Button*, void*) { - minkcounter->value(0); -minkcounter->do_callback(); -maxkcounter->value(127); -maxkcounter->do_callback(); -} -void PartUI::cb_R1(Fl_Button* o, void* v) { - ((PartUI*)(o->parent()->parent()->user_data()))->cb_R1_i(o,v); -} - -void PartUI::cb_MIDI_i(Fl_Choice* o, void*) { - part->Prcvchn=(int) o->value(); -} -void PartUI::cb_MIDI(Fl_Choice* o, void* v) { - ((PartUI*)(o->parent()->parent()->user_data()))->cb_MIDI_i(o,v); -} - -void PartUI::cb_keylimitlist_i(Fl_Choice* o, void*) { - int val=0; -val=atoi(o->text()); -part->setkeylimit(val); -} -void PartUI::cb_keylimitlist(Fl_Choice* o, void* v) { - ((PartUI*)(o->parent()->parent()->user_data()))->cb_keylimitlist_i(o,v); -} - -void PartUI::cb_Mode_i(Fl_Choice* o, void*) { - if ((int) o->value()==0){ /* Poly (implies no legato) */ - part->Ppolymode=1; - part->Plegatomode=0; -} else { - if ((int) o->value()==1){ /* Mono (implies no legato) */ - part->Ppolymode=0; - part->Plegatomode=0; - } else { - if ((int) o->value()==2){ /* Legato (implies mono) */ - part->Ppolymode=0; - part->Plegatomode=1; - }; - }; -}; -} -void PartUI::cb_Mode(Fl_Choice* o, void* v) { - ((PartUI*)(o->parent()->parent()->user_data()))->cb_Mode_i(o,v); -} - -void PartUI::cb_Enabled_i(Fl_Check_Button* o, void*) { - pthread_mutex_lock(&master->mutex); -master->partonoff(npart,(int) o->value()); -pthread_mutex_unlock(&master->mutex); -if (part->Penabled==0) partgroupui->deactivate(); - else partgroupui->activate(); -} -void PartUI::cb_Enabled(Fl_Check_Button* o, void* v) { - ((PartUI*)(o->parent()->user_data()))->cb_Enabled_i(o,v); -} - -void PartUI::cb_Expr_i(Fl_Check_Button* o, void*) { - part->ctl.expression.receive=(int) o->value(); -} -void PartUI::cb_Expr(Fl_Check_Button* o, void* v) { - ((PartUI*)(o->parent()->user_data()))->cb_Expr_i(o,v); -} - -void PartUI::cb_PanDpth_i(WidgetPDial* o, void*) { - part->ctl.panning.depth=(int) o->value(); -} -void PartUI::cb_PanDpth(WidgetPDial* o, void* v) { - ((PartUI*)(o->parent()->user_data()))->cb_PanDpth_i(o,v); -} - -void PartUI::cb_FltCut_i(WidgetPDial* o, void*) { - part->ctl.filtercutoff.depth=(int) o->value(); -} -void PartUI::cb_FltCut(WidgetPDial* o, void* v) { - ((PartUI*)(o->parent()->user_data()))->cb_FltCut_i(o,v); -} - -void PartUI::cb_FltQ_i(WidgetPDial* o, void*) { - part->ctl.filterq.depth=(int) o->value(); -} -void PartUI::cb_FltQ(WidgetPDial* o, void* v) { - ((PartUI*)(o->parent()->user_data()))->cb_FltQ_i(o,v); -} - -void PartUI::cb_BwDpth_i(WidgetPDial* o, void*) { - part->ctl.bandwidth.depth=(int) o->value(); -} -void PartUI::cb_BwDpth(WidgetPDial* o, void* v) { - ((PartUI*)(o->parent()->user_data()))->cb_BwDpth_i(o,v); -} - -void PartUI::cb_ModWh_i(WidgetPDial* o, void*) { - part->ctl.modwheel.depth=(int) o->value(); -} -void PartUI::cb_ModWh(WidgetPDial* o, void* v) { - ((PartUI*)(o->parent()->user_data()))->cb_ModWh_i(o,v); -} - -void PartUI::cb_PWheelB_i(Fl_Counter* o, void*) { - part->ctl.pitchwheel.bendrange=(int) o->value(); -} -void PartUI::cb_PWheelB(Fl_Counter* o, void* v) { - ((PartUI*)(o->parent()->user_data()))->cb_PWheelB_i(o,v); -} - -void PartUI::cb_FMamp_i(Fl_Check_Button* o, void*) { - part->ctl.fmamp.receive=(int) o->value(); -} -void PartUI::cb_FMamp(Fl_Check_Button* o, void* v) { - ((PartUI*)(o->parent()->user_data()))->cb_FMamp_i(o,v); -} - -void PartUI::cb_Vol_i(Fl_Check_Button* o, void*) { - part->ctl.volume.receive=(int) o->value(); -} -void PartUI::cb_Vol(Fl_Check_Button* o, void* v) { - ((PartUI*)(o->parent()->user_data()))->cb_Vol_i(o,v); -} - -void PartUI::cb_Sustain_i(Fl_Check_Button* o, void*) { - part->ctl.sustain.receive=(int) o->value(); -if (part->ctl.sustain.receive==0) { - part->RelaseSustainedKeys(); - part->ctl.setsustain(0); -}; -} -void PartUI::cb_Sustain(Fl_Check_Button* o, void* v) { - ((PartUI*)(o->parent()->user_data()))->cb_Sustain_i(o,v); -} - -void PartUI::cb_Close_i(Fl_Button*, void*) { - ctlwindow->hide(); -} -void PartUI::cb_Close(Fl_Button* o, void* v) { - ((PartUI*)(o->parent()->user_data()))->cb_Close_i(o,v); -} - -void PartUI::cb_Reset_i(Fl_Button*, void*) { - part->SetController(C_resetallcontrollers,0); -} -void PartUI::cb_Reset(Fl_Button* o, void* v) { - ((PartUI*)(o->parent()->user_data()))->cb_Reset_i(o,v); -} - -void PartUI::cb_Rcv_i(Fl_Check_Button* o, void*) { - part->ctl.portamento.receive=(int) o->value(); -} -void PartUI::cb_Rcv(Fl_Check_Button* o, void* v) { - ((PartUI*)(o->parent()->parent()->user_data()))->cb_Rcv_i(o,v); -} - -void PartUI::cb_time_i(WidgetPDial* o, void*) { - part->ctl.portamento.time=(int) o->value(); -} -void PartUI::cb_time(WidgetPDial* o, void* v) { - ((PartUI*)(o->parent()->parent()->user_data()))->cb_time_i(o,v); -} - -void PartUI::cb_thresh_i(Fl_Counter* o, void*) { - part->ctl.portamento.pitchthresh=(int) o->value(); -} -void PartUI::cb_thresh(Fl_Counter* o, void* v) { - ((PartUI*)(o->parent()->parent()->user_data()))->cb_thresh_i(o,v); -} - -void PartUI::cb_th_i(Fl_Check_Button* o, void*) { - part->ctl.portamento.pitchthreshtype=(int) o->value(); -} -void PartUI::cb_th(Fl_Check_Button* o, void* v) { - ((PartUI*)(o->parent()->parent()->user_data()))->cb_th_i(o,v); -} - -void PartUI::cb_t_i(WidgetPDial* o, void*) { - int x=(int) o->value(); - -part->ctl.portamento.updowntimestretch=x; -} -void PartUI::cb_t(WidgetPDial* o, void* v) { - ((PartUI*)(o->parent()->parent()->user_data()))->cb_t_i(o,v); -} - -void PartUI::cb_propta_i(WidgetPDial* o, void*) { - part->ctl.portamento.propRate=(int) o->value(); -} -void PartUI::cb_propta(WidgetPDial* o, void* v) { - ((PartUI*)(o->parent()->parent()->user_data()))->cb_propta_i(o,v); -} - -void PartUI::cb_proptb_i(WidgetPDial* o, void*) { - part->ctl.portamento.propDepth=(int) o->value(); -} -void PartUI::cb_proptb(WidgetPDial* o, void* v) { - ((PartUI*)(o->parent()->parent()->user_data()))->cb_proptb_i(o,v); -} - -void PartUI::cb_Proprt_i(Fl_Check_Button* o, void*) { - part->ctl.portamento.proportional=(int) o->value(); -if(o->value()){propta->activate();proptb->activate();} -else {propta->deactivate();proptb->deactivate();}; -} -void PartUI::cb_Proprt(Fl_Check_Button* o, void* v) { - ((PartUI*)(o->parent()->parent()->user_data()))->cb_Proprt_i(o,v); -} - -void PartUI::cb_BWdpth_i(WidgetPDial* o, void*) { - part->ctl.resonancebandwidth.depth=(int) o->value(); -} -void PartUI::cb_BWdpth(WidgetPDial* o, void* v) { - ((PartUI*)(o->parent()->parent()->user_data()))->cb_BWdpth_i(o,v); -} - -void PartUI::cb_CFdpth_i(WidgetPDial* o, void*) { - part->ctl.resonancecenter.depth=(int) o->value(); -} -void PartUI::cb_CFdpth(WidgetPDial* o, void* v) { - ((PartUI*)(o->parent()->parent()->user_data()))->cb_CFdpth_i(o,v); -} - -void PartUI::cb_Exp_i(Fl_Check_Button* o, void*) { - part->ctl.modwheel.exponential=(int) o->value(); -} -void PartUI::cb_Exp(Fl_Check_Button* o, void* v) { - ((PartUI*)(o->parent()->user_data()))->cb_Exp_i(o,v); -} - -void PartUI::cb_Exp1_i(Fl_Check_Button* o, void*) { - part->ctl.bandwidth.exponential=(int) o->value(); -} -void PartUI::cb_Exp1(Fl_Check_Button* o, void* v) { - ((PartUI*)(o->parent()->user_data()))->cb_Exp1_i(o,v); -} - -void PartUI::cb_inseffnocounter_i(Fl_Counter* o, void*) { - ninseff=(int) o->value()-1; -insefftype->value(part->partefx[ninseff]->geteffect()); -//insefftype->do_callback(); -inseffectui->refresh(part->partefx[ninseff]); -int x=part->Pefxroute[ninseff]; -if (x==127) x=1; -bypasseff->value(part->Pefxbypass[ninseff]); - -sendtochoice->value(x); -} -void PartUI::cb_inseffnocounter(Fl_Counter* o, void* v) { - ((PartUI*)(o->parent()->user_data()))->cb_inseffnocounter_i(o,v); -} - -void PartUI::cb_insefftype_i(Fl_Choice* o, void*) { - pthread_mutex_lock(part->mutex); -part->partefx[ninseff]->changeeffect((int) o->value()); -pthread_mutex_unlock(part->mutex); -inseffectui->refresh(part->partefx[ninseff]); -} -void PartUI::cb_insefftype(Fl_Choice* o, void* v) { - ((PartUI*)(o->parent()->user_data()))->cb_insefftype_i(o,v); -} - -Fl_Menu_Item PartUI::menu_insefftype[] = { - {"No Effect", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {"Reverb", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {"Echo", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {"Chorus", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {"Phaser", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {"AlienWah", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {"Distortion", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {"EQ", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {"DynFilter", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {0,0,0,0,0,0,0,0,0} -}; - -void PartUI::cb_Close1_i(Fl_Button*, void*) { - partfx->hide(); -} -void PartUI::cb_Close1(Fl_Button* o, void* v) { - ((PartUI*)(o->parent()->user_data()))->cb_Close1_i(o,v); -} - -void PartUI::cb_sendtochoice_i(Fl_Choice* o, void*) { - int x=(int) o->value(); -part->Pefxroute[ninseff]=x; -if (x==2) part->partefx[ninseff]->setdryonly(true); - else part->partefx[ninseff]->setdryonly(false); -} -void PartUI::cb_sendtochoice(Fl_Choice* o, void* v) { - ((PartUI*)(o->parent()->user_data()))->cb_sendtochoice_i(o,v); -} - -Fl_Menu_Item PartUI::menu_sendtochoice[] = { - {"Next Effect", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {"Part Out", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {"Dry Out", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {0,0,0,0,0,0,0,0,0} -}; - -void PartUI::cb_bypasseff_i(Fl_Check_Button* o, void*) { - part->Pefxbypass[ninseff]=(((int)o->value())!=0); -} -void PartUI::cb_bypasseff(Fl_Check_Button* o, void* v) { - ((PartUI*)(o->parent()->user_data()))->cb_bypasseff_i(o,v); -} - -void PartUI::cb_C_i(Fl_Button*, void*) { - presetsui->copy(part->partefx[ninseff]); -} -void PartUI::cb_C(Fl_Button* o, void* v) { - ((PartUI*)(o->parent()->user_data()))->cb_C_i(o,v); -} - -void PartUI::cb_P_i(Fl_Button*, void*) { - pthread_mutex_lock(&master->mutex); -presetsui->paste(part->partefx[ninseff],inseffectui); -pthread_mutex_unlock(&master->mutex); -} -void PartUI::cb_P(Fl_Button* o, void* v) { - ((PartUI*)(o->parent()->user_data()))->cb_P_i(o,v); -} - -void PartUI::cb_Close2_i(Fl_Button*, void*) { - instrumentkitlist->hide(); -} -void PartUI::cb_Close2(Fl_Button* o, void* v) { - ((PartUI*)(o->parent()->user_data()))->cb_Close2_i(o,v); -} - -void PartUI::cb_Mode1_i(Fl_Choice* o, void*) { - part->Pkitmode=(int) o->value(); -if (part->Pkitmode==0) { - kitlist->deactivate(); - } else { - kitlist->activate(); -}; -} -void PartUI::cb_Mode1(Fl_Choice* o, void* v) { - ((PartUI*)(o->parent()->user_data()))->cb_Mode1_i(o,v); -} - -Fl_Menu_Item PartUI::menu_Mode[] = { - {"OFF", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 11, 0}, - {"MULTI", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 11, 0}, - {"SINGLE", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 11, 0}, - {0,0,0,0,0,0,0,0,0} -}; - -void PartUI::cb_Drum_i(Fl_Check_Button* o, void*) { - part->Pdrummode=(int) o->value(); -} -void PartUI::cb_Drum(Fl_Check_Button* o, void* v) { - ((PartUI*)(o->parent()->user_data()))->cb_Drum_i(o,v); -} - -void PartUI::cb_padeditbutton1_i(Fl_Button*, void*) { - showparameters(0,2); -} -void PartUI::cb_padeditbutton1(Fl_Button* o, void* v) { - ((PartUI*)(o->parent()->parent()->parent()->user_data()))->cb_padeditbutton1_i(o,v); -} - -void PartUI::cb_padsynenabledcheck_i(Fl_Check_Button* o, void*) { - int x=(int) o->value(); -part->kit[0].Ppadenabled=x; -if (x==0) padeditbutton->deactivate(); - else padeditbutton->activate(); -} -void PartUI::cb_padsynenabledcheck(Fl_Check_Button* o, void* v) { - ((PartUI*)(o->parent()->parent()->parent()->user_data()))->cb_padsynenabledcheck_i(o,v); -} - -void PartUI::cb_adsynenabledcheck_i(Fl_Check_Button* o, void*) { - int x=(int) o->value(); -part->kit[0].Padenabled=x; -if (x==0) adeditbutton->deactivate(); - else adeditbutton->activate(); -} -void PartUI::cb_adsynenabledcheck(Fl_Check_Button* o, void* v) { - ((PartUI*)(o->parent()->parent()->parent()->user_data()))->cb_adsynenabledcheck_i(o,v); -} - -void PartUI::cb_adeditbutton1_i(Fl_Button*, void*) { - showparameters(0,0); -} -void PartUI::cb_adeditbutton1(Fl_Button* o, void* v) { - ((PartUI*)(o->parent()->parent()->parent()->user_data()))->cb_adeditbutton1_i(o,v); -} - -void PartUI::cb_subsynenabledcheck_i(Fl_Check_Button* o, void*) { - int x=(int) o->value(); -part->kit[0].Psubenabled=x; -if (x==0) subeditbutton->deactivate(); - else subeditbutton->activate(); -} -void PartUI::cb_subsynenabledcheck(Fl_Check_Button* o, void* v) { - ((PartUI*)(o->parent()->parent()->parent()->user_data()))->cb_subsynenabledcheck_i(o,v); -} - -void PartUI::cb_subeditbutton1_i(Fl_Button*, void*) { - showparameters(0,1); -} -void PartUI::cb_subeditbutton1(Fl_Button* o, void* v) { - ((PartUI*)(o->parent()->parent()->parent()->user_data()))->cb_subeditbutton1_i(o,v); -} - -void PartUI::cb_Kit_i(Fl_Button*, void*) { - instrumentkitlist->show(); -} -void PartUI::cb_Kit(Fl_Button* o, void* v) { - ((PartUI*)(o->parent()->parent()->user_data()))->cb_Kit_i(o,v); -} - -void PartUI::cb_Effects_i(Fl_Button*, void*) { - partfx->show(); -} -void PartUI::cb_Effects(Fl_Button* o, void* v) { - ((PartUI*)(o->parent()->parent()->user_data()))->cb_Effects_i(o,v); -} - -void PartUI::cb_Author_i(Fl_Input* o, void*) { - snprintf((char *)part->info.Pauthor,MAX_INFO_TEXT_SIZE,"%s",o->value()); -} -void PartUI::cb_Author(Fl_Input* o, void* v) { - ((PartUI*)(o->parent()->parent()->user_data()))->cb_Author_i(o,v); -} - -void PartUI::cb_Comments_i(Fl_Input* o, void*) { - snprintf((char *)part->info.Pcomments,MAX_INFO_TEXT_SIZE,"%s",o->value()); -} -void PartUI::cb_Comments(Fl_Input* o, void* v) { - ((PartUI*)(o->parent()->parent()->user_data()))->cb_Comments_i(o,v); -} - -void PartUI::cb_Type_i(Fl_Choice* o, void*) { - part->info.Ptype=o->value(); -} -void PartUI::cb_Type(Fl_Choice* o, void* v) { - ((PartUI*)(o->parent()->parent()->user_data()))->cb_Type_i(o,v); -} - -Fl_Menu_Item PartUI::menu_Type[] = { - {"--------------------------", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 11, 0}, - {"Piano", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 11, 0}, - {"Chromatic Percussion", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 11, 0}, - {"Organ", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 11, 0}, - {"Guitar", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 11, 0}, - {"Bass", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 11, 0}, - {"Solo Strings", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 11, 0}, - {"Ensemble", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 11, 0}, - {"Brass", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 11, 0}, - {"Reed", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 11, 0}, - {"Pipe", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 11, 0}, - {"Synth Lead", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 11, 0}, - {"Synth Pad", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 11, 0}, - {"Synth Effects", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 11, 0}, - {"Ethnic", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 11, 0}, - {"Percussive", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 11, 0}, - {"Sound Effects", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 11, 0}, - {0,0,0,0,0,0,0,0,0} -}; - -void PartUI::cb_Close3_i(Fl_Button*, void*) { - instrumenteditwindow->hide(); -} -void PartUI::cb_Close3(Fl_Button* o, void* v) { - ((PartUI*)(o->parent()->user_data()))->cb_Close3_i(o,v); -} - -Fl_Group* PartUI::make_window() { - { partgroup = new Fl_Group(0, 0, 385, 180); - partgroup->box(FL_FLAT_BOX); - partgroup->color(FL_BACKGROUND_COLOR); - partgroup->selection_color(FL_BACKGROUND_COLOR); - partgroup->labeltype(FL_NO_LABEL); - partgroup->labelfont(0); - partgroup->labelsize(14); - partgroup->labelcolor(FL_FOREGROUND_COLOR); - partgroup->user_data((void*)(this)); - partgroup->align(Fl_Align(FL_ALIGN_TOP)); - partgroup->when(FL_WHEN_RELEASE); - { Fl_Group* o = partgroupui = new Fl_Group(0, 0, 385, 180); - { WidgetPDial* o = new WidgetPDial(50, 40, 25, 25, "Pan"); - o->box(FL_ROUND_UP_BOX); - o->color(FL_BACKGROUND_COLOR); - o->selection_color(FL_INACTIVE_COLOR); - o->labeltype(FL_NORMAL_LABEL); - o->labelfont(0); - o->labelsize(11); - o->labelcolor(FL_FOREGROUND_COLOR); - o->maximum(127); - o->step(1); - o->callback((Fl_Callback*)cb_Pan); - o->align(Fl_Align(FL_ALIGN_BOTTOM)); - o->when(FL_WHEN_CHANGED); - o->value(part->Ppanning); - } // WidgetPDial* o - { Fl_Counter* o = new Fl_Counter(195, 45, 90, 20, "KeyShift"); - o->labelsize(11); - o->minimum(-64); - o->maximum(64); - o->step(1); - o->callback((Fl_Callback*)cb_KeyShift); - o->align(Fl_Align(FL_ALIGN_TOP)); - o->lstep(12); - o->value(part->Pkeyshift-64); - } // Fl_Counter* o - { Fl_Scroll* o = new Fl_Scroll(166, 91, 125, 60); - o->box(FL_ENGRAVED_FRAME); - o->labelfont(1); - o->labelsize(10); - o->align(Fl_Align(FL_ALIGN_TOP_LEFT|FL_ALIGN_INSIDE)); - { Fl_Pack* o = new Fl_Pack(171, 96, 115, 35); - o->type(1); - o->spacing(5); - for (int i=0;iinit(master,npart,i);} - o->end(); - } // Fl_Pack* o - o->end(); - } // Fl_Scroll* o - { Fl_Button* o = new Fl_Button(195, 5, 185, 20, "Grand Piano"); - o->tooltip("left mousebutton - to choose/save/.. from/to bank or right mousebutton to cha\ -nge the name or middle button to change the instrument information"); - o->box(FL_THIN_DOWN_BOX); - o->down_box(FL_FLAT_BOX); - o->labelfont(1); - o->labelsize(11); - o->callback((Fl_Callback*)cb_Grand); - o->align(Fl_Align(68|FL_ALIGN_INSIDE)); - o->label((char *)part->Pname); - } // Fl_Button* o - { Fl_Box* o = new Fl_Box(166, 81, 95, 10, "To Sys.Efx."); - o->labelfont(1); - o->labelsize(10); - } // Fl_Box* o - { Fl_Check_Button* o = new Fl_Check_Button(10, 155, 65, 20, "NoteOn"); - o->tooltip("set if the part receives NoteOn messages"); - o->down_box(FL_DOWN_BOX); - o->labelfont(1); - o->labelsize(11); - o->callback((Fl_Callback*)cb_NoteOn); - o->value(part->Pnoteon); - } // Fl_Check_Button* o - { Fl_Counter* o = minkcounter = new Fl_Counter(295, 125, 40, 15, "Min.k"); - minkcounter->tooltip("Minimum key (that the part receives NoteOn messages)"); - minkcounter->type(1); - minkcounter->labelfont(1); - minkcounter->labelsize(10); - minkcounter->minimum(0); - minkcounter->maximum(127); - minkcounter->step(1); - minkcounter->textsize(10); - minkcounter->callback((Fl_Callback*)cb_minkcounter1); - o->value(part->Pminkey); - } // Fl_Counter* minkcounter - { Fl_Counter* o = maxkcounter = new Fl_Counter(340, 125, 40, 15, "Max.k"); - maxkcounter->tooltip("Maximum key (that the part receives NoteOn messages)"); - maxkcounter->type(1); - maxkcounter->labelfont(1); - maxkcounter->labelsize(10); - maxkcounter->minimum(0); - maxkcounter->maximum(127); - maxkcounter->step(1); - maxkcounter->textsize(10); - maxkcounter->callback((Fl_Callback*)cb_maxkcounter1); - o->value(part->Pmaxkey); - } // Fl_Counter* maxkcounter - { WidgetPDial* o = new WidgetPDial(10, 35, 30, 30, "Volume"); - o->tooltip("Part Volume"); - o->box(FL_ROUND_UP_BOX); - o->color(FL_BACKGROUND_COLOR); - o->selection_color(FL_INACTIVE_COLOR); - o->labeltype(FL_NORMAL_LABEL); - o->labelfont(0); - o->labelsize(11); - o->labelcolor(FL_FOREGROUND_COLOR); - o->maximum(127); - o->step(1); - o->callback((Fl_Callback*)cb_Volume); - o->align(Fl_Align(FL_ALIGN_BOTTOM)); - o->when(FL_WHEN_CHANGED); - o->value(part->Pvolume); - } // WidgetPDial* o - { WidgetPDial* o = new WidgetPDial(135, 40, 25, 25, "Vel.Ofs."); - o->tooltip("Velocity Offset"); - o->box(FL_ROUND_UP_BOX); - o->color(FL_BACKGROUND_COLOR); - o->selection_color(FL_INACTIVE_COLOR); - o->labeltype(FL_NORMAL_LABEL); - o->labelfont(0); - o->labelsize(10); - o->labelcolor(FL_FOREGROUND_COLOR); - o->maximum(127); - o->step(1); - o->callback((Fl_Callback*)cb_Vel); - o->align(Fl_Align(FL_ALIGN_BOTTOM)); - o->when(FL_WHEN_CHANGED); - o->value(part->Pveloffs); - } // WidgetPDial* o - { WidgetPDial* o = new WidgetPDial(95, 40, 25, 25, "Vel.Sns."); - o->tooltip("Velocity Sensing Function"); - o->box(FL_ROUND_UP_BOX); - o->color(FL_BACKGROUND_COLOR); - o->selection_color(FL_INACTIVE_COLOR); - o->labeltype(FL_NORMAL_LABEL); - o->labelfont(0); - o->labelsize(10); - o->labelcolor(FL_FOREGROUND_COLOR); - o->maximum(127); - o->step(1); - o->callback((Fl_Callback*)cb_Vel1); - o->align(Fl_Align(FL_ALIGN_BOTTOM)); - o->when(FL_WHEN_CHANGED); - o->value(part->Pvelsns); - } // WidgetPDial* o - { Fl_Button* o = new Fl_Button(295, 90, 85, 30, "Controllers"); - o->box(FL_PLASTIC_UP_BOX); - o->labelfont(1); - o->labelsize(11); - o->callback((Fl_Callback*)cb_Controllers); - } // Fl_Button* o - { Fl_Check_Button* o = new Fl_Check_Button(95, 155, 88, 20, "Portamento"); - o->tooltip("Enable/Disable the portamento"); - o->down_box(FL_DOWN_BOX); - o->labelfont(1); - o->labelsize(11); - o->callback((Fl_Callback*)cb_Portamento); - o->value(part->ctl.portamento.portamento); - } // Fl_Check_Button* o - { Fl_Button* o = new Fl_Button(15, 90, 130, 30, "Edit instrument"); - o->box(FL_PLASTIC_UP_BOX); - o->color((Fl_Color)230); - o->labelfont(1); - o->labelsize(13); - o->callback((Fl_Callback*)cb_Edit); - } // Fl_Button* o - { Fl_Button* o = new Fl_Button(315, 155, 15, 12, "m"); - o->tooltip("set the minimum key to the last pressed key"); - o->box(FL_THIN_UP_BOX); - o->labelsize(10); - o->callback((Fl_Callback*)cb_m1); - } // Fl_Button* o - { Fl_Button* o = new Fl_Button(345, 155, 15, 12, "M"); - o->tooltip("set the maximum key to the last pressed key"); - o->box(FL_THIN_UP_BOX); - o->labelsize(10); - o->callback((Fl_Callback*)cb_M1); - } // Fl_Button* o - { Fl_Button* o = new Fl_Button(330, 155, 15, 12, "R"); - o->tooltip("reset the minimum key to 0 and maximum key to 127"); - o->box(FL_THIN_UP_BOX); - o->labelfont(1); - o->labelsize(10); - o->callback((Fl_Callback*)cb_R1); - } // Fl_Button* o - { Fl_Choice* o = new Fl_Choice(310, 45, 70, 20, "MIDI Chn.Rcv."); - o->tooltip("receive from Midi channel"); - o->down_box(FL_BORDER_BOX); - o->labelsize(10); - o->textfont(1); - o->textsize(10); - o->callback((Fl_Callback*)cb_MIDI); - o->align(Fl_Align(FL_ALIGN_TOP_LEFT)); - char nrstr[10]; for(int i=0;iadd(nrstr); else o->add("Drms10");}; - o->value(part->Prcvchn); - } // Fl_Choice* o - { keylimitlist = new Fl_Choice(215, 155, 50, 20, "KLmt"); - keylimitlist->tooltip("Key Limit"); - keylimitlist->down_box(FL_BORDER_BOX); - keylimitlist->labelsize(10); - keylimitlist->textfont(1); - keylimitlist->textsize(10); - keylimitlist->callback((Fl_Callback*)cb_keylimitlist); - keylimitlist->align(Fl_Align(FL_ALIGN_RIGHT)); - } // Fl_Choice* keylimitlist - { Fl_Choice* o = new Fl_Choice(80, 130, 64, 18, "Mode :"); - o->tooltip("Poly, Mono or Legato mode"); - o->down_box(FL_BORDER_BOX); - o->labelfont(1); - o->labelsize(11); - o->textfont(1); - o->textsize(10); - o->callback((Fl_Callback*)cb_Mode); - o->add("Poly"); o->add("Mono"); o->add("Legato"); - if (part->Ppolymode!=0) o->value(0); else o->value(1); - if (part->Ppolymode==0 && part->Plegatomode!=0) o->value(2); - } // Fl_Choice* o - if (part->Penabled==0) o->deactivate(); - partgroupui->end(); - } // Fl_Group* partgroupui - { Fl_Check_Button* o = new Fl_Check_Button(90, 5, 75, 20, "Enabled"); - o->down_box(FL_DOWN_BOX); - o->labelfont(1); - o->labelsize(11); - o->callback((Fl_Callback*)cb_Enabled); - o->value(part->Penabled); - } // Fl_Check_Button* o - partgroup->end(); - } // Fl_Group* partgroup - { ctlwindow = new Fl_Double_Window(500, 130, "Controllers"); - ctlwindow->user_data((void*)(this)); - { Fl_Check_Button* o = new Fl_Check_Button(155, 55, 45, 20, "Expr"); - o->tooltip("Expression enable"); - o->box(FL_THIN_UP_BOX); - o->down_box(FL_DOWN_BOX); - o->labelsize(10); - o->callback((Fl_Callback*)cb_Expr); - o->value(part->ctl.expression.receive); - } // Fl_Check_Button* o - { WidgetPDial* o = new WidgetPDial(10, 55, 30, 30, "PanDpth"); - o->tooltip("Panning Depth"); - o->box(FL_OVAL_BOX); - o->color(FL_BACKGROUND_COLOR); - o->selection_color(FL_INACTIVE_COLOR); - o->labeltype(FL_NORMAL_LABEL); - o->labelfont(0); - o->labelsize(10); - o->labelcolor(FL_FOREGROUND_COLOR); - o->maximum(127); - o->step(1); - o->callback((Fl_Callback*)cb_PanDpth); - o->align(Fl_Align(FL_ALIGN_BOTTOM)); - o->when(FL_WHEN_CHANGED); - o->value(part->ctl.panning.depth); - } // WidgetPDial* o - { WidgetPDial* o = new WidgetPDial(90, 55, 30, 30, "FltCut"); - o->tooltip("Filter Cutoff depth"); - o->box(FL_OVAL_BOX); - o->color(FL_BACKGROUND_COLOR); - o->selection_color(FL_INACTIVE_COLOR); - o->labeltype(FL_NORMAL_LABEL); - o->labelfont(0); - o->labelsize(10); - o->labelcolor(FL_FOREGROUND_COLOR); - o->maximum(127); - o->step(1); - o->callback((Fl_Callback*)cb_FltCut); - o->align(Fl_Align(FL_ALIGN_BOTTOM)); - o->when(FL_WHEN_CHANGED); - o->value(part->ctl.filtercutoff.depth); - } // WidgetPDial* o - { WidgetPDial* o = new WidgetPDial(50, 55, 30, 30, "FltQ"); - o->tooltip("Filter Q depth"); - o->box(FL_OVAL_BOX); - o->color(FL_BACKGROUND_COLOR); - o->selection_color(FL_INACTIVE_COLOR); - o->labeltype(FL_NORMAL_LABEL); - o->labelfont(0); - o->labelsize(10); - o->labelcolor(FL_FOREGROUND_COLOR); - o->maximum(127); - o->step(1); - o->callback((Fl_Callback*)cb_FltQ); - o->align(Fl_Align(FL_ALIGN_BOTTOM)); - o->when(FL_WHEN_CHANGED); - o->value(part->ctl.filterq.depth); - } // WidgetPDial* o - { WidgetPDial* o = new WidgetPDial(125, 10, 30, 30, "BwDpth"); - o->tooltip("BandWidth depth"); - o->box(FL_OVAL_BOX); - o->color(FL_BACKGROUND_COLOR); - o->selection_color(FL_INACTIVE_COLOR); - o->labeltype(FL_NORMAL_LABEL); - o->labelfont(0); - o->labelsize(10); - o->labelcolor(FL_FOREGROUND_COLOR); - o->maximum(127); - o->step(1); - o->callback((Fl_Callback*)cb_BwDpth); - o->align(Fl_Align(FL_ALIGN_BOTTOM)); - o->when(FL_WHEN_CHANGED); - o->value(part->ctl.bandwidth.depth); - } // WidgetPDial* o - { WidgetPDial* o = new WidgetPDial(50, 10, 30, 30, "ModWh"); - o->tooltip("Modulation Wheel depth"); - o->box(FL_OVAL_BOX); - o->color(FL_BACKGROUND_COLOR); - o->selection_color(FL_INACTIVE_COLOR); - o->labeltype(FL_NORMAL_LABEL); - o->labelfont(0); - o->labelsize(10); - o->labelcolor(FL_FOREGROUND_COLOR); - o->maximum(127); - o->step(1); - o->callback((Fl_Callback*)cb_ModWh); - o->align(Fl_Align(FL_ALIGN_BOTTOM)); - o->when(FL_WHEN_CHANGED); - o->value(part->ctl.modwheel.depth); - } // WidgetPDial* o - { Fl_Counter* o = new Fl_Counter(165, 15, 110, 20, "PWheelB.Rng (cents)"); - o->tooltip("Pitch Wheel Bend Range (cents)"); - o->labelsize(10); - o->minimum(-6400); - o->maximum(6400); - o->step(1); - o->callback((Fl_Callback*)cb_PWheelB); - o->align(Fl_Align(FL_ALIGN_TOP)); - o->value(part->ctl.pitchwheel.bendrange); - o->lstep(100); - } // Fl_Counter* o - { Fl_Check_Button* o = new Fl_Check_Button(205, 55, 60, 20, "FMamp"); - o->tooltip("FM amplitude enable"); - o->box(FL_THIN_UP_BOX); - o->down_box(FL_DOWN_BOX); - o->labelsize(10); - o->callback((Fl_Callback*)cb_FMamp); - o->value(part->ctl.fmamp.receive); - } // Fl_Check_Button* o - { Fl_Check_Button* o = new Fl_Check_Button(155, 80, 45, 20, "Vol"); - o->tooltip("Volume enable"); - o->box(FL_THIN_UP_BOX); - o->down_box(FL_DOWN_BOX); - o->labelsize(10); - o->callback((Fl_Callback*)cb_Vol); - o->value(part->ctl.volume.receive); - } // Fl_Check_Button* o - { Fl_Check_Button* o = new Fl_Check_Button(205, 80, 60, 20, "Sustain"); - o->tooltip("Sustain pedal enable"); - o->box(FL_THIN_UP_BOX); - o->down_box(FL_DOWN_BOX); - o->labelsize(10); - o->callback((Fl_Callback*)cb_Sustain); - o->value(part->ctl.sustain.receive); - } // Fl_Check_Button* o - { Fl_Button* o = new Fl_Button(330, 105, 95, 20, "Close"); - o->box(FL_THIN_UP_BOX); - o->callback((Fl_Callback*)cb_Close); - } // Fl_Button* o - { Fl_Button* o = new Fl_Button(5, 105, 210, 20, "Reset all controllers"); - o->box(FL_THIN_UP_BOX); - o->callback((Fl_Callback*)cb_Reset); - } // Fl_Button* o - { Fl_Group* o = new Fl_Group(280, 15, 160, 90, "Portamento"); - o->box(FL_ENGRAVED_FRAME); - o->labelfont(1); - o->labelsize(10); - { Fl_Check_Button* o = new Fl_Check_Button(285, 20, 40, 20, "Rcv"); - o->tooltip("Receive Portamento Controllers"); - o->box(FL_THIN_UP_BOX); - o->down_box(FL_DOWN_BOX); - o->labelsize(10); - o->callback((Fl_Callback*)cb_Rcv); - o->value(part->ctl.portamento.receive); - } // Fl_Check_Button* o - { WidgetPDial* o = new WidgetPDial(285, 60, 25, 25, "time"); - o->tooltip("Portamento time"); - o->box(FL_OVAL_BOX); - o->color(FL_BACKGROUND_COLOR); - o->selection_color(FL_INACTIVE_COLOR); - o->labeltype(FL_NORMAL_LABEL); - o->labelfont(0); - o->labelsize(10); - o->labelcolor(FL_FOREGROUND_COLOR); - o->maximum(127); - o->step(1); - o->callback((Fl_Callback*)cb_time); - o->align(Fl_Align(FL_ALIGN_BOTTOM)); - o->when(FL_WHEN_CHANGED); - o->value(part->ctl.portamento.time); - } // WidgetPDial* o - { Fl_Counter* o = new Fl_Counter(340, 20, 50, 20, "thresh"); - o->tooltip("Minimum or max. difference of the notes in order to do the portamento (x 100 \ -cents)"); - o->type(1); - o->labelsize(10); - o->minimum(0); - o->maximum(127); - o->step(1); - o->callback((Fl_Callback*)cb_thresh); - o->value(part->ctl.portamento.pitchthresh); - } // Fl_Counter* o - { Fl_Check_Button* o = new Fl_Check_Button(365, 70, 15, 15, "th.type"); - o->tooltip("Threshold type (min/max)"); - o->down_box(FL_DOWN_BOX); - o->labelsize(10); - o->callback((Fl_Callback*)cb_th); - o->align(Fl_Align(FL_ALIGN_BOTTOM)); - o->value(part->ctl.portamento.pitchthreshtype); - } // Fl_Check_Button* o - { Fl_Box* o = new Fl_Box(340, 50, 55, 15, "x100 cnt."); - o->labelsize(10); - o->align(Fl_Align(FL_ALIGN_CENTER|FL_ALIGN_INSIDE)); - } // Fl_Box* o - { WidgetPDial* o = new WidgetPDial(315, 60, 25, 25, "t.dn/up"); - o->tooltip("Portamento time stretch (up/down)"); - o->box(FL_OVAL_BOX); - o->color(FL_BACKGROUND_COLOR); - o->selection_color(FL_INACTIVE_COLOR); - o->labeltype(FL_NORMAL_LABEL); - o->labelfont(0); - o->labelsize(10); - o->labelcolor(FL_FOREGROUND_COLOR); - o->maximum(127); - o->step(1); - o->callback((Fl_Callback*)cb_t); - o->align(Fl_Align(FL_ALIGN_BOTTOM)); - o->when(FL_WHEN_CHANGED); - o->value(part->ctl.portamento.updowntimestretch); - } // WidgetPDial* o - { WidgetPDial* o = propta = new WidgetPDial(405, 20, 25, 25, "Prp.Rate"); - propta->tooltip("Distance required to double change from nonpropotinal portamento time"); - propta->box(FL_OVAL_BOX); - propta->color(FL_BACKGROUND_COLOR); - propta->selection_color(FL_INACTIVE_COLOR); - propta->labeltype(FL_NORMAL_LABEL); - propta->labelfont(0); - propta->labelsize(9); - propta->labelcolor(FL_FOREGROUND_COLOR); - propta->maximum(127); - propta->step(1); - propta->callback((Fl_Callback*)cb_propta); - propta->align(Fl_Align(FL_ALIGN_BOTTOM)); - propta->when(FL_WHEN_CHANGED); - o->value(part->ctl.portamento.propRate); - } // WidgetPDial* propta - { WidgetPDial* o = proptb = new WidgetPDial(405, 60, 25, 25, "Prp.Dpth"); - proptb->tooltip("The difference from nonproportinal portamento"); - proptb->box(FL_OVAL_BOX); - proptb->color(FL_BACKGROUND_COLOR); - proptb->selection_color(FL_INACTIVE_COLOR); - proptb->labeltype(FL_NORMAL_LABEL); - proptb->labelfont(0); - proptb->labelsize(9); - proptb->labelcolor(FL_FOREGROUND_COLOR); - proptb->maximum(127); - proptb->step(1); - proptb->callback((Fl_Callback*)cb_proptb); - proptb->align(Fl_Align(FL_ALIGN_BOTTOM)); - proptb->when(FL_WHEN_CHANGED); - o->value(part->ctl.portamento.propDepth); - } // WidgetPDial* proptb - { Fl_Check_Button* o = new Fl_Check_Button(285, 40, 50, 15, "Proprt."); - o->tooltip("Enable Proportinal Portamento (over fixed Portamento)"); - o->box(FL_THIN_UP_BOX); - o->down_box(FL_DOWN_BOX); - o->labelsize(9); - o->callback((Fl_Callback*)cb_Proprt); - o->value(part->ctl.portamento.proportional); - if(o->value()){propta->activate();proptb->activate();} - else {propta->deactivate();proptb->deactivate();} - } // Fl_Check_Button* o - o->end(); - } // Fl_Group* o - { Fl_Group* o = new Fl_Group(440, 15, 50, 90, "Resonance"); - o->box(FL_ENGRAVED_BOX); - o->labelfont(1); - o->labelsize(10); - { WidgetPDial* o = new WidgetPDial(450, 60, 25, 25, "BWdpth"); - o->tooltip("BandWidth controller depth"); - o->box(FL_OVAL_BOX); - o->color(FL_BACKGROUND_COLOR); - o->selection_color(FL_INACTIVE_COLOR); - o->labeltype(FL_NORMAL_LABEL); - o->labelfont(0); - o->labelsize(10); - o->labelcolor(FL_FOREGROUND_COLOR); - o->maximum(127); - o->step(1); - o->callback((Fl_Callback*)cb_BWdpth); - o->align(Fl_Align(FL_ALIGN_BOTTOM)); - o->when(FL_WHEN_CHANGED); - o->value(part->ctl.resonancebandwidth.depth); - } // WidgetPDial* o - { WidgetPDial* o = new WidgetPDial(450, 20, 25, 25, "CFdpth"); - o->tooltip("Center Frequency controller Depth"); - o->box(FL_OVAL_BOX); - o->color(FL_BACKGROUND_COLOR); - o->selection_color(FL_INACTIVE_COLOR); - o->labeltype(FL_NORMAL_LABEL); - o->labelfont(0); - o->labelsize(10); - o->labelcolor(FL_FOREGROUND_COLOR); - o->maximum(127); - o->step(1); - o->callback((Fl_Callback*)cb_CFdpth); - o->align(Fl_Align(FL_ALIGN_BOTTOM)); - o->when(FL_WHEN_CHANGED); - o->value(part->ctl.resonancecenter.depth); - } // WidgetPDial* o - o->end(); - } // Fl_Group* o - { Fl_Check_Button* o = new Fl_Check_Button(10, 15, 40, 25, "Exp MWh"); - o->tooltip("Exponential modulation wheel"); - o->down_box(FL_DOWN_BOX); - o->labelsize(10); - o->callback((Fl_Callback*)cb_Exp); - o->align(Fl_Align(132|FL_ALIGN_INSIDE)); - o->value(part->ctl.modwheel.exponential); - } // Fl_Check_Button* o - { Fl_Check_Button* o = new Fl_Check_Button(85, 15, 35, 25, "Exp BW"); - o->tooltip("Exponential BandWidth Controller"); - o->down_box(FL_DOWN_BOX); - o->labelsize(10); - o->callback((Fl_Callback*)cb_Exp1); - o->align(Fl_Align(132|FL_ALIGN_INSIDE)); - o->value(part->ctl.bandwidth.exponential); - } // Fl_Check_Button* o - ctlwindow->end(); - } // Fl_Double_Window* ctlwindow - { partfx = new Fl_Double_Window(390, 145, "Part\'s Insert Effects"); - partfx->user_data((void*)(this)); - { Fl_Counter* o = inseffnocounter = new Fl_Counter(5, 110, 80, 20, "FX No."); - inseffnocounter->type(1); - inseffnocounter->labelfont(1); - inseffnocounter->minimum(1); - inseffnocounter->maximum(127); - inseffnocounter->step(1); - inseffnocounter->textfont(1); - inseffnocounter->callback((Fl_Callback*)cb_inseffnocounter); - inseffnocounter->align(Fl_Align(FL_ALIGN_BOTTOM_LEFT)); - o->bounds(1,NUM_PART_EFX); - o->value(ninseff+1); - } // Fl_Counter* inseffnocounter - { Fl_Choice* o = insefftype = new Fl_Choice(155, 110, 70, 15, "EffType"); - insefftype->down_box(FL_BORDER_BOX); - insefftype->labelsize(10); - insefftype->callback((Fl_Callback*)cb_insefftype); - insefftype->align(Fl_Align(FL_ALIGN_BOTTOM_LEFT)); - insefftype->menu(menu_insefftype); - o->value(part->partefx[ninseff]->geteffect()); - } // Fl_Choice* insefftype - { inseffectuigroup = new Fl_Group(5, 5, 380, 100); - inseffectuigroup->box(FL_FLAT_BOX); - inseffectuigroup->color((Fl_Color)48); - { EffUI* o = inseffectui = new EffUI(5, 5, 380, 95); - inseffectui->box(FL_NO_BOX); - inseffectui->color(FL_BACKGROUND_COLOR); - inseffectui->selection_color(FL_BACKGROUND_COLOR); - inseffectui->labeltype(FL_NORMAL_LABEL); - inseffectui->labelfont(0); - inseffectui->labelsize(14); - inseffectui->labelcolor(FL_FOREGROUND_COLOR); - inseffectui->align(Fl_Align(FL_ALIGN_TOP)); - inseffectui->when(FL_WHEN_RELEASE); - o->init(part->partefx[ninseff]); - inseffectui->end(); - } // EffUI* inseffectui - inseffectuigroup->end(); - } // Fl_Group* inseffectuigroup - { Fl_Button* o = new Fl_Button(325, 115, 60, 20, "Close"); - o->box(FL_THIN_UP_BOX); - o->callback((Fl_Callback*)cb_Close1); - } // Fl_Button* o - { Fl_Choice* o = sendtochoice = new Fl_Choice(235, 110, 80, 15, "Send To."); - sendtochoice->down_box(FL_BORDER_BOX); - sendtochoice->labelsize(10); - sendtochoice->callback((Fl_Callback*)cb_sendtochoice); - sendtochoice->align(Fl_Align(FL_ALIGN_BOTTOM_LEFT)); - sendtochoice->menu(menu_sendtochoice); - int x=part->Pefxroute[ninseff]; if (x==127) x=1; - o->value(x); - } // Fl_Choice* sendtochoice - { Fl_Check_Button* o = bypasseff = new Fl_Check_Button(90, 110, 60, 15, "bypass"); - bypasseff->tooltip("if the effect is not used (is bypassed)"); - bypasseff->down_box(FL_DOWN_BOX); - bypasseff->labelsize(11); - bypasseff->callback((Fl_Callback*)cb_bypasseff); - int x=part->Pefxbypass[ninseff];o->value(x); - } // Fl_Check_Button* bypasseff - { Fl_Button* o = new Fl_Button(90, 127, 25, 15, "C"); - o->box(FL_THIN_UP_BOX); - o->color((Fl_Color)179); - o->labelfont(1); - o->labelsize(11); - o->labelcolor(FL_BACKGROUND2_COLOR); - o->callback((Fl_Callback*)cb_C); - } // Fl_Button* o - { Fl_Button* o = new Fl_Button(120, 127, 25, 15, "P"); - o->box(FL_THIN_UP_BOX); - o->color((Fl_Color)179); - o->labelfont(1); - o->labelsize(11); - o->labelcolor(FL_BACKGROUND2_COLOR); - o->callback((Fl_Callback*)cb_P); - } // Fl_Button* o - partfx->end(); - } // Fl_Double_Window* partfx - { instrumentkitlist = new Fl_Double_Window(670, 370, "Instrument Kit"); - instrumentkitlist->user_data((void*)(this)); - { Fl_Button* o = new Fl_Button(375, 350, 160, 20, "Close Window"); - o->box(FL_THIN_UP_BOX); - o->callback((Fl_Callback*)cb_Close2); - } // Fl_Button* o - { Fl_Scroll* o = kitlist = new Fl_Scroll(0, 15, 670, 330); - kitlist->type(2); - kitlist->box(FL_THIN_UP_BOX); - { Fl_Pack* o = new Fl_Pack(0, 20, 670, 320); - for (int i=0;iinit(part,i,master,this);} - o->end(); - } // Fl_Pack* o - if (part->Pkitmode==0) o->deactivate(); - kitlist->end(); - } // Fl_Scroll* kitlist - { Fl_Box* o = new Fl_Box(5, 0, 25, 15, "No."); - o->labelfont(1); - o->labelsize(11); - o->align(Fl_Align(FL_ALIGN_BOTTOM|FL_ALIGN_INSIDE)); - } // Fl_Box* o - { Fl_Box* o = new Fl_Box(55, 0, 25, 15, "M."); - o->labelfont(1); - o->labelsize(11); - o->align(Fl_Align(FL_ALIGN_BOTTOM|FL_ALIGN_INSIDE)); - } // Fl_Box* o - { Fl_Box* o = new Fl_Box(235, 0, 40, 15, "Min.k"); - o->labelfont(1); - o->labelsize(11); - o->align(Fl_Align(FL_ALIGN_BOTTOM|FL_ALIGN_INSIDE)); - } // Fl_Box* o - { Fl_Box* o = new Fl_Box(345, 0, 40, 15, "Max.k"); - o->labelfont(1); - o->labelsize(11); - o->align(Fl_Align(FL_ALIGN_BOTTOM|FL_ALIGN_INSIDE)); - } // Fl_Box* o - { Fl_Box* o = new Fl_Box(405, 0, 50, 15, "ADsynth"); - o->labelfont(1); - o->labelsize(11); - o->align(Fl_Align(FL_ALIGN_BOTTOM|FL_ALIGN_INSIDE)); - } // Fl_Box* o - { Fl_Box* o = new Fl_Box(470, 0, 60, 15, "SUBsynth"); - o->labelfont(1); - o->labelsize(11); - o->align(Fl_Align(FL_ALIGN_BOTTOM|FL_ALIGN_INSIDE)); - } // Fl_Box* o - { Fl_Choice* o = new Fl_Choice(35, 350, 70, 15, "Mode"); - o->down_box(FL_BORDER_BOX); - o->labelsize(11); - o->textfont(1); - o->textsize(11); - o->callback((Fl_Callback*)cb_Mode1); - o->menu(menu_Mode); - o->value(part->Pkitmode); - } // Fl_Choice* o - { Fl_Check_Button* o = new Fl_Check_Button(285, 350, 70, 15, "Drum mode"); - o->down_box(FL_DOWN_BOX); - o->labelsize(10); - o->callback((Fl_Callback*)cb_Drum); - o->value(part->Pdrummode); - } // Fl_Check_Button* o - { Fl_Box* o = new Fl_Box(620, 0, 30, 15, "FX.r."); - o->labelfont(1); - o->labelsize(11); - o->align(Fl_Align(FL_ALIGN_BOTTOM|FL_ALIGN_INSIDE)); - } // Fl_Box* o - { Fl_Box* o = new Fl_Box(540, 0, 60, 15, "PADsynth"); - o->labelfont(1); - o->labelsize(11); - o->align(Fl_Align(FL_ALIGN_BOTTOM|FL_ALIGN_INSIDE)); - } // Fl_Box* o - instrumentkitlist->end(); - } // Fl_Double_Window* instrumentkitlist - { instrumenteditwindow = new Fl_Double_Window(395, 360, "Instrument Edit"); - instrumenteditwindow->user_data((void*)(this)); - { Fl_Group* o = new Fl_Group(0, 220, 395, 110); - o->box(FL_ENGRAVED_FRAME); - { Fl_Group* o = new Fl_Group(205, 245, 100, 80, "PADsynth"); - o->box(FL_ENGRAVED_FRAME); - o->labelfont(1); - { Fl_Button* o = padeditbutton = new Fl_Button(215, 280, 80, 35, "Edit"); - padeditbutton->box(FL_PLASTIC_UP_BOX); - padeditbutton->color((Fl_Color)222); - padeditbutton->selection_color((Fl_Color)220); - padeditbutton->labelfont(1); - padeditbutton->labelsize(13); - padeditbutton->callback((Fl_Callback*)cb_padeditbutton1); - padeditbutton->align(Fl_Align(FL_ALIGN_WRAP)); - if (part->kit[0].Ppadenabled==0) o->deactivate(); - } // Fl_Button* padeditbutton - { Fl_Check_Button* o = padsynenabledcheck = new Fl_Check_Button(215, 255, 80, 20, "Enabled"); - padsynenabledcheck->tooltip("enable/disable PADsynth"); - padsynenabledcheck->box(FL_PLASTIC_UP_BOX); - padsynenabledcheck->down_box(FL_DOWN_BOX); - padsynenabledcheck->color((Fl_Color)222); - padsynenabledcheck->selection_color((Fl_Color)218); - padsynenabledcheck->labelfont(1); - padsynenabledcheck->labelsize(11); - padsynenabledcheck->callback((Fl_Callback*)cb_padsynenabledcheck); - o->value(part->kit[0].Ppadenabled); - } // Fl_Check_Button* padsynenabledcheck - o->end(); - } // Fl_Group* o - { Fl_Group* o = new Fl_Group(5, 245, 100, 80, "ADDsynth"); - o->box(FL_ENGRAVED_FRAME); - o->labelfont(1); - { Fl_Check_Button* o = adsynenabledcheck = new Fl_Check_Button(15, 255, 80, 20, "Enabled"); - adsynenabledcheck->tooltip("enable/disable ADsynth"); - adsynenabledcheck->box(FL_PLASTIC_UP_BOX); - adsynenabledcheck->down_box(FL_DOWN_BOX); - adsynenabledcheck->color((Fl_Color)222); - adsynenabledcheck->selection_color((Fl_Color)218); - adsynenabledcheck->labelfont(1); - adsynenabledcheck->labelsize(11); - adsynenabledcheck->callback((Fl_Callback*)cb_adsynenabledcheck); - o->value(part->kit[0].Padenabled); - } // Fl_Check_Button* adsynenabledcheck - { Fl_Button* o = adeditbutton = new Fl_Button(15, 281, 80, 34, "Edit"); - adeditbutton->box(FL_PLASTIC_UP_BOX); - adeditbutton->color((Fl_Color)222); - adeditbutton->selection_color((Fl_Color)220); - adeditbutton->labelfont(1); - adeditbutton->labelsize(13); - adeditbutton->callback((Fl_Callback*)cb_adeditbutton1); - adeditbutton->align(Fl_Align(FL_ALIGN_WRAP)); - if (part->kit[0].Padenabled==0) o->deactivate(); - } // Fl_Button* adeditbutton - o->end(); - } // Fl_Group* o - { Fl_Group* o = new Fl_Group(105, 245, 100, 80, "SUBsynth"); - o->box(FL_ENGRAVED_FRAME); - o->labelfont(1); - { Fl_Check_Button* o = subsynenabledcheck = new Fl_Check_Button(115, 255, 80, 20, "Enabled"); - subsynenabledcheck->tooltip("enable/disable SUBsynth"); - subsynenabledcheck->box(FL_PLASTIC_UP_BOX); - subsynenabledcheck->down_box(FL_DOWN_BOX); - subsynenabledcheck->color((Fl_Color)222); - subsynenabledcheck->selection_color((Fl_Color)218); - subsynenabledcheck->labelfont(1); - subsynenabledcheck->labelsize(11); - subsynenabledcheck->callback((Fl_Callback*)cb_subsynenabledcheck); - o->value(part->kit[0].Psubenabled); - } // Fl_Check_Button* subsynenabledcheck - { Fl_Button* o = subeditbutton = new Fl_Button(115, 280, 80, 35, "Edit"); - subeditbutton->box(FL_PLASTIC_UP_BOX); - subeditbutton->color((Fl_Color)222); - subeditbutton->selection_color((Fl_Color)220); - subeditbutton->labelfont(1); - subeditbutton->labelsize(13); - subeditbutton->callback((Fl_Callback*)cb_subeditbutton1); - subeditbutton->align(Fl_Align(FL_ALIGN_WRAP)); - if (part->kit[0].Psubenabled==0) o->deactivate(); - } // Fl_Button* subeditbutton - o->end(); - } // Fl_Group* o - { Fl_Button* o = new Fl_Button(310, 245, 80, 35, "Kit Edit"); - o->box(FL_PLASTIC_UP_BOX); - o->color((Fl_Color)238); - o->selection_color((Fl_Color)220); - o->labelfont(1); - o->callback((Fl_Callback*)cb_Kit); - o->align(Fl_Align(FL_ALIGN_WRAP)); - } // Fl_Button* o - { Fl_Button* o = new Fl_Button(310, 290, 80, 35, "Effects"); - o->box(FL_PLASTIC_UP_BOX); - o->color((Fl_Color)230); - o->labelfont(1); - o->labelsize(13); - o->callback((Fl_Callback*)cb_Effects); - } // Fl_Button* o - o->end(); - } // Fl_Group* o - { Fl_Group* o = new Fl_Group(0, 5, 395, 215); - o->box(FL_ENGRAVED_FRAME); - { Fl_Input* o = new Fl_Input(5, 60, 385, 50, "Author and Copyright"); - o->type(4); - o->color((Fl_Color)26); - o->labelsize(10); - o->callback((Fl_Callback*)cb_Author); - o->align(Fl_Align(FL_ALIGN_TOP_LEFT)); - o->maximum_size(MAX_INFO_TEXT_SIZE); - o->value((char *) &part->info.Pauthor); - } // Fl_Input* o - { Fl_Input* o = new Fl_Input(5, 125, 385, 90, "Comments"); - o->type(4); - o->color((Fl_Color)26); - o->labelsize(11); - o->callback((Fl_Callback*)cb_Comments); - o->align(Fl_Align(FL_ALIGN_TOP_LEFT)); - o->maximum_size(MAX_INFO_TEXT_SIZE); - o->value((char *) &part->info.Pcomments); - } // Fl_Input* o - { Fl_Choice* o = new Fl_Choice(5, 25, 155, 20, "Type:"); - o->down_box(FL_BORDER_BOX); - o->labelfont(1); - o->labelsize(11); - o->textsize(10); - o->callback((Fl_Callback*)cb_Type); - o->align(Fl_Align(FL_ALIGN_TOP_LEFT)); - o->menu(menu_Type); - o->value(part->info.Ptype); - } // Fl_Choice* o - o->end(); - } // Fl_Group* o - { Fl_Button* o = new Fl_Button(150, 335, 95, 25, "Close"); - o->box(FL_THIN_UP_BOX); - o->callback((Fl_Callback*)cb_Close3); - } // Fl_Button* o - instrumenteditwindow->end(); - } // Fl_Double_Window* instrumenteditwindow - return instrumenteditwindow; -} - -PartUI::PartUI(int x,int y, int w, int h, const char *label):Fl_Group(x,y,w,h,label) { - part=NULL; - adnoteui=NULL; - subnoteui=NULL; - padnoteui=NULL; - lastkititem=-1; -} - -void PartUI::init(Part *part_,Master *master_,int npart_,BankUI *bankui_) { - bankui=bankui_; - part=part_; - npart=npart_; - master=master_; - ninseff=0; - - make_window(); - partgroup->position(this->parent()->x()+2,this->parent()->y()+2); - partgroup->show(); - end(); - - - //if (config.ui.showinstrumentinfo!=0) instrumenteditwindow->show(); - - int klimits[]={1,2,3,4,5,6,7,8,9,10,15,20,30,50,100,0}; - - keylimitlist->add("OFF"); - int k=0; - int val=-1; - char tmp[10]; - while (klimits[k]!=0){ - sprintf(tmp,"%d",klimits[k]); - keylimitlist->add(tmp); - if ((val==-1)){ - if (klimits[k]>part->Pkeylimit) val=k; - }; - k++; - }; - - if (val==-1) val=k; - keylimitlist->value(val); -} - -void PartUI::showparameters(int kititem,int engine) { - if (engine==-1){//this is used if I want to clear the engine from the part - if (kititem==lastkititem) kititem=-1; - else kititem=lastkititem; - }; - - if (kititem!=lastkititem){ - if (adnoteui!=NULL) delete (adnoteui); - if (subnoteui!=NULL) delete (subnoteui); - if (padnoteui!=NULL) delete (padnoteui); - adnoteui=NULL;subnoteui=NULL;padnoteui=NULL; - lastkititem=kititem; - - if (kititem>=NUM_KIT_ITEMS) return;//bad kit item - if (kititem<0) return; - - if (part->kit[kititem].adpars!=NULL) - adnoteui=new ADnoteUI(part->kit[kititem].adpars,master); - - if (part->kit[kititem].subpars!=NULL) - subnoteui=new SUBnoteUI(part->kit[kititem].subpars); - - if (part->kit[kititem].padpars!=NULL) - padnoteui=new PADnoteUI(part->kit[kititem].padpars,master); - - }; - - - - if ((engine==0)&&(adnoteui!=NULL)) adnoteui->ADnoteGlobalParameters->show(); - if ((engine==1)&&(subnoteui!=NULL)) subnoteui->SUBparameters->show(); - if ((engine==2)&&(adnoteui!=NULL)) padnoteui->padnotewindow->show(); -} - -PartUI::~PartUI() { - if (adnoteui!=NULL) delete (adnoteui); - if (subnoteui!=NULL) delete (subnoteui); - if (padnoteui!=NULL) delete (padnoteui); - - partgroup->hide(); - //delete(partgroup); - - ctlwindow->hide(); - delete(ctlwindow); - - partfx->hide(); - delete(partfx); - - instrumentkitlist->hide(); - delete(instrumentkitlist); - - instrumenteditwindow->hide(); - delete(instrumenteditwindow); -} diff --git a/plugins/zynaddsubfx/src/UI/PartUI.fl b/plugins/zynaddsubfx/src/UI/PartUI.fl deleted file mode 100644 index fc8dcd5e8..000000000 --- a/plugins/zynaddsubfx/src/UI/PartUI.fl +++ /dev/null @@ -1,1125 +0,0 @@ -# data file for the Fltk User Interface Designer (fluid) -version 1.0107 -header_name {.h} -code_name {.cc} -decl {//Copyright (c) 2002-2005 Nasca Octavian Paul} {} - -decl {//License: GNU GPL version 2 or later} {} - -decl {\#include } {public -} - -decl {\#include } {public -} - -decl {\#include } {public -} - -decl {\#include "WidgetPDial.h"} {public -} - -decl {\#include "EffUI.h"} {public -} - -decl {\#include "BankUI.h"} {public -} - -decl {\#include "ADnoteUI.h"} {public -} - -decl {\#include "SUBnoteUI.h"} {public -} - -decl {\#include "PADnoteUI.h"} {public -} - -decl {\#include "../Misc/Config.h"} {public -} - -decl {\#include "../Misc/Master.h"} {public -} - -decl {\#include "../Misc/Part.h"} {public -} - -class PartSysEffSend {: {public Fl_Group} -} { - Function {make_window()} {private - } { - Fl_Window syseffsend { - private xywh {584 83 90 35} type Double hide - class Fl_Group - } { - Fl_Dial {} { - label 01 - callback {master->setPsysefxvol(npart,neff,(int) o->value());} - xywh {0 0 25 25} box ROUND_UP_BOX labelfont 1 labelsize 10 align 130 maximum 127 step 1 - code0 {o->size(25,25);} - code1 {o->value(master->Psysefxvol[neff][npart]);} - code2 {char tmp[10];snprintf(tmp,10,"%d",neff+1);o->copy_label(tmp);} - class WidgetPDial - } - } - } - Function {PartSysEffSend(int x,int y, int w, int h, const char *label=0):Fl_Group(x,y,w,h,label)} {} { - code {master=NULL; -neff=0; -npart=0;} {} - } - Function {init(Master *master_,int npart_,int neff_)} {} { - code {npart=npart_; -neff=neff_; -master=master_; -make_window(); -syseffsend->show(); -end();} {} - } - Function {~PartSysEffSend()} {} { - code {syseffsend->hide(); -//delete(syseffsend);} {} - } - decl {Master *master;} {} - decl {int neff;} {} - decl {int npart;} {} -} - -class PartUI_ {} { - Function {showparameters(int kititem,int engine)} {return_type virtual - } {} -} - -class PartKitItem {: {public Fl_Group} -} { - Function {make_window()} {private - } { - Fl_Window partkititem { - private xywh {113 271 670 30} type Double hide - class Fl_Group - } { - Fl_Group partkititemgroup { - private xywh {55 0 605 20} box FLAT_BOX - code0 {if (part->kit[n].Penabled==0) o->deactivate();} - } { - Fl_Counter minkcounter { - callback {part->kit[n].Pminkey=(int)o->value();} - xywh {225 0 55 15} type Simple minimum 0 maximum 128 step 1 - code0 {o->value(part->kit[n].Pminkey);} - } - Fl_Button {} { - label m - callback {if (part->lastnote>=0) minkcounter->value(part->lastnote); -minkcounter->do_callback(); -maxkcounter->do_callback();} - tooltip {set the minimum key to the last pressed key} xywh {285 3 15 12} box THIN_UP_BOX labelsize 10 - } - Fl_Button {} { - label M - callback {if (part->lastnote>=0) maxkcounter->value(part->lastnote); -maxkcounter->do_callback(); -minkcounter->do_callback();} - tooltip {set the maximum key to the last pressed key} xywh {315 3 15 12} box THIN_UP_BOX labelsize 10 - } - Fl_Button {} { - label R - callback {minkcounter->value(0); -minkcounter->do_callback(); -maxkcounter->value(127); -maxkcounter->do_callback();} - tooltip {reset the minimum key to 0 and maximum key to 127} xywh {300 3 15 12} box THIN_UP_BOX labelfont 1 labelsize 10 - } - Fl_Button adeditbutton { - label edit - callback {partui->showparameters(n,0);} - xywh {420 0 40 15} box THIN_UP_BOX labelsize 11 - code0 {if (part->kit[n].Padenabled==0) o->deactivate();} - code1 {if (n==0) o->hide();} - } - Fl_Button subeditbutton { - label edit - callback {partui->showparameters(n,1);} - xywh {490 0 40 15} box THIN_UP_BOX labelsize 11 - code0 {if (part->kit[n].Psubenabled==0) o->deactivate();} - code1 {if (n==0) o->hide();} - } - Fl_Check_Button mutedcheck { - callback {part->kit[n].Pmuted=(int)o->value();} - private xywh {60 0 20 15} down_box DOWN_BOX labelfont 1 labelsize 11 align 4 - code0 {o->value(part->kit[n].Pmuted);} - } - Fl_Counter maxkcounter { - callback {part->kit[n].Pmaxkey=(int)o->value();} - xywh {335 0 55 15} type Simple minimum 0 maximum 128 step 1 - code0 {o->value(part->kit[n].Pmaxkey);} - } - Fl_Button labelbutton { - label {Bass Drum} - callback {const char *tmp=fl_input("Kit item name:",(const char *)part->kit[n].Pname); -if (tmp!=NULL) snprintf((char *)part->kit[n].Pname,PART_MAX_NAME_LEN,"%s",tmp);} - xywh {90 0 130 15} box THIN_DOWN_BOX down_box FLAT_BOX labelfont 1 labelsize 10 align 20 - code0 {o->label((char *)part->kit[n].Pname);} - } - Fl_Check_Button adcheck { - callback {part->kit[n].Padenabled=(int)o->value(); -if (part->kit[n].Padenabled!=0) adeditbutton->activate(); - else adeditbutton->deactivate();} - private xywh {400 0 20 15} down_box DOWN_BOX labelfont 1 labelsize 11 align 4 - code0 {o->value(part->kit[n].Padenabled);} - code1 {if (n==0) o->hide();} - } - Fl_Check_Button subcheck { - callback {part->kit[n].Psubenabled=(int)o->value(); -if (part->kit[n].Psubenabled!=0) subeditbutton->activate(); - else subeditbutton->deactivate();} - private xywh {470 0 20 15} down_box DOWN_BOX labelfont 1 labelsize 11 align 4 - code0 {o->value(part->kit[n].Psubenabled);} - code1 {if (n==0) o->hide();} - } - Fl_Choice sendtoeffect { - callback {if (o->value()!=0) part->kit[n].Psendtoparteffect=(int)o->value()-1; - else part->kit[n].Psendtoparteffect=127;} open - xywh {615 0 45 15} down_box BORDER_BOX labelsize 10 align 5 textfont 1 textsize 10 - code0 {o->add("OFF");char nrstr[10]; for(int i=0;iadd(nrstr);};} - code1 {o->value(part->kit[n].Psendtoparteffect+1);if (part->kit[n].Psendtoparteffect==127) o->value(0);} - } {} - Fl_Button padeditbutton { - label edit - callback {partui->showparameters(n,2);} - xywh {560 0 40 15} box THIN_UP_BOX labelsize 11 - code0 {if (part->kit[n].Ppadenabled==0) o->deactivate();} - code1 {if (n==0) o->hide();} - } - Fl_Check_Button padcheck { - callback {part->kit[n].Ppadenabled=(int)o->value(); -if (part->kit[n].Ppadenabled!=0) padeditbutton->activate(); - else padeditbutton->deactivate();} - private xywh {540 0 20 15} down_box DOWN_BOX labelfont 1 labelsize 11 align 4 - code0 {o->value(part->kit[n].Ppadenabled);} - code1 {if (n==0) o->hide();} - } - } - Fl_Check_Button enabledcheck { - label 01 - callback {int answer=1; -if (o->value()==0) answer=fl_choice("Delete the item?","No","Yes",NULL); -if (answer!=0){ -pthread_mutex_lock(&master->mutex); - part->setkititemstatus(n,(int) o->value()); -pthread_mutex_unlock(&master->mutex); - -if (o->value()==0) partkititemgroup->deactivate(); -else partkititemgroup->activate(); -o->redraw(); -partui->showparameters(n,-1);//use to delete the ui, if it is not to item 0 -} else o->value(1);} - private xywh {30 0 20 15} down_box DOWN_BOX labeltype EMBOSSED_LABEL labelfont 1 labelsize 13 align 4 - code0 {snprintf(label,10,"%d",n+1);o->label(label);} - code1 {o->value(part->kit[n].Penabled);} - code2 {if (n==0) o->deactivate();} - } - } - } - Function {PartKitItem(int x,int y, int w, int h, const char *label=0):Fl_Group(x,y,w,h,label)} {} { - code {n=0; -part=NULL;} {} - } - Function {refresh()} {} { - code {enabledcheck->value(part->kit[n].Penabled); -if (part->kit[n].Penabled==0) partkititemgroup->deactivate(); -else partkititemgroup->activate(); - -mutedcheck->value(part->kit[n].Pmuted); -labelbutton->label((char *)part->kit[n].Pname); -minkcounter->value(part->kit[n].Pminkey); -maxkcounter->value(part->kit[n].Pmaxkey); -adcheck->value(part->kit[n].Padenabled); -adcheck->do_callback(); -subcheck->value(part->kit[n].Psubenabled); -subcheck->do_callback(); - -sendtoeffect->value(part->kit[n].Psendtoparteffect+1); -if (part->kit[n].Psendtoparteffect==127) sendtoeffect->value(0); - -this->redraw();} { - callback {int answer=1; -if (o->value()==0) answer=fl_choice("Delete the item?","No","Yes",NULL); -if (answer!=0){ -pthread_mutex_lock(&master->mutex); - part->setkititemstatus(n,(int) o->value()); -pthread_mutex_unlock(&master->mutex); - -if (o->value()==0) partkititemgroup->deactivate(); -else partkititemgroup->activate(); -o->redraw(); -partui->showparameters(n,-1);//use to delete the ui, if it is not to item 0 -} else o->value(1);} - } - } - Function {init(Part *part_,int n_,Master *master_,PartUI_ *partui_)} {} { - code {part=part_; -n=n_; -partui=partui_; -master=master_; -make_window(); -//partkititem->show(); -end();} {} - } - Function {~PartKitItem()} {} { - code {partkititem->hide(); -//delete(partkititem);} {} - } - decl {Part *part;} {} - decl {int n;} {} - decl {Master *master;} {} - decl {char label[10];} {} - decl {PartUI_ *partui;} {} -} - -class PartUI {: {public Fl_Group,PartUI_} -} { - Function {make_window()} {private - } { - Fl_Window partgroup { - private xywh {424 178 385 180} type Double hide - class Fl_Group - } { - Fl_Group partgroupui { - xywh {0 0 385 180} - code0 {if (part->Penabled==0) o->deactivate();} - } { - Fl_Dial {} { - label Pan - callback {part->setPpanning((int) o->value());} - xywh {50 40 25 25} box ROUND_UP_BOX labelsize 11 maximum 127 step 1 - code0 {o->value(part->Ppanning);} - class WidgetPDial - } - Fl_Counter {} { - label KeyShift - callback {part->Pkeyshift=(int) o->value()+64;} - xywh {195 45 90 20} labelsize 11 align 1 minimum -64 maximum 64 step 1 - code0 {o->lstep(12);} - code1 {o->value(part->Pkeyshift-64);} - } - Fl_Scroll {} {open - xywh {166 91 125 60} box ENGRAVED_FRAME labelfont 1 labelsize 10 align 21 - } { - Fl_Pack {} {open - xywh {171 96 115 35} type HORIZONTAL - code0 {o->spacing(5);} - code1 {for (int i=0;iinit(master,npart,i);}} - } {} - } - Fl_Button {} { - label {Grand Piano} - callback {int event=Fl::event_button(); -if (event==FL_RIGHT_MOUSE){ - const char *tmp=fl_input("Instrument name:",(const char *)part->Pname); - if (tmp!=NULL) snprintf((char *)part->Pname,PART_MAX_NAME_LEN,"%s",tmp); -} else { - if (event==FL_LEFT_MOUSE) bankui->show(); - else instrumenteditwindow->show(); -};} - tooltip {left mousebutton - to choose/save/.. from/to bank or right mousebutton to change the name or middle button to change the instrument information} xywh {195 5 185 20} box THIN_DOWN_BOX down_box FLAT_BOX labelfont 1 labelsize 11 align 84 - code0 {o->label((char *)part->Pname);} - } - Fl_Box {} { - label {To Sys.Efx.} - xywh {166 81 95 10} labelfont 1 labelsize 10 - } - Fl_Check_Button {} { - label NoteOn - callback {part->Pnoteon=(int) o->value();} - tooltip {set if the part receives NoteOn messages} xywh {10 155 65 20} down_box DOWN_BOX labelfont 1 labelsize 11 - code0 {o->value(part->Pnoteon);} - } - Fl_Counter minkcounter { - label {Min.k} - callback {part->Pminkey=(int) o->value(); -if (part->Pminkey>part->Pmaxkey) o->textcolor(FL_RED); - else o->textcolor(FL_BLACK);} - tooltip {Minimum key (that the part receives NoteOn messages)} xywh {295 125 40 15} type Simple labelfont 1 labelsize 10 minimum 0 maximum 127 step 1 textsize 10 - code0 {o->value(part->Pminkey);} - } - Fl_Counter maxkcounter { - label {Max.k} - callback {part->Pmaxkey=(int) o->value(); - -if (part->Pminkey>part->Pmaxkey) o->textcolor(FL_RED); - else o->textcolor(FL_BLACK);} - tooltip {Maximum key (that the part receives NoteOn messages)} xywh {340 125 40 15} type Simple labelfont 1 labelsize 10 minimum 0 maximum 127 step 1 textsize 10 - code0 {o->value(part->Pmaxkey);} - } - Fl_Dial {} { - label Volume - callback {part->setPvolume((int) o->value());} - tooltip {Part Volume} xywh {10 35 30 30} box ROUND_UP_BOX labelsize 11 maximum 127 step 1 - code0 {o->value(part->Pvolume);} - class WidgetPDial - } - Fl_Dial {} { - label {Vel.Ofs.} - callback {part->Pveloffs=(int) o->value();} - tooltip {Velocity Offset} xywh {135 40 25 25} box ROUND_UP_BOX labelsize 10 maximum 127 step 1 - code0 {o->value(part->Pveloffs);} - class WidgetPDial - } - Fl_Dial {} { - label {Vel.Sns.} - callback {part->Pvelsns=(int) o->value();} - tooltip {Velocity Sensing Function} xywh {95 40 25 25} box ROUND_UP_BOX labelsize 10 maximum 127 step 1 - code0 {o->value(part->Pvelsns);} - class WidgetPDial - } - Fl_Button {} { - label Controllers - callback {ctlwindow->show();} - xywh {295 90 85 30} box PLASTIC_UP_BOX labelfont 1 labelsize 11 - } - Fl_Check_Button {} { - label Portamento - callback {part->ctl.portamento.portamento=(int) o->value();} - tooltip {Enable/Disable the portamento} xywh {95 155 88 20} down_box DOWN_BOX labelfont 1 labelsize 11 - code0 {o->value(part->ctl.portamento.portamento);} - } - Fl_Button {} { - label {Edit instrument} - callback {instrumenteditwindow->show();} - xywh {15 90 130 30} box PLASTIC_UP_BOX color 230 labelfont 1 labelsize 13 - } - Fl_Button {} { - label m - callback {if (part->lastnote>=0) minkcounter->value(part->lastnote); -minkcounter->do_callback(); -maxkcounter->do_callback();} - tooltip {set the minimum key to the last pressed key} xywh {315 155 15 12} box THIN_UP_BOX labelsize 10 - } - Fl_Button {} { - label M - callback {if (part->lastnote>=0) maxkcounter->value(part->lastnote); -maxkcounter->do_callback(); -minkcounter->do_callback();} - tooltip {set the maximum key to the last pressed key} xywh {345 155 15 12} box THIN_UP_BOX labelsize 10 - } - Fl_Button {} { - label R - callback {minkcounter->value(0); -minkcounter->do_callback(); -maxkcounter->value(127); -maxkcounter->do_callback();} - tooltip {reset the minimum key to 0 and maximum key to 127} xywh {330 155 15 12} box THIN_UP_BOX labelfont 1 labelsize 10 - } - Fl_Choice {} { - label {MIDI Chn.Rcv.} - callback {part->Prcvchn=(int) o->value();} open - tooltip {receive from Midi channel} xywh {310 45 70 20} down_box BORDER_BOX labelsize 10 align 5 textfont 1 textsize 10 - code0 {char nrstr[10]; for(int i=0;iadd(nrstr); else o->add("Drms10");};} - code1 {o->value(part->Prcvchn);} - } {} - Fl_Choice keylimitlist { - label KLmt - callback {int val=0; -val=atoi(o->text()); -part->setkeylimit(val);} open - tooltip {Key Limit} xywh {215 155 50 20} down_box BORDER_BOX labelsize 10 align 8 textfont 1 textsize 10 - } {} - Fl_Choice {} { - label {Mode :} - callback {if ((int) o->value()==0){ /* Poly (implies no legato) */ - part->Ppolymode=1; - part->Plegatomode=0; -} else { - if ((int) o->value()==1){ /* Mono (implies no legato) */ - part->Ppolymode=0; - part->Plegatomode=0; - } else { - if ((int) o->value()==2){ /* Legato (implies mono) */ - part->Ppolymode=0; - part->Plegatomode=1; - }; - }; -};} open - tooltip {Poly, Mono or Legato mode} xywh {80 130 64 18} down_box BORDER_BOX labelfont 1 labelsize 11 textfont 1 textsize 10 - code0 {o->add("Poly"); o->add("Mono"); o->add("Legato");} - code1 {if (part->Ppolymode!=0) o->value(0); else o->value(1);} - code2 {if (part->Ppolymode==0 && part->Plegatomode!=0) o->value(2);} - } {} - } - Fl_Check_Button {} { - label Enabled - callback {pthread_mutex_lock(&master->mutex); -master->partonoff(npart,(int) o->value()); -pthread_mutex_unlock(&master->mutex); -if (part->Penabled==0) partgroupui->deactivate(); - else partgroupui->activate();} - xywh {90 5 75 20} down_box DOWN_BOX labelfont 1 labelsize 11 - code0 {o->value(part->Penabled);} - } - } - Fl_Window ctlwindow { - label Controllers - private xywh {542 212 500 130} type Double hide - } { - Fl_Check_Button {} { - label Expr - callback {part->ctl.expression.receive=(int) o->value();} - tooltip {Expression enable} xywh {155 55 45 20} box THIN_UP_BOX down_box DOWN_BOX labelsize 10 - code0 {o->value(part->ctl.expression.receive);} - } - Fl_Dial {} { - label PanDpth - callback {part->ctl.panning.depth=(int) o->value();} - tooltip {Panning Depth} xywh {10 55 30 30} labelsize 10 maximum 127 step 1 - code0 {o->value(part->ctl.panning.depth);} - class WidgetPDial - } - Fl_Dial {} { - label FltCut - callback {part->ctl.filtercutoff.depth=(int) o->value();} - tooltip {Filter Cutoff depth} xywh {90 55 30 30} labelsize 10 maximum 127 step 1 - code0 {o->value(part->ctl.filtercutoff.depth);} - class WidgetPDial - } - Fl_Dial {} { - label FltQ - callback {part->ctl.filterq.depth=(int) o->value();} - tooltip {Filter Q depth} xywh {50 55 30 30} labelsize 10 maximum 127 step 1 - code0 {o->value(part->ctl.filterq.depth);} - class WidgetPDial - } - Fl_Dial {} { - label BwDpth - callback {part->ctl.bandwidth.depth=(int) o->value();} - tooltip {BandWidth depth} xywh {125 10 30 30} labelsize 10 maximum 127 step 1 - code0 {o->value(part->ctl.bandwidth.depth);} - class WidgetPDial - } - Fl_Dial {} { - label ModWh - callback {part->ctl.modwheel.depth=(int) o->value();} - tooltip {Modulation Wheel depth} xywh {50 10 30 30} labelsize 10 maximum 127 step 1 - code0 {o->value(part->ctl.modwheel.depth);} - class WidgetPDial - } - Fl_Counter {} { - label {PWheelB.Rng (cents)} - callback {part->ctl.pitchwheel.bendrange=(int) o->value();} - tooltip {Pitch Wheel Bend Range (cents)} xywh {165 15 110 20} labelsize 10 align 1 minimum -6400 maximum 6400 step 1 - code0 {o->value(part->ctl.pitchwheel.bendrange);} - code1 {o->lstep(100);} - } - Fl_Check_Button {} { - label FMamp - callback {part->ctl.fmamp.receive=(int) o->value();} - tooltip {FM amplitude enable} xywh {205 55 60 20} box THIN_UP_BOX down_box DOWN_BOX labelsize 10 - code0 {o->value(part->ctl.fmamp.receive);} - } - Fl_Check_Button {} { - label Vol - callback {part->ctl.volume.receive=(int) o->value();} - tooltip {Volume enable} xywh {155 80 45 20} box THIN_UP_BOX down_box DOWN_BOX labelsize 10 - code0 {o->value(part->ctl.volume.receive);} - } - Fl_Check_Button {} { - label Sustain - callback {part->ctl.sustain.receive=(int) o->value(); -if (part->ctl.sustain.receive==0) { - part->RelaseSustainedKeys(); - part->ctl.setsustain(0); -};} - tooltip {Sustain pedal enable} xywh {205 80 60 20} box THIN_UP_BOX down_box DOWN_BOX labelsize 10 - code0 {o->value(part->ctl.sustain.receive);} - } - Fl_Button {} { - label Close - callback {ctlwindow->hide();} - xywh {330 105 95 20} box THIN_UP_BOX - } - Fl_Button {} { - label {Reset all controllers} - callback {part->SetController(C_resetallcontrollers,0);} - xywh {5 105 210 20} box THIN_UP_BOX - } - Fl_Group {} { - label Portamento - xywh {280 15 160 90} box ENGRAVED_FRAME labelfont 1 labelsize 10 - } { - Fl_Check_Button {} { - label Rcv - callback {part->ctl.portamento.receive=(int) o->value();} - tooltip {Receive Portamento Controllers} xywh {285 20 40 20} box THIN_UP_BOX down_box DOWN_BOX labelsize 10 - code0 {o->value(part->ctl.portamento.receive);} - } - Fl_Dial {} { - label time - callback {part->ctl.portamento.time=(int) o->value();} - tooltip {Portamento time} xywh {285 60 25 25} labelsize 10 maximum 127 step 1 - code0 {o->value(part->ctl.portamento.time);} - class WidgetPDial - } - Fl_Counter {} { - label thresh - callback {part->ctl.portamento.pitchthresh=(int) o->value();} - tooltip {Minimum or max. difference of the notes in order to do the portamento (x 100 cents)} xywh {340 20 50 20} type Simple labelsize 10 minimum 0 maximum 127 step 1 - code0 {o->value(part->ctl.portamento.pitchthresh);} - } - Fl_Check_Button {} { - label {th.type} - callback {part->ctl.portamento.pitchthreshtype=(int) o->value();} - tooltip {Threshold type (min/max)} xywh {365 70 15 15} down_box DOWN_BOX labelsize 10 align 2 - code0 {o->value(part->ctl.portamento.pitchthreshtype);} - } - Fl_Box {} { - label {x100 cnt.} - xywh {340 50 55 15} labelsize 10 align 16 - } - Fl_Dial {} { - label {t.dn/up} - callback {int x=(int) o->value(); - -part->ctl.portamento.updowntimestretch=x;} - tooltip {Portamento time stretch (up/down)} xywh {315 60 25 25} labelsize 10 maximum 127 step 1 - code0 {o->value(part->ctl.portamento.updowntimestretch);} - class WidgetPDial - } - Fl_Dial propta { - label {Prp.Rate} - callback {part->ctl.portamento.propRate=(int) o->value();} - tooltip {Distance required to double change from nonpropotinal portamento time} xywh {405 20 25 25} labelsize 9 maximum 127 step 1 - code0 {o->value(part->ctl.portamento.propRate);} - class WidgetPDial - } - Fl_Dial proptb { - label {Prp.Dpth} - callback {part->ctl.portamento.propDepth=(int) o->value();} - tooltip {The difference from nonproportinal portamento} xywh {405 60 25 25} labelsize 9 maximum 127 step 1 - code0 {o->value(part->ctl.portamento.propDepth);} - class WidgetPDial - } - Fl_Check_Button {} { - label {Proprt.} - callback {part->ctl.portamento.proportional=(int) o->value(); -if(o->value()){propta->activate();proptb->activate();} -else {propta->deactivate();proptb->deactivate();}} - tooltip {Enable Proportinal Portamento (over fixed Portamento)} xywh {285 40 50 15} box THIN_UP_BOX down_box DOWN_BOX labelsize 9 - code0 {o->value(part->ctl.portamento.proportional);} - code1 {if(o->value()){propta->activate();proptb->activate();}} - code2 {else {propta->deactivate();proptb->deactivate();}} - } - } - Fl_Group {} { - label Resonance - xywh {440 15 50 90} box ENGRAVED_BOX labelfont 1 labelsize 10 - } { - Fl_Dial {} { - label BWdpth - callback {part->ctl.resonancebandwidth.depth=(int) o->value();} - tooltip {BandWidth controller depth} xywh {450 60 25 25} labelsize 10 maximum 127 step 1 - code0 {o->value(part->ctl.resonancebandwidth.depth);} - class WidgetPDial - } - Fl_Dial {} { - label CFdpth - callback {part->ctl.resonancecenter.depth=(int) o->value();} - tooltip {Center Frequency controller Depth} xywh {450 20 25 25} labelsize 10 maximum 127 step 1 - code0 {o->value(part->ctl.resonancecenter.depth);} - class WidgetPDial - } - } - Fl_Check_Button {} { - label {Exp MWh} - callback {part->ctl.modwheel.exponential=(int) o->value();} - tooltip {Exponential modulation wheel} xywh {10 15 40 25} down_box DOWN_BOX labelsize 10 align 148 - code0 {o->value(part->ctl.modwheel.exponential);} - } - Fl_Check_Button {} { - label {Exp BW} - callback {part->ctl.bandwidth.exponential=(int) o->value();} - tooltip {Exponential BandWidth Controller} xywh {85 15 35 25} down_box DOWN_BOX labelsize 10 align 148 - code0 {o->value(part->ctl.bandwidth.exponential);} - } - } - Fl_Window partfx { - label {Part's Insert Effects} - private xywh {121 424 390 145} type Double hide - } { - Fl_Counter inseffnocounter { - label {FX No.} - callback {ninseff=(int) o->value()-1; -insefftype->value(part->partefx[ninseff]->geteffect()); -//insefftype->do_callback(); -inseffectui->refresh(part->partefx[ninseff]); -int x=part->Pefxroute[ninseff]; -if (x==127) x=1; -bypasseff->value(part->Pefxbypass[ninseff]); - -sendtochoice->value(x);} - xywh {5 110 80 20} type Simple labelfont 1 align 6 minimum 1 maximum 127 step 1 textfont 1 - code0 {o->bounds(1,NUM_PART_EFX);} - code1 {o->value(ninseff+1);} - } - Fl_Choice insefftype { - label EffType - callback {pthread_mutex_lock(part->mutex); -part->partefx[ninseff]->changeeffect((int) o->value()); -pthread_mutex_unlock(part->mutex); -inseffectui->refresh(part->partefx[ninseff]);} - xywh {155 110 70 15} down_box BORDER_BOX labelsize 10 align 6 - code0 {o->value(part->partefx[ninseff]->geteffect());} - } { - MenuItem {} { - label {No Effect} - xywh {35 35 100 20} labelfont 1 labelsize 10 - } - MenuItem {} { - label Reverb - xywh {45 45 100 20} labelfont 1 labelsize 10 - } - MenuItem {} { - label Echo - xywh {55 55 100 20} labelfont 1 labelsize 10 - } - MenuItem {} { - label Chorus - xywh {65 65 100 20} labelfont 1 labelsize 10 - } - MenuItem {} { - label Phaser - xywh {70 70 100 20} labelfont 1 labelsize 10 - } - MenuItem {} { - label AlienWah - xywh {80 80 100 20} labelfont 1 labelsize 10 - } - MenuItem {} { - label Distortion - xywh {90 90 100 20} labelfont 1 labelsize 10 - } - MenuItem {} { - label EQ - xywh {100 100 100 20} labelfont 1 labelsize 10 - } - MenuItem {} { - label DynFilter - xywh {110 110 100 20} labelfont 1 labelsize 10 - } - } - Fl_Group inseffectuigroup { - xywh {5 5 380 100} box FLAT_BOX color 48 - } { - Fl_Group inseffectui { - xywh {5 5 380 95} - code0 {o->init(part->partefx[ninseff]);} - class EffUI - } {} - } - Fl_Button {} { - label Close - callback {partfx->hide();} - xywh {325 115 60 20} box THIN_UP_BOX - } - Fl_Choice sendtochoice { - label {Send To.} - callback {int x=(int) o->value(); -part->Pefxroute[ninseff]=x; -if (x==2) part->partefx[ninseff]->setdryonly(true); - else part->partefx[ninseff]->setdryonly(false);} - xywh {235 110 80 15} down_box BORDER_BOX labelsize 10 align 6 - code0 {int x=part->Pefxroute[ninseff]; if (x==127) x=1;} - code1 {o->value(x);} - } { - MenuItem {} { - label {Next Effect} - xywh {45 45 100 20} labelfont 1 labelsize 10 - } - MenuItem {} { - label {Part Out} - xywh {55 55 100 20} labelfont 1 labelsize 10 - } - MenuItem {} { - label {Dry Out} - xywh {65 65 100 20} labelfont 1 labelsize 10 - } - } - Fl_Check_Button bypasseff { - label bypass - callback {part->Pefxbypass[ninseff]=(((int)o->value())!=0);} - tooltip {if the effect is not used (is bypassed)} xywh {90 110 60 15} down_box DOWN_BOX labelsize 11 - code0 {int x=part->Pefxbypass[ninseff];o->value(x);} - } - Fl_Button {} { - label C - callback {presetsui->copy(part->partefx[ninseff]);} - xywh {90 127 25 15} box THIN_UP_BOX color 179 labelfont 1 labelsize 11 labelcolor 7 - } - Fl_Button {} { - label P - callback {pthread_mutex_lock(&master->mutex); -presetsui->paste(part->partefx[ninseff],inseffectui); -pthread_mutex_unlock(&master->mutex);} - xywh {120 127 25 15} box THIN_UP_BOX color 179 labelfont 1 labelsize 11 labelcolor 7 - } - } - Fl_Window instrumentkitlist { - label {Instrument Kit} - xywh {113 324 670 370} type Double hide - } { - Fl_Button {} { - label {Close Window} - callback {instrumentkitlist->hide();} - xywh {375 350 160 20} box THIN_UP_BOX - } - Fl_Scroll kitlist { - xywh {0 15 670 330} type VERTICAL box THIN_UP_BOX - code0 {if (part->Pkitmode==0) o->deactivate();} - } { - Fl_Pack {} { - xywh {0 20 670 320} - code0 {for (int i=0;iinit(part,i,master,this);}} - } {} - } - Fl_Box {} { - label {No.} - xywh {5 0 25 15} labelfont 1 labelsize 11 align 18 - } - Fl_Box {} { - label {M.} - xywh {55 0 25 15} labelfont 1 labelsize 11 align 18 - } - Fl_Box {} { - label {Min.k} - xywh {235 0 40 15} labelfont 1 labelsize 11 align 18 - } - Fl_Box {} { - label {Max.k} - xywh {345 0 40 15} labelfont 1 labelsize 11 align 18 - } - Fl_Box {} { - label ADsynth - xywh {405 0 50 15} labelfont 1 labelsize 11 align 18 - } - Fl_Box {} { - label SUBsynth - xywh {470 0 60 15} labelfont 1 labelsize 11 align 18 - } - Fl_Choice {} { - label Mode - callback {part->Pkitmode=(int) o->value(); -if (part->Pkitmode==0) { - kitlist->deactivate(); - } else { - kitlist->activate(); -};} - xywh {35 350 70 15} down_box BORDER_BOX labelsize 11 textfont 1 textsize 11 - code0 {o->value(part->Pkitmode);} - } { - MenuItem {} { - label OFF - xywh {0 0 100 20} labelfont 1 labelsize 11 - } - MenuItem {} { - label MULTI - xywh {10 10 100 20} labelfont 1 labelsize 11 - } - MenuItem {} { - label SINGLE - xywh {20 20 100 20} labelfont 1 labelsize 11 - } - } - Fl_Check_Button {} { - label {Drum mode} - callback {part->Pdrummode=(int) o->value();} - xywh {285 350 70 15} down_box DOWN_BOX labelsize 10 - code0 {o->value(part->Pdrummode);} - } - Fl_Box {} { - label {FX.r.} - xywh {620 0 30 15} labelfont 1 labelsize 11 align 18 - } - Fl_Box {} { - label PADsynth - xywh {540 0 60 15} labelfont 1 labelsize 11 align 18 - } - } - Fl_Window instrumenteditwindow { - label {Instrument Edit} selected - xywh {182 214 395 360} type Double hide - } { - Fl_Group {} { - xywh {0 220 395 110} box ENGRAVED_FRAME - } { - Fl_Group {} { - label PADsynth - xywh {205 245 100 80} box ENGRAVED_FRAME labelfont 1 - } { - Fl_Button padeditbutton { - label Edit - callback {showparameters(0,2);} - xywh {215 280 80 35} box PLASTIC_UP_BOX color 222 selection_color 220 labelfont 1 labelsize 13 align 128 - code0 {if (part->kit[0].Ppadenabled==0) o->deactivate();} - } - Fl_Check_Button padsynenabledcheck { - label Enabled - callback {int x=(int) o->value(); -part->kit[0].Ppadenabled=x; -if (x==0) padeditbutton->deactivate(); - else padeditbutton->activate();} - tooltip {enable/disable PADsynth} xywh {215 255 80 20} box PLASTIC_UP_BOX down_box DOWN_BOX color 222 selection_color 218 labelfont 1 labelsize 11 - code1 {o->value(part->kit[0].Ppadenabled);} - } - } - Fl_Group {} { - label ADDsynth - xywh {5 245 100 80} box ENGRAVED_FRAME labelfont 1 - } { - Fl_Check_Button adsynenabledcheck { - label Enabled - callback {int x=(int) o->value(); -part->kit[0].Padenabled=x; -if (x==0) adeditbutton->deactivate(); - else adeditbutton->activate();} - tooltip {enable/disable ADsynth} xywh {15 255 80 20} box PLASTIC_UP_BOX down_box DOWN_BOX color 222 selection_color 218 labelfont 1 labelsize 11 - code1 {o->value(part->kit[0].Padenabled);} - } - Fl_Button adeditbutton { - label Edit - callback {showparameters(0,0);} - xywh {15 281 80 34} box PLASTIC_UP_BOX color 222 selection_color 220 labelfont 1 labelsize 13 align 128 - code0 {if (part->kit[0].Padenabled==0) o->deactivate();} - } - } - Fl_Group {} { - label SUBsynth - xywh {105 245 100 80} box ENGRAVED_FRAME labelfont 1 - } { - Fl_Check_Button subsynenabledcheck { - label Enabled - callback {int x=(int) o->value(); -part->kit[0].Psubenabled=x; -if (x==0) subeditbutton->deactivate(); - else subeditbutton->activate();} - tooltip {enable/disable SUBsynth} xywh {115 255 80 20} box PLASTIC_UP_BOX down_box DOWN_BOX color 222 selection_color 218 labelfont 1 labelsize 11 - code1 {o->value(part->kit[0].Psubenabled);} - } - Fl_Button subeditbutton { - label Edit - callback {showparameters(0,1);} - xywh {115 280 80 35} box PLASTIC_UP_BOX color 222 selection_color 220 labelfont 1 labelsize 13 align 128 - code0 {if (part->kit[0].Psubenabled==0) o->deactivate();} - } - } - Fl_Button {} { - label {Kit Edit} - callback {instrumentkitlist->show();} - xywh {310 245 80 35} box PLASTIC_UP_BOX color 238 selection_color 220 labelfont 1 align 128 - } - Fl_Button {} { - label Effects - callback {partfx->show();} - xywh {310 290 80 35} box PLASTIC_UP_BOX color 230 labelfont 1 labelsize 13 - } - } - Fl_Group {} { - xywh {0 5 395 215} box ENGRAVED_FRAME - } { - Fl_Input {} { - label {Author and Copyright} - callback {snprintf((char *)part->info.Pauthor,MAX_INFO_TEXT_SIZE,"%s",o->value());} - xywh {5 60 385 50} type Multiline color 26 labelsize 10 align 5 - code0 {o->maximum_size(MAX_INFO_TEXT_SIZE);} - code1 {o->value((char *) &part->info.Pauthor);} - } - Fl_Input {} { - label Comments - callback {snprintf((char *)part->info.Pcomments,MAX_INFO_TEXT_SIZE,"%s",o->value());} - xywh {5 125 385 90} type Multiline color 26 labelsize 11 align 5 - code0 {o->maximum_size(MAX_INFO_TEXT_SIZE);} - code1 {o->value((char *) &part->info.Pcomments);} - } - Fl_Choice {} { - label {Type:} - callback {part->info.Ptype=o->value();} - xywh {5 25 155 20} down_box BORDER_BOX labelfont 1 labelsize 11 align 5 textsize 10 - code0 {o->value(part->info.Ptype);} - } { - MenuItem {} { - label {--------------------------} - xywh {20 20 100 20} labelfont 1 labelsize 11 - } - MenuItem {} { - label Piano - xywh {10 10 100 20} labelfont 1 labelsize 11 - } - MenuItem {} { - label {Chromatic Percussion} - xywh {20 20 100 20} labelfont 1 labelsize 11 - } - MenuItem {} { - label Organ - xywh {30 30 100 20} labelfont 1 labelsize 11 - } - MenuItem {} { - label Guitar - xywh {40 40 100 20} labelfont 1 labelsize 11 - } - MenuItem {} { - label Bass - xywh {50 50 100 20} labelfont 1 labelsize 11 - } - MenuItem {} { - label {Solo Strings} - xywh {60 60 100 20} labelfont 1 labelsize 11 - } - MenuItem {} { - label Ensemble - xywh {70 70 100 20} labelfont 1 labelsize 11 - } - MenuItem {} { - label Brass - xywh {80 80 100 20} labelfont 1 labelsize 11 - } - MenuItem {} { - label Reed - xywh {90 90 100 20} labelfont 1 labelsize 11 - } - MenuItem {} { - label Pipe - xywh {100 100 100 20} labelfont 1 labelsize 11 - } - MenuItem {} { - label {Synth Lead} - xywh {110 110 100 20} labelfont 1 labelsize 11 - } - MenuItem {} { - label {Synth Pad} - xywh {120 120 100 20} labelfont 1 labelsize 11 - } - MenuItem {} { - label {Synth Effects} - xywh {130 130 100 20} labelfont 1 labelsize 11 - } - MenuItem {} { - label Ethnic - xywh {140 140 100 20} labelfont 1 labelsize 11 - } - MenuItem {} { - label Percussive - xywh {150 150 100 20} labelfont 1 labelsize 11 - } - MenuItem {} { - label {Sound Effects} - xywh {160 160 100 20} labelfont 1 labelsize 11 - } - } - } - Fl_Button {} { - label Close - callback {instrumenteditwindow->hide();} - xywh {150 335 95 25} box THIN_UP_BOX - } - } - } - Function {PartUI(int x,int y, int w, int h, const char *label=0):Fl_Group(x,y,w,h,label)} {} { - code {part=NULL; -adnoteui=NULL; -subnoteui=NULL; -padnoteui=NULL; -lastkititem=-1;} {} - } - Function {init(Part *part_,Master *master_,int npart_,BankUI *bankui_)} {} { - code {bankui=bankui_; -part=part_; -npart=npart_; -master=master_; -ninseff=0; - -make_window(); -partgroup->position(this->parent()->x()+2,this->parent()->y()+2); -partgroup->show(); -end(); - - -//if (config.ui.showinstrumentinfo!=0) instrumenteditwindow->show(); - -int klimits[]={1,2,3,4,5,6,7,8,9,10,15,20,30,50,100,0}; - -keylimitlist->add("OFF"); -int k=0; -int val=-1; -char tmp[10]; -while (klimits[k]!=0){ - sprintf(tmp,"%d",klimits[k]); - keylimitlist->add(tmp); - if (val==-1){ - if (klimits[k]>part->Pkeylimit) val=k; - }; - k++; -}; - -if (val==-1) val=k; -keylimitlist->value(val);} {} - } - Function {showparameters(int kititem,int engine)} {} { - code {if (engine==-1){//this is used if I want to clear the engine from the part - if (kititem==lastkititem) kititem=-1; - else kititem=lastkititem; -}; - -if (kititem!=lastkititem){ - if (adnoteui!=NULL) delete (adnoteui); - if (subnoteui!=NULL) delete (subnoteui); - if (padnoteui!=NULL) delete (padnoteui); - adnoteui=NULL;subnoteui=NULL;padnoteui=NULL; - lastkititem=kititem; - - if (kititem>=NUM_KIT_ITEMS) return;//bad kit item - if (kititem<0) return; - - if (part->kit[kititem].adpars!=NULL) - adnoteui=new ADnoteUI(part->kit[kititem].adpars,master); - - if (part->kit[kititem].subpars!=NULL) - subnoteui=new SUBnoteUI(part->kit[kititem].subpars); - - if (part->kit[kititem].padpars!=NULL) - padnoteui=new PADnoteUI(part->kit[kititem].padpars,master); - -}; - - - -if ((engine==0)&&(adnoteui!=NULL)) adnoteui->ADnoteGlobalParameters->show(); -if ((engine==1)&&(subnoteui!=NULL)) subnoteui->SUBparameters->show(); -if ((engine==2)&&(adnoteui!=NULL)) padnoteui->padnotewindow->show();} {} - } - Function {~PartUI()} {} { - code {if (adnoteui!=NULL) delete (adnoteui); -if (subnoteui!=NULL) delete (subnoteui); -if (padnoteui!=NULL) delete (padnoteui); - -partgroup->hide(); -//delete(partgroup); - -ctlwindow->hide(); -delete(ctlwindow); - -partfx->hide(); -delete(partfx); - -instrumentkitlist->hide(); -delete(instrumentkitlist); - -instrumenteditwindow->hide(); -delete(instrumenteditwindow);} {} - } - decl {Part *part;} {} - decl {Master *master;} {} - decl {BankUI *bankui;} {} - decl {ADnoteUI *adnoteui;} {} - decl {SUBnoteUI *subnoteui;} {} - decl {PADnoteUI *padnoteui;} {} - decl {PartSysEffSend *psyef[NUM_SYS_EFX];} {} - decl {int npart;} {} - decl {int ninseff;} {} - decl {int lastkititem;} {} - decl {PartKitItem *partkititem[NUM_KIT_ITEMS];} {} -} diff --git a/plugins/zynaddsubfx/src/UI/PartUI.h b/plugins/zynaddsubfx/src/UI/PartUI.h deleted file mode 100644 index 6e3f1ada9..000000000 --- a/plugins/zynaddsubfx/src/UI/PartUI.h +++ /dev/null @@ -1,338 +0,0 @@ -// generated by Fast Light User Interface Designer (fluid) version 1.0300 - -#ifndef PartUI_h -#define PartUI_h -#include -#include -#include -#include -#include "WidgetPDial.h" -#include "EffUI.h" -#include "BankUI.h" -#include "ADnoteUI.h" -#include "SUBnoteUI.h" -#include "PADnoteUI.h" -#include "../Misc/Config.h" -#include "../Misc/Master.h" -#include "../Misc/Part.h" - -class PartSysEffSend : public Fl_Group { - Fl_Group* make_window(); - Fl_Group *syseffsend; - void cb_01_i(WidgetPDial*, void*); - static void cb_01(WidgetPDial*, void*); -public: - PartSysEffSend(int x,int y, int w, int h, const char *label=0); - void init(Master *master_,int npart_,int neff_); - ~PartSysEffSend(); -private: - Master *master; - int neff; - int npart; -}; - -class PartUI_ { -public: - virtual void showparameters(int kititem,int engine); -}; -#include -#include -#include -#include -#include - -class PartKitItem : public Fl_Group { - Fl_Group* make_window(); - Fl_Group *partkititem; - Fl_Group *partkititemgroup; -public: - Fl_Counter *minkcounter; -private: - void cb_minkcounter_i(Fl_Counter*, void*); - static void cb_minkcounter(Fl_Counter*, void*); - void cb_m_i(Fl_Button*, void*); - static void cb_m(Fl_Button*, void*); - void cb_M_i(Fl_Button*, void*); - static void cb_M(Fl_Button*, void*); - void cb_R_i(Fl_Button*, void*); - static void cb_R(Fl_Button*, void*); -public: - Fl_Button *adeditbutton; -private: - void cb_adeditbutton_i(Fl_Button*, void*); - static void cb_adeditbutton(Fl_Button*, void*); -public: - Fl_Button *subeditbutton; -private: - void cb_subeditbutton_i(Fl_Button*, void*); - static void cb_subeditbutton(Fl_Button*, void*); - Fl_Check_Button *mutedcheck; - void cb_mutedcheck_i(Fl_Check_Button*, void*); - static void cb_mutedcheck(Fl_Check_Button*, void*); -public: - Fl_Counter *maxkcounter; -private: - void cb_maxkcounter_i(Fl_Counter*, void*); - static void cb_maxkcounter(Fl_Counter*, void*); -public: - Fl_Button *labelbutton; -private: - void cb_labelbutton_i(Fl_Button*, void*); - static void cb_labelbutton(Fl_Button*, void*); - Fl_Check_Button *adcheck; - void cb_adcheck_i(Fl_Check_Button*, void*); - static void cb_adcheck(Fl_Check_Button*, void*); - Fl_Check_Button *subcheck; - void cb_subcheck_i(Fl_Check_Button*, void*); - static void cb_subcheck(Fl_Check_Button*, void*); -public: - Fl_Choice *sendtoeffect; -private: - void cb_sendtoeffect_i(Fl_Choice*, void*); - static void cb_sendtoeffect(Fl_Choice*, void*); -public: - Fl_Button *padeditbutton; -private: - void cb_padeditbutton_i(Fl_Button*, void*); - static void cb_padeditbutton(Fl_Button*, void*); - Fl_Check_Button *padcheck; - void cb_padcheck_i(Fl_Check_Button*, void*); - static void cb_padcheck(Fl_Check_Button*, void*); - Fl_Check_Button *enabledcheck; - void cb_enabledcheck_i(Fl_Check_Button*, void*); - static void cb_enabledcheck(Fl_Check_Button*, void*); -public: - PartKitItem(int x,int y, int w, int h, const char *label=0); - void refresh(); - void init(Part *part_,int n_,Master *master_,PartUI_ *partui_); - ~PartKitItem(); -private: - Part *part; - int n; - Master *master; - char label[10]; - PartUI_ *partui; -}; -#include -#include -#include -#include -#include - -class PartUI : public Fl_Group,PartUI_ { - Fl_Group* make_window(); - Fl_Group *partgroup; -public: - Fl_Group *partgroupui; -private: - void cb_Pan_i(WidgetPDial*, void*); - static void cb_Pan(WidgetPDial*, void*); - void cb_KeyShift_i(Fl_Counter*, void*); - static void cb_KeyShift(Fl_Counter*, void*); - void cb_Grand_i(Fl_Button*, void*); - static void cb_Grand(Fl_Button*, void*); - void cb_NoteOn_i(Fl_Check_Button*, void*); - static void cb_NoteOn(Fl_Check_Button*, void*); -public: - Fl_Counter *minkcounter; -private: - void cb_minkcounter1_i(Fl_Counter*, void*); - static void cb_minkcounter1(Fl_Counter*, void*); -public: - Fl_Counter *maxkcounter; -private: - void cb_maxkcounter1_i(Fl_Counter*, void*); - static void cb_maxkcounter1(Fl_Counter*, void*); - void cb_Volume_i(WidgetPDial*, void*); - static void cb_Volume(WidgetPDial*, void*); - void cb_Vel_i(WidgetPDial*, void*); - static void cb_Vel(WidgetPDial*, void*); - void cb_Vel1_i(WidgetPDial*, void*); - static void cb_Vel1(WidgetPDial*, void*); - void cb_Controllers_i(Fl_Button*, void*); - static void cb_Controllers(Fl_Button*, void*); - void cb_Portamento_i(Fl_Check_Button*, void*); - static void cb_Portamento(Fl_Check_Button*, void*); - void cb_Edit_i(Fl_Button*, void*); - static void cb_Edit(Fl_Button*, void*); - void cb_m1_i(Fl_Button*, void*); - static void cb_m1(Fl_Button*, void*); - void cb_M1_i(Fl_Button*, void*); - static void cb_M1(Fl_Button*, void*); - void cb_R1_i(Fl_Button*, void*); - static void cb_R1(Fl_Button*, void*); - void cb_MIDI_i(Fl_Choice*, void*); - static void cb_MIDI(Fl_Choice*, void*); -public: - Fl_Choice *keylimitlist; -private: - void cb_keylimitlist_i(Fl_Choice*, void*); - static void cb_keylimitlist(Fl_Choice*, void*); - void cb_Mode_i(Fl_Choice*, void*); - static void cb_Mode(Fl_Choice*, void*); - void cb_Enabled_i(Fl_Check_Button*, void*); - static void cb_Enabled(Fl_Check_Button*, void*); - Fl_Double_Window *ctlwindow; - void cb_Expr_i(Fl_Check_Button*, void*); - static void cb_Expr(Fl_Check_Button*, void*); - void cb_PanDpth_i(WidgetPDial*, void*); - static void cb_PanDpth(WidgetPDial*, void*); - void cb_FltCut_i(WidgetPDial*, void*); - static void cb_FltCut(WidgetPDial*, void*); - void cb_FltQ_i(WidgetPDial*, void*); - static void cb_FltQ(WidgetPDial*, void*); - void cb_BwDpth_i(WidgetPDial*, void*); - static void cb_BwDpth(WidgetPDial*, void*); - void cb_ModWh_i(WidgetPDial*, void*); - static void cb_ModWh(WidgetPDial*, void*); - void cb_PWheelB_i(Fl_Counter*, void*); - static void cb_PWheelB(Fl_Counter*, void*); - void cb_FMamp_i(Fl_Check_Button*, void*); - static void cb_FMamp(Fl_Check_Button*, void*); - void cb_Vol_i(Fl_Check_Button*, void*); - static void cb_Vol(Fl_Check_Button*, void*); - void cb_Sustain_i(Fl_Check_Button*, void*); - static void cb_Sustain(Fl_Check_Button*, void*); - void cb_Close_i(Fl_Button*, void*); - static void cb_Close(Fl_Button*, void*); - void cb_Reset_i(Fl_Button*, void*); - static void cb_Reset(Fl_Button*, void*); - void cb_Rcv_i(Fl_Check_Button*, void*); - static void cb_Rcv(Fl_Check_Button*, void*); - void cb_time_i(WidgetPDial*, void*); - static void cb_time(WidgetPDial*, void*); - void cb_thresh_i(Fl_Counter*, void*); - static void cb_thresh(Fl_Counter*, void*); - void cb_th_i(Fl_Check_Button*, void*); - static void cb_th(Fl_Check_Button*, void*); - void cb_t_i(WidgetPDial*, void*); - static void cb_t(WidgetPDial*, void*); -public: - WidgetPDial *propta; -private: - void cb_propta_i(WidgetPDial*, void*); - static void cb_propta(WidgetPDial*, void*); -public: - WidgetPDial *proptb; -private: - void cb_proptb_i(WidgetPDial*, void*); - static void cb_proptb(WidgetPDial*, void*); - void cb_Proprt_i(Fl_Check_Button*, void*); - static void cb_Proprt(Fl_Check_Button*, void*); - void cb_BWdpth_i(WidgetPDial*, void*); - static void cb_BWdpth(WidgetPDial*, void*); - void cb_CFdpth_i(WidgetPDial*, void*); - static void cb_CFdpth(WidgetPDial*, void*); - void cb_Exp_i(Fl_Check_Button*, void*); - static void cb_Exp(Fl_Check_Button*, void*); - void cb_Exp1_i(Fl_Check_Button*, void*); - static void cb_Exp1(Fl_Check_Button*, void*); - Fl_Double_Window *partfx; -public: - Fl_Counter *inseffnocounter; -private: - void cb_inseffnocounter_i(Fl_Counter*, void*); - static void cb_inseffnocounter(Fl_Counter*, void*); -public: - Fl_Choice *insefftype; -private: - void cb_insefftype_i(Fl_Choice*, void*); - static void cb_insefftype(Fl_Choice*, void*); - static Fl_Menu_Item menu_insefftype[]; -public: - Fl_Group *inseffectuigroup; - EffUI *inseffectui; -private: - void cb_Close1_i(Fl_Button*, void*); - static void cb_Close1(Fl_Button*, void*); -public: - Fl_Choice *sendtochoice; -private: - void cb_sendtochoice_i(Fl_Choice*, void*); - static void cb_sendtochoice(Fl_Choice*, void*); - static Fl_Menu_Item menu_sendtochoice[]; -public: - Fl_Check_Button *bypasseff; -private: - void cb_bypasseff_i(Fl_Check_Button*, void*); - static void cb_bypasseff(Fl_Check_Button*, void*); - void cb_C_i(Fl_Button*, void*); - static void cb_C(Fl_Button*, void*); - void cb_P_i(Fl_Button*, void*); - static void cb_P(Fl_Button*, void*); -public: - Fl_Double_Window *instrumentkitlist; -private: - void cb_Close2_i(Fl_Button*, void*); - static void cb_Close2(Fl_Button*, void*); -public: - Fl_Scroll *kitlist; -private: - void cb_Mode1_i(Fl_Choice*, void*); - static void cb_Mode1(Fl_Choice*, void*); - static Fl_Menu_Item menu_Mode[]; - void cb_Drum_i(Fl_Check_Button*, void*); - static void cb_Drum(Fl_Check_Button*, void*); -public: - Fl_Double_Window *instrumenteditwindow; - Fl_Button *padeditbutton; -private: - void cb_padeditbutton1_i(Fl_Button*, void*); - static void cb_padeditbutton1(Fl_Button*, void*); -public: - Fl_Check_Button *padsynenabledcheck; -private: - void cb_padsynenabledcheck_i(Fl_Check_Button*, void*); - static void cb_padsynenabledcheck(Fl_Check_Button*, void*); -public: - Fl_Check_Button *adsynenabledcheck; -private: - void cb_adsynenabledcheck_i(Fl_Check_Button*, void*); - static void cb_adsynenabledcheck(Fl_Check_Button*, void*); -public: - Fl_Button *adeditbutton; -private: - void cb_adeditbutton1_i(Fl_Button*, void*); - static void cb_adeditbutton1(Fl_Button*, void*); -public: - Fl_Check_Button *subsynenabledcheck; -private: - void cb_subsynenabledcheck_i(Fl_Check_Button*, void*); - static void cb_subsynenabledcheck(Fl_Check_Button*, void*); -public: - Fl_Button *subeditbutton; -private: - void cb_subeditbutton1_i(Fl_Button*, void*); - static void cb_subeditbutton1(Fl_Button*, void*); - void cb_Kit_i(Fl_Button*, void*); - static void cb_Kit(Fl_Button*, void*); - void cb_Effects_i(Fl_Button*, void*); - static void cb_Effects(Fl_Button*, void*); - void cb_Author_i(Fl_Input*, void*); - static void cb_Author(Fl_Input*, void*); - void cb_Comments_i(Fl_Input*, void*); - static void cb_Comments(Fl_Input*, void*); - void cb_Type_i(Fl_Choice*, void*); - static void cb_Type(Fl_Choice*, void*); - static Fl_Menu_Item menu_Type[]; - void cb_Close3_i(Fl_Button*, void*); - static void cb_Close3(Fl_Button*, void*); -public: - PartUI(int x,int y, int w, int h, const char *label=0); - void init(Part *part_,Master *master_,int npart_,BankUI *bankui_); - void showparameters(int kititem,int engine); - ~PartUI(); -private: - Part *part; - Master *master; - BankUI *bankui; - ADnoteUI *adnoteui; - SUBnoteUI *subnoteui; - PADnoteUI *padnoteui; - PartSysEffSend *psyef[NUM_SYS_EFX]; - int npart; - int ninseff; - int lastkititem; - PartKitItem *partkititem[NUM_KIT_ITEMS]; -}; -#endif diff --git a/plugins/zynaddsubfx/src/UI/PresetsUI.cc b/plugins/zynaddsubfx/src/UI/PresetsUI.cc deleted file mode 100644 index 56be5f4a1..000000000 --- a/plugins/zynaddsubfx/src/UI/PresetsUI.cc +++ /dev/null @@ -1,274 +0,0 @@ -// generated by Fast Light User Interface Designer (fluid) version 1.0300 - -#include "PresetsUI.h" -#include "../Params/PresetsArray.h" - -void PresetsUI_::refresh() { - ; -} - -PresetsUI_::~PresetsUI_() { - ; -} - -void PresetsUI::cb_copybrowse_i(Fl_Browser* o, void*) { - int val=o->value(); -if (val!=0){ - presetname->cut(0,presetname->maximum_size()); - presetname->insert(o->text(val)); -}; -} -void PresetsUI::cb_copybrowse(Fl_Browser* o, void* v) { - ((PresetsUI*)(o->parent()->user_data()))->cb_copybrowse_i(o,v); -} - -void PresetsUI::cb_copypbutton_i(Fl_Button*, void*) { - const char *tmp=presetname->value(); -if (tmp!=NULL) { - if (strlen(tmp)>0){ - p->copy(tmp); - copywin->hide(); - }; -}; -} -void PresetsUI::cb_copypbutton(Fl_Button* o, void* v) { - ((PresetsUI*)(o->parent()->user_data()))->cb_copypbutton_i(o,v); -} - -void PresetsUI::cb_copybutton_i(Fl_Button*, void*) { - p->copy(NULL); -copywin->hide(); -} -void PresetsUI::cb_copybutton(Fl_Button* o, void* v) { - ((PresetsUI*)(o->parent()->user_data()))->cb_copybutton_i(o,v); -} - -void PresetsUI::cb_Cancel_i(Fl_Button*, void*) { - copywin->hide(); -} -void PresetsUI::cb_Cancel(Fl_Button* o, void* v) { - ((PresetsUI*)(o->parent()->user_data()))->cb_Cancel_i(o,v); -} - -void PresetsUI::cb_presetname_i(Fl_Input* o, void*) { - const char *tmp=o->value(); -if (tmp==NULL) tmp=""; -if (strlen(tmp)>0) { - copybutton->deactivate(); - copypbutton->activate(); -} else { - copybutton->activate(); - copypbutton->deactivate(); -}; -} -void PresetsUI::cb_presetname(Fl_Input* o, void* v) { - ((PresetsUI*)(o->parent()->user_data()))->cb_presetname_i(o,v); -} - -void PresetsUI::cb_pastebrowse_i(Fl_Browser* o, void*) { - if (o->value()==0) { - pastepbutton->deactivate(); - deletepbutton->deactivate(); -}else{ - pastepbutton->activate(); - deletepbutton->activate(); -}; -} -void PresetsUI::cb_pastebrowse(Fl_Browser* o, void* v) { - ((PresetsUI*)(o->parent()->user_data()))->cb_pastebrowse_i(o,v); -} - -void PresetsUI::cb_pastepbutton_i(Fl_Button*, void*) { - int n=pastebrowse->value(); -if (n!=0) p->paste(n); -pastewin->hide(); -pui->refresh(); -} -void PresetsUI::cb_pastepbutton(Fl_Button* o, void* v) { - ((PresetsUI*)(o->parent()->user_data()))->cb_pastepbutton_i(o,v); -} - -void PresetsUI::cb_pastebutton_i(Fl_Button*, void*) { - p->paste(0); -pastewin->hide(); -pui->refresh(); -} -void PresetsUI::cb_pastebutton(Fl_Button* o, void* v) { - ((PresetsUI*)(o->parent()->user_data()))->cb_pastebutton_i(o,v); -} - -void PresetsUI::cb_Cancel1_i(Fl_Button*, void*) { - pastewin->hide(); -} -void PresetsUI::cb_Cancel1(Fl_Button* o, void* v) { - ((PresetsUI*)(o->parent()->user_data()))->cb_Cancel1_i(o,v); -} - -void PresetsUI::cb_deletepbutton_i(Fl_Button*, void*) { - int n=pastebrowse->value(); -if (n!=0) p->deletepreset(n); -rescan(); -} -void PresetsUI::cb_deletepbutton(Fl_Button* o, void* v) { - ((PresetsUI*)(o->parent()->user_data()))->cb_deletepbutton_i(o,v); -} - -PresetsUI::PresetsUI() { - p=NULL; - make_window(); -} - -PresetsUI::~PresetsUI() { - copywin->hide();delete(copywin); - pastewin->hide();delete(pastewin); -} - -Fl_Double_Window* PresetsUI::make_window() { - { copywin = new Fl_Double_Window(265, 430, "Copy to Clipboard/Preset"); - copywin->box(FL_PLASTIC_THIN_UP_BOX); - copywin->color((Fl_Color)238); - copywin->user_data((void*)(this)); - { copybrowse = new Fl_Browser(10, 25, 245, 320); - copybrowse->type(1); - copybrowse->callback((Fl_Callback*)cb_copybrowse); - } // Fl_Browser* copybrowse - { copypbutton = new Fl_Button(145, 355, 110, 20, "Copy to Preset"); - copypbutton->box(FL_THIN_UP_BOX); - copypbutton->callback((Fl_Callback*)cb_copypbutton); - } // Fl_Button* copypbutton - { copybutton = new Fl_Button(25, 385, 90, 35, "Copy to Clipboard"); - copybutton->box(FL_THIN_UP_BOX); - copybutton->callback((Fl_Callback*)cb_copybutton); - copybutton->align(Fl_Align(192)); - } // Fl_Button* copybutton - { Fl_Button* o = new Fl_Button(160, 385, 80, 35, "Cancel"); - o->box(FL_THIN_UP_BOX); - o->callback((Fl_Callback*)cb_Cancel); - o->align(Fl_Align(192)); - } // Fl_Button* o - { Fl_Box* o = new Fl_Box(10, 5, 40, 15, "Type:"); - o->labelsize(11); - o->align(Fl_Align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE)); - } // Fl_Box* o - { copytypetext = new Fl_Box(50, 5, 205, 15); - copytypetext->box(FL_FLAT_BOX); - copytypetext->color((Fl_Color)238); - copytypetext->labelfont(1); - copytypetext->labelsize(11); - copytypetext->align(Fl_Align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE)); - } // Fl_Box* copytypetext - { presetname = new Fl_Input(10, 355, 130, 20); - presetname->callback((Fl_Callback*)cb_presetname); - presetname->when(FL_WHEN_CHANGED); - } // Fl_Input* presetname - copywin->set_modal(); - copywin->end(); - } // Fl_Double_Window* copywin - { pastewin = new Fl_Double_Window(265, 430, "Paste from Clipboard/Preset"); - pastewin->box(FL_PLASTIC_THIN_UP_BOX); - pastewin->color((Fl_Color)238); - pastewin->user_data((void*)(this)); - { pastebrowse = new Fl_Browser(10, 25, 245, 320); - pastebrowse->type(2); - pastebrowse->callback((Fl_Callback*)cb_pastebrowse); - } // Fl_Browser* pastebrowse - { pastepbutton = new Fl_Button(10, 355, 160, 20, "Paste from Preset"); - pastepbutton->box(FL_THIN_UP_BOX); - pastepbutton->callback((Fl_Callback*)cb_pastepbutton); - } // Fl_Button* pastepbutton - { pastebutton = new Fl_Button(25, 385, 90, 35, "Paste from Clipboard"); - pastebutton->box(FL_THIN_UP_BOX); - pastebutton->callback((Fl_Callback*)cb_pastebutton); - pastebutton->align(Fl_Align(192)); - } // Fl_Button* pastebutton - { Fl_Button* o = new Fl_Button(160, 385, 80, 35, "Cancel"); - o->box(FL_THIN_UP_BOX); - o->callback((Fl_Callback*)cb_Cancel1); - o->align(Fl_Align(192)); - } // Fl_Button* o - { pastetypetext = new Fl_Box(55, 5, 200, 15); - pastetypetext->box(FL_FLAT_BOX); - pastetypetext->color((Fl_Color)238); - pastetypetext->labelfont(1); - pastetypetext->labelsize(11); - pastetypetext->align(Fl_Align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE)); - } // Fl_Box* pastetypetext - { Fl_Box* o = new Fl_Box(15, 5, 40, 15, "Type:"); - o->labelsize(11); - o->align(Fl_Align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE)); - } // Fl_Box* o - { deletepbutton = new Fl_Button(180, 355, 75, 20, "Delete"); - deletepbutton->box(FL_THIN_UP_BOX); - deletepbutton->callback((Fl_Callback*)cb_deletepbutton); - } // Fl_Button* deletepbutton - pastewin->set_modal(); - pastewin->end(); - } // Fl_Double_Window* pastewin - return pastewin; -} - -void PresetsUI::copy(Presets *p) { - copybutton->activate(); - copypbutton->deactivate(); - - - this->p=p; - this->pui=NULL; - bool but=(Fl::event_button()!=FL_LEFT_MOUSE); - presetname->cut(0,presetname->maximum_size()); - - if (but) p->copy(NULL); - else { - rescan(); - copytypetext->label(&p->type[1]); - copywin->show(); - }; -} - -void PresetsUI::paste(Presets *p,PresetsUI_ *pui) { - this->p=p; - this->pui=pui; - bool but=(Fl::event_button()!=FL_LEFT_MOUSE); - pastepbutton->deactivate(); - deletepbutton->deactivate(); - - if (but) { - p->paste(0); - pui->refresh(); - } else { - rescan(); - pastetypetext->label(&p->type[1]); - if (p->checkclipboardtype()) pastebutton->activate(); - else pastebutton->deactivate(); - pastewin->show(); - }; -} - -void PresetsUI::copy(Presets *p,int n) { - PresetsArray *pre = dynamic_cast(p); - if(pre) - pre->setelement(n); - copy(p); -} - -void PresetsUI::paste(Presets *p,PresetsUI_ *pui,int n) { - PresetsArray *pre = dynamic_cast(p); - if(pre) - pre->setelement(n); - paste(p,pui); -} - -void PresetsUI::rescan() { - copybrowse->clear(); - pastebrowse->clear(); - p->rescanforpresets(); - - for (unsigned int i=0;iadd(name.c_str()); - pastebrowse->add(name.c_str()); - }; -} -PresetsUI *presetsui; diff --git a/plugins/zynaddsubfx/src/UI/PresetsUI.fl b/plugins/zynaddsubfx/src/UI/PresetsUI.fl deleted file mode 100644 index adf8da050..000000000 --- a/plugins/zynaddsubfx/src/UI/PresetsUI.fl +++ /dev/null @@ -1,208 +0,0 @@ -# data file for the Fltk User Interface Designer (fluid) -version 1.0107 -header_name {.h} -code_name {.cc} -decl {\#include } {public -} - -decl {\#include } {public -} - -decl {\#include } {public -} - -decl {\#include "../Params/PresetsArray.h"} {} - -decl {\#include "../Params/Presets.h"} {public -} - -class PresetsUI_ {} { - Function {refresh()} {open return_type {virtual void} - } {code{;}} - Function {~PresetsUI_()} {open return_type virtual - } {code{;}} -} - -class PresetsUI {} { - Function {PresetsUI()} {} { - code {p=NULL; -make_window();} {} - } - Function {~PresetsUI()} {} { - code {copywin->hide();delete(copywin); -pastewin->hide();delete(pastewin);} {} - } - Function {make_window()} {} { - Fl_Window copywin { - label {Copy to Clipboard/Preset} - xywh {190 173 265 430} type Double box PLASTIC_THIN_UP_BOX color 238 hide modal - } { - Fl_Browser copybrowse { - callback {int val=o->value(); -if (val!=0){ - presetname->cut(0,presetname->maximum_size()); - presetname->insert(o->text(val)); -};} - xywh {10 25 245 320} type Select - } - Fl_Button copypbutton { - label {Copy to Preset} - callback {const char *tmp=presetname->value(); -if (tmp!=NULL) { - if (strlen(tmp)>0){ - p->copy(tmp); - copywin->hide(); - }; -};} - xywh {145 355 110 20} box THIN_UP_BOX - } - Fl_Button copybutton { - label {Copy to Clipboard} - callback {p->copy(NULL); -copywin->hide();} - xywh {25 385 90 35} box THIN_UP_BOX align 192 - } - Fl_Button {} { - label Cancel - callback {copywin->hide();} - xywh {160 385 80 35} box THIN_UP_BOX align 192 - } - Fl_Box {} { - label {Type:} - xywh {10 5 40 15} labelsize 11 align 20 - } - Fl_Box copytypetext { - xywh {50 5 205 15} box FLAT_BOX color 238 labelfont 1 labelsize 11 align 20 - } - Fl_Input presetname { - callback {const char *tmp=o->value(); -if (tmp==NULL) tmp=""; -if (strlen(tmp)>0) { - copybutton->deactivate(); - copypbutton->activate(); -} else { - copybutton->activate(); - copypbutton->deactivate(); -};} - xywh {10 355 130 20} when 1 - } - } - Fl_Window pastewin { - label {Paste from Clipboard/Preset} - xywh {463 173 265 430} type Double box PLASTIC_THIN_UP_BOX color 238 hide modal - } { - Fl_Browser pastebrowse { - callback {if (o->value()==0) { - pastepbutton->deactivate(); - deletepbutton->deactivate(); -}else{ - pastepbutton->activate(); - deletepbutton->activate(); -};} - xywh {10 25 245 320} type Hold - } - Fl_Button pastepbutton { - label {Paste from Preset} - callback {int n=pastebrowse->value(); -if (n!=0) p->paste(n); -pastewin->hide(); -pui->refresh();} - xywh {10 355 160 20} box THIN_UP_BOX - } - Fl_Button pastebutton { - label {Paste from Clipboard} - callback {p->paste(0); -pastewin->hide(); -pui->refresh();} - xywh {25 385 90 35} box THIN_UP_BOX align 192 - } - Fl_Button {} { - label Cancel - callback {pastewin->hide();} - xywh {160 385 80 35} box THIN_UP_BOX align 192 - } - Fl_Box pastetypetext { - xywh {55 5 200 15} box FLAT_BOX color 238 labelfont 1 labelsize 11 align 20 - } - Fl_Box {} { - label {Type:} - xywh {15 5 40 15} labelsize 11 align 20 - } - Fl_Button deletepbutton { - label Delete - callback {int n=pastebrowse->value(); -if (n!=0) p->deletepreset(n); -rescan();} - xywh {180 355 75 20} box THIN_UP_BOX - } - } - } - Function {copy(Presets *p)} {} { - code {copybutton->activate(); -copypbutton->deactivate(); - - -this->p=p; -this->pui=NULL; -bool but=(Fl::event_button()!=FL_LEFT_MOUSE); -presetname->cut(0,presetname->maximum_size()); - -if (but) p->copy(NULL); - else { - rescan(); - copytypetext->label(&p->type[1]); - copywin->show(); - };} {} - } - Function {paste(Presets *p,PresetsUI_ *pui)} {} { - code {this->p=p; -this->pui=pui; -bool but=(Fl::event_button()!=FL_LEFT_MOUSE); -pastepbutton->deactivate(); -deletepbutton->deactivate(); - -if (but) { - p->paste(0); - pui->refresh(); -} else { - rescan(); - pastetypetext->label(&p->type[1]); - if (p->checkclipboardtype()) pastebutton->activate(); - else pastebutton->deactivate(); - pastewin->show(); - };} {} - } - Function {copy(Presets *p,int n)} {} { - code {PresetsArray *pre = dynamic_cast(p); -if(pre) - pre->setelement(n); -copy(p);} {} - } - Function {paste(Presets *p,PresetsUI_ *pui,int n)} {} { - code {PresetsArray *pre = dynamic_cast(p); -if(pre) - pre->setelement(n); -paste(p,pui);} {} - } - Function {rescan()} {} { - code {copybrowse->clear(); -pastebrowse->clear(); -p->rescanforpresets(); - -for (int i=0;iadd(name.c_str()); - pastebrowse->add(name.c_str()); -};} {selected - } - } - decl {Presets *p;} {public - } - decl {PresetsUI_ *pui;} {public - } -} - -decl {PresetsUI *presetsui;} {public -} diff --git a/plugins/zynaddsubfx/src/UI/PresetsUI.h b/plugins/zynaddsubfx/src/UI/PresetsUI.h deleted file mode 100644 index 4adf0f1c0..000000000 --- a/plugins/zynaddsubfx/src/UI/PresetsUI.h +++ /dev/null @@ -1,84 +0,0 @@ -// generated by Fast Light User Interface Designer (fluid) version 1.0300 - -#ifndef PresetsUI_h -#define PresetsUI_h -#include -#include -#include -#include -#include "../Params/Presets.h" - -class PresetsUI_ { -public: - virtual void refresh(); - virtual ~PresetsUI_(); -}; -#include -#include -#include -#include -#include - -class PresetsUI { -public: - PresetsUI(); - ~PresetsUI(); - Fl_Double_Window* make_window(); - Fl_Double_Window *copywin; - Fl_Browser *copybrowse; -private: - void cb_copybrowse_i(Fl_Browser*, void*); - static void cb_copybrowse(Fl_Browser*, void*); -public: - Fl_Button *copypbutton; -private: - void cb_copypbutton_i(Fl_Button*, void*); - static void cb_copypbutton(Fl_Button*, void*); -public: - Fl_Button *copybutton; -private: - void cb_copybutton_i(Fl_Button*, void*); - static void cb_copybutton(Fl_Button*, void*); - void cb_Cancel_i(Fl_Button*, void*); - static void cb_Cancel(Fl_Button*, void*); -public: - Fl_Box *copytypetext; - Fl_Input *presetname; -private: - void cb_presetname_i(Fl_Input*, void*); - static void cb_presetname(Fl_Input*, void*); -public: - Fl_Double_Window *pastewin; - Fl_Browser *pastebrowse; -private: - void cb_pastebrowse_i(Fl_Browser*, void*); - static void cb_pastebrowse(Fl_Browser*, void*); -public: - Fl_Button *pastepbutton; -private: - void cb_pastepbutton_i(Fl_Button*, void*); - static void cb_pastepbutton(Fl_Button*, void*); -public: - Fl_Button *pastebutton; -private: - void cb_pastebutton_i(Fl_Button*, void*); - static void cb_pastebutton(Fl_Button*, void*); - void cb_Cancel1_i(Fl_Button*, void*); - static void cb_Cancel1(Fl_Button*, void*); -public: - Fl_Box *pastetypetext; - Fl_Button *deletepbutton; -private: - void cb_deletepbutton_i(Fl_Button*, void*); - static void cb_deletepbutton(Fl_Button*, void*); -public: - void copy(Presets *p); - void paste(Presets *p,PresetsUI_ *pui); - void copy(Presets *p,int n); - void paste(Presets *p,PresetsUI_ *pui,int n); - void rescan(); - Presets *p; - PresetsUI_ *pui; -}; -extern PresetsUI *presetsui; -#endif diff --git a/plugins/zynaddsubfx/src/UI/ResonanceUI.cc b/plugins/zynaddsubfx/src/UI/ResonanceUI.cc deleted file mode 100644 index 3481134d9..000000000 --- a/plugins/zynaddsubfx/src/UI/ResonanceUI.cc +++ /dev/null @@ -1,553 +0,0 @@ -// generated by Fast Light User Interface Designer (fluid) version 1.0300 - -#include "ResonanceUI.h" -//Copyright (c) 2002-2005 Nasca Octavian Paul -//License: GNU GPL version 2 or later -#include -#include -#include -#include - -ResonanceGraph::ResonanceGraph(int x,int y, int w, int h, const char *label):Fl_Box(x,y,w,h,label) { - respar=NULL; - cbwidget=NULL; - applybutton=NULL; -} - -void ResonanceGraph::init(Resonance *respar_,Fl_Value_Output *khzvalue_,Fl_Value_Output *dbvalue_) { - respar=respar_; - khzvalue=khzvalue_; - dbvalue=dbvalue_; - oldx=-1; - khzval=-1; -} - -void ResonanceGraph::draw_freq_line(REALTYPE freq,int type) { - REALTYPE freqx=respar->getfreqpos(freq); - switch(type){ - case 0:fl_line_style(FL_SOLID);break; - case 1:fl_line_style(FL_DOT);break; - case 2:fl_line_style(FL_DASH);break; - }; - - - if ((freqx>0.0)&&(freqx<1.0)) - fl_line(x()+(int) (freqx*w()),y(), - x()+(int) (freqx*w()),y()+h()); -} - -void ResonanceGraph::draw() { - int ox=x(),oy=y(),lx=w(),ly=h(),i,ix,iy,oiy; - REALTYPE freqx; - - fl_color(FL_BLACK); - fl_rectf(ox,oy,lx,ly); - - - //draw the lines - fl_color(FL_GRAY); - - fl_line_style(FL_SOLID); - fl_line(ox+2,oy+ly/2,ox+lx-2,oy+ly/2); - - freqx=respar->getfreqpos(1000.0); - if ((freqx>0.0)&&(freqx<1.0)) - fl_line(ox+(int) (freqx*lx),oy, - ox+(int) (freqx*lx),oy+ly); - - for (i=1;i<10;i++){ - if(i==1){ - draw_freq_line(i*100.0,0); - draw_freq_line(i*1000.0,0); - }else - if (i==5){ - draw_freq_line(i*100.0,2); - draw_freq_line(i*1000.0,2); - }else{ - draw_freq_line(i*100.0,1); - draw_freq_line(i*1000.0,1); - }; - }; - - draw_freq_line(10000.0,0); - draw_freq_line(20000.0,1); - - fl_line_style(FL_DOT); - int GY=10;if (lyPrespoints[0]/128.0*ly); - for (i=1;iPrespoints[i]/128.0*ly); - fl_line(ox+ix-1,oy+ly-oiy,ox+ix,oy+ly-iy); - oiy=iy; - }; -} - -int ResonanceGraph::handle(int event) { - int x_=Fl::event_x()-x(); - int y_=Fl::event_y()-y(); - if ( (x_>=0)&&(x_=0)&&(y_value(respar->getfreqx(x_*1.0/w())/1000.0); - dbvalue->value((1.0-y_*2.0/h())*respar->PmaxdB); - }; - - if ((event==FL_PUSH)||(event==FL_DRAG)){ - int leftbutton=1; - if (Fl::event_button()==FL_RIGHT_MOUSE) leftbutton=0; - if (x_<0) x_=0;if (y_<0) y_=0; - if (x_>=w()) x_=w();if (y_>=h()-1) y_=h()-1; - - if ((oldx<0)||(oldx==x_)){ - int sn=(int)(x_*1.0/w()*N_RES_POINTS); - int sp=127-(int)(y_*1.0/h()*127); - if (leftbutton!=0) respar->setpoint(sn,sp); - else respar->setpoint(sn,64); - } else { - int x1=oldx; - int x2=x_; - int y1=oldy; - int y2=y_; - if (oldx>x_){ - x1=x_;y1=y_; - x2=oldx;y2=oldy; - }; - for (int i=0;isetpoint(sn,sp); - else respar->setpoint(sn,64); - }; - }; - - oldx=x_;oldy=y_; - redraw(); - }; - - if (event==FL_RELEASE) { - oldx=-1; - if (cbwidget!=NULL) { - cbwidget->do_callback(); - if (applybutton!=NULL) { - applybutton->color(FL_RED); - applybutton->redraw(); - - }; - }; - }; - - return(1); -} - -void ResonanceGraph::setcbwidget(Fl_Widget *cbwidget,Fl_Widget *applybutton) { - this->cbwidget=cbwidget; - this->applybutton=applybutton; -} - -void ResonanceUI::cb_Close_i(Fl_Button*, void*) { - resonancewindow->hide(); -} -void ResonanceUI::cb_Close(Fl_Button* o, void* v) { - ((ResonanceUI*)(o->parent()->user_data()))->cb_Close_i(o,v); -} - -void ResonanceUI::cb_Zero_i(Fl_Button*, void*) { - for (int i=0;isetpoint(i,64); -resonancewindow->redraw(); -redrawPADnoteApply(); -} -void ResonanceUI::cb_Zero(Fl_Button* o, void* v) { - ((ResonanceUI*)(o->parent()->user_data()))->cb_Zero_i(o,v); -} - -void ResonanceUI::cb_Smooth_i(Fl_Button*, void*) { - respar->smooth(); -resonancewindow->redraw(); -redrawPADnoteApply(); -} -void ResonanceUI::cb_Smooth(Fl_Button* o, void* v) { - ((ResonanceUI*)(o->parent()->user_data()))->cb_Smooth_i(o,v); -} - -void ResonanceUI::cb_enabled_i(Fl_Check_Button* o, void*) { - respar->Penabled=(int) o->value(); -redrawPADnoteApply(); -} -void ResonanceUI::cb_enabled(Fl_Check_Button* o, void* v) { - ((ResonanceUI*)(o->parent()->user_data()))->cb_enabled_i(o,v); -} - -void ResonanceUI::cb_maxdb_i(Fl_Roller* o, void*) { - maxdbvo->value(o->value()); -respar->PmaxdB=(int) o->value(); -redrawPADnoteApply(); -} -void ResonanceUI::cb_maxdb(Fl_Roller* o, void* v) { - ((ResonanceUI*)(o->parent()->user_data()))->cb_maxdb_i(o,v); -} - -void ResonanceUI::cb_maxdbvo_i(Fl_Value_Output* o, void*) { - o->value(respar->PmaxdB); -} -void ResonanceUI::cb_maxdbvo(Fl_Value_Output* o, void* v) { - ((ResonanceUI*)(o->parent()->user_data()))->cb_maxdbvo_i(o,v); -} - -void ResonanceUI::cb_centerfreqvo_i(Fl_Value_Output* o, void*) { - o->value(respar->getcenterfreq()/1000.0); -} -void ResonanceUI::cb_centerfreqvo(Fl_Value_Output* o, void* v) { - ((ResonanceUI*)(o->parent()->user_data()))->cb_centerfreqvo_i(o,v); -} - -void ResonanceUI::cb_octavesfreqvo_i(Fl_Value_Output* o, void*) { - o->value(respar->getoctavesfreq()); -} -void ResonanceUI::cb_octavesfreqvo(Fl_Value_Output* o, void* v) { - ((ResonanceUI*)(o->parent()->user_data()))->cb_octavesfreqvo_i(o,v); -} - -void ResonanceUI::cb_RND2_i(Fl_Button*, void*) { - respar->randomize(1); -resonancewindow->redraw(); -redrawPADnoteApply(); -} -void ResonanceUI::cb_RND2(Fl_Button* o, void* v) { - ((ResonanceUI*)(o->parent()->user_data()))->cb_RND2_i(o,v); -} - -void ResonanceUI::cb_RND1_i(Fl_Button*, void*) { - respar->randomize(0); -resonancewindow->redraw(); -redrawPADnoteApply(); -} -void ResonanceUI::cb_RND1(Fl_Button* o, void* v) { - ((ResonanceUI*)(o->parent()->user_data()))->cb_RND1_i(o,v); -} - -void ResonanceUI::cb_RND3_i(Fl_Button*, void*) { - respar->randomize(2); -resonancewindow->redraw(); -redrawPADnoteApply(); -} -void ResonanceUI::cb_RND3(Fl_Button* o, void* v) { - ((ResonanceUI*)(o->parent()->user_data()))->cb_RND3_i(o,v); -} - -void ResonanceUI::cb_p1st_i(Fl_Check_Button* o, void*) { - respar->Pprotectthefundamental=(int) o->value(); -redrawPADnoteApply(); -} -void ResonanceUI::cb_p1st(Fl_Check_Button* o, void* v) { - ((ResonanceUI*)(o->parent()->user_data()))->cb_p1st_i(o,v); -} - -void ResonanceUI::cb_InterpP_i(Fl_Button*, void*) { - int type; -if (Fl::event_button()==FL_LEFT_MOUSE) type=0; - else type=1; -respar->interpolatepeaks(type); -resonancewindow->redraw(); -redrawPADnoteApply(); -} -void ResonanceUI::cb_InterpP(Fl_Button* o, void* v) { - ((ResonanceUI*)(o->parent()->user_data()))->cb_InterpP_i(o,v); -} - -void ResonanceUI::cb_centerfreq_i(WidgetPDial* o, void*) { - respar->Pcenterfreq=(int)o->value(); -centerfreqvo->do_callback(); -rg->redraw(); -redrawPADnoteApply(); -} -void ResonanceUI::cb_centerfreq(WidgetPDial* o, void* v) { - ((ResonanceUI*)(o->parent()->user_data()))->cb_centerfreq_i(o,v); -} - -void ResonanceUI::cb_octavesfreq_i(WidgetPDial* o, void*) { - respar->Poctavesfreq=(int)o->value(); -octavesfreqvo->do_callback(); -rg->redraw(); -redrawPADnoteApply(); -} -void ResonanceUI::cb_octavesfreq(WidgetPDial* o, void* v) { - ((ResonanceUI*)(o->parent()->user_data()))->cb_octavesfreq_i(o,v); -} - -void ResonanceUI::cb_C_i(Fl_Button*, void*) { - presetsui->copy(respar); -} -void ResonanceUI::cb_C(Fl_Button* o, void* v) { - ((ResonanceUI*)(o->parent()->user_data()))->cb_C_i(o,v); -} - -void ResonanceUI::cb_P_i(Fl_Button*, void*) { - presetsui->paste(respar,this); -} -void ResonanceUI::cb_P(Fl_Button* o, void* v) { - ((ResonanceUI*)(o->parent()->user_data()))->cb_P_i(o,v); -} - -void ResonanceUI::cb_applybutton_i(Fl_Button*, void*) { - applybutton->color(FL_GRAY); -applybutton->redraw(); -if (cbapplywidget!=NULL) { - cbapplywidget->do_callback(); - cbapplywidget->color(FL_GRAY); - cbapplywidget->redraw(); -}; -} -void ResonanceUI::cb_applybutton(Fl_Button* o, void* v) { - ((ResonanceUI*)(o->parent()->user_data()))->cb_applybutton_i(o,v); -} - -Fl_Double_Window* ResonanceUI::make_window() { - { resonancewindow = new Fl_Double_Window(780, 305, "Resonance"); - resonancewindow->user_data((void*)(this)); - { khzvalue = new Fl_Value_Output(415, 264, 45, 18, "kHz"); - khzvalue->labelsize(12); - khzvalue->minimum(0.001); - khzvalue->maximum(48); - khzvalue->step(0.01); - khzvalue->textfont(1); - khzvalue->textsize(12); - khzvalue->align(Fl_Align(FL_ALIGN_RIGHT)); - //this widget must be before the calling widgets - } // Fl_Value_Output* khzvalue - { dbvalue = new Fl_Value_Output(415, 282, 45, 18, "dB"); - dbvalue->labelsize(12); - dbvalue->minimum(-150); - dbvalue->maximum(150); - dbvalue->step(0.1); - dbvalue->textfont(1); - dbvalue->textsize(12); - dbvalue->align(Fl_Align(FL_ALIGN_RIGHT)); - //this widget must be before the calling widgets - } // Fl_Value_Output* dbvalue - { Fl_Group* o = new Fl_Group(6, 5, 768, 256); - o->box(FL_BORDER_BOX); - rg=new ResonanceGraph(o->x(),o->y(),o->w(),o->h(),""); - rg->init(respar,khzvalue,dbvalue); - rg->show(); - o->end(); - } // Fl_Group* o - { Fl_Button* o = new Fl_Button(690, 283, 84, 17, "Close"); - o->box(FL_THIN_UP_BOX); - o->callback((Fl_Callback*)cb_Close); - } // Fl_Button* o - { Fl_Button* o = new Fl_Button(491, 264, 66, 15, "Zero"); - o->tooltip("Clear the resonance function"); - o->box(FL_THIN_UP_BOX); - o->labelfont(1); - o->labelsize(12); - o->callback((Fl_Callback*)cb_Zero); - } // Fl_Button* o - { Fl_Button* o = new Fl_Button(491, 282, 66, 18, "Smooth"); - o->tooltip("Smooth the resonance function"); - o->box(FL_THIN_UP_BOX); - o->labelfont(1); - o->labelsize(12); - o->callback((Fl_Callback*)cb_Smooth); - } // Fl_Button* o - { Fl_Check_Button* o = enabled = new Fl_Check_Button(6, 270, 78, 27, "Enable"); - enabled->box(FL_THIN_UP_BOX); - enabled->down_box(FL_DOWN_BOX); - enabled->callback((Fl_Callback*)cb_enabled); - o->value(respar->Penabled); - } // Fl_Check_Button* enabled - { maxdb = new Fl_Roller(90, 282, 84, 15); - maxdb->type(1); - maxdb->minimum(1); - maxdb->maximum(90); - maxdb->step(1); - maxdb->value(30); - maxdb->callback((Fl_Callback*)cb_maxdb); - } // Fl_Roller* maxdb - { Fl_Value_Output* o = maxdbvo = new Fl_Value_Output(126, 264, 24, 18, "Max."); - maxdbvo->tooltip("The Maximum amplitude (dB)"); - maxdbvo->labelsize(12); - maxdbvo->minimum(1); - maxdbvo->maximum(127); - maxdbvo->step(1); - maxdbvo->value(30); - maxdbvo->textfont(1); - maxdbvo->textsize(12); - maxdbvo->callback((Fl_Callback*)cb_maxdbvo); - o->value(respar->PmaxdB); - } // Fl_Value_Output* maxdbvo - { new Fl_Box(150, 264, 24, 18, "dB"); - } // Fl_Box* o - { Fl_Value_Output* o = centerfreqvo = new Fl_Value_Output(210, 264, 33, 18, "C.f."); - centerfreqvo->tooltip("Center Frequency (kHz)"); - centerfreqvo->labelsize(12); - centerfreqvo->minimum(1); - centerfreqvo->maximum(10); - centerfreqvo->step(0.01); - centerfreqvo->value(1); - centerfreqvo->textfont(1); - centerfreqvo->textsize(12); - centerfreqvo->callback((Fl_Callback*)cb_centerfreqvo); - centerfreqvo->when(3); - o->value(respar->getcenterfreq()/1000.0); - } // Fl_Value_Output* centerfreqvo - { Fl_Value_Output* o = octavesfreqvo = new Fl_Value_Output(210, 282, 33, 18, "Oct."); - octavesfreqvo->tooltip("No. of octaves"); - octavesfreqvo->labelsize(12); - octavesfreqvo->minimum(1); - octavesfreqvo->maximum(127); - octavesfreqvo->step(1); - octavesfreqvo->value(30); - octavesfreqvo->textfont(1); - octavesfreqvo->textsize(12); - octavesfreqvo->callback((Fl_Callback*)cb_octavesfreqvo); - octavesfreqvo->when(3); - o->value(respar->getoctavesfreq()); - } // Fl_Value_Output* octavesfreqvo - { Fl_Button* o = new Fl_Button(566, 276, 42, 12, "RND2"); - o->tooltip("Randomize the resonance function"); - o->box(FL_THIN_UP_BOX); - o->labelfont(1); - o->labelsize(10); - o->callback((Fl_Callback*)cb_RND2); - } // Fl_Button* o - { Fl_Button* o = new Fl_Button(566, 264, 42, 12, "RND1"); - o->tooltip("Randomize the resonance function"); - o->box(FL_THIN_UP_BOX); - o->labelfont(1); - o->labelsize(10); - o->callback((Fl_Callback*)cb_RND1); - } // Fl_Button* o - { Fl_Button* o = new Fl_Button(566, 288, 42, 12, "RND3"); - o->tooltip("Randomize the resonance function"); - o->box(FL_THIN_UP_BOX); - o->labelfont(1); - o->labelsize(10); - o->callback((Fl_Callback*)cb_RND3); - } // Fl_Button* o - { Fl_Check_Button* o = p1st = new Fl_Check_Button(365, 285, 45, 15, "P.1st"); - p1st->tooltip("Protect the fundamental frequency (do not damp the first harmonic)"); - p1st->down_box(FL_DOWN_BOX); - p1st->labelsize(10); - p1st->callback((Fl_Callback*)cb_p1st); - o->value(respar->Pprotectthefundamental); - } // Fl_Check_Button* p1st - { Fl_Button* o = new Fl_Button(365, 265, 46, 15, "InterpP"); - o->tooltip("Interpolate the peaks"); - o->box(FL_THIN_UP_BOX); - o->labelfont(1); - o->labelsize(10); - o->callback((Fl_Callback*)cb_InterpP); - } // Fl_Button* o - { WidgetPDial* o = centerfreq = new WidgetPDial(245, 265, 30, 30, "C.f."); - centerfreq->box(FL_ROUND_UP_BOX); - centerfreq->color(FL_BACKGROUND_COLOR); - centerfreq->selection_color(FL_INACTIVE_COLOR); - centerfreq->labeltype(FL_NORMAL_LABEL); - centerfreq->labelfont(0); - centerfreq->labelsize(10); - centerfreq->labelcolor(FL_FOREGROUND_COLOR); - centerfreq->maximum(127); - centerfreq->step(1); - centerfreq->callback((Fl_Callback*)cb_centerfreq); - centerfreq->align(Fl_Align(FL_ALIGN_BOTTOM)); - centerfreq->when(FL_WHEN_CHANGED); - o->value(respar->Pcenterfreq); - } // WidgetPDial* centerfreq - { WidgetPDial* o = octavesfreq = new WidgetPDial(280, 265, 30, 30, "Oct."); - octavesfreq->box(FL_ROUND_UP_BOX); - octavesfreq->color(FL_BACKGROUND_COLOR); - octavesfreq->selection_color(FL_INACTIVE_COLOR); - octavesfreq->labeltype(FL_NORMAL_LABEL); - octavesfreq->labelfont(0); - octavesfreq->labelsize(10); - octavesfreq->labelcolor(FL_FOREGROUND_COLOR); - octavesfreq->maximum(127); - octavesfreq->step(1); - octavesfreq->callback((Fl_Callback*)cb_octavesfreq); - octavesfreq->align(Fl_Align(FL_ALIGN_BOTTOM)); - octavesfreq->when(FL_WHEN_CHANGED); - o->value(respar->Poctavesfreq); - } // WidgetPDial* octavesfreq - { Fl_Button* o = new Fl_Button(625, 275, 25, 15, "C"); - o->box(FL_THIN_UP_BOX); - o->color((Fl_Color)179); - o->labelfont(1); - o->labelsize(11); - o->labelcolor(FL_BACKGROUND2_COLOR); - o->callback((Fl_Callback*)cb_C); - } // Fl_Button* o - { Fl_Button* o = new Fl_Button(655, 275, 25, 15, "P"); - o->box(FL_THIN_UP_BOX); - o->color((Fl_Color)179); - o->labelfont(1); - o->labelsize(11); - o->labelcolor(FL_BACKGROUND2_COLOR); - o->callback((Fl_Callback*)cb_P); - } // Fl_Button* o - { applybutton = new Fl_Button(690, 265, 85, 15, "Apply"); - applybutton->box(FL_THIN_UP_BOX); - applybutton->labelfont(1); - applybutton->labelsize(11); - applybutton->callback((Fl_Callback*)cb_applybutton); - } // Fl_Button* applybutton - resonancewindow->end(); - } // Fl_Double_Window* resonancewindow - return resonancewindow; -} - -ResonanceUI::ResonanceUI(Resonance *respar_) { - respar=respar_; - cbwidget=NULL; - cbapplywidget=NULL; - make_window(); - applybutton->hide(); -} - -ResonanceUI::~ResonanceUI() { - resonancewindow->hide(); -} - -void ResonanceUI::redrawPADnoteApply() { - if (cbwidget!=NULL) { - cbwidget->do_callback(); - applybutton->color(FL_RED); - applybutton->redraw(); - }; -} - -void ResonanceUI::setcbwidget(Fl_Widget *cbwidget,Fl_Widget *cbapplywidget) { - this->cbwidget=cbwidget; - this->cbapplywidget=cbapplywidget; - rg->setcbwidget(cbwidget,applybutton); - applybutton->show(); -} - -void ResonanceUI::refresh() { - redrawPADnoteApply(); - - enabled->value(respar->Penabled); - - maxdb->value(respar->PmaxdB); - maxdbvo->value(respar->PmaxdB); - - centerfreqvo->value(respar->getcenterfreq()/1000.0); - octavesfreqvo->value(respar->getoctavesfreq()); - - centerfreq->value(respar->Pcenterfreq); - octavesfreq->value(respar->Poctavesfreq); - - p1st->value(respar->Pprotectthefundamental); - - rg->redraw(); -} diff --git a/plugins/zynaddsubfx/src/UI/ResonanceUI.fl b/plugins/zynaddsubfx/src/UI/ResonanceUI.fl deleted file mode 100644 index 3c06c5215..000000000 --- a/plugins/zynaddsubfx/src/UI/ResonanceUI.fl +++ /dev/null @@ -1,392 +0,0 @@ -# data file for the Fltk User Interface Designer (fluid) -version 1.0107 -header_name {.h} -code_name {.cc} -decl {//Copyright (c) 2002-2005 Nasca Octavian Paul} {} - -decl {//License: GNU GPL version 2 or later} {} - -decl {\#include } {public -} - -decl {\#include } {public -} - -decl {\#include } {public -} - -decl {\#include } {} - -decl {\#include } {} - -decl {\#include } {} - -decl {\#include } {} - -decl {\#include "../Synth/Resonance.h"} {public -} - -decl {\#include "WidgetPDial.h"} {public -} - -decl {\#include "PresetsUI.h"} {public -} - -class ResonanceGraph {: {public Fl_Box} -} { - Function {ResonanceGraph(int x,int y, int w, int h, const char *label=0):Fl_Box(x,y,w,h,label)} {} { - code {respar=NULL; -cbwidget=NULL; -applybutton=NULL;} {} - } - Function {init(Resonance *respar_,Fl_Value_Output *khzvalue_,Fl_Value_Output *dbvalue_)} {} { - code {respar=respar_; -khzvalue=khzvalue_; -dbvalue=dbvalue_; -oldx=-1; -khzval=-1;} {} - } - Function {draw_freq_line(REALTYPE freq,int type)} {} { - code {REALTYPE freqx=respar->getfreqpos(freq); -switch(type){ - case 0:fl_line_style(FL_SOLID);break; - case 1:fl_line_style(FL_DOT);break; - case 2:fl_line_style(FL_DASH);break; -}; - - -if ((freqx>0.0)&&(freqx<1.0)) - fl_line(x()+(int) (freqx*w()),y(), - x()+(int) (freqx*w()),y()+h());} {} - } - Function {draw()} {} { - code {int ox=x(),oy=y(),lx=w(),ly=h(),i,ix,iy,oiy; -REALTYPE freqx; - -fl_color(FL_BLACK); -fl_rectf(ox,oy,lx,ly); - - -//draw the lines -fl_color(FL_GRAY); - -fl_line_style(FL_SOLID); -fl_line(ox+2,oy+ly/2,ox+lx-2,oy+ly/2); - -freqx=respar->getfreqpos(1000.0); -if ((freqx>0.0)&&(freqx<1.0)) - fl_line(ox+(int) (freqx*lx),oy, - ox+(int) (freqx*lx),oy+ly); - -for (i=1;i<10;i++){ - if(i==1){ - draw_freq_line(i*100.0,0); - draw_freq_line(i*1000.0,0); - }else - if (i==5){ - draw_freq_line(i*100.0,2); - draw_freq_line(i*1000.0,2); - }else{ - draw_freq_line(i*100.0,1); - draw_freq_line(i*1000.0,1); - }; -}; - -draw_freq_line(10000.0,0); -draw_freq_line(20000.0,1); - -fl_line_style(FL_DOT); -int GY=10;if (lyPrespoints[0]/128.0*ly); -for (i=1;iPrespoints[i]/128.0*ly); - fl_line(ox+ix-1,oy+ly-oiy,ox+ix,oy+ly-iy); - oiy=iy; -};} {} - } - Function {handle(int event)} {return_type int - } { - code {int x_=Fl::event_x()-x(); -int y_=Fl::event_y()-y(); -if ( (x_>=0)&&(x_=0)&&(y_value(respar->getfreqx(x_*1.0/w())/1000.0); - dbvalue->value((1.0-y_*2.0/h())*respar->PmaxdB); -}; - -if ((event==FL_PUSH)||(event==FL_DRAG)){ - int leftbutton=1; - if (Fl::event_button()==FL_RIGHT_MOUSE) leftbutton=0; - if (x_<0) x_=0;if (y_<0) y_=0; - if (x_>=w()) x_=w();if (y_>=h()-1) y_=h()-1; - - if ((oldx<0)||(oldx==x_)){ - int sn=(int)(x_*1.0/w()*N_RES_POINTS); - int sp=127-(int)(y_*1.0/h()*127); - if (leftbutton!=0) respar->setpoint(sn,sp); - else respar->setpoint(sn,64); - } else { - int x1=oldx; - int x2=x_; - int y1=oldy; - int y2=y_; - if (oldx>x_){ - x1=x_;y1=y_; - x2=oldx;y2=oldy; - }; - for (int i=0;isetpoint(sn,sp); - else respar->setpoint(sn,64); - }; - }; - - oldx=x_;oldy=y_; - redraw(); -}; - -if (event==FL_RELEASE) { - oldx=-1; - if (cbwidget!=NULL) { - cbwidget->do_callback(); - if (applybutton!=NULL) { - applybutton->color(FL_RED); - applybutton->redraw(); - - }; - }; -}; - -return(1);} {} - } - Function {setcbwidget(Fl_Widget *cbwidget,Fl_Widget *applybutton)} {} { - code {this->cbwidget=cbwidget; -this->applybutton=applybutton;} {} - } - decl {Fl_Value_Output *khzvalue;} {} - decl {Fl_Value_Output *dbvalue;} {} - decl {Resonance *respar;} {} - decl {int oldx,oldy;} {} - decl {REALTYPE khzval;} {public - } - decl {Fl_Widget *cbwidget,*applybutton;} {} -} - -class ResonanceUI {open : PresetsUI_ -} { - Function {make_window()} {open - } { - Fl_Window resonancewindow { - label Resonance selected - xywh {120 70 780 305} type Double hide - } { - Fl_Value_Output khzvalue { - label kHz - xywh {415 264 45 18} labelsize 12 align 8 minimum 0.001 maximum 48 step 0.01 textfont 1 textsize 12 - code0 {//this widget must be before the calling widgets} - } - Fl_Value_Output dbvalue { - label dB - xywh {415 282 45 18} labelsize 12 align 8 minimum -150 maximum 150 step 0.1 textfont 1 textsize 12 - code0 {//this widget must be before the calling widgets} - } - Fl_Group {} { - xywh {6 5 768 256} box BORDER_BOX - code0 {rg=new ResonanceGraph(o->x(),o->y(),o->w(),o->h(),"");} - code1 {rg->init(respar,khzvalue,dbvalue);} - code2 {rg->show();} - } {} - Fl_Button {} { - label Close - callback {resonancewindow->hide();} - xywh {690 283 84 17} box THIN_UP_BOX - } - Fl_Button {} { - label Zero - callback {for (int i=0;isetpoint(i,64); -resonancewindow->redraw(); -redrawPADnoteApply();} - tooltip {Clear the resonance function} xywh {491 264 66 15} box THIN_UP_BOX labelfont 1 labelsize 12 - } - Fl_Button {} { - label Smooth - callback {respar->smooth(); -resonancewindow->redraw(); -redrawPADnoteApply();} - tooltip {Smooth the resonance function} xywh {491 282 66 18} box THIN_UP_BOX labelfont 1 labelsize 12 - } - Fl_Check_Button enabled { - label Enable - callback {respar->Penabled=(int) o->value(); -redrawPADnoteApply();} - xywh {6 270 78 27} box THIN_UP_BOX down_box DOWN_BOX - code0 {o->value(respar->Penabled);} - } - Fl_Roller maxdb { - callback {maxdbvo->value(o->value()); -respar->PmaxdB=(int) o->value(); -redrawPADnoteApply();} - xywh {90 282 84 15} type Horizontal minimum 1 maximum 90 step 1 value 30 - } - Fl_Value_Output maxdbvo { - label {Max.} - callback {o->value(respar->PmaxdB);} - tooltip {The Maximum amplitude (dB)} xywh {126 264 24 18} labelsize 12 minimum 1 maximum 127 step 1 value 30 textfont 1 textsize 12 - code0 {o->value(respar->PmaxdB);} - } - Fl_Box {} { - label dB - xywh {150 264 24 18} - } - Fl_Value_Output centerfreqvo { - label {C.f.} - callback {o->value(respar->getcenterfreq()/1000.0);} - tooltip {Center Frequency (kHz)} xywh {210 264 33 18} labelsize 12 when 3 minimum 1 maximum 10 step 0.01 value 1 textfont 1 textsize 12 - code0 {o->value(respar->getcenterfreq()/1000.0);} - } - Fl_Value_Output octavesfreqvo { - label {Oct.} - callback {o->value(respar->getoctavesfreq());} - tooltip {No. of octaves} xywh {210 282 33 18} labelsize 12 when 3 minimum 1 maximum 127 step 1 value 30 textfont 1 textsize 12 - code0 {o->value(respar->getoctavesfreq());} - } - Fl_Button {} { - label RND2 - callback {respar->randomize(1); -resonancewindow->redraw(); -redrawPADnoteApply();} - tooltip {Randomize the resonance function} xywh {566 276 42 12} box THIN_UP_BOX labelfont 1 labelsize 10 - } - Fl_Button {} { - label RND1 - callback {respar->randomize(0); -resonancewindow->redraw(); -redrawPADnoteApply();} - tooltip {Randomize the resonance function} xywh {566 264 42 12} box THIN_UP_BOX labelfont 1 labelsize 10 - } - Fl_Button {} { - label RND3 - callback {respar->randomize(2); -resonancewindow->redraw(); -redrawPADnoteApply();} - tooltip {Randomize the resonance function} xywh {566 288 42 12} box THIN_UP_BOX labelfont 1 labelsize 10 - } - Fl_Check_Button p1st { - label {P.1st} - callback {respar->Pprotectthefundamental=(int) o->value(); -redrawPADnoteApply();} - tooltip {Protect the fundamental frequency (do not damp the first harmonic)} xywh {365 285 45 15} down_box DOWN_BOX labelsize 10 - code0 {o->value(respar->Pprotectthefundamental);} - } - Fl_Button {} { - label InterpP - callback {int type; -if (Fl::event_button()==FL_LEFT_MOUSE) type=0; - else type=1; -respar->interpolatepeaks(type); -resonancewindow->redraw(); -redrawPADnoteApply();} - tooltip {Interpolate the peaks} xywh {365 265 46 15} box THIN_UP_BOX labelfont 1 labelsize 10 - } - Fl_Dial centerfreq { - label {C.f.} - callback {respar->Pcenterfreq=(int)o->value(); -centerfreqvo->do_callback(); -rg->redraw(); -redrawPADnoteApply();} - xywh {245 265 30 30} box ROUND_UP_BOX labelsize 10 maximum 127 step 1 - code0 {o->value(respar->Pcenterfreq);} - class WidgetPDial - } - Fl_Dial octavesfreq { - label {Oct.} - callback {respar->Poctavesfreq=(int)o->value(); -octavesfreqvo->do_callback(); -rg->redraw(); -redrawPADnoteApply();} - xywh {280 265 30 30} box ROUND_UP_BOX labelsize 10 maximum 127 step 1 - code0 {o->value(respar->Poctavesfreq);} - class WidgetPDial - } - Fl_Button {} { - label C - callback {presetsui->copy(respar);} - xywh {625 275 25 15} box THIN_UP_BOX color 179 labelfont 1 labelsize 11 labelcolor 7 - } - Fl_Button {} { - label P - callback {presetsui->paste(respar,this);} - xywh {655 275 25 15} box THIN_UP_BOX color 179 labelfont 1 labelsize 11 labelcolor 7 - } - Fl_Button applybutton { - label Apply - callback {applybutton->color(FL_GRAY); -applybutton->redraw(); -if (cbapplywidget!=NULL) { - cbapplywidget->do_callback(); - cbapplywidget->color(FL_GRAY); - cbapplywidget->redraw(); -};} - xywh {690 265 85 15} box THIN_UP_BOX labelfont 1 labelsize 11 - } - } - } - Function {ResonanceUI(Resonance *respar_)} {} { - code {respar=respar_; -cbwidget=NULL; -cbapplywidget=NULL; -make_window(); -applybutton->hide();} {} - } - Function {~ResonanceUI()} {} { - code {resonancewindow->hide();} {} - } - Function {redrawPADnoteApply()} {} { - code {if (cbwidget!=NULL) { - cbwidget->do_callback(); - applybutton->color(FL_RED); - applybutton->redraw(); -};} {} - } - Function {setcbwidget(Fl_Widget *cbwidget,Fl_Widget *cbapplywidget)} {} { - code {this->cbwidget=cbwidget; -this->cbapplywidget=cbapplywidget; -rg->setcbwidget(cbwidget,applybutton); -applybutton->show();} {} - } - Function {refresh()} {} { - code {redrawPADnoteApply(); - -enabled->value(respar->Penabled); - -maxdb->value(respar->PmaxdB); -maxdbvo->value(respar->PmaxdB); - -centerfreqvo->value(respar->getcenterfreq()/1000.0); -octavesfreqvo->value(respar->getoctavesfreq()); - -centerfreq->value(respar->Pcenterfreq); -octavesfreq->value(respar->Poctavesfreq); - -p1st->value(respar->Pprotectthefundamental); - -rg->redraw();} {} - } - decl {Resonance *respar;} {public - } - decl {ResonanceGraph *rg;} {} - decl {Fl_Widget *cbwidget,*cbapplywidget;} {} -} diff --git a/plugins/zynaddsubfx/src/UI/ResonanceUI.h b/plugins/zynaddsubfx/src/UI/ResonanceUI.h deleted file mode 100644 index b95475992..000000000 --- a/plugins/zynaddsubfx/src/UI/ResonanceUI.h +++ /dev/null @@ -1,120 +0,0 @@ -// generated by Fast Light User Interface Designer (fluid) version 1.0300 - -#ifndef ResonanceUI_h -#define ResonanceUI_h -#include -#include -#include -#include -#include "../Synth/Resonance.h" -#include "WidgetPDial.h" -#include "PresetsUI.h" - -class ResonanceGraph : public Fl_Box { -public: - ResonanceGraph(int x,int y, int w, int h, const char *label=0); - void init(Resonance *respar_,Fl_Value_Output *khzvalue_,Fl_Value_Output *dbvalue_); - void draw_freq_line(REALTYPE freq,int type); - void draw(); - int handle(int event); - void setcbwidget(Fl_Widget *cbwidget,Fl_Widget *applybutton); -private: - Fl_Value_Output *khzvalue; - Fl_Value_Output *dbvalue; - Resonance *respar; - int oldx,oldy; -public: - REALTYPE khzval; -private: - Fl_Widget *cbwidget,*applybutton; -}; -#include -#include -#include -#include -#include -#include -#include - -class ResonanceUI : PresetsUI_ { -public: - Fl_Double_Window* make_window(); - Fl_Double_Window *resonancewindow; - Fl_Value_Output *khzvalue; - Fl_Value_Output *dbvalue; -private: - void cb_Close_i(Fl_Button*, void*); - static void cb_Close(Fl_Button*, void*); - void cb_Zero_i(Fl_Button*, void*); - static void cb_Zero(Fl_Button*, void*); - void cb_Smooth_i(Fl_Button*, void*); - static void cb_Smooth(Fl_Button*, void*); -public: - Fl_Check_Button *enabled; -private: - void cb_enabled_i(Fl_Check_Button*, void*); - static void cb_enabled(Fl_Check_Button*, void*); -public: - Fl_Roller *maxdb; -private: - void cb_maxdb_i(Fl_Roller*, void*); - static void cb_maxdb(Fl_Roller*, void*); -public: - Fl_Value_Output *maxdbvo; -private: - void cb_maxdbvo_i(Fl_Value_Output*, void*); - static void cb_maxdbvo(Fl_Value_Output*, void*); -public: - Fl_Value_Output *centerfreqvo; -private: - void cb_centerfreqvo_i(Fl_Value_Output*, void*); - static void cb_centerfreqvo(Fl_Value_Output*, void*); -public: - Fl_Value_Output *octavesfreqvo; -private: - void cb_octavesfreqvo_i(Fl_Value_Output*, void*); - static void cb_octavesfreqvo(Fl_Value_Output*, void*); - void cb_RND2_i(Fl_Button*, void*); - static void cb_RND2(Fl_Button*, void*); - void cb_RND1_i(Fl_Button*, void*); - static void cb_RND1(Fl_Button*, void*); - void cb_RND3_i(Fl_Button*, void*); - static void cb_RND3(Fl_Button*, void*); -public: - Fl_Check_Button *p1st; -private: - void cb_p1st_i(Fl_Check_Button*, void*); - static void cb_p1st(Fl_Check_Button*, void*); - void cb_InterpP_i(Fl_Button*, void*); - static void cb_InterpP(Fl_Button*, void*); -public: - WidgetPDial *centerfreq; -private: - void cb_centerfreq_i(WidgetPDial*, void*); - static void cb_centerfreq(WidgetPDial*, void*); -public: - WidgetPDial *octavesfreq; -private: - void cb_octavesfreq_i(WidgetPDial*, void*); - static void cb_octavesfreq(WidgetPDial*, void*); - void cb_C_i(Fl_Button*, void*); - static void cb_C(Fl_Button*, void*); - void cb_P_i(Fl_Button*, void*); - static void cb_P(Fl_Button*, void*); -public: - Fl_Button *applybutton; -private: - void cb_applybutton_i(Fl_Button*, void*); - static void cb_applybutton(Fl_Button*, void*); -public: - ResonanceUI(Resonance *respar_); - ~ResonanceUI(); - void redrawPADnoteApply(); - void setcbwidget(Fl_Widget *cbwidget,Fl_Widget *cbapplywidget); - void refresh(); - Resonance *respar; -private: - ResonanceGraph *rg; - Fl_Widget *cbwidget,*cbapplywidget; -}; -#endif diff --git a/plugins/zynaddsubfx/src/UI/SUBnoteUI.cc b/plugins/zynaddsubfx/src/UI/SUBnoteUI.cc deleted file mode 100644 index 9314333c5..000000000 --- a/plugins/zynaddsubfx/src/UI/SUBnoteUI.cc +++ /dev/null @@ -1,735 +0,0 @@ -// generated by Fast Light User Interface Designer (fluid) version 1.0300 - -#include "SUBnoteUI.h" -//Copyright (c) 2002-2005 Nasca Octavian Paul -//License: GNU GPL version 2 or later - -void SUBnoteharmonic::cb_mag_i(Fl_Slider* o, void*) { - int x=0; -if (Fl::event_button1()) x=127-(int)o->value(); - else o->value(127-x); -pars->Phmag[n]=x; -if (pars->Phmag[n]==0) o->selection_color(0); - else o->selection_color(222); -} -void SUBnoteharmonic::cb_mag(Fl_Slider* o, void* v) { - ((SUBnoteharmonic*)(o->parent()->user_data()))->cb_mag_i(o,v); -} - -void SUBnoteharmonic::cb_bw_i(Fl_Slider* o, void*) { - int x=64; -if (Fl::event_button1()) x=127-(int)o->value(); - else o->value(x); -pars->Phrelbw[n]=x; -} -void SUBnoteharmonic::cb_bw(Fl_Slider* o, void* v) { - ((SUBnoteharmonic*)(o->parent()->user_data()))->cb_bw_i(o,v); -} - -Fl_Group* SUBnoteharmonic::make_window() { - { harmonic = new Fl_Group(0, 0, 90, 225); - harmonic->box(FL_FLAT_BOX); - harmonic->color(FL_BACKGROUND_COLOR); - harmonic->selection_color(FL_BACKGROUND_COLOR); - harmonic->labeltype(FL_NO_LABEL); - harmonic->labelfont(0); - harmonic->labelsize(14); - harmonic->labelcolor(FL_FOREGROUND_COLOR); - harmonic->user_data((void*)(this)); - harmonic->align(Fl_Align(FL_ALIGN_TOP)); - harmonic->when(FL_WHEN_RELEASE); - { Fl_Slider* o = mag = new Fl_Slider(0, 15, 10, 115); - mag->tooltip("harmonic\'s magnitude"); - mag->type(4); - mag->box(FL_FLAT_BOX); - mag->selection_color((Fl_Color)222); - mag->maximum(127); - mag->step(1); - mag->value(127); - mag->callback((Fl_Callback*)cb_mag); - o->value(127-pars->Phmag[n]); - if (pars->Phmag[n]==0) o->selection_color(0); - } // Fl_Slider* mag - { Fl_Slider* o = bw = new Fl_Slider(0, 135, 10, 75); - bw->tooltip("harmonic\'s bandwidth"); - bw->type(4); - bw->box(FL_FLAT_BOX); - bw->selection_color((Fl_Color)222); - bw->maximum(127); - bw->step(1); - bw->value(64); - bw->callback((Fl_Callback*)cb_bw); - o->value(127-pars->Phrelbw[n]); - } // Fl_Slider* bw - { Fl_Box* o = new Fl_Box(10, 170, 5, 5); - o->box(FL_FLAT_BOX); - o->color(FL_DARK2); - if (n+1==MAX_SUB_HARMONICS) o->hide(); - } // Fl_Box* o - { Fl_Box* o = new Fl_Box(0, 210, 10, 15, "01"); - o->labelfont(1); - o->labelsize(9); - o->align(Fl_Align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE)); - char tmp[10];snprintf(tmp,10,"%d",n+1);o->label(strdup(tmp)); - } // Fl_Box* o - { Fl_Box* o = new Fl_Box(0, 0, 10, 15, "01"); - o->labelfont(1); - o->labelsize(9); - o->align(Fl_Align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE)); - char tmp[10];snprintf(tmp,10,"%d",n+1);o->label(strdup(tmp)); - } // Fl_Box* o - harmonic->end(); - } // Fl_Group* harmonic - return harmonic; -} - -SUBnoteharmonic::SUBnoteharmonic(int x,int y, int w, int h, const char *label):Fl_Group(x,y,w,h,label) { - n=0; -} - -void SUBnoteharmonic::init(SUBnoteParameters *pars_,int n_) { - pars=pars_; - n=n_; - make_window(); - harmonic->show(); - end(); -} - -void SUBnoteharmonic::refresh() { - mag->value(127-pars->Phmag[n]); - if (pars->Phmag[n]==0) mag->selection_color(0); - bw->value(127-pars->Phrelbw[n]); -} - -SUBnoteharmonic::~SUBnoteharmonic() { - harmonic->hide(); - hide(); - //delete(harmonic); -} - -void SUBnoteUI::cb_Close_i(Fl_Button*, void*) { - SUBparameters->hide(); -} -void SUBnoteUI::cb_Close(Fl_Button* o, void* v) { - ((SUBnoteUI*)(o->parent()->user_data()))->cb_Close_i(o,v); -} - -void SUBnoteUI::cb_vol_i(Fl_Value_Slider* o, void*) { - pars->PVolume=(int)o->value(); -} -void SUBnoteUI::cb_vol(Fl_Value_Slider* o, void* v) { - ((SUBnoteUI*)(o->parent()->parent()->user_data()))->cb_vol_i(o,v); -} - -void SUBnoteUI::cb_vsns_i(Fl_Value_Slider* o, void*) { - pars->PAmpVelocityScaleFunction=(int) o->value(); -} -void SUBnoteUI::cb_vsns(Fl_Value_Slider* o, void* v) { - ((SUBnoteUI*)(o->parent()->parent()->user_data()))->cb_vsns_i(o,v); -} - -void SUBnoteUI::cb_pan_i(WidgetPDial* o, void*) { - pars->PPanning=(int) o->value(); -} -void SUBnoteUI::cb_pan(WidgetPDial* o, void* v) { - ((SUBnoteUI*)(o->parent()->parent()->user_data()))->cb_pan_i(o,v); -} - -void SUBnoteUI::cb_filterstages_i(Fl_Counter* o, void*) { - pars->Pnumstages=(int) o->value(); -} -void SUBnoteUI::cb_filterstages(Fl_Counter* o, void* v) { - ((SUBnoteUI*)(o->parent()->parent()->user_data()))->cb_filterstages_i(o,v); -} - -void SUBnoteUI::cb_magtype_i(Fl_Choice* o, void*) { - pars->Phmagtype=(int) o->value(); -} -void SUBnoteUI::cb_magtype(Fl_Choice* o, void* v) { - ((SUBnoteUI*)(o->parent()->parent()->user_data()))->cb_magtype_i(o,v); -} - -Fl_Menu_Item SUBnoteUI::menu_magtype[] = { - {"Linear", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 11, 0}, - {"-40dB", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 11, 0}, - {"-60dB", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 11, 0}, - {"-80dB", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 11, 0}, - {"-100dB", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 11, 0}, - {0,0,0,0,0,0,0,0,0} -}; - -void SUBnoteUI::cb_start_i(Fl_Choice* o, void*) { - pars->Pstart=(int) o->value(); -} -void SUBnoteUI::cb_start(Fl_Choice* o, void* v) { - ((SUBnoteUI*)(o->parent()->parent()->user_data()))->cb_start_i(o,v); -} - -Fl_Menu_Item SUBnoteUI::menu_start[] = { - {"Zero", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 11, 0}, - {"RND", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 11, 0}, - {"Max.", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 11, 0}, - {0,0,0,0,0,0,0,0,0} -}; - -void SUBnoteUI::cb_freqee_i(Fl_Check_Button* o, void*) { - pars->PFreqEnvelopeEnabled=o->value(); -if (o->value()==0) freqenvelopegroup->deactivate(); - else freqenvelopegroup->activate(); -o->show(); -freqsettingsui->redraw(); -} -void SUBnoteUI::cb_freqee(Fl_Check_Button* o, void* v) { - ((SUBnoteUI*)(o->parent()->parent()->user_data()))->cb_freqee_i(o,v); -} - -void SUBnoteUI::cb_octave_i(Fl_Counter* o, void*) { - int k=(int) o->value(); -if (k<0) k+=16; -pars->PCoarseDetune = k*1024+ - pars->PCoarseDetune%1024; -} -void SUBnoteUI::cb_octave(Fl_Counter* o, void* v) { - ((SUBnoteUI*)(o->parent()->parent()->user_data()))->cb_octave_i(o,v); -} - -void SUBnoteUI::cb_coarsedet_i(Fl_Counter* o, void*) { - int k=(int) o->value(); -if (k<0) k+=1024; -pars->PCoarseDetune = k+ - (pars->PCoarseDetune/1024)*1024; -} -void SUBnoteUI::cb_coarsedet(Fl_Counter* o, void* v) { - ((SUBnoteUI*)(o->parent()->parent()->user_data()))->cb_coarsedet_i(o,v); -} - -void SUBnoteUI::cb_detune_i(Fl_Slider* o, void*) { - pars->PDetune=(int)o->value()+8192; -detunevalueoutput->do_callback(); -} -void SUBnoteUI::cb_detune(Fl_Slider* o, void* v) { - ((SUBnoteUI*)(o->parent()->parent()->user_data()))->cb_detune_i(o,v); -} - -void SUBnoteUI::cb_detunevalueoutput_i(Fl_Value_Output* o, void*) { - o->value(getdetune(pars->PDetuneType,0,pars->PDetune)); -} -void SUBnoteUI::cb_detunevalueoutput(Fl_Value_Output* o, void* v) { - ((SUBnoteUI*)(o->parent()->parent()->user_data()))->cb_detunevalueoutput_i(o,v); -} - -void SUBnoteUI::cb_hz440_i(Fl_Check_Button* o, void*) { - int x=(int) o->value(); -pars->Pfixedfreq=x; -if (x==0) fixedfreqetdial->deactivate(); - else fixedfreqetdial->activate(); -} -void SUBnoteUI::cb_hz440(Fl_Check_Button* o, void* v) { - ((SUBnoteUI*)(o->parent()->parent()->user_data()))->cb_hz440_i(o,v); -} - -void SUBnoteUI::cb_fixedfreqetdial_i(WidgetPDial* o, void*) { - pars->PfixedfreqET=(int) o->value(); -} -void SUBnoteUI::cb_fixedfreqetdial(WidgetPDial* o, void* v) { - ((SUBnoteUI*)(o->parent()->parent()->user_data()))->cb_fixedfreqetdial_i(o,v); -} - -void SUBnoteUI::cb_detunetype_i(Fl_Choice* o, void*) { - pars->PDetuneType=(int) o->value()+1; -detunevalueoutput->do_callback(); -} -void SUBnoteUI::cb_detunetype(Fl_Choice* o, void* v) { - ((SUBnoteUI*)(o->parent()->parent()->user_data()))->cb_detunetype_i(o,v); -} - -void SUBnoteUI::cb_stereo_i(Fl_Check_Button* o, void*) { - pars->Pstereo=(int) o->value(); -} -void SUBnoteUI::cb_stereo(Fl_Check_Button* o, void* v) { - ((SUBnoteUI*)(o->parent()->user_data()))->cb_stereo_i(o,v); -} - -void SUBnoteUI::cb_Clear_i(Fl_Button*, void*) { - for (int i=0;imag->value(127); - pars->Phmag[i]=0; - h[i]->bw->value(64); - pars->Phrelbw[i]=64; -}; -pars->Phmag[0]=127; -h[0]->mag->value(0); -SUBparameters->redraw(); -} -void SUBnoteUI::cb_Clear(Fl_Button* o, void* v) { - ((SUBnoteUI*)(o->parent()->user_data()))->cb_Clear_i(o,v); -} - -void SUBnoteUI::cb_bwee_i(Fl_Check_Button* o, void*) { - pars->PBandWidthEnvelopeEnabled=o->value(); -if (o->value()==0) bandwidthenvelopegroup->deactivate(); - else bandwidthenvelopegroup->activate(); -o->show(); -bandwidthsettingsui->redraw(); -} -void SUBnoteUI::cb_bwee(Fl_Check_Button* o, void* v) { - ((SUBnoteUI*)(o->parent()->parent()->user_data()))->cb_bwee_i(o,v); -} - -void SUBnoteUI::cb_bandwidth_i(Fl_Value_Slider* o, void*) { - pars->Pbandwidth=(int) o->value(); -} -void SUBnoteUI::cb_bandwidth(Fl_Value_Slider* o, void* v) { - ((SUBnoteUI*)(o->parent()->parent()->user_data()))->cb_bandwidth_i(o,v); -} - -void SUBnoteUI::cb_bwidthscale_i(Fl_Value_Slider* o, void*) { - pars->Pbwscale=(int) o->value()+64; -} -void SUBnoteUI::cb_bwidthscale(Fl_Value_Slider* o, void* v) { - ((SUBnoteUI*)(o->parent()->parent()->user_data()))->cb_bwidthscale_i(o,v); -} - -void SUBnoteUI::cb_filtere_i(Fl_Check_Button* o, void*) { - pars->PGlobalFilterEnabled=o->value(); -if (o->value()==0) globalfiltergroup->deactivate(); - else globalfiltergroup->activate(); -o->show(); -globalfiltergroup->redraw(); -} -void SUBnoteUI::cb_filtere(Fl_Check_Button* o, void* v) { - ((SUBnoteUI*)(o->parent()->user_data()))->cb_filtere_i(o,v); -} - -void SUBnoteUI::cb_C_i(Fl_Button*, void*) { - presetsui->copy(pars); -} -void SUBnoteUI::cb_C(Fl_Button* o, void* v) { - ((SUBnoteUI*)(o->parent()->user_data()))->cb_C_i(o,v); -} - -void SUBnoteUI::cb_P_i(Fl_Button*, void*) { - presetsui->paste(pars,this); -} -void SUBnoteUI::cb_P(Fl_Button* o, void* v) { - ((SUBnoteUI*)(o->parent()->user_data()))->cb_P_i(o,v); -} - -Fl_Double_Window* SUBnoteUI::make_window() { - { SUBparameters = new Fl_Double_Window(735, 390, "SUBsynth Parameters"); - SUBparameters->user_data((void*)(this)); - { Fl_Scroll* o = new Fl_Scroll(5, 140, 435, 245); - o->type(1); - o->box(FL_THIN_UP_BOX); - { Fl_Pack* o = harmonics = new Fl_Pack(10, 145, 425, 235); - harmonics->type(1); - for (int i=0;ih(),"");h[i]->init(pars,i);} - harmonics->end(); - } // Fl_Pack* harmonics - o->end(); - } // Fl_Scroll* o - { Fl_Button* o = new Fl_Button(625, 365, 105, 20, "Close"); - o->box(FL_THIN_UP_BOX); - o->labelfont(1); - o->labelsize(11); - o->callback((Fl_Callback*)cb_Close); - } // Fl_Button* o - { Fl_Group* o = new Fl_Group(5, 5, 215, 135, "AMPLITUDE"); - o->box(FL_THIN_UP_FRAME); - o->labeltype(FL_EMBOSSED_LABEL); - o->labelfont(1); - o->align(Fl_Align(FL_ALIGN_TOP|FL_ALIGN_INSIDE)); - { Fl_Value_Slider* o = vol = new Fl_Value_Slider(10, 25, 140, 15, "Vol"); - vol->tooltip("Volume"); - vol->type(5); - vol->box(FL_FLAT_BOX); - vol->labelsize(11); - vol->maximum(127); - vol->step(1); - vol->callback((Fl_Callback*)cb_vol); - vol->align(Fl_Align(FL_ALIGN_RIGHT)); - o->value(pars->PVolume); - } // Fl_Value_Slider* vol - { Fl_Value_Slider* o = vsns = new Fl_Value_Slider(10, 45, 140, 15, "V.Sns"); - vsns->tooltip("Velocity Sensing Function (rightmost to disable)"); - vsns->type(5); - vsns->box(FL_FLAT_BOX); - vsns->labelsize(11); - vsns->maximum(127); - vsns->step(1); - vsns->callback((Fl_Callback*)cb_vsns); - vsns->align(Fl_Align(FL_ALIGN_RIGHT)); - o->value(pars->PAmpVelocityScaleFunction); - } // Fl_Value_Slider* vsns - { WidgetPDial* o = pan = new WidgetPDial(185, 20, 30, 30, "Pan"); - pan->tooltip("Panning (leftmost is Random)"); - pan->box(FL_ROUND_UP_BOX); - pan->color(FL_BACKGROUND_COLOR); - pan->selection_color(FL_INACTIVE_COLOR); - pan->labeltype(FL_NORMAL_LABEL); - pan->labelfont(0); - pan->labelsize(10); - pan->labelcolor(FL_FOREGROUND_COLOR); - pan->maximum(127); - pan->step(1); - pan->callback((Fl_Callback*)cb_pan); - pan->align(Fl_Align(FL_ALIGN_BOTTOM)); - pan->when(FL_WHEN_CHANGED); - o->value(pars->PPanning); - } // WidgetPDial* pan - { EnvelopeUI* o = ampenv = new EnvelopeUI(10, 65, 205, 70, "SUBsynth - Amplitude Envelope"); - ampenv->box(FL_FLAT_BOX); - ampenv->color((Fl_Color)51); - ampenv->selection_color(FL_BACKGROUND_COLOR); - ampenv->labeltype(FL_NORMAL_LABEL); - ampenv->labelfont(0); - ampenv->labelsize(14); - ampenv->labelcolor(FL_FOREGROUND_COLOR); - ampenv->align(Fl_Align(FL_ALIGN_WRAP|FL_ALIGN_INSIDE)); - ampenv->when(FL_WHEN_RELEASE); - o->init(pars->AmpEnvelope); - ampenv->end(); - } // EnvelopeUI* ampenv - o->end(); - } // Fl_Group* o - { Fl_Group* o = new Fl_Group(495, 325, 235, 35); - o->box(FL_THIN_UP_FRAME); - { Fl_Counter* o = filterstages = new Fl_Counter(515, 340, 45, 15, "Filter Stages"); - filterstages->tooltip("How many times the noise is filtered"); - filterstages->type(1); - filterstages->labelfont(1); - filterstages->labelsize(10); - filterstages->minimum(1); - filterstages->maximum(5); - filterstages->step(1); - filterstages->textsize(10); - filterstages->callback((Fl_Callback*)cb_filterstages); - filterstages->align(Fl_Align(FL_ALIGN_TOP)); - o->value(pars->Pnumstages); - } // Fl_Counter* filterstages - { Fl_Choice* o = magtype = new Fl_Choice(585, 340, 65, 15, "Mag.Type"); - magtype->down_box(FL_BORDER_BOX); - magtype->labelfont(1); - magtype->labelsize(10); - magtype->textsize(11); - magtype->callback((Fl_Callback*)cb_magtype); - magtype->align(Fl_Align(FL_ALIGN_TOP)); - magtype->menu(menu_magtype); - o->value(pars->Phmagtype); - } // Fl_Choice* magtype - { Fl_Choice* o = start = new Fl_Choice(670, 340, 50, 15, "Start"); - start->down_box(FL_BORDER_BOX); - start->labelfont(1); - start->labelsize(10); - start->textsize(11); - start->callback((Fl_Callback*)cb_start); - start->align(Fl_Align(FL_ALIGN_TOP)); - start->menu(menu_start); - o->value(pars->Pstart); - } // Fl_Choice* start - o->end(); - } // Fl_Group* o - { freqsettingsui = new Fl_Group(440, 5, 290, 135, "FREQUENCY"); - freqsettingsui->box(FL_THIN_UP_FRAME); - freqsettingsui->labeltype(FL_EMBOSSED_LABEL); - freqsettingsui->labelfont(1); - freqsettingsui->align(Fl_Align(FL_ALIGN_TOP|FL_ALIGN_INSIDE)); - { EnvelopeUI* o = freqenvelopegroup = new EnvelopeUI(445, 65, 205, 70, "SUBsynth - Frequency Envelope"); - freqenvelopegroup->box(FL_FLAT_BOX); - freqenvelopegroup->color((Fl_Color)51); - freqenvelopegroup->selection_color(FL_BACKGROUND_COLOR); - freqenvelopegroup->labeltype(FL_NORMAL_LABEL); - freqenvelopegroup->labelfont(0); - freqenvelopegroup->labelsize(14); - freqenvelopegroup->labelcolor(FL_FOREGROUND_COLOR); - freqenvelopegroup->align(Fl_Align(FL_ALIGN_WRAP|FL_ALIGN_INSIDE)); - freqenvelopegroup->when(FL_WHEN_RELEASE); - o->init(pars->FreqEnvelope); - if (pars->PFreqEnvelopeEnabled==0) o->deactivate(); - freqenvelopegroup->end(); - } // EnvelopeUI* freqenvelopegroup - { Fl_Check_Button* o = freqee = new Fl_Check_Button(445, 68, 55, 15, "Enabled"); - freqee->down_box(FL_DOWN_BOX); - freqee->labelfont(1); - freqee->labelsize(10); - freqee->callback((Fl_Callback*)cb_freqee); - o->value(pars->PFreqEnvelopeEnabled); - } // Fl_Check_Button* freqee - { Fl_Counter* o = octave = new Fl_Counter(670, 50, 45, 15, "Octave"); - octave->tooltip("Octave"); - octave->type(1); - octave->labelsize(10); - octave->minimum(-8); - octave->maximum(7); - octave->step(1); - octave->textfont(1); - octave->textsize(11); - octave->callback((Fl_Callback*)cb_octave); - octave->align(Fl_Align(FL_ALIGN_TOP)); - int k=pars->PCoarseDetune/1024;if (k>=8) k-=16; - o->value(k); - } // Fl_Counter* octave - { Fl_Counter* o = coarsedet = new Fl_Counter(655, 115, 60, 20, "Coarse Det."); - coarsedet->tooltip("Coarse Detune"); - coarsedet->labelsize(10); - coarsedet->minimum(-64); - coarsedet->maximum(63); - coarsedet->step(1); - coarsedet->textfont(1); - coarsedet->textsize(11); - coarsedet->callback((Fl_Callback*)cb_coarsedet); - coarsedet->align(Fl_Align(FL_ALIGN_TOP)); - int k=pars->PCoarseDetune%1024;if (k>=512) k-=1024; - o->value(k); - o->lstep(10); - } // Fl_Counter* coarsedet - { Fl_Slider* o = detune = new Fl_Slider(495, 25, 230, 15); - detune->tooltip("Fine Detune (cents)"); - detune->type(5); - detune->box(FL_FLAT_BOX); - detune->minimum(-8192); - detune->maximum(8191); - detune->step(1); - detune->callback((Fl_Callback*)cb_detune); - o->value(pars->PDetune-8192); - } // Fl_Slider* detune - { Fl_Value_Output* o = detunevalueoutput = new Fl_Value_Output(448, 25, 45, 15, "Detune"); - detunevalueoutput->labelsize(10); - detunevalueoutput->minimum(-5000); - detunevalueoutput->maximum(5000); - detunevalueoutput->step(0.01); - detunevalueoutput->textfont(1); - detunevalueoutput->textsize(10); - detunevalueoutput->callback((Fl_Callback*)cb_detunevalueoutput); - detunevalueoutput->align(Fl_Align(FL_ALIGN_TOP_LEFT)); - o->value(getdetune(pars->PDetuneType,0,pars->PDetune)); - } // Fl_Value_Output* detunevalueoutput - { Fl_Check_Button* o = hz440 = new Fl_Check_Button(555, 45, 50, 15, "440Hz"); - hz440->tooltip("set the base frequency to 440Hz"); - hz440->down_box(FL_DOWN_BOX); - hz440->labelfont(1); - hz440->labelsize(10); - hz440->callback((Fl_Callback*)cb_hz440); - o->value(pars->Pfixedfreq); - } // Fl_Check_Button* hz440 - { WidgetPDial* o = fixedfreqetdial = new WidgetPDial(610, 45, 15, 15, "Eq.T."); - fixedfreqetdial->tooltip("How the frequency varies acording to the keyboard (leftmost for fixed frequen\ -cy)"); - fixedfreqetdial->box(FL_ROUND_UP_BOX); - fixedfreqetdial->color(FL_BACKGROUND_COLOR); - fixedfreqetdial->selection_color(FL_INACTIVE_COLOR); - fixedfreqetdial->labeltype(FL_NORMAL_LABEL); - fixedfreqetdial->labelfont(0); - fixedfreqetdial->labelsize(10); - fixedfreqetdial->labelcolor(FL_FOREGROUND_COLOR); - fixedfreqetdial->maximum(127); - fixedfreqetdial->step(1); - fixedfreqetdial->callback((Fl_Callback*)cb_fixedfreqetdial); - fixedfreqetdial->align(Fl_Align(FL_ALIGN_RIGHT)); - fixedfreqetdial->when(FL_WHEN_CHANGED); - o->value(pars->PfixedfreqET); - if (pars->Pfixedfreq==0) o->deactivate(); - } // WidgetPDial* fixedfreqetdial - { Fl_Choice* o = detunetype = new Fl_Choice(655, 85, 70, 15, "Detune Type"); - detunetype->down_box(FL_BORDER_BOX); - detunetype->labelsize(10); - detunetype->textfont(1); - detunetype->textsize(10); - detunetype->callback((Fl_Callback*)cb_detunetype); - detunetype->align(Fl_Align(FL_ALIGN_TOP_LEFT)); - o->add("L35cents");o->add("L10cents");o->add("E100cents");o->add("E1200cents"); - o->value(pars->PDetuneType-1); - } // Fl_Choice* detunetype - freqsettingsui->end(); - } // Fl_Group* freqsettingsui - { Fl_Check_Button* o = stereo = new Fl_Check_Button(440, 325, 55, 35, "Stereo"); - stereo->box(FL_THIN_UP_BOX); - stereo->down_box(FL_DOWN_BOX); - stereo->labelfont(1); - stereo->labelsize(10); - stereo->callback((Fl_Callback*)cb_stereo); - o->value(pars->Pstereo); - } // Fl_Check_Button* stereo - { Fl_Button* o = new Fl_Button(445, 365, 70, 20, "Clear"); - o->tooltip("Clear the harmonics"); - o->box(FL_THIN_UP_BOX); - o->labelfont(1); - o->labelsize(11); - o->callback((Fl_Callback*)cb_Clear); - } // Fl_Button* o - { bandwidthsettingsui = new Fl_Group(220, 5, 220, 135, "BANDWIDTH"); - bandwidthsettingsui->box(FL_THIN_UP_FRAME); - bandwidthsettingsui->labeltype(FL_EMBOSSED_LABEL); - bandwidthsettingsui->labelfont(1); - bandwidthsettingsui->align(Fl_Align(FL_ALIGN_TOP|FL_ALIGN_INSIDE)); - { EnvelopeUI* o = bandwidthenvelopegroup = new EnvelopeUI(225, 65, 205, 70, "SUBsynth - BandWidth Envelope"); - bandwidthenvelopegroup->box(FL_FLAT_BOX); - bandwidthenvelopegroup->color((Fl_Color)51); - bandwidthenvelopegroup->selection_color(FL_BACKGROUND_COLOR); - bandwidthenvelopegroup->labeltype(FL_NORMAL_LABEL); - bandwidthenvelopegroup->labelfont(0); - bandwidthenvelopegroup->labelsize(14); - bandwidthenvelopegroup->labelcolor(FL_FOREGROUND_COLOR); - bandwidthenvelopegroup->align(Fl_Align(FL_ALIGN_WRAP|FL_ALIGN_INSIDE)); - bandwidthenvelopegroup->when(FL_WHEN_RELEASE); - o->init(pars->BandWidthEnvelope); - if (pars->PBandWidthEnvelopeEnabled==0) o->deactivate(); - bandwidthenvelopegroup->end(); - } // EnvelopeUI* bandwidthenvelopegroup - { Fl_Check_Button* o = bwee = new Fl_Check_Button(225, 67, 55, 15, "Enabled"); - bwee->down_box(FL_DOWN_BOX); - bwee->labelfont(1); - bwee->labelsize(10); - bwee->callback((Fl_Callback*)cb_bwee); - o->value(pars->PBandWidthEnvelopeEnabled); - } // Fl_Check_Button* bwee - { Fl_Value_Slider* o = bandwidth = new Fl_Value_Slider(225, 40, 115, 15, "Band Width"); - bandwidth->type(5); - bandwidth->box(FL_FLAT_BOX); - bandwidth->labelsize(10); - bandwidth->maximum(127); - bandwidth->step(1); - bandwidth->callback((Fl_Callback*)cb_bandwidth); - bandwidth->align(Fl_Align(FL_ALIGN_TOP)); - o->value(pars->Pbandwidth); - } // Fl_Value_Slider* bandwidth - { Fl_Value_Slider* o = bwidthscale = new Fl_Value_Slider(345, 40, 90, 15, "B.Width Scale"); - bwidthscale->tooltip("How much I increase the BandWidth according to lower/higher harmonics"); - bwidthscale->type(5); - bwidthscale->box(FL_FLAT_BOX); - bwidthscale->labelsize(10); - bwidthscale->minimum(-64); - bwidthscale->maximum(63); - bwidthscale->step(1); - bwidthscale->callback((Fl_Callback*)cb_bwidthscale); - bwidthscale->align(Fl_Align(FL_ALIGN_TOP)); - o->value(pars->Pbwscale-64); - } // Fl_Value_Slider* bwidthscale - bandwidthsettingsui->end(); - } // Fl_Group* bandwidthsettingsui - { Fl_Group* o = globalfiltergroup = new Fl_Group(440, 140, 290, 185, "FILTER"); - globalfiltergroup->box(FL_THIN_UP_FRAME); - globalfiltergroup->labeltype(FL_EMBOSSED_LABEL); - globalfiltergroup->labelfont(1); - globalfiltergroup->labelsize(13); - globalfiltergroup->align(Fl_Align(FL_ALIGN_TOP|FL_ALIGN_INSIDE)); - { EnvelopeUI* o = filterenv = new EnvelopeUI(445, 250, 275, 70, "SUBsynth - Filter Envelope"); - filterenv->box(FL_FLAT_BOX); - filterenv->color((Fl_Color)51); - filterenv->selection_color(FL_BACKGROUND_COLOR); - filterenv->labeltype(FL_NORMAL_LABEL); - filterenv->labelfont(0); - filterenv->labelsize(14); - filterenv->labelcolor(FL_FOREGROUND_COLOR); - filterenv->align(Fl_Align(FL_ALIGN_WRAP|FL_ALIGN_INSIDE)); - filterenv->when(FL_WHEN_RELEASE); - o->init(pars->GlobalFilterEnvelope); - filterenv->end(); - } // EnvelopeUI* filterenv - { FilterUI* o = filterui = new FilterUI(445, 170, 275, 75, "SUBsynthl - Filter"); - filterui->box(FL_FLAT_BOX); - filterui->color(FL_LIGHT1); - filterui->selection_color(FL_BACKGROUND_COLOR); - filterui->labeltype(FL_NORMAL_LABEL); - filterui->labelfont(0); - filterui->labelsize(14); - filterui->labelcolor(FL_FOREGROUND_COLOR); - filterui->align(Fl_Align(FL_ALIGN_WRAP|FL_ALIGN_INSIDE)); - filterui->when(FL_WHEN_RELEASE); - o->init(pars->GlobalFilter,&pars->PGlobalFilterVelocityScale,&pars->PGlobalFilterVelocityScaleFunction); - filterui->end(); - } // FilterUI* filterui - if (pars->PGlobalFilterEnabled==0) o->deactivate(); - globalfiltergroup->end(); - } // Fl_Group* globalfiltergroup - { Fl_Check_Button* o = filtere = new Fl_Check_Button(445, 145, 85, 20, "Enabled"); - filtere->down_box(FL_DOWN_BOX); - filtere->labelfont(1); - filtere->labelsize(11); - filtere->callback((Fl_Callback*)cb_filtere); - o->value(pars->PGlobalFilterEnabled); - } // Fl_Check_Button* filtere - { Fl_Button* o = new Fl_Button(540, 370, 25, 15, "C"); - o->box(FL_THIN_UP_BOX); - o->color((Fl_Color)179); - o->labelfont(1); - o->labelsize(11); - o->labelcolor(FL_BACKGROUND2_COLOR); - o->callback((Fl_Callback*)cb_C); - } // Fl_Button* o - { Fl_Button* o = new Fl_Button(570, 370, 25, 15, "P"); - o->box(FL_THIN_UP_BOX); - o->color((Fl_Color)179); - o->labelfont(1); - o->labelsize(11); - o->labelcolor(FL_BACKGROUND2_COLOR); - o->callback((Fl_Callback*)cb_P); - } // Fl_Button* o - SUBparameters->end(); - } // Fl_Double_Window* SUBparameters - return SUBparameters; -} - -void SUBnoteUI::refresh() { - for (int i=0;irefresh(); - vol->value(pars->PVolume); - vsns->value(pars->PAmpVelocityScaleFunction); - pan->value(pars->PPanning); - - - bandwidth->value(pars->Pbandwidth); - bwidthscale->value(pars->Pbwscale-64); - bwee->value(pars->PBandWidthEnvelopeEnabled); - if (pars->PBandWidthEnvelopeEnabled==0) bandwidthenvelopegroup->deactivate(); - else bandwidthenvelopegroup->activate(); - bwee->show(); - bandwidthsettingsui->redraw(); - - detunevalueoutput->value(getdetune(pars->PDetuneType,0,pars->PDetune)); - freqee->value(pars->PFreqEnvelopeEnabled); - if (pars->PFreqEnvelopeEnabled==0) freqenvelopegroup->deactivate(); - else freqenvelopegroup->activate(); - freqee->show(); - freqsettingsui->redraw(); - - detune->value(pars->PDetune-8192); - hz440->value(pars->Pfixedfreq); - - fixedfreqetdial->value(pars->PfixedfreqET); - - int k=pars->PCoarseDetune/1024;if (k>=8) k-=16; - octave->value(k); - - detunetype->value(pars->PDetuneType-1); - - k=pars->PCoarseDetune%1024;if (k>=512) k-=1024; - coarsedet->value(k); - - filtere->value(pars->PGlobalFilterEnabled); - if (pars->PGlobalFilterEnabled==0) globalfiltergroup->deactivate(); - else globalfiltergroup->activate(); - filtere->show(); - globalfiltergroup->redraw(); - - stereo->value(pars->Pstereo); - filterstages->value(pars->Pnumstages); - magtype->value(pars->Phmagtype); - start->value(pars->Pstart); - - ampenv->refresh(); - bandwidthenvelopegroup->refresh(); - freqenvelopegroup->refresh(); - filterui->refresh(); - filterenv->refresh(); -} - -SUBnoteUI::SUBnoteUI(SUBnoteParameters *parameters) { - pars=parameters; - make_window(); -} - -SUBnoteUI::~SUBnoteUI() { - //for (int i=0;ihide(); - delete(SUBparameters); -} diff --git a/plugins/zynaddsubfx/src/UI/SUBnoteUI.fl b/plugins/zynaddsubfx/src/UI/SUBnoteUI.fl deleted file mode 100644 index ef50a0bb9..000000000 --- a/plugins/zynaddsubfx/src/UI/SUBnoteUI.fl +++ /dev/null @@ -1,449 +0,0 @@ -# data file for the Fltk User Interface Designer (fluid) -version 1.0105 -header_name {.h} -code_name {.cc} -decl {//Copyright (c) 2002-2005 Nasca Octavian Paul} {} - -decl {//License: GNU GPL version 2 or later} {} - -decl {\#include } {public -} - -decl {\#include } {public -} - -decl {\#include } {public -} - -decl {\#include "../globals.h"} {public -} - -decl {\#include "WidgetPDial.h"} {public -} - -decl {\#include "EnvelopeUI.h"} {public -} - -decl {\#include "FilterUI.h"} {public -} - -decl {\#include "../Misc/Util.h"} {public -} - -decl {\#include "../Params/SUBnoteParameters.h"} {public -} - -decl {\#include "PresetsUI.h"} {public -} - -class SUBnoteharmonic {: {public Fl_Group} -} { - Function {make_window()} {private - } { - Fl_Window harmonic { - xywh {329 403 90 225} type Double hide - class Fl_Group - } { - Fl_Slider mag { - callback {int x=0; -if (Fl::event_button1()) x=127-(int)o->value(); - else o->value(127-x); -pars->Phmag[n]=x; -if (pars->Phmag[n]==0) o->selection_color(0); - else o->selection_color(222);} - tooltip {harmonic's magnitude} xywh {0 15 10 115} type {Vert Knob} box FLAT_BOX selection_color 222 labelcolor 0 maximum 127 step 1 value 127 - code0 {o->value(127-pars->Phmag[n]);} - code1 {if (pars->Phmag[n]==0) o->selection_color(0);} - } - Fl_Slider bw { - callback {int x=64; -if (Fl::event_button1()) x=127-(int)o->value(); - else o->value(x); -pars->Phrelbw[n]=x;} - tooltip {harmonic's bandwidth} xywh {0 135 10 75} type {Vert Knob} box FLAT_BOX selection_color 222 maximum 127 step 1 value 64 - code0 {o->value(127-pars->Phrelbw[n]);} - } - Fl_Box {} { - xywh {10 170 5 5} box FLAT_BOX color 45 - code0 {if (n+1==MAX_SUB_HARMONICS) o->hide();} - } - Fl_Box {} { - label 01 - xywh {0 210 10 15} labelfont 1 labelsize 9 align 20 - code0 {char tmp[10];snprintf(tmp,10,"%d",n+1);o->label(strdup(tmp));} - } - Fl_Box {} { - label 01 - xywh {0 0 10 15} labelfont 1 labelsize 9 align 20 - code0 {char tmp[10];snprintf(tmp,10,"%d",n+1);o->label(strdup(tmp));} - } - } - } - Function {SUBnoteharmonic(int x,int y, int w, int h, const char *label=0):Fl_Group(x,y,w,h,label)} {} { - code {n=0;} {} - } - Function {init(SUBnoteParameters *pars_,int n_)} {} { - code {pars=pars_; -n=n_; -make_window(); -harmonic->show(); -end();} {} - } - Function {refresh()} {} { - code {mag->value(127-pars->Phmag[n]); -if (pars->Phmag[n]==0) mag->selection_color(0); -bw->value(127-pars->Phrelbw[n]);} {selected - } - } - Function {~SUBnoteharmonic()} {} { - code {harmonic->hide(); -hide(); -//delete(harmonic);} {} - } - decl {SUBnoteParameters *pars;} {} - decl {int n;} {} -} - -class SUBnoteUI {: {public PresetsUI_} -} { - Function {make_window()} {} { - Fl_Window SUBparameters { - label {SUBsynth Parameters} - xywh {26 214 735 390} type Double hide - } { - Fl_Scroll {} { - xywh {5 140 435 245} type HORIZONTAL box THIN_UP_BOX - } { - Fl_Pack harmonics {open - xywh {10 145 425 235} type HORIZONTAL - code0 {for (int i=0;ih(),"");h[i]->init(pars,i);}} - } {} - } - Fl_Button {} { - label Close - callback {SUBparameters->hide();} - xywh {625 365 105 20} box THIN_UP_BOX labelfont 1 labelsize 11 - } - Fl_Group {} { - label AMPLITUDE - xywh {5 5 215 135} box THIN_UP_FRAME labeltype EMBOSSED_LABEL labelfont 1 align 17 - } { - Fl_Value_Slider vol { - label Vol - callback {pars->PVolume=(int)o->value();} - tooltip Volume xywh {10 25 140 15} type {Horz Knob} box FLAT_BOX labelsize 11 align 8 maximum 127 step 1 - code0 {o->value(pars->PVolume);} - } - Fl_Value_Slider vsns { - label {V.Sns} - callback {pars->PAmpVelocityScaleFunction=(int) o->value();} - tooltip {Velocity Sensing Function (rightmost to disable)} xywh {10 45 140 15} type {Horz Knob} box FLAT_BOX labelsize 11 align 8 maximum 127 step 1 - code0 {o->value(pars->PAmpVelocityScaleFunction);} - } - Fl_Dial pan { - label Pan - callback {pars->PPanning=(int) o->value();} - tooltip {Panning (leftmost is Random)} xywh {185 20 30 30} box ROUND_UP_BOX labelsize 10 maximum 127 step 1 - code0 {o->value(pars->PPanning);} - class WidgetPDial - } - Fl_Group ampenv { - label {SUBsynth - Amplitude Envelope} open - xywh {10 65 205 70} box FLAT_BOX color 51 align 144 - code0 {o->init(pars->AmpEnvelope);} - class EnvelopeUI - } {} - } - Fl_Group {} { - xywh {495 325 235 35} box THIN_UP_FRAME - } { - Fl_Counter filterstages { - label {Filter Stages} - callback {pars->Pnumstages=(int) o->value();} - tooltip {How many times the noise is filtered} xywh {515 340 45 15} type Simple labelfont 1 labelsize 10 align 1 minimum 1 maximum 5 step 1 textsize 10 - code0 {o->value(pars->Pnumstages);} - } - Fl_Choice magtype { - label {Mag.Type} - callback {pars->Phmagtype=(int) o->value();} - xywh {585 340 65 15} down_box BORDER_BOX labelfont 1 labelsize 10 align 1 textsize 11 - code0 {o->value(pars->Phmagtype);} - } { - menuitem {} { - label Linear - xywh {20 20 100 20} labelfont 1 labelsize 11 - } - menuitem {} { - label {-40dB} - xywh {30 30 100 20} labelfont 1 labelsize 11 - } - menuitem {} { - label {-60dB} - xywh {40 40 100 20} labelfont 1 labelsize 11 - } - menuitem {} { - label {-80dB} - xywh {50 50 100 20} labelfont 1 labelsize 11 - } - menuitem {} { - label {-100dB} - xywh {60 60 100 20} labelfont 1 labelsize 11 - } - } - Fl_Choice start { - label Start - callback {pars->Pstart=(int) o->value();} open - xywh {670 340 50 15} down_box BORDER_BOX labelfont 1 labelsize 10 align 1 textsize 11 - code0 {o->value(pars->Pstart);} - } { - menuitem {} { - label Zero - xywh {30 30 100 20} labelfont 1 labelsize 11 - } - menuitem {} { - label RND - xywh {40 40 100 20} labelfont 1 labelsize 11 - } - menuitem {} { - label {Max.} - xywh {50 50 100 20} labelfont 1 labelsize 11 - } - } - } - Fl_Group freqsettingsui { - label FREQUENCY - xywh {440 5 290 135} box THIN_UP_FRAME labeltype EMBOSSED_LABEL labelfont 1 align 17 - } { - Fl_Group freqenvelopegroup { - label {SUBsynth - Frequency Envelope} open - xywh {445 65 205 70} box FLAT_BOX color 51 align 144 - code0 {o->init(pars->FreqEnvelope);} - code1 {if (pars->PFreqEnvelopeEnabled==0) o->deactivate();} - class EnvelopeUI - } {} - Fl_Check_Button freqee { - label Enabled - callback {pars->PFreqEnvelopeEnabled=o->value(); -if (o->value()==0) freqenvelopegroup->deactivate(); - else freqenvelopegroup->activate(); -o->show(); -freqsettingsui->redraw();} - xywh {445 68 55 15} down_box DOWN_BOX labelfont 1 labelsize 10 - code0 {o->value(pars->PFreqEnvelopeEnabled);} - } - Fl_Counter octave { - label Octave - callback {int k=(int) o->value(); -if (k<0) k+=16; -pars->PCoarseDetune = k*1024+ - pars->PCoarseDetune%1024;} - tooltip Octave xywh {670 50 45 15} type Simple labelsize 10 align 1 minimum -8 maximum 7 step 1 textfont 1 textsize 11 - code0 {int k=pars->PCoarseDetune/1024;if (k>=8) k-=16;} - code2 {o->value(k);} - } - Fl_Counter coarsedet { - label {Coarse Det.} - callback {int k=(int) o->value(); -if (k<0) k+=1024; -pars->PCoarseDetune = k+ - (pars->PCoarseDetune/1024)*1024;} - tooltip {Coarse Detune} xywh {655 115 60 20} labelsize 10 align 1 minimum -64 maximum 63 step 1 textfont 1 textsize 11 - code0 {int k=pars->PCoarseDetune%1024;if (k>=512) k-=1024;} - code2 {o->value(k);} - code3 {o->lstep(10);} - } - Fl_Slider detune { - callback {pars->PDetune=(int)o->value()+8192; -detunevalueoutput->do_callback();} - tooltip {Fine Detune (cents)} xywh {495 25 230 15} type {Horz Knob} box FLAT_BOX minimum -8192 maximum 8191 step 1 - code0 {o->value(pars->PDetune-8192);} - } - Fl_Value_Output detunevalueoutput { - label Detune - callback {o->value(getdetune(pars->PDetuneType,0,pars->PDetune));} - xywh {448 25 45 15} labelsize 10 align 5 minimum -5000 maximum 5000 step 0.01 textfont 1 textsize 10 - code0 {o->value(getdetune(pars->PDetuneType,0,pars->PDetune));} - } - Fl_Check_Button hz440 { - label 440Hz - callback {int x=(int) o->value(); -pars->Pfixedfreq=x; -if (x==0) fixedfreqetdial->deactivate(); - else fixedfreqetdial->activate();} - tooltip {set the base frequency to 440Hz} xywh {555 45 50 15} down_box DOWN_BOX labelfont 1 labelsize 10 - code0 {o->value(pars->Pfixedfreq);} - } - Fl_Dial fixedfreqetdial { - label {Eq.T.} - callback {pars->PfixedfreqET=(int) o->value();} - tooltip {How the frequency varies acording to the keyboard (leftmost for fixed frequency)} xywh {610 45 15 15} box ROUND_UP_BOX labelsize 10 align 8 maximum 127 step 1 - code0 {o->value(pars->PfixedfreqET);} - code1 {if (pars->Pfixedfreq==0) o->deactivate();} - class WidgetPDial - } - Fl_Choice detunetype { - label {Detune Type} - callback {pars->PDetuneType=(int) o->value()+1; -detunevalueoutput->do_callback();} open - xywh {655 85 70 15} down_box BORDER_BOX labelsize 10 align 5 textfont 1 textsize 10 - code0 {o->add("L35cents");o->add("L10cents");o->add("E100cents");o->add("E1200cents");} - code1 {o->value(pars->PDetuneType-1);} - } {} - } - Fl_Check_Button stereo { - label Stereo - callback {pars->Pstereo=(int) o->value();} - xywh {440 325 55 35} box THIN_UP_BOX down_box DOWN_BOX labelfont 1 labelsize 10 - code0 {o->value(pars->Pstereo);} - } - Fl_Button {} { - label Clear - callback {for (int i=0;imag->value(127); - pars->Phmag[i]=0; - h[i]->bw->value(64); - pars->Phrelbw[i]=64; -}; -pars->Phmag[0]=127; -h[0]->mag->value(0); -SUBparameters->redraw();} - tooltip {Clear the harmonics} xywh {445 365 70 20} box THIN_UP_BOX labelfont 1 labelsize 11 - } - Fl_Group bandwidthsettingsui { - label BANDWIDTH - xywh {220 5 220 135} box THIN_UP_FRAME labeltype EMBOSSED_LABEL labelfont 1 align 17 - } { - Fl_Group bandwidthenvelopegroup { - label {SUBsynth - BandWidth Envelope} open - xywh {225 65 205 70} box FLAT_BOX color 51 align 144 - code0 {o->init(pars->BandWidthEnvelope);} - code1 {if (pars->PBandWidthEnvelopeEnabled==0) o->deactivate();} - class EnvelopeUI - } {} - Fl_Check_Button bwee { - label Enabled - callback {pars->PBandWidthEnvelopeEnabled=o->value(); -if (o->value()==0) bandwidthenvelopegroup->deactivate(); - else bandwidthenvelopegroup->activate(); -o->show(); -bandwidthsettingsui->redraw();} - xywh {225 67 55 15} down_box DOWN_BOX labelfont 1 labelsize 10 - code0 {o->value(pars->PBandWidthEnvelopeEnabled);} - } - Fl_Value_Slider bandwidth { - label {Band Width} - callback {pars->Pbandwidth=(int) o->value();} - xywh {225 40 115 15} type {Horz Knob} box FLAT_BOX labelsize 10 align 1 maximum 127 step 1 - code0 {o->value(pars->Pbandwidth);} - } - Fl_Value_Slider bwidthscale { - label {B.Width Scale} - callback {pars->Pbwscale=(int) o->value()+64;} - tooltip {How much I increase the BandWidth according to lower/higher harmonics} xywh {345 40 90 15} type {Horz Knob} box FLAT_BOX labelsize 10 align 1 minimum -64 maximum 63 step 1 - code0 {o->value(pars->Pbwscale-64);} - } - } - Fl_Group globalfiltergroup { - label FILTER - xywh {440 140 290 185} box THIN_UP_FRAME labeltype EMBOSSED_LABEL labelfont 1 labelsize 13 align 17 - code0 {if (pars->PGlobalFilterEnabled==0) o->deactivate();} - } { - Fl_Group filterenv { - label {SUBsynth - Filter Envelope} open - xywh {445 250 275 70} box FLAT_BOX color 51 align 144 - code0 {o->init(pars->GlobalFilterEnvelope);} - class EnvelopeUI - } {} - Fl_Group filterui { - label {SUBsynthl - Filter} open - xywh {445 170 275 75} box FLAT_BOX color 50 align 144 - code0 {o->init(pars->GlobalFilter,&pars->PGlobalFilterVelocityScale,&pars->PGlobalFilterVelocityScaleFunction);} - class FilterUI - } {} - } - Fl_Check_Button filtere { - label Enabled - callback {pars->PGlobalFilterEnabled=o->value(); -if (o->value()==0) globalfiltergroup->deactivate(); - else globalfiltergroup->activate(); -o->show(); -globalfiltergroup->redraw();} - xywh {445 145 85 20} down_box DOWN_BOX labelfont 1 labelsize 11 - code0 {o->value(pars->PGlobalFilterEnabled);} - } - Fl_Button {} { - label C - callback {presetsui->copy(pars);} - xywh {540 370 25 15} box THIN_UP_BOX color 179 labelfont 1 labelsize 11 labelcolor 7 - } - Fl_Button {} { - label P - callback {presetsui->paste(pars,this);} - xywh {570 370 25 15} box THIN_UP_BOX color 179 labelfont 1 labelsize 11 labelcolor 7 - } - } - } - Function {refresh()} {} { - code {for (int i=0;irefresh(); -vol->value(pars->PVolume); -vsns->value(pars->PAmpVelocityScaleFunction); -pan->value(pars->PPanning); - - -bandwidth->value(pars->Pbandwidth); -bwidthscale->value(pars->Pbwscale-64); -bwee->value(pars->PBandWidthEnvelopeEnabled); -if (pars->PBandWidthEnvelopeEnabled==0) bandwidthenvelopegroup->deactivate(); - else bandwidthenvelopegroup->activate(); -bwee->show(); -bandwidthsettingsui->redraw(); - -detunevalueoutput->value(getdetune(pars->PDetuneType,0,pars->PDetune)); -freqee->value(pars->PFreqEnvelopeEnabled); -if (pars->PFreqEnvelopeEnabled==0) freqenvelopegroup->deactivate(); - else freqenvelopegroup->activate(); -freqee->show(); -freqsettingsui->redraw(); - -detune->value(pars->PDetune-8192); -hz440->value(pars->Pfixedfreq); - -fixedfreqetdial->value(pars->PfixedfreqET); - -int k=pars->PCoarseDetune/1024;if (k>=8) k-=16; -octave->value(k); - -detunetype->value(pars->PDetuneType-1); - -k=pars->PCoarseDetune%1024;if (k>=512) k-=1024; -coarsedet->value(k); - -filtere->value(pars->PGlobalFilterEnabled); -if (pars->PGlobalFilterEnabled==0) globalfiltergroup->deactivate(); - else globalfiltergroup->activate(); -filtere->show(); -globalfiltergroup->redraw(); - -stereo->value(pars->Pstereo); -filterstages->value(pars->Pnumstages); -magtype->value(pars->Phmagtype); -start->value(pars->Pstart); - -ampenv->refresh(); -bandwidthenvelopegroup->refresh(); -freqenvelopegroup->refresh(); -filterui->refresh(); -filterenv->refresh();} {} - } - Function {SUBnoteUI(SUBnoteParameters *parameters)} {} { - code {pars=parameters; -make_window();} {} - } - Function {~SUBnoteUI()} {} { - code {//for (int i=0;ihide(); -delete(SUBparameters);} {} - } - decl {SUBnoteParameters *pars;} {} - decl {SUBnoteharmonic *h[MAX_SUB_HARMONICS];} {} -} diff --git a/plugins/zynaddsubfx/src/UI/SUBnoteUI.h b/plugins/zynaddsubfx/src/UI/SUBnoteUI.h deleted file mode 100644 index 569e69d3a..000000000 --- a/plugins/zynaddsubfx/src/UI/SUBnoteUI.h +++ /dev/null @@ -1,179 +0,0 @@ -// generated by Fast Light User Interface Designer (fluid) version 1.0300 - -#ifndef SUBnoteUI_h -#define SUBnoteUI_h -#include -#include -#include -#include -#include "../globals.h" -#include "WidgetPDial.h" -#include "EnvelopeUI.h" -#include "FilterUI.h" -#include "../Misc/Util.h" -#include "../Params/SUBnoteParameters.h" -#include "PresetsUI.h" -#include -#include - -class SUBnoteharmonic : public Fl_Group { - Fl_Group* make_window(); -public: - Fl_Group *harmonic; - Fl_Slider *mag; -private: - void cb_mag_i(Fl_Slider*, void*); - static void cb_mag(Fl_Slider*, void*); -public: - Fl_Slider *bw; -private: - void cb_bw_i(Fl_Slider*, void*); - static void cb_bw(Fl_Slider*, void*); -public: - SUBnoteharmonic(int x,int y, int w, int h, const char *label=0); - void init(SUBnoteParameters *pars_,int n_); - void refresh(); - ~SUBnoteharmonic(); -private: - SUBnoteParameters *pars; - int n; -}; -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -class SUBnoteUI : public PresetsUI_ { -public: - Fl_Double_Window* make_window(); - Fl_Double_Window *SUBparameters; - Fl_Pack *harmonics; -private: - void cb_Close_i(Fl_Button*, void*); - static void cb_Close(Fl_Button*, void*); -public: - Fl_Value_Slider *vol; -private: - void cb_vol_i(Fl_Value_Slider*, void*); - static void cb_vol(Fl_Value_Slider*, void*); -public: - Fl_Value_Slider *vsns; -private: - void cb_vsns_i(Fl_Value_Slider*, void*); - static void cb_vsns(Fl_Value_Slider*, void*); -public: - WidgetPDial *pan; -private: - void cb_pan_i(WidgetPDial*, void*); - static void cb_pan(WidgetPDial*, void*); -public: - EnvelopeUI *ampenv; - Fl_Counter *filterstages; -private: - void cb_filterstages_i(Fl_Counter*, void*); - static void cb_filterstages(Fl_Counter*, void*); -public: - Fl_Choice *magtype; -private: - void cb_magtype_i(Fl_Choice*, void*); - static void cb_magtype(Fl_Choice*, void*); - static Fl_Menu_Item menu_magtype[]; -public: - Fl_Choice *start; -private: - void cb_start_i(Fl_Choice*, void*); - static void cb_start(Fl_Choice*, void*); - static Fl_Menu_Item menu_start[]; -public: - Fl_Group *freqsettingsui; - EnvelopeUI *freqenvelopegroup; - Fl_Check_Button *freqee; -private: - void cb_freqee_i(Fl_Check_Button*, void*); - static void cb_freqee(Fl_Check_Button*, void*); -public: - Fl_Counter *octave; -private: - void cb_octave_i(Fl_Counter*, void*); - static void cb_octave(Fl_Counter*, void*); -public: - Fl_Counter *coarsedet; -private: - void cb_coarsedet_i(Fl_Counter*, void*); - static void cb_coarsedet(Fl_Counter*, void*); -public: - Fl_Slider *detune; -private: - void cb_detune_i(Fl_Slider*, void*); - static void cb_detune(Fl_Slider*, void*); -public: - Fl_Value_Output *detunevalueoutput; -private: - void cb_detunevalueoutput_i(Fl_Value_Output*, void*); - static void cb_detunevalueoutput(Fl_Value_Output*, void*); -public: - Fl_Check_Button *hz440; -private: - void cb_hz440_i(Fl_Check_Button*, void*); - static void cb_hz440(Fl_Check_Button*, void*); -public: - WidgetPDial *fixedfreqetdial; -private: - void cb_fixedfreqetdial_i(WidgetPDial*, void*); - static void cb_fixedfreqetdial(WidgetPDial*, void*); -public: - Fl_Choice *detunetype; -private: - void cb_detunetype_i(Fl_Choice*, void*); - static void cb_detunetype(Fl_Choice*, void*); -public: - Fl_Check_Button *stereo; -private: - void cb_stereo_i(Fl_Check_Button*, void*); - static void cb_stereo(Fl_Check_Button*, void*); - void cb_Clear_i(Fl_Button*, void*); - static void cb_Clear(Fl_Button*, void*); -public: - Fl_Group *bandwidthsettingsui; - EnvelopeUI *bandwidthenvelopegroup; - Fl_Check_Button *bwee; -private: - void cb_bwee_i(Fl_Check_Button*, void*); - static void cb_bwee(Fl_Check_Button*, void*); -public: - Fl_Value_Slider *bandwidth; -private: - void cb_bandwidth_i(Fl_Value_Slider*, void*); - static void cb_bandwidth(Fl_Value_Slider*, void*); -public: - Fl_Value_Slider *bwidthscale; -private: - void cb_bwidthscale_i(Fl_Value_Slider*, void*); - static void cb_bwidthscale(Fl_Value_Slider*, void*); -public: - Fl_Group *globalfiltergroup; - EnvelopeUI *filterenv; - FilterUI *filterui; - Fl_Check_Button *filtere; -private: - void cb_filtere_i(Fl_Check_Button*, void*); - static void cb_filtere(Fl_Check_Button*, void*); - void cb_C_i(Fl_Button*, void*); - static void cb_C(Fl_Button*, void*); - void cb_P_i(Fl_Button*, void*); - static void cb_P(Fl_Button*, void*); -public: - void refresh(); - SUBnoteUI(SUBnoteParameters *parameters); - ~SUBnoteUI(); -private: - SUBnoteParameters *pars; - SUBnoteharmonic *h[MAX_SUB_HARMONICS]; -}; -#endif diff --git a/plugins/zynaddsubfx/src/UI/SeqUI.cc b/plugins/zynaddsubfx/src/UI/SeqUI.cc deleted file mode 100644 index d48fd4de6..000000000 --- a/plugins/zynaddsubfx/src/UI/SeqUI.cc +++ /dev/null @@ -1,98 +0,0 @@ -// generated by Fast Light User Interface Designer (fluid) version 1.0300 - -#include "SeqUI.h" -//Copyright (c) 2002-2005 Nasca Octavian Paul -//License: GNU GPL version 2 or later - -void SeqUI::cb_playbutton_i(Fl_Button* o, void*) { - o->deactivate(); -stopbutton_play->activate(); - -master->seq.startplay(); -} -void SeqUI::cb_playbutton(Fl_Button* o, void* v) { - ((SeqUI*)(o->parent()->parent()->user_data()))->cb_playbutton_i(o,v); -} - -void SeqUI::cb_stopbutton_play_i(Fl_Button* o, void*) { - o->deactivate(); -playbutton->activate(); - -master->seq.stopplay(); -} -void SeqUI::cb_stopbutton_play(Fl_Button* o, void* v) { - ((SeqUI*)(o->parent()->parent()->user_data()))->cb_stopbutton_play_i(o,v); -} - -void SeqUI::cb_Open_i(Fl_Button*, void*) { - master->seq.importmidifile("test.mid"); -} -void SeqUI::cb_Open(Fl_Button* o, void* v) { - ((SeqUI*)(o->parent()->user_data()))->cb_Open_i(o,v); -} - -void SeqUI::cb_Play_i(Fl_Value_Slider* o, void*) { - master->seq.setplayspeed((int) o->value()); -} -void SeqUI::cb_Play(Fl_Value_Slider* o, void* v) { - ((SeqUI*)(o->parent()->user_data()))->cb_Play_i(o,v); -} - -Fl_Double_Window* SeqUI::make_window() { - { seqwin = new Fl_Double_Window(280, 265, "Sequencer - ZynAddSubFX"); - seqwin->user_data((void*)(this)); - { Fl_Group* o = new Fl_Group(120, 20, 100, 65, "Player"); - o->box(FL_ENGRAVED_BOX); - o->labelfont(1); - { playbutton = new Fl_Button(130, 30, 30, 30, "Play"); - playbutton->tooltip("Start Playing"); - playbutton->box(FL_DIAMOND_UP_BOX); - playbutton->color((Fl_Color)79); - playbutton->labelfont(1); - playbutton->labelsize(13); - playbutton->callback((Fl_Callback*)cb_playbutton); - playbutton->align(Fl_Align(FL_ALIGN_BOTTOM)); - } // Fl_Button* playbutton - { stopbutton_play = new Fl_Button(175, 29, 30, 31, "Stop"); - stopbutton_play->tooltip("Stop Playing"); - stopbutton_play->box(FL_THIN_UP_BOX); - stopbutton_play->color((Fl_Color)4); - stopbutton_play->labelfont(1); - stopbutton_play->labelsize(13); - stopbutton_play->callback((Fl_Callback*)cb_stopbutton_play); - stopbutton_play->align(Fl_Align(FL_ALIGN_BOTTOM)); - stopbutton_play->deactivate(); - } // Fl_Button* stopbutton_play - o->end(); - } // Fl_Group* o - { Fl_Button* o = new Fl_Button(20, 25, 75, 55, "Open test.mid"); - o->callback((Fl_Callback*)cb_Open); - o->align(Fl_Align(FL_ALIGN_WRAP)); - } // Fl_Button* o - { Fl_Value_Slider* o = new Fl_Value_Slider(15, 105, 190, 20, "Play speed"); - o->type(5); - o->minimum(-128); - o->maximum(128); - o->step(1); - o->callback((Fl_Callback*)cb_Play); - o->value(master->seq.playspeed); - } // Fl_Value_Slider* o - { Fl_Box* o = new Fl_Box(25, 155, 225, 90, "This is not finished"); - o->labelfont(1); - o->labelsize(22); - o->align(Fl_Align(FL_ALIGN_WRAP)); - } // Fl_Box* o - seqwin->end(); - } // Fl_Double_Window* seqwin - return seqwin; -} - -SeqUI::SeqUI(Master *master_) { - master=master_; - - make_window(); -} - -void SeqUI::show() { - seqwin->show(); -} diff --git a/plugins/zynaddsubfx/src/UI/SeqUI.fl b/plugins/zynaddsubfx/src/UI/SeqUI.fl deleted file mode 100644 index 343719c65..000000000 --- a/plugins/zynaddsubfx/src/UI/SeqUI.fl +++ /dev/null @@ -1,73 +0,0 @@ -# data file for the Fltk User Interface Designer (fluid) -version 1.0105 -header_name {.h} -code_name {.cc} -decl {//Copyright (c) 2002-2005 Nasca Octavian Paul} {} - -decl {//License: GNU GPL version 2 or later} {} - -decl {\#include "../globals.h"} {public -} - -decl {\#include "../Misc/Master.h"} {public -} - -decl {\#include "WidgetPDial.h"} {public -} - -class SeqUI {} { - Function {make_window()} {} { - Fl_Window seqwin { - label {Sequencer - ZynAddSubFX} - xywh {104 235 280 265} type Double hide - } { - Fl_Group {} { - label Player - xywh {120 20 100 65} box ENGRAVED_BOX labelfont 1 - } { - Fl_Button playbutton { - label Play - callback {o->deactivate(); -stopbutton_play->activate(); - -master->seq.startplay();} - tooltip {Start Playing} xywh {130 30 30 30} box DIAMOND_UP_BOX color 79 labelfont 1 labelsize 13 align 2 - } - Fl_Button stopbutton_play { - label Stop - callback {o->deactivate(); -playbutton->activate(); - -master->seq.stopplay();} - tooltip {Stop Playing} xywh {175 29 30 31} box THIN_UP_BOX color 4 labelfont 1 labelsize 13 align 2 deactivate - } - } - Fl_Button {} { - label {Open test.mid} - callback {master->seq.importmidifile("test.mid");} - xywh {20 25 75 55} align 128 - } - Fl_Value_Slider {} { - label {Play speed} - callback {master->seq.setplayspeed((int) o->value());} - xywh {15 105 190 20} type {Horz Knob} minimum -128 maximum 128 step 1 - code0 {o->value(master->seq.playspeed);} - } - Fl_Box {} { - label {This is not finished} selected - xywh {25 155 225 90} labelfont 1 labelsize 22 align 128 - } - } - } - Function {SeqUI(Master *master_)} {open - } { - code {master=master_; - -make_window();} {} - } - decl {Master *master} {} - Function {show()} {open - } { - code {seqwin->show();} {} - } -} diff --git a/plugins/zynaddsubfx/src/UI/SeqUI.h b/plugins/zynaddsubfx/src/UI/SeqUI.h deleted file mode 100644 index 0cdad0544..000000000 --- a/plugins/zynaddsubfx/src/UI/SeqUI.h +++ /dev/null @@ -1,39 +0,0 @@ -// generated by Fast Light User Interface Designer (fluid) version 1.0300 - -#ifndef SeqUI_h -#define SeqUI_h -#include -#include "../globals.h" -#include "../Misc/Master.h" -#include "WidgetPDial.h" -#include -#include -#include -#include -#include - -class SeqUI { -public: - Fl_Double_Window* make_window(); - Fl_Double_Window *seqwin; - Fl_Button *playbutton; -private: - void cb_playbutton_i(Fl_Button*, void*); - static void cb_playbutton(Fl_Button*, void*); -public: - Fl_Button *stopbutton_play; -private: - void cb_stopbutton_play_i(Fl_Button*, void*); - static void cb_stopbutton_play(Fl_Button*, void*); - void cb_Open_i(Fl_Button*, void*); - static void cb_Open(Fl_Button*, void*); - void cb_Play_i(Fl_Value_Slider*, void*); - static void cb_Play(Fl_Value_Slider*, void*); -public: - SeqUI(Master *master_); -private: - Master *master; -public: - void show(); -}; -#endif diff --git a/plugins/zynaddsubfx/src/UI/VirKeyboard.cc b/plugins/zynaddsubfx/src/UI/VirKeyboard.cc deleted file mode 100644 index 8e6d2eee8..000000000 --- a/plugins/zynaddsubfx/src/UI/VirKeyboard.cc +++ /dev/null @@ -1,499 +0,0 @@ -// generated by Fast Light User Interface Designer (fluid) version 1.0300 - -#include "VirKeyboard.h" -//Copyright (c) 2002-2005 Nasca Octavian Paul -//License: GNU GPL version 2 or later -static const int keyspos[12]={0,-1,1,-2,2,3,-4,4,-5,5,-6,6}; -static const int keysoct1qwerty[]={'q','2','w','3','e','r','5','t','6','y','7','u','i','9','o','0','p','[','=',']','\\',FL_Enter,0}; -static const int keysoct2qwerty[]={'z','s','x','d','c','v','g','b','h','n','j','m',',','l','.',';','/',0}; -static const int keysoct1dw[]={'\'','2',',','3','.','p','5','y','6','f','7','g','c','9','r','0','l','/',']','=','\\',FL_Enter,0}; -static const int keysoct2dw[]={';','o','q','e','j','k','i','x','d','b','h','m','w','n','v','s','z',0}; -static const int keysoct1qwertz[]={'q','2','w','3','e','r','5','t','6','z','7','u','i','9','o','0','p',252,'\'','+','\\',FL_Enter,0}; -static const int keysoct2qwertz[]={'y','s','x','d','c','v','g','b','h','n','j','m',',','l','.',246,'-',0}; -static const int keysoct1az[]={'a',233,'z','\"','e','r','(','t','-','y',232,'u','i',231,'o',224,'p',65106,'=','$',0}; -static const int keysoct2az[]={'w','s','x','d','c','v','g','b','h','n','j',',',';','l',':','m','!',0}; - -VirKeys::VirKeys(int x,int y, int w, int h, const char *label):Fl_Box(x,y,w,h,label) { - master=NULL; -} - -void VirKeys::init(Master *master_) { - master=master_; - for (int i=0;i=0){//white keys - if (pressed[i]==0) fl_color(250,240,230); - else fl_color(FL_BLUE); - fl_rectf(ox+(kv+7*noct)*SIZE_WHITE+3,oy+ly*3/5+2, - SIZE_WHITE-4,ly*2/5-3); - } else {//black keys - kv=keyspos[(i+1)%12]; - if (pressed[i]==0) fl_color(FL_BLACK); - else fl_color(FL_BLUE); - fl_rectf(ox+(kv+7*noct)*SIZE_WHITE-SIZE_BLACK/2+2,oy+2, - SIZE_BLACK-3,ly*3/5-5); - }; - }; -} - -int VirKeys::handle(int event) { - int i; - int ly=h(); - int x_=Fl::event_x()-x(); - int y_=Fl::event_y()-y(); - if ( (x_<0)&&(x_>w()) && (y_<0)&&(y_>h())){ - return(0); - }; - - - if ((event==FL_PUSH)||(event==FL_DRAG)||(event==FL_RELEASE)){ - int kpos=-1; - - if (y_>ly*3/5){//white keys - int pos=x_/SIZE_WHITE; - if (pos<0) return(1); - for (i=0;i<12;i++) { - if (pos%7==keyspos[i]) { - kpos=pos/7*12+i; - break; - }; - }; - } else {//black keys - int pos=(x_+SIZE_WHITE/2)/SIZE_WHITE; - if (pos<0) return(1); - for (i=1;i<12;i++) { - if (pos%7==-keyspos[i]) { - kpos=pos/7*12+i; - break; - }; - }; - }; - - if ((kpos!=-1)&&((event==FL_PUSH)||(event==FL_DRAG))&& - (Fl::event_shift()==0)) { - presskey(kpos,1,1); - }; - - if ((event==FL_PUSH)&&(Fl::event_shift()!=0)) { - if (pressed[kpos]==0) presskey(kpos,0,1); - else relasekey(kpos,1); - }; - if ((event==FL_RELEASE)&&(Fl::event_shift()==0)) - relaseallkeys(1); - take_focus(); - }; - - - const int *keysoct1=keysoct1qwerty; - const int *keysoct2=keysoct2qwerty; - - if (config.cfg.VirKeybLayout==2) { - keysoct1=keysoct1dw; - keysoct2=keysoct2dw; - }else if (config.cfg.VirKeybLayout==3) { - keysoct1=keysoct1qwertz; - keysoct2=keysoct2qwertz; - }else if (config.cfg.VirKeybLayout==4) { - keysoct1=keysoct1az; - keysoct2=keysoct2az; - }; - - if ((event==FL_KEYDOWN)||(event==FL_KEYUP)){ - int key=Fl::event_key(); - int kpos=-1; - for (i=0;keysoct1[i]!=0;i++) if (key==keysoct1[i]) kpos=i+12*keyoct1; - for (i=0;keysoct2[i]!=0;i++) if (key==keysoct2[i]) kpos=i+12*keyoct2; - - - - - if (kpos==-1) return(0); - if ((event==FL_KEYUP) && (Fl::event_key(key)==0) && (Fl::get_key(key)!=0)) return(0); - if (event==FL_KEYDOWN) presskey(kpos,0,2); - else relasekey(kpos,2); - }; - - return(1); -} - -void VirKeys::presskey(int nk,int exclusive,int type) { - //Exclusive means that multiple keys can be pressed at once - //when the user uses the shift key - if (nk>=N_OCT*12) return; - if ((nk<0)&&(exclusive==0)) { - relaseallkeys(type); - return; - }; - if (nk<0) return; - if (pressed[nk]!=0) return;//the key is already pressed - - if (exclusive!=0) relaseallkeys(type); - pressed[nk]=type; - - damage(1); - float vel=midivel; - if (rndvelocity!=0){ - vel=midivel*(127.0-rndvelocity)/127.0+RND*rndvelocity; - }; - - pthread_mutex_lock(&master->mutex); - master->NoteOn(midich,nk+midioct*12,(int)vel); - pthread_mutex_unlock(&master->mutex); -} - -void VirKeys::relasekey(int nk,int type) { - if ((nk<0)||(nk>=N_OCT*12)) return; - if (pressed[nk]==0) return;//the key is not pressed - if ((type!=0)&&(pressed[nk]!=type)) return; - - pressed[nk]=0; - - - damage(1); - - pthread_mutex_lock(&master->mutex); - master->NoteOff(midich,nk+12*midioct); - pthread_mutex_unlock(&master->mutex); -} - -void VirKeys::relaseallkeys(int type) { - for (int i=0;ihide(); -} -void VirKeyboard::cb_virkeyboardwindow(Fl_Double_Window* o, void* v) { - ((VirKeyboard*)(o->user_data()))->cb_virkeyboardwindow_i(o,v); -} - -void VirKeyboard::cb_qwer_i(Fl_Counter* o, void*) { - relaseallkeys(); -virkeys->keyoct1=(int) o->value(); -virkeys->take_focus(); -} -void VirKeyboard::cb_qwer(Fl_Counter* o, void* v) { - ((VirKeyboard*)(o->parent()->user_data()))->cb_qwer_i(o,v); -} - -void VirKeyboard::cb_zxcv_i(Fl_Counter* o, void*) { - relaseallkeys(); -virkeys->keyoct2=(int) o->value(); -virkeys->take_focus(); -} -void VirKeyboard::cb_zxcv(Fl_Counter* o, void* v) { - ((VirKeyboard*)(o->parent()->user_data()))->cb_zxcv_i(o,v); -} - -void VirKeyboard::cb_Vel_i(Fl_Value_Slider* o, void*) { - virkeys->midivel=(int) o->value(); -virkeys->take_focus(); -} -void VirKeyboard::cb_Vel(Fl_Value_Slider* o, void* v) { - ((VirKeyboard*)(o->parent()->user_data()))->cb_Vel_i(o,v); -} - -void VirKeyboard::cb_Oct_i(Fl_Counter* o, void*) { - relaseallkeys(); -virkeys->midioct=(int) o->value(); -virkeys->take_focus(); -} -void VirKeyboard::cb_Oct(Fl_Counter* o, void* v) { - ((VirKeyboard*)(o->parent()->user_data()))->cb_Oct_i(o,v); -} - -void VirKeyboard::cb_Close_i(Fl_Button*, void*) { - relaseallkeys(); -virkeyboardwindow->hide(); -} -void VirKeyboard::cb_Close(Fl_Button* o, void* v) { - ((VirKeyboard*)(o->parent()->user_data()))->cb_Close_i(o,v); -} - -void VirKeyboard::cb_Cval_i(Fl_Value_Slider* o, void*) { - int ctl=midictl; - -pthread_mutex_lock(&master->mutex); - master->SetController(virkeys->midich,ctl,(int) o->value()); -pthread_mutex_unlock(&master->mutex); -virkeys->take_focus(); -} -void VirKeyboard::cb_Cval(Fl_Value_Slider* o, void* v) { - ((VirKeyboard*)(o->parent()->user_data()))->cb_Cval_i(o,v); -} - -void VirKeyboard::cb_Controller_i(Fl_Choice* o, void*) { - switch((int) o->value()+1){ - case 1: midictl=C_modwheel; break; - case 2: midictl=C_volume; break; - case 3: midictl=C_panning; break; - case 4: midictl=C_expression; break; - case 5: midictl=C_sustain; break; - case 6: midictl=C_portamento; break; - case 7: midictl=C_filterq; break; - case 8: midictl=C_filtercutoff; break; - case 9: midictl=C_bandwidth; break; - case 10: midictl=C_fmamp; break; - case 11: midictl=C_resonance_center; break; - case 12: midictl=C_resonance_bandwidth; break; - default: midictl=C_NULL; break; - -}; - - - -virkeys->take_focus(); -} -void VirKeyboard::cb_Controller(Fl_Choice* o, void* v) { - ((VirKeyboard*)(o->parent()->user_data()))->cb_Controller_i(o,v); -} - -Fl_Menu_Item VirKeyboard::menu_Controller[] = { - {"01: Mod.Wheel", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {"07: Volume", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {"10: Panning", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {"11: Expression", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {"64: Sustain", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {"65: Portamento", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {"71: Filter Q", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {"74: Filter Freq.", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {"75: Bandwidth", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {"76: FM Gain", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {"77: Res. c. freq", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {"78: Res. bw.", 0, 0, 0, 0, FL_NORMAL_LABEL, 1, 10, 0}, - {0,0,0,0,0,0,0,0,0} -}; - -void VirKeyboard::cb_pitchwheelroller_i(Fl_Roller* o, void*) { - pthread_mutex_lock(&master->mutex); - master->SetController(virkeys->midich,C_pitchwheel,-(int) o->value()); -pthread_mutex_unlock(&master->mutex); -virkeys->take_focus(); -} -void VirKeyboard::cb_pitchwheelroller(Fl_Roller* o, void* v) { - ((VirKeyboard*)(o->parent()->user_data()))->cb_pitchwheelroller_i(o,v); -} - -void VirKeyboard::cb_R_i(Fl_Button*, void*) { - pitchwheelroller->value(0); -pitchwheelroller->do_callback(); -} -void VirKeyboard::cb_R(Fl_Button* o, void* v) { - ((VirKeyboard*)(o->parent()->user_data()))->cb_R_i(o,v); -} - -void VirKeyboard::cb_Vrnd_i(WidgetPDial* o, void*) { - virkeys->rndvelocity=(int) o->value(); -} -void VirKeyboard::cb_Vrnd(WidgetPDial* o, void* v) { - ((VirKeyboard*)(o->parent()->user_data()))->cb_Vrnd_i(o,v); -} - -void VirKeyboard::cb_partrcv_i(Fl_Choice* o, void*) { - relaseallkeys(); -virkeys->midich=(int) o->value(); -virkeys->take_focus(); -} -void VirKeyboard::cb_partrcv(Fl_Choice* o, void* v) { - ((VirKeyboard*)(o->parent()->user_data()))->cb_partrcv_i(o,v); -} - -Fl_Double_Window* VirKeyboard::make_window() { - { virkeyboardwindow = new Fl_Double_Window(650, 130, "Virtual Keyboard - ZynAddSubFX"); - virkeyboardwindow->callback((Fl_Callback*)cb_virkeyboardwindow, (void*)(this)); - { VirKeys* o = virkeys = new VirKeys(10, 10, 590, 80, "Keyboard"); - virkeys->box(FL_FLAT_BOX); - virkeys->color((Fl_Color)17); - virkeys->selection_color(FL_BACKGROUND_COLOR); - virkeys->labeltype(FL_NORMAL_LABEL); - virkeys->labelfont(0); - virkeys->labelsize(14); - virkeys->labelcolor(FL_FOREGROUND_COLOR); - virkeys->align(Fl_Align(FL_ALIGN_CENTER)); - virkeys->when(FL_WHEN_RELEASE); - o->init(master); - } // VirKeys* virkeys - { Fl_Counter* o = new Fl_Counter(380, 95, 45, 15, "\"qwer..\" Oct"); - o->tooltip("keys \"q2w3er5t6y...\" octave"); - o->type(1); - o->labelsize(10); - o->minimum(0); - o->maximum(5); - o->step(1); - o->textfont(1); - o->textsize(10); - o->callback((Fl_Callback*)cb_qwer); - o->align(Fl_Align(FL_ALIGN_LEFT)); - o->when(FL_WHEN_RELEASE_ALWAYS); - o->value(virkeys->keyoct1); - } // Fl_Counter* o - { Fl_Counter* o = new Fl_Counter(380, 110, 45, 15, "\"zxcv..\" Oct"); - o->tooltip("keys \"zsxdcvgbh...\" octave"); - o->type(1); - o->labelsize(10); - o->minimum(0); - o->maximum(5); - o->step(1); - o->textfont(1); - o->textsize(10); - o->callback((Fl_Callback*)cb_zxcv); - o->align(Fl_Align(FL_ALIGN_LEFT)); - o->when(FL_WHEN_RELEASE_ALWAYS); - o->value(virkeys->keyoct2); - } // Fl_Counter* o - { Fl_Value_Slider* o = new Fl_Value_Slider(95, 105, 100, 15, "Vel"); - o->tooltip("Velocity"); - o->type(5); - o->box(FL_FLAT_BOX); - o->labelsize(10); - o->minimum(1); - o->maximum(127); - o->step(1); - o->callback((Fl_Callback*)cb_Vel); - o->align(Fl_Align(FL_ALIGN_TOP_LEFT)); - o->value(virkeys->midivel); - } // Fl_Value_Slider* o - { Fl_Counter* o = new Fl_Counter(255, 100, 55, 20, "Oct."); - o->tooltip("Midi Octave"); - o->type(1); - o->labelsize(11); - o->minimum(0); - o->maximum(5); - o->step(1); - o->textfont(1); - o->textsize(11); - o->callback((Fl_Callback*)cb_Oct); - o->align(Fl_Align(FL_ALIGN_LEFT)); - o->when(FL_WHEN_RELEASE_ALWAYS); - o->value(virkeys->midioct); - } // Fl_Counter* o - { Fl_Button* o = new Fl_Button(545, 105, 55, 20, "Close"); - o->box(FL_THIN_UP_BOX); - o->callback((Fl_Callback*)cb_Close); - } // Fl_Button* o - { Fl_Value_Slider* o = new Fl_Value_Slider(605, 10, 15, 115, "Cval"); - o->tooltip("Controller value"); - o->type(2); - o->box(FL_ENGRAVED_BOX); - o->selection_color((Fl_Color)229); - o->labelsize(8); - o->minimum(127); - o->maximum(0); - o->step(1); - o->value(64); - o->textsize(7); - o->callback((Fl_Callback*)cb_Cval); - o->align(Fl_Align(FL_ALIGN_TOP_LEFT)); - } // Fl_Value_Slider* o - { Fl_Choice* o = new Fl_Choice(435, 105, 100, 15, "Controller"); - o->down_box(FL_BORDER_BOX); - o->labelsize(10); - o->textfont(1); - o->textsize(10); - o->callback((Fl_Callback*)cb_Controller); - o->align(Fl_Align(FL_ALIGN_TOP_LEFT)); - o->when(FL_WHEN_RELEASE_ALWAYS); - o->menu(menu_Controller); - midictl=C_filtercutoff;o->value(7); - } // Fl_Choice* o - { pitchwheelroller = new Fl_Roller(625, 10, 20, 95, "Pwh"); - pitchwheelroller->tooltip("Pitch Wheel"); - pitchwheelroller->box(FL_PLASTIC_UP_BOX); - pitchwheelroller->labelsize(8); - pitchwheelroller->minimum(-8192); - pitchwheelroller->maximum(8192); - pitchwheelroller->step(64); - pitchwheelroller->callback((Fl_Callback*)cb_pitchwheelroller); - pitchwheelroller->align(Fl_Align(FL_ALIGN_TOP)); - pitchwheelroller->when(3); - } // Fl_Roller* pitchwheelroller - { Fl_Button* o = new Fl_Button(625, 110, 20, 15, "R"); - o->tooltip("Reset Pitch Bend"); - o->box(FL_THIN_UP_BOX); - o->labelfont(1); - o->callback((Fl_Callback*)cb_R); - } // Fl_Button* o - { WidgetPDial* o = new WidgetPDial(205, 105, 20, 20, "Vrnd"); - o->tooltip("Velocity Randomness"); - o->box(FL_ROUND_UP_BOX); - o->color(FL_BACKGROUND_COLOR); - o->selection_color(FL_INACTIVE_COLOR); - o->labeltype(FL_NORMAL_LABEL); - o->labelfont(0); - o->labelsize(10); - o->labelcolor(FL_FOREGROUND_COLOR); - o->maximum(127); - o->step(1); - o->callback((Fl_Callback*)cb_Vrnd); - o->align(Fl_Align(129)); - o->when(FL_WHEN_CHANGED); - o->value(virkeys->rndvelocity); - } // WidgetPDial* o - { Fl_Choice* o = partrcv = new Fl_Choice(20, 105, 65, 20, "MIDI Ch."); - partrcv->tooltip("Send to Midi Channel"); - partrcv->down_box(FL_BORDER_BOX); - partrcv->labelsize(10); - partrcv->textfont(1); - partrcv->textsize(10); - partrcv->callback((Fl_Callback*)cb_partrcv); - partrcv->align(Fl_Align(FL_ALIGN_TOP_LEFT)); - char nrstr[10]; for(int i=0;iadd(nrstr); else o->add("Drum10");}; - o->value(virkeys->midich); - } // Fl_Choice* partrcv - virkeyboardwindow->end(); - } // Fl_Double_Window* virkeyboardwindow - return virkeyboardwindow; -} - -VirKeyboard::VirKeyboard(Master *master_) { - master=master_; - midictl=75; - make_window(); -} - -VirKeyboard::~VirKeyboard() { - delete virkeyboardwindow; -} - -void VirKeyboard::show() { - virkeyboardwindow->show(); -} - -void VirKeyboard::relaseallkeys() { - virkeys->relaseallkeys(0); -} diff --git a/plugins/zynaddsubfx/src/UI/VirKeyboard.fl b/plugins/zynaddsubfx/src/UI/VirKeyboard.fl deleted file mode 100644 index a0b4c721c..000000000 --- a/plugins/zynaddsubfx/src/UI/VirKeyboard.fl +++ /dev/null @@ -1,424 +0,0 @@ -# data file for the Fltk User Interface Designer (fluid) -version 1.0107 -header_name {.h} -code_name {.cc} -decl {//Copyright (c) 2002-2005 Nasca Octavian Paul} {} - -decl {//License: GNU GPL version 2 or later} {} - -decl {\#include } {public -} - -decl {\#include } {public -} - -decl {\#include } {public -} - -decl {\#include "../globals.h"} {public -} - -decl {\#include "../Misc/Master.h"} {public -} - -decl {\#include "../Input/MidiIn.h"} {public -} - -decl {\#include "WidgetPDial.h"} {public -} - -decl {const int keyspos[12]={0,-1,1,-2,2,3,-4,4,-5,5,-6,6};} {} - -decl {const int keysoct1qwerty[]={'q','2','w','3','e','r','5','t','6','y','7','u','i','9','o','0','p','[','=',']','\\\\',FL_Enter,0};} {} - -decl {const int keysoct2qwerty[]={'z','s','x','d','c','v','g','b','h','n','j','m',',','l','.',';','/',0};} {} - -decl {const int keysoct1dw[]={'\\'','2',',','3','.','p','5','y','6','f','7','g','c','9','r','0','l','/',']','=','\\\\',FL_Enter,0};} {} - -decl {const int keysoct2dw[]={';','o','q','e','j','k','i','x','d','b','h','m','w','n','v','s','z',0};} {} - -decl {const int keysoct1qwertz[]={'q','2','w','3','e','r','5','t','6','z','7','u','i','9','o','0','p',252,'\\'','+','\\\\',FL_Enter,0};} {} - -decl {const int keysoct2qwertz[]={'y','s','x','d','c','v','g','b','h','n','j','m',',','l','.',246,'-',0};} {} - -decl {const int keysoct1az[]={'a',233,'z','\\"','e','r','(','t','-','y',232,'u','i',231,'o',224,'p',65106,'=','$',0};} {} - -decl {const int keysoct2az[]={'w','s','x','d','c','v','g','b','h','n','j',',',';','l',':','m','!',0};} {} - -class VirKeys {: {public Fl_Box} -} { - decl {static const int N_OCT=6;} {} - decl {static const int SIZE_WHITE=14;} {} - decl {static const int SIZE_BLACK=8;} {} - Function {VirKeys(int x,int y, int w, int h, const char *label=0):Fl_Box(x,y,w,h,label)} {} { - code {master=NULL;} {} - } - Function {init(Master *master_)} {} { - code {master=master_; -for (int i=0;i=0){//white keys - if (pressed[i]==0) fl_color(250,240,230); - else fl_color(FL_BLUE); - fl_rectf(ox+(kv+7*noct)*SIZE_WHITE+3,oy+ly*3/5+2, - SIZE_WHITE-4,ly*2/5-3); - } else {//black keys - kv=keyspos[(i+1)%12]; - if (pressed[i]==0) fl_color(FL_BLACK); - else fl_color(FL_BLUE); - fl_rectf(ox+(kv+7*noct)*SIZE_WHITE-SIZE_BLACK/2+2,oy+2, - SIZE_BLACK-3,ly*3/5-5); - }; -};} {} - } - Function {handle(int event)} {return_type int - } { - code {int i; -int ly=h(); -int x_=Fl::event_x()-x(); -int y_=Fl::event_y()-y(); -if ( (x_<0)&&(x_>w()) && (y_<0)&&(y_>h())){ - return(0); -}; - - -if ((event==FL_PUSH)||(event==FL_DRAG)||(event==FL_RELEASE)){ - int kpos=-1; - - if (y_>ly*3/5){//white keys - int pos=x_/SIZE_WHITE; - if (pos<0) return(1); - for (i=0;i<12;i++) { - if (pos%7==keyspos[i]) { - kpos=pos/7*12+i; - break; - }; - }; - } else {//black keys - int pos=(x_+SIZE_WHITE/2)/SIZE_WHITE; - if (pos<0) return(1); - for (i=1;i<12;i++) { - if (pos%7==-keyspos[i]) { - kpos=pos/7*12+i; - break; - }; - }; - }; - - if ((kpos!=-1)&&((event==FL_PUSH)||(event==FL_DRAG))&& - (Fl::event_shift()==0)) { - presskey(kpos,1,1); - }; - - if ((event==FL_PUSH)&&(Fl::event_shift()!=0)) { - if (pressed[kpos]==0) presskey(kpos,0,1); - else relasekey(kpos,1); - }; - if ((event==FL_RELEASE)&&(Fl::event_shift()==0)) - relaseallkeys(1); - take_focus(); -}; - - -const int *keysoct1=keysoct1qwerty; -const int *keysoct2=keysoct2qwerty; - -if (config.cfg.VirKeybLayout==2) { - keysoct1=keysoct1dw; - keysoct2=keysoct2dw; -}else if (config.cfg.VirKeybLayout==3) { - keysoct1=keysoct1qwertz; - keysoct2=keysoct2qwertz; -}else if (config.cfg.VirKeybLayout==4) { - keysoct1=keysoct1az; - keysoct2=keysoct2az; -}; - -if ((event==FL_KEYDOWN)||(event==FL_KEYUP)){ - int key=Fl::event_key(); - int kpos=-1; - for (i=0;keysoct1[i]!=0;i++) if (key==keysoct1[i]) kpos=i+12*keyoct1; - for (i=0;keysoct2[i]!=0;i++) if (key==keysoct2[i]) kpos=i+12*keyoct2; - - - - - if (kpos==-1) return(0); - if ((event==FL_KEYUP) && (Fl::event_key(key)==0) && (Fl::get_key(key)!=0)) return(0); - if (event==FL_KEYDOWN) presskey(kpos,0,2); - else relasekey(kpos,2); -}; - -return(1);} {} - } - Function {presskey(int nk,int exclusive,int type)} {} { - code {//Exclusive means that multiple keys can be pressed at once -//when the user uses the shift key -if (nk>=N_OCT*12) return; -if ((nk<0)&&(exclusive==0)) { - relaseallkeys(type); - return; -}; -if (nk<0) return; -if (pressed[nk]!=0) return;//the key is already pressed - -if (exclusive!=0) relaseallkeys(type); -pressed[nk]=type; - -damage(1); -float vel=midivel; -if (rndvelocity!=0){ - vel=midivel*(127.0-rndvelocity)/127.0+RND*rndvelocity; -}; - -pthread_mutex_lock(&master->mutex); - master->NoteOn(midich,nk+midioct*12,(int)vel); -pthread_mutex_unlock(&master->mutex);} {} - } - Function {relasekey(int nk,int type)} {} { - code {if ((nk<0)||(nk>=N_OCT*12)) return; -if (pressed[nk]==0) return;//the key is not pressed -if ((type!=0)&&(pressed[nk]!=type)) return; - -pressed[nk]=0; - - -damage(1); - -pthread_mutex_lock(&master->mutex); - master->NoteOff(midich,nk+12*midioct); -pthread_mutex_unlock(&master->mutex);} {} - } - Function {relaseallkeys(int type)} {} { - code {for (int i=0;ihide();} - xywh {95 563 650 130} type Double hide - } { - Fl_Box virkeys { - label Keyboard - xywh {10 10 590 80} box FLAT_BOX color 17 - code0 {o->init(master);} - class VirKeys - } - Fl_Counter {} { - label {"qwer.." Oct} - callback {relaseallkeys(); -virkeys->keyoct1=(int) o->value(); -virkeys->take_focus();} - tooltip {keys "q2w3er5t6y..." octave} xywh {380 95 45 15} type Simple labelsize 10 align 4 when 6 minimum 0 maximum 5 step 1 textfont 1 textsize 10 - code0 {o->value(virkeys->keyoct1);} - } - Fl_Counter {} { - label {"zxcv.." Oct} - callback {relaseallkeys(); -virkeys->keyoct2=(int) o->value(); -virkeys->take_focus();} - tooltip {keys "zsxdcvgbh..." octave} xywh {380 110 45 15} type Simple labelsize 10 align 4 when 6 minimum 0 maximum 5 step 1 textfont 1 textsize 10 - code0 {o->value(virkeys->keyoct2);} - } - Fl_Value_Slider {} { - label Vel - callback {virkeys->midivel=(int) o->value(); -virkeys->take_focus();} - tooltip Velocity xywh {95 105 100 15} type {Horz Knob} box FLAT_BOX labelsize 10 align 5 minimum 1 maximum 127 step 1 - code0 {o->value(virkeys->midivel);} - } - Fl_Counter {} { - label {Oct.} - callback {relaseallkeys(); -virkeys->midioct=(int) o->value(); -virkeys->take_focus();} - tooltip {Midi Octave} xywh {255 100 55 20} type Simple labelsize 11 align 4 when 6 minimum 0 maximum 5 step 1 textfont 1 textsize 11 - code0 {o->value(virkeys->midioct);} - } - Fl_Button {} { - label Close - callback {relaseallkeys(); -virkeyboardwindow->hide();} - xywh {545 105 55 20} box THIN_UP_BOX - } - Fl_Value_Slider {} { - label Cval - callback {int ctl=midictl; - -pthread_mutex_lock(&master->mutex); - master->SetController(virkeys->midich,ctl,(int) o->value()); -pthread_mutex_unlock(&master->mutex); -virkeys->take_focus();} - tooltip {Controller value} xywh {605 10 15 115} type {Vert Fill} box ENGRAVED_BOX selection_color 229 labelsize 8 align 5 minimum 127 maximum 0 step 1 value 64 textsize 7 - } - Fl_Choice {} { - label Controller - callback {switch((int) o->value()+1){ - case 1: midictl=C_modwheel; break; - case 2: midictl=C_volume; break; - case 3: midictl=C_panning; break; - case 4: midictl=C_expression; break; - case 5: midictl=C_sustain; break; - case 6: midictl=C_portamento; break; - case 7: midictl=C_filterq; break; - case 8: midictl=C_filtercutoff; break; - case 9: midictl=C_bandwidth; break; - case 10: midictl=C_fmamp; break; - case 11: midictl=C_resonance_center; break; - case 12: midictl=C_resonance_bandwidth; break; - default: midictl=C_NULL; break; - -}; - - - -virkeys->take_focus();} - xywh {435 105 100 15} down_box BORDER_BOX labelsize 10 align 5 when 6 textfont 1 textsize 10 - code0 {midictl=C_filtercutoff;o->value(7);} - } { - MenuItem {} { - label {01: Mod.Wheel} - xywh {0 0 100 20} labelfont 1 labelsize 10 - } - MenuItem {} { - label {07: Volume} - xywh {10 10 100 20} labelfont 1 labelsize 10 - } - MenuItem {} { - label {10: Panning} - xywh {20 20 100 20} labelfont 1 labelsize 10 - } - MenuItem {} { - label {11: Expression} - xywh {30 30 100 20} labelfont 1 labelsize 10 - } - MenuItem {} { - label {64: Sustain} - xywh {40 40 100 20} labelfont 1 labelsize 10 - } - MenuItem {} { - label {65: Portamento} - xywh {50 50 100 20} labelfont 1 labelsize 10 - } - MenuItem {} { - label {71: Filter Q} - xywh {60 60 100 20} labelfont 1 labelsize 10 - } - MenuItem {} { - label {74: Filter Freq.} - xywh {70 70 100 20} labelfont 1 labelsize 10 - } - MenuItem {} { - label {75: Bandwidth} - xywh {80 80 100 20} labelfont 1 labelsize 10 - } - MenuItem {} { - label {76: FM Gain} - xywh {90 90 100 20} labelfont 1 labelsize 10 - } - MenuItem {} { - label {77: Res. c. freq} - xywh {100 100 100 20} labelfont 1 labelsize 10 - } - MenuItem {} { - label {78: Res. bw.} - xywh {110 110 100 20} labelfont 1 labelsize 10 - } - } - Fl_Roller pitchwheelroller { - label Pwh - callback {pthread_mutex_lock(&master->mutex); - master->SetController(virkeys->midich,C_pitchwheel,-(int) o->value()); -pthread_mutex_unlock(&master->mutex); -virkeys->take_focus();} - tooltip {Pitch Wheel} xywh {625 10 20 95} box PLASTIC_UP_BOX labelsize 8 align 1 when 3 minimum -8192 maximum 8192 step 64 - } - Fl_Button {} { - label R - callback {pitchwheelroller->value(0); -pitchwheelroller->do_callback();} - tooltip {Reset Pitch Bend} xywh {625 110 20 15} box THIN_UP_BOX labelfont 1 - } - Fl_Dial {} { - label Vrnd - callback {virkeys->rndvelocity=(int) o->value();} - tooltip {Velocity Randomness} xywh {205 105 20 20} box ROUND_UP_BOX labelsize 10 align 129 maximum 127 step 1 - code0 {o->value(virkeys->rndvelocity);} - class WidgetPDial - } - Fl_Choice partrcv { - label {MIDI Ch.} - callback {relaseallkeys(); -virkeys->midich=(int) o->value(); -virkeys->take_focus();} open - tooltip {Send to Midi Channel} xywh {20 105 65 20} down_box BORDER_BOX labelsize 10 align 5 textfont 1 textsize 10 - code0 {char nrstr[10]; for(int i=0;iadd(nrstr); else o->add("Drum10");};} - code1 {o->value(virkeys->midich);} - } {} - } - } - Function {VirKeyboard(Master *master_)} {} { - code {master=master_; -midictl=75; -make_window();} {} - } - Function {~VirKeyboard()} {} { - code {delete virkeyboardwindow;} {selected - } - } - Function {show()} {} { - code {virkeyboardwindow->show();} {} - } - Function {relaseallkeys()} {} { - code {virkeys->relaseallkeys(0);} {} - } - decl {Master *master;} {} - decl {int midictl;} {} -} diff --git a/plugins/zynaddsubfx/src/UI/VirKeyboard.h b/plugins/zynaddsubfx/src/UI/VirKeyboard.h deleted file mode 100644 index 7d7e7b95e..000000000 --- a/plugins/zynaddsubfx/src/UI/VirKeyboard.h +++ /dev/null @@ -1,90 +0,0 @@ -// generated by Fast Light User Interface Designer (fluid) version 1.0300 - -#ifndef VirKeyboard_h -#define VirKeyboard_h -#include -#include -#include -#include -#include "../globals.h" -#include "../Misc/Master.h" -#include "../Input/MidiIn.h" -#include "WidgetPDial.h" - -class VirKeys : public Fl_Box { - static const int N_OCT=6; - static const int SIZE_WHITE=14; - static const int SIZE_BLACK=8; -public: - VirKeys(int x,int y, int w, int h, const char *label=0); - void init(Master *master_); - void draw(); - int handle(int event); - void presskey(int nk,int exclusive,int type); - void relasekey(int nk,int type); - void relaseallkeys(int type); -private: - Master *master; - int pressed[N_OCT*12+1]; -public: - unsigned char midich; - unsigned char midivel; - char midioct,keyoct1,keyoct2; - unsigned char rndvelocity; -}; -#include -#include -#include -#include -#include -#include - -class VirKeyboard { -public: - Fl_Double_Window* make_window(); - Fl_Double_Window *virkeyboardwindow; -private: - void cb_virkeyboardwindow_i(Fl_Double_Window*, void*); - static void cb_virkeyboardwindow(Fl_Double_Window*, void*); -public: - VirKeys *virkeys; -private: - void cb_qwer_i(Fl_Counter*, void*); - static void cb_qwer(Fl_Counter*, void*); - void cb_zxcv_i(Fl_Counter*, void*); - static void cb_zxcv(Fl_Counter*, void*); - void cb_Vel_i(Fl_Value_Slider*, void*); - static void cb_Vel(Fl_Value_Slider*, void*); - void cb_Oct_i(Fl_Counter*, void*); - static void cb_Oct(Fl_Counter*, void*); - void cb_Close_i(Fl_Button*, void*); - static void cb_Close(Fl_Button*, void*); - void cb_Cval_i(Fl_Value_Slider*, void*); - static void cb_Cval(Fl_Value_Slider*, void*); - void cb_Controller_i(Fl_Choice*, void*); - static void cb_Controller(Fl_Choice*, void*); - static Fl_Menu_Item menu_Controller[]; -public: - Fl_Roller *pitchwheelroller; -private: - void cb_pitchwheelroller_i(Fl_Roller*, void*); - static void cb_pitchwheelroller(Fl_Roller*, void*); - void cb_R_i(Fl_Button*, void*); - static void cb_R(Fl_Button*, void*); - void cb_Vrnd_i(WidgetPDial*, void*); - static void cb_Vrnd(WidgetPDial*, void*); -public: - Fl_Choice *partrcv; -private: - void cb_partrcv_i(Fl_Choice*, void*); - static void cb_partrcv(Fl_Choice*, void*); -public: - VirKeyboard(Master *master_); - ~VirKeyboard(); - void show(); - void relaseallkeys(); -private: - Master *master; - int midictl; -}; -#endif diff --git a/plugins/zynaddsubfx/src/UI/WidgetPDial.cc b/plugins/zynaddsubfx/src/UI/WidgetPDial.cc deleted file mode 100644 index 05e31b89c..000000000 --- a/plugins/zynaddsubfx/src/UI/WidgetPDial.cc +++ /dev/null @@ -1,215 +0,0 @@ -// generated by Fast Light User Interface Designer (fluid) version 1.0300 - -#include "WidgetPDial.h" -//Copyright (c) 2003-2005 Nasca Octavian Paul -//License: GNU GPL version 2 or later - -TipWin::TipWin():Fl_Menu_Window(1,1) { - strcpy(tip, "X.XX"); - set_override(); - end(); -} - -void TipWin::draw() { - draw_box(FL_BORDER_BOX, 0, 0, w(), h(), Fl_Color(175)); - fl_color(FL_BLACK); - fl_font(labelfont(), labelsize()); - if(textmode) - fl_draw(text, 3, 3, w()-6, h()-6, Fl_Align(FL_ALIGN_LEFT|FL_ALIGN_WRAP)); - else - fl_draw(tip, 3, 3, w()-6, h()-6, Fl_Align(FL_ALIGN_LEFT|FL_ALIGN_WRAP)); -} - -void TipWin::value(float f) { - sprintf(tip, "%.2f", f); - textmode=false; - // Recalc size of window - fl_font(labelfont(), labelsize()); - int W = w(), H = h(); - fl_measure(tip, W, H, 0); - W += 8; - size(W, H); - redraw(); -} - -void TipWin::setText(const char * c) { - strncpy(text, c, max_tooltip_len-1); - text[max_tooltip_len-1] = 0; - textmode=true; - // Recalc size of window - fl_font(labelfont(), labelsize()); - int W = w(), H = h(); - fl_measure(text, W, H, 0); - W += 8; - size(W, H); - redraw(); -} - -void TipWin::setTextmode() { - textmode=true; - // Recalc size of window - fl_font(labelfont(), labelsize()); - int W = w(), H = h(); - fl_measure(text, W, H, 0); - W += 8; - size(W, H); - redraw(); -} - -WidgetPDial::WidgetPDial(int x,int y, int w, int h, const char *label):Fl_Dial(x,y,w,h,label) { - callback(value_cb, (void*)this); - Fl_Group *save = Fl_Group::current(); - tipwin = new TipWin(); - tipwin->hide(); - Fl_Group::current(save); - oldvalue=0.0; - pos=false; - textset=false; -} - -WidgetPDial::~WidgetPDial() { - delete tipwin; -} - -int WidgetPDial::handle(int event) { - double dragsize,v,min=minimum(),max=maximum(); - int my; - - switch (event){ - case FL_PUSH: - oldvalue=value(); - case FL_DRAG: - if(!pos){ - tipwin->position(Fl::event_x_root(), Fl::event_y_root()+20); - pos=true; - } - tipwin->value(value()); - tipwin->show(); - my=-(Fl::event_y()-y()-h()/2); - - dragsize=200.0; - if (Fl::event_state(FL_BUTTON1)==0) dragsize*=10; - v=oldvalue+my/dragsize*(max-min); - if (vmax) v=max; - - //printf("%d %g %g\n",my,v,oldvalue); - value(v); - value_damage(); - if (this->when()!=0) do_callback(); - return(1); - break; - case FL_ENTER: - if(textset){ - if(!pos){ - tipwin->position(Fl::event_x_root(), Fl::event_y_root()+20); - pos=true; - } - tipwin->setTextmode(); - tipwin->show(); - return(1);} - break; - case FL_HIDE: - case FL_LEAVE: - tipwin->hide(); - pos=false; - break; - case FL_RELEASE: - tipwin->hide(); - pos=false; - if (this->when()==0) do_callback(); - return(1); - break; - }; - return(0); -} - -void WidgetPDial::drawgradient(int cx,int cy,int sx,double m1,double m2) { - for (int i=(int)(m1*sx);i<(int)(m2*sx);i++){ - double tmp=1.0-pow(i*1.0/sx,2.0); - pdialcolor(140+(int) (tmp*90),140+(int)(tmp*90),140+(int) (tmp*100)); - fl_arc(cx+sx/2-i/2,cy+sx/2-i/2,i,i,0,360); - }; -} - -void WidgetPDial::draw() { - int cx=x(),cy=y(),sx=w(),sy=h(); - - - //clears the button face - pdialcolor(190,190,200); - fl_pie(cx-1,cy-1,sx+2,sy+2,0,360); - - //Draws the button face (gradinet) - drawgradient(cx,cy,sx,0.5,1.0); - - double val=(value()-minimum())/(maximum()-minimum()); - - //draws the scale - pdialcolor(220,220,250); - double a1=angle1(),a2=angle2(); - for (int i=0;i<12;i++){ - double a=-i/12.0*360.0-val*(a2-a1)-a1; - fl_pie(cx,cy,sx,sy,a+270-3,a+3+270); - }; - - drawgradient(cx,cy,sx,0.0,0.75); - - //draws the value - double a=-(a2-a1)*val-a1; - - - - - - //draws the max and min points - pdialcolor(0,100,200); - int xp=(int)(cx+sx/2.0+sx/2.0*sin(angle1()/180.0*3.141592)); - int yp=(int)(cy+sy/2.0+sy/2.0*cos(angle1()/180.0*3.141592)); - fl_pie(xp-2,yp-2,4,4,0,360); - - xp=(int)(cx+sx/2.0+sx/2.0*sin(angle2()/180.0*3.141592)); - yp=(int)(cy+sy/2.0+sy/2.0*cos(angle2()/180.0*3.141592)); - fl_pie(xp-2,yp-2,4,4,0,360); - - - - - - fl_push_matrix(); - - fl_translate(cx+sx/2,cy+sy/2); - fl_rotate(a-90.0); - - fl_translate(sx/2,0); - - - fl_begin_polygon(); - pdialcolor(0,0,0); - fl_vertex(-10,-4); - fl_vertex(-10,4); - fl_vertex(0,0); - fl_end_polygon(); - - - fl_pop_matrix(); -} - -void WidgetPDial::pdialcolor(int r,int g,int b) { - if (active_r()) fl_color(r,g,b); - else fl_color(160-(160-r)/3,160-(160-b)/3,160-(160-b)/3); -} - -void WidgetPDial::value_cb2() { - tipwin->value(value()); -} - -void WidgetPDial::value_cb(Fl_Widget*, void*data) { - WidgetPDial *val = (WidgetPDial*)data; - val->value_cb2(); -} - -void WidgetPDial::tooltip(const char * c) { - tipwin->setText(c); - textset=true; -} diff --git a/plugins/zynaddsubfx/src/UI/WidgetPDial.fl b/plugins/zynaddsubfx/src/UI/WidgetPDial.fl deleted file mode 100644 index f68a96ec3..000000000 --- a/plugins/zynaddsubfx/src/UI/WidgetPDial.fl +++ /dev/null @@ -1,253 +0,0 @@ -# data file for the Fltk User Interface Designer (fluid) -version 1.0107 -header_name {.h} -code_name {.cc} -decl {//Copyright (c) 2003-2005 Nasca Octavian Paul} {} - -decl {//License: GNU GPL version 2 or later} {} - -decl {\#include } {public -} - -decl {\#include } {public -} - -decl {\#include } {public -} - -decl {\#include } {public -} - -decl {\#include } {public -} - -decl {\#include } {public -} - -decl {\#include } {public -} - -decl {\#include } {public -} - -class TipWin {: {public Fl_Menu_Window} -} { - Function {TipWin():Fl_Menu_Window(1,1)} {} { - code {strcpy(tip, "X.XX"); -set_override(); -end();} {} - } - Function {draw()} {return_type void - } { - code {draw_box(FL_BORDER_BOX, 0, 0, w(), h(), Fl_Color(175)); - fl_color(FL_BLACK); - fl_font(labelfont(), labelsize()); - if(textmode) - fl_draw(text, 3, 3, w()-6, h()-6, Fl_Align(FL_ALIGN_LEFT|FL_ALIGN_WRAP)); - else - fl_draw(tip, 3, 3, w()-6, h()-6, Fl_Align(FL_ALIGN_LEFT|FL_ALIGN_WRAP));} {} - } - Function {value(float f)} {return_type void - } { - code {sprintf(tip, "%.2f", f); -textmode=false; - // Recalc size of window - fl_font(labelfont(), labelsize()); - int W = w(), H = h(); - fl_measure(tip, W, H, 0); - W += 8; - size(W, H); - redraw();} {} - } - Function {setText(const char * c)} {return_type void - } { - code {strncpy(text, c, max_tooltip_len-1); -text[max_tooltip_len-1] = 0; -textmode=true; - // Recalc size of window - fl_font(labelfont(), labelsize()); - int W = w(), H = h(); - fl_measure(text, W, H, 0); - W += 8; - size(W, H); - redraw();} {} - } - Function {setTextmode()} {return_type void - } { - code {textmode=true; - // Recalc size of window - fl_font(labelfont(), labelsize()); - int W = w(), H = h(); - fl_measure(text, W, H, 0); - W += 8; - size(W, H); - redraw();} {} - } - decl {char tip[40];} {} - decl {bool textmode;} {} - decl {enum { max_tooltip_len = 400 };} {selected - } - decl {char text[max_tooltip_len];} {} -} - -class WidgetPDial {: {public Fl_Dial} -} { - Function {WidgetPDial(int x,int y, int w, int h, const char *label=0):Fl_Dial(x,y,w,h,label)} {} { - code {callback(value_cb, (void*)this); -Fl_Group *save = Fl_Group::current(); -tipwin = new TipWin(); -tipwin->hide(); -Fl_Group::current(save); -oldvalue=0.0; -pos=false; -textset=false;} {} - } - Function {~WidgetPDial()} {} { - code {delete tipwin;} {} - } - Function {handle(int event)} {return_type int - } { - code {double dragsize,v,min=minimum(),max=maximum(); -int my; - -switch (event){ -case FL_PUSH: - oldvalue=value(); -case FL_DRAG: - if(!pos){ - tipwin->position(Fl::event_x_root(), Fl::event_y_root()+20); - pos=true; - } - tipwin->value(value()); - tipwin->show(); - my=-(Fl::event_y()-y()-h()/2); - - dragsize=200.0; - if (Fl::event_state(FL_BUTTON1)==0) dragsize*=10; - v=oldvalue+my/dragsize*(max-min); - if (vmax) v=max; - - //printf("%d %g %g\\n",my,v,oldvalue); - value(v); - value_damage(); - if (this->when()!=0) do_callback(); - return(1); - break; -case FL_ENTER: - if(textset){ - if(!pos){ - tipwin->position(Fl::event_x_root(), Fl::event_y_root()+20); - pos=true; - } - tipwin->setTextmode(); - tipwin->show(); - return(1);} - break; -case FL_HIDE: -case FL_LEAVE: - tipwin->hide(); - pos=false; - break; -case FL_RELEASE: - tipwin->hide(); - pos=false; - if (this->when()==0) do_callback(); - return(1); - break; -}; -return(0);} {} - } - Function {drawgradient(int cx,int cy,int sx,double m1,double m2)} {return_type void - } { - code {for (int i=(int)(m1*sx);i<(int)(m2*sx);i++){ - double tmp=1.0-pow(i*1.0/sx,2.0); - pdialcolor(140+(int) (tmp*90),140+(int)(tmp*90),140+(int) (tmp*100)); - fl_arc(cx+sx/2-i/2,cy+sx/2-i/2,i,i,0,360); -};} {} - } - Function {draw()} {} { - code {int cx=x(),cy=y(),sx=w(),sy=h(); - - -//clears the button face -pdialcolor(190,190,200); -fl_pie(cx-1,cy-1,sx+2,sy+2,0,360); - -//Draws the button face (gradinet) -drawgradient(cx,cy,sx,0.5,1.0); - -double val=(value()-minimum())/(maximum()-minimum()); - -//draws the scale -pdialcolor(220,220,250); -double a1=angle1(),a2=angle2(); -for (int i=0;i<12;i++){ - double a=-i/12.0*360.0-val*(a2-a1)-a1; - fl_pie(cx,cy,sx,sy,a+270-3,a+3+270); -}; - -drawgradient(cx,cy,sx,0.0,0.75); - -//draws the value -double a=-(a2-a1)*val-a1; - - - - - -//draws the max and min points -pdialcolor(0,100,200); -int xp=(int)(cx+sx/2.0+sx/2.0*sin(angle1()/180.0*3.141592)); -int yp=(int)(cy+sy/2.0+sy/2.0*cos(angle1()/180.0*3.141592)); -fl_pie(xp-2,yp-2,4,4,0,360); - -xp=(int)(cx+sx/2.0+sx/2.0*sin(angle2()/180.0*3.141592)); -yp=(int)(cy+sy/2.0+sy/2.0*cos(angle2()/180.0*3.141592)); -fl_pie(xp-2,yp-2,4,4,0,360); - - - - - -fl_push_matrix(); - - fl_translate(cx+sx/2,cy+sy/2); - fl_rotate(a-90.0); - - fl_translate(sx/2,0); - - - fl_begin_polygon(); - pdialcolor(0,0,0); - fl_vertex(-10,-4); - fl_vertex(-10,4); - fl_vertex(0,0); - fl_end_polygon(); - - -fl_pop_matrix();} {} - } - Function {pdialcolor(int r,int g,int b)} {} { - code {if (active_r()) fl_color(r,g,b); - else fl_color(160-(160-r)/3,160-(160-b)/3,160-(160-b)/3);} {} - } - Function {value_cb2()} {return_type void - } { - code {tipwin->value(value());} {} - } - Function {value_cb(Fl_Widget*, void*data)} {return_type {static void} - } { - code {WidgetPDial *val = (WidgetPDial*)data; - val->value_cb2();} {} - } - Function {tooltip(const char * c)} {return_type void - } { - code {tipwin->setText(c); -textset=true;} {} - } - decl {bool textset;} {} - decl {bool pos;} {} - decl {double oldvalue;} {} - decl {TipWin *tipwin;} {} -} diff --git a/plugins/zynaddsubfx/src/UI/WidgetPDial.h b/plugins/zynaddsubfx/src/UI/WidgetPDial.h deleted file mode 100644 index e81f17e18..000000000 --- a/plugins/zynaddsubfx/src/UI/WidgetPDial.h +++ /dev/null @@ -1,46 +0,0 @@ -// generated by Fast Light User Interface Designer (fluid) version 1.0300 - -#ifndef WidgetPDial_h -#define WidgetPDial_h -#include -#include -#include -#include -#include -#include -#include -#include -#include - -class TipWin : public Fl_Menu_Window { -public: - TipWin(); - void draw(); - void value(float f); - void setText(const char * c); - void setTextmode(); -private: - char tip[40]; - bool textmode; - enum { max_tooltip_len = 400 }; - char text[max_tooltip_len]; -}; - -class WidgetPDial : public Fl_Dial { -public: - WidgetPDial(int x,int y, int w, int h, const char *label=0); - ~WidgetPDial(); - int handle(int event); - void drawgradient(int cx,int cy,int sx,double m1,double m2); - void draw(); - void pdialcolor(int r,int g,int b); - void value_cb2(); - static void value_cb(Fl_Widget*, void*data); - void tooltip(const char * c); -private: - bool textset; - bool pos; - double oldvalue; - TipWin *tipwin; -}; -#endif diff --git a/plugins/zynaddsubfx/src/UI/filechooser.h b/plugins/zynaddsubfx/src/UI/filechooser.h deleted file mode 100644 index b557db94c..000000000 --- a/plugins/zynaddsubfx/src/UI/filechooser.h +++ /dev/null @@ -1,27 +0,0 @@ -#define fl_file_chooser fixed_file_chooser -#include - -extern std::string __presets_dir; - -static inline char * fixed_file_chooser(const char * message, const char *pattern, const char *fname, int relative = 0) -{ - Fl_File_Chooser* fc = new Fl_File_Chooser( __presets_dir.c_str(), - pattern, - Fl_File_Chooser::SINGLE, - message ); - fc->show(); - while( fc->shown() ) - { - Fl::wait(); - } - - char * r = NULL; - if( fc->count() > 0 ) - { - r = strdup( fc->value() ); - } - delete fc; - - return r; -} - diff --git a/plugins/zynaddsubfx/src/globals.h b/plugins/zynaddsubfx/src/globals.h deleted file mode 100644 index 9f52c3569..000000000 --- a/plugins/zynaddsubfx/src/globals.h +++ /dev/null @@ -1,235 +0,0 @@ -/* - ZynAddSubFX - a software synthesizer - - globals.h - it contains program settings and the program capabilities - like number of parts, of effects - Copyright (C) 2002-2005 Nasca Octavian Paul - Author: Nasca Octavian Paul - - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License - as published by the Free Software Foundation. - - 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 (version 2 or later) for more details. - - You should have received a copy of the GNU General Public License (version 2) - along with this program; if not, write to the Free Software Foundation, - Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -*/ - - -#ifndef GLOBALS_H -#define GLOBALS_H - -//What float type I use for internal sampledata -#define REALTYPE float - -struct FFTFREQS { - REALTYPE *s, *c; //sine and cosine components -}; - -extern void newFFTFREQS(FFTFREQS *f, int size); -extern void deleteFFTFREQS(FFTFREQS *f); - -/**Sampling rate*/ -extern int SAMPLE_RATE; - -/** - * The size of a sound buffer (or the granularity) - * All internal transfer of sound data use buffer of this size - * All parameters are constant during this period of time, exception - * some parameters(like amplitudes) which are linear interpolated. - * If you increase this you'll ecounter big latencies, but if you - * decrease this the CPU requirements gets high. - */ -extern int SOUND_BUFFER_SIZE; - - -/** - * The size of ADnote Oscillator - * Decrease this => poor quality - * Increase this => CPU requirements gets high (only at start of the note) - */ -extern int OSCIL_SIZE; - -/** - * The number of harmonics of additive synth - * This must be smaller than OSCIL_SIZE/2 - */ -#define MAX_AD_HARMONICS 128 - - -/** - * The number of harmonics of substractive - */ -#define MAX_SUB_HARMONICS 64 - - -/* - * The maximum number of samples that are used for 1 PADsynth instrument(or item) - */ -#define PAD_MAX_SAMPLES 64 - - -/* - * Number of parts - */ -#define NUM_MIDI_PARTS 16 - -/* - * Number of Midi channes - */ -#define NUM_MIDI_CHANNELS 16 - -/* - * The number of voices of additive synth for a single note - */ -#define NUM_VOICES 8 - -/* - * The poliphony (notes) - */ -#define POLIPHONY 128 - -/* - * Number of system effects - */ -#define NUM_SYS_EFX 4 - - -/* - * Number of insertion effects - */ -#define NUM_INS_EFX 8 - -/* - * Number of part's insertion effects - */ -#define NUM_PART_EFX 3 - -/* - * Maximum number of the instrument on a part - */ -#define NUM_KIT_ITEMS 16 - - -/* - * How is applied the velocity sensing - */ -#define VELOCITY_MAX_SCALE 8.0 - -/* - * The maximum length of instrument's name - */ -#define PART_MAX_NAME_LEN 30 - -/* - * The maximum number of bands of the equaliser - */ -#define MAX_EQ_BANDS 8 -#if (MAX_EQ_BANDS >= 20) -#error "Too many EQ bands in globals.h" -#endif - - -/* - * Maximum filter stages - */ -#define MAX_FILTER_STAGES 5 - -/* - * Formant filter (FF) limits - */ -#define FF_MAX_VOWELS 6 -#define FF_MAX_FORMANTS 12 -#define FF_MAX_SEQUENCE 8 - -#define LOG_2 0.693147181 -#define PI 3.1415926536 -#define LOG_10 2.302585093 - -/* - * The threshold for the amplitude interpolation used if the amplitude - * is changed (by LFO's or Envelope's). If the change of the amplitude - * is below this, the amplitude is not interpolated - */ -#define AMPLITUDE_INTERPOLATION_THRESHOLD 0.0001 - -/* - * How the amplitude threshold is computed - */ -#define ABOVE_AMPLITUDE_THRESHOLD(a, b) ((2.0 * fabs((b) - (a)) \ - / (fabs((b) + (a) + 0.0000000001))) > \ - AMPLITUDE_INTERPOLATION_THRESHOLD) - -/* - * Interpolate Amplitude - */ -#define INTERPOLATE_AMPLITUDE(a, b, x, size) ((a) \ - + ((b) \ - - (a)) * (REALTYPE)(x) \ - / (REALTYPE) (size)) - - -/* - * dB - */ -#define dB2rap(dB) ((exp((dB) * LOG_10 / 20.0))) -#define rap2dB(rap) ((20 * log(rap) / LOG_10)) - -/* - * The random generator (0.0..1.0) - */ -#define RND (rand() / (RAND_MAX + 1.0)) - -#define ZERO(data, size) {char *data_ = (char *) data; for(int i = 0; \ - i < size; \ - i++) \ - data_[i] = 0;} -#define ZERO_REALTYPE(data, size) {REALTYPE *data_ = (REALTYPE *) data; \ - for(int i = 0; \ - i < size; \ - i++) \ - data_[i] = 0.0;} - -enum ONOFFTYPE { - OFF = 0, ON = 1 -}; - -enum MidiControllers { - C_NULL = 0, C_pitchwheel = 1000, C_expression = 11, C_panning = 10, - C_filtercutoff = 74, C_filterq = 71, C_bandwidth = 75, C_modwheel = 1, - C_fmamp = 76, - C_volume = 7, C_sustain = 64, C_allnotesoff = 123, C_allsoundsoff = 120, - C_resetallcontrollers = 121, - C_portamento = 65, C_resonance_center = 77, C_resonance_bandwidth = 78, - - C_dataentryhi = 0x06, C_dataentrylo = 0x26, C_nrpnhi = 99, C_nrpnlo = 98 -}; - -enum LegatoMsg { - LM_Norm, LM_FadeIn, LM_FadeOut, LM_CatchUp, LM_ToNorm -}; - -//is like i=(int)(floor(f)) -#ifdef ASM_F2I_YES -#define F2I(f, \ - i) __asm__ __volatile__ ("fistpl %0" : "=m" (i) : "t" (f \ - - 0.49999999) \ - : "st"); -#else -#define F2I(f, i) (i) = ((f > 0) ? ((int)(f)) : ((int)(f - 1.0))); -#endif - - - -#ifndef O_BINARY -#define O_BINARY 0 -#endif - -#endif - diff --git a/src/core/midi/MidiPort.cpp b/src/core/midi/MidiPort.cpp index 0dd0ae760..4ec70ecfa 100644 --- a/src/core/midi/MidiPort.cpp +++ b/src/core/midi/MidiPort.cpp @@ -48,7 +48,7 @@ MidiPort::MidiPort( const QString& name, m_outputControllerModel( 0, 0, MidiControllerCount, this, tr( "Output controller" ) ), m_fixedInputVelocityModel( -1, -1, MidiMaxVelocity, this, tr( "Fixed input velocity" ) ), m_fixedOutputVelocityModel( -1, -1, MidiMaxVelocity, this, tr( "Fixed output velocity" ) ), - m_fixedOutputNoteModel( -1, -1, MidiMaxNote, this, tr( "Fixed output note" ) ), + m_fixedOutputNoteModel( -1, -1, MidiMaxKey, this, tr( "Fixed output note" ) ), m_outputProgramModel( 1, 1, MidiProgramCount, this, tr( "Output MIDI program" ) ), m_readableModel( false, this, tr( "Receive MIDI-events" ) ), m_writableModel( false, this, tr( "Send MIDI-events" ) ) From ed56bdc47d1fa602e3fb76071a2c40eaa1e4a6f1 Mon Sep 17 00:00:00 2001 From: Tobias Doerffel Date: Tue, 18 Feb 2014 20:03:41 +0100 Subject: [PATCH 015/647] ZynAddSubFX: Use upstream icon file --- plugins/zynaddsubfx/zynaddsubfx.rc.in | 2 +- plugins/zynaddsubfx/zynaddsubfx_icon.ico | Bin 9662 -> 0 bytes 2 files changed, 1 insertion(+), 1 deletion(-) delete mode 100644 plugins/zynaddsubfx/zynaddsubfx_icon.ico diff --git a/plugins/zynaddsubfx/zynaddsubfx.rc.in b/plugins/zynaddsubfx/zynaddsubfx.rc.in index ebc0c32ad..3cb13470c 100644 --- a/plugins/zynaddsubfx/zynaddsubfx.rc.in +++ b/plugins/zynaddsubfx/zynaddsubfx.rc.in @@ -1,4 +1,4 @@ -zynaddsubfx_icon ICON zynaddsubfx_icon.ico +zynaddsubfx_icon ICON zynaddsubfx/zynaddsubfx.ico #include VS_VERSION_INFO VERSIONINFO diff --git a/plugins/zynaddsubfx/zynaddsubfx_icon.ico b/plugins/zynaddsubfx/zynaddsubfx_icon.ico deleted file mode 100644 index 80f0519d3e48071cd514952a62d9b04561d6c4db..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9662 zcmeI2d32Ojn#QB;u8614Gzg5ijELju?y+5_Z3Gu~za83Kj8(zV_QEeI_D z47(xent50mF<l}@nl{YTk{L*&5`47Jo_u%!-d zwdG=M$86aM)81H-r4`}xF{LU@XvQX5yF2d`*HiO;hF2H85a>Vc{dInyI|s$CZ20UM zXmjmFdqFC+nsBUKI2R{Nb1_i2AA=_j<8<3G4EMBPxWALeRt(W&rB7|yxDLh6Or$05 z#;z@qIOf!%&65J-)-}*Ztwr|%H~MOQ7-*;z^Cx`hZpN9elNf4kz{?9?5VbFPajw`W zR<2zzq4lfqa}9^x>BOHT_`4{tk;@m+yi7*go^3dFqFQ)9+}nn;r+P5l*N)R2$H{XQ zURk;b`h-~WAd70qLW$FcR%asdQx1#L5x#gHe)HHYRMH+iKp7k&&zXC;zl%PnLwt^Q z_YT~7$L*N&^b;aWE7vZZ82>=M-{-N@`5_mzZd1Vj&Jqi)w_Gfq`!t?;;@9Y@KR`a! zOTU-AKhxDr{x_hZ(g&_RAezT=IzP0@{GG(#S(=4;PyHIV+AW%6e3Y0^&>Xhm zOm_>0D3dMKWyBravnS5q;4gG!!I+YWYPX!9e4X5T?4oaWR(WxX)*G)~u7PvJBd_Bl z`@O_Y^@r3@?y`~(?0<^f2eQygJvcpXEA_7mF_%0C%*`3(dRnVXrL%~9?wBZlQ+JL3 z_SjkZ(dMT7)9>vp;{KB*^&heBN~wlQoH|}bYoVGL4vU&9i`-)Fcn%|0yn@-Y z9>$*S8nn_nYI7%{qcBbCofQuBRu!O+dI7Hi{+v_f2j`O4^Re>$;8}`l7|nmrxchI% z;4%Nh4?T!UlkURa-O)JV(M!LV)^MQz^V;JYYD;J>Q}3ho%wzL`LOl2E?+~|Zo0x-n zbDj}C%$xIDG`LcwEb?3yXP~PrTX@lXxRBOy3H4C=4BAUr{YOiYsf&l(k{YOC)w)F? z`M(~&4t##=7;N-gje2-pIVde~qmuTeHg~d^gAT6&ypF{lM*9Hw(mwwER7+1)AvAQh z;4{+QlP1x>&qhjoELOhqGMt$i*zeAyIY<(pCFX$lLQwSlX1+mNnJz|nj&n)6c8P8sGt*y^*P z-j|DVuUsqFP1;xBB7T;WMEr6cMKq^HSq7Y-J+aM0b4r=)pmoK$>?pCJ&YJ}v^;$k3 z=F@#dT4F4*OK0-c>&MT}@+I@deS_dXP5j|2!s7z8f*yG$Kz`ZZi(k8Lr%sfw=8zIw#S&S3Y}i z4a)hQYgoO0@woXP&EG`)#8@QBnPtV(PdS>#>2H$G6Wm^Y=4 zKn*T^gBuooAgEJQ_l zu2GNqwHKb7i**sJ;kIXr+PH3I-lRH|JW-}-zPKl->3rnN%S8#T2c?GJ{p(XA>uYH~ z`OLv*UU7csIgrocq5eM*GrIpQU%EitFK~XkhMWD&w!gR#`+bVMbgf8vjz)S&)FU2`py?#j`Kg@rB$o*G<|K(@VP5jJi z&oaYA``37K(H>n>br3v?_ZX94Vj1=d8EF(sON5bRN=<-~rH>af=;L6}k+gec?S>(R z6$?Xh4APQV(PAvf&Jg^+C<_B?`i4oEw)IYNJ;nYryh8nl?|0@h|JfG5*W*N#VKw5M zn*xfb>v+c|n2KZY_8*4v{rBJFhaY|r#oJ-;t z?8I*?OTv}UKgD<7e~00B`%u%e4`<%)5s$BY_6c%Ik_3NBcBI5E_$BsGe!G3jGi4x$)VrL>>>PPy_eWk!heO|$o>cTRY<2fm@q%xb8>zJ zzeDDi^ON9;#D$T!L{`chJxFvAyMx&!CDB-Q!YlIh=J`R1U#>xytqRGG3aOc-fcGj0 zcJkk7Q3(m}&BV?k{tWg%k@E9X{ww^ixBJ}=yW~G--WiFbT@`|@Yq&|UEBwsOO14WH zrY!NAsH}HGOZ+X%y~s|6 z8hD`*-#>T<-(LL&*3v|YpKEYR?1Ep^K)zEA>_79fD(YNf4m$elWPUYe zhoxjk=BEr9t!lx~HJHq5TDK%QHyJX&j@R!``fn8dr}xb+;&;McVGs;`Z?qxN#oQ9R z!k^6S4z&ynufPX4PY^DO3Pc8Q<8m-wX`1bcvA4NHaw z4torKihspYUcVB5AMxkAUC8&j(A3m~&2iyawRIs@MakN-5UUkw=vvKMfN<49Nt@}K zq&4kEeSJNW^g9u;aRF(*q}OQNztDngQp7q*Yu3`^HFO>EJi^1D$DTbJ>?p}>vfvN zIB;k`8jl~trl^;(LA_Y$H5y-2FTqAxn`qpmT7pQ@X4O(56^*-gu10Tf4;t#LksPN% z_;~qYe)>K*;J?ftZCj57mx{8Zk}}V^cdBXKs-@hB>~Mah+~_DjLX;iOk3L(Cy5=&G z!DG$)LvkbKN92aHFY-^Bx2Tap*%6}L_jEUie_M0dE#+tZQcO8a-yf1@Y^MKq5q+1q zzBixGKiB7H_5i<&xQSng*{{b>+`15cWA0X5`ST@QzH$ksoUJ1FM#{dB%+B136n;nU zZhZaqSNQ0|_h}8#XVUr&->?+Zn&|smlJxy8ok8h(dii+#8v^WN&5q*N1o*YoFUNYH zO5U^oso5Gd$aB!tb}-0K?27*id#L|s&vpv$4^(8sLj7OxuXzbGO_MOwI0+9epBg;B ziTo_OCO@dG14U9Qaxb(@NL@&y8M$6u7q})&)3cupLuf&A! zzPpM){QeDMryeBpM=W24S^xAPWdi$?UEn%X?7?>oHz{&`r< zTPDs=_g|s?U)g_St>izSHRba{aKBa9L;9wiozUDfzrxP`bI+-$vg7L2Z}G{eeiRm` zQVqmTI@Y*PJb(G}ML4PVNV(_ikMWiOfW+tBPN z{6@-6_0a-x4|nzIRg8Ra0UuxdP-N!f#gCB3nWug^mY>hh;hg_*_@(|Y-GBAI(djQK zD#SK@gmlgq=Nvxk$mcY1){)LTqxLJF1G#4^>(;<$9rm6^spoU|!CRi;-$}7tN3oF9_YepKZ>8a!+OAoV22eXl6&>}-91sQ3{$Vg=+k@g~8 zPtwu%EV=}kwDFQs;^=$Vc=|rn1~a{u7`+vVyGT2uNL$2r(+NAspTrn(|FtM$;RkPh z`uf3h?+v|o`a=K6=?en^ouO-1=yT#d=jnat`$mRX|JEz%-JX#l(%?JYq^^-uZ?if_ zPQBG3H1KBo$iN$Iq}GxC*I6wi{pXrT`p%sk={rjrZX%r+={<9t)Hu>}nlyBb)G*RB zSU=J|SU1vrs&1rf;3( Date: Tue, 18 Feb 2014 20:24:36 +0100 Subject: [PATCH 016/647] VeSTige: adapt rename of MidiMaxKey constant --- plugins/vestige/vestige.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/vestige/vestige.cpp b/plugins/vestige/vestige.cpp index 20729675a..31a262771 100644 --- a/plugins/vestige/vestige.cpp +++ b/plugins/vestige/vestige.cpp @@ -776,7 +776,7 @@ void VestigeInstrumentView::noteOffAll( void ) m_vi->m_pluginMutex.lock(); if( m_vi->m_plugin != NULL ) { - for( int key = 0; key <= MidiMaxNote; ++key ) + for( int key = 0; key <= MidiMaxKey; ++key ) { m_vi->m_plugin->processMidiEvent( MidiEvent( MidiNoteOff, 0, key, 0 ), 0 ); } From a5f21cf61bb31d998271afd60b4af4743d5846f7 Mon Sep 17 00:00:00 2001 From: Tobias Doerffel Date: Tue, 18 Feb 2014 20:28:13 +0100 Subject: [PATCH 017/647] ZynAddSubFX: initialize IO engine after setting up synth instance --- plugins/zynaddsubfx/LocalZynAddSubFx.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/plugins/zynaddsubfx/LocalZynAddSubFx.cpp b/plugins/zynaddsubfx/LocalZynAddSubFx.cpp index 5f053ff48..9c80d4bc4 100644 --- a/plugins/zynaddsubfx/LocalZynAddSubFx.cpp +++ b/plugins/zynaddsubfx/LocalZynAddSubFx.cpp @@ -42,7 +42,7 @@ int LocalZynAddSubFx::s_instanceCount = 0; LocalZynAddSubFx::LocalZynAddSubFx() : m_master( NULL ), - m_ioEngine( new NulEngine ) + m_ioEngine( NULL ) { for( int i = 0; i < NumKeys; ++i ) { @@ -74,6 +74,8 @@ LocalZynAddSubFx::LocalZynAddSubFx() : ++s_instanceCount; + m_ioEngine = new NulEngine; + m_master = new Master(); m_master->swaplr = 0; } From df53432289afb2f2e6c20f45de341eed77ad950c Mon Sep 17 00:00:00 2001 From: Tobias Doerffel Date: Tue, 18 Feb 2014 20:47:54 +0100 Subject: [PATCH 018/647] ZynAddSubFX: define PLUGINVERSION macro Removes exit confirmation dialogs etc. in MasterUI.fl --- plugins/zynaddsubfx/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/plugins/zynaddsubfx/CMakeLists.txt b/plugins/zynaddsubfx/CMakeLists.txt index ea2ed51af..3fd07c891 100644 --- a/plugins/zynaddsubfx/CMakeLists.txt +++ b/plugins/zynaddsubfx/CMakeLists.txt @@ -46,6 +46,7 @@ INCLUDE_DIRECTORIES("${FLTK_INCLUDE_DIR}" include_directories( ${CMAKE_CURRENT_SOURCE_DIR}/zynaddsubfx/src/UI) +ADD_DEFINITIONS(-DPLUGINVERSION) # removes exit confirmation dialogs etc. in MasterUI.fl add_subdirectory(zynaddsubfx/src/Nio) add_subdirectory(zynaddsubfx/src/UI) From 66ca51bf431f7f7579358ee4493588ab3a182f59 Mon Sep 17 00:00:00 2001 From: Tobias Doerffel Date: Tue, 18 Feb 2014 20:48:21 +0100 Subject: [PATCH 019/647] RemoteZynAddSubFX: start/stop NIO system Fixes crash when showing GUI of ZynAddSubFX. --- plugins/zynaddsubfx/RemoteZynAddSubFx.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/plugins/zynaddsubfx/RemoteZynAddSubFx.cpp b/plugins/zynaddsubfx/RemoteZynAddSubFx.cpp index a57e69489..cdd7a6f16 100644 --- a/plugins/zynaddsubfx/RemoteZynAddSubFx.cpp +++ b/plugins/zynaddsubfx/RemoteZynAddSubFx.cpp @@ -35,6 +35,7 @@ #include "RemoteZynAddSubFx.h" #include "LocalZynAddSubFx.h" +#include "zynaddsubfx/src/Nio/Nio.h" #include "zynaddsubfx/src/UI/MasterUI.h" #include @@ -49,6 +50,8 @@ public: m_guiSleepTime( 100 ), m_guiExit( false ) { + Nio::start(); + setInputCount( 0 ); sendMessage( IdInitDone ); waitForMessage( IdInitDone ); @@ -65,6 +68,8 @@ public: #else usleep( m_guiSleepTime * 2 * 1000 ); #endif + + Nio::stop(); } virtual void updateSampleRate() From 296a1585bdb92a68f348a54f8a730575d93f5acc Mon Sep 17 00:00:00 2001 From: Tobias Doerffel Date: Tue, 18 Feb 2014 20:48:50 +0100 Subject: [PATCH 020/647] ZynAddSubFX: update submodule reference --- plugins/zynaddsubfx/zynaddsubfx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/zynaddsubfx/zynaddsubfx b/plugins/zynaddsubfx/zynaddsubfx index 0d76dc8aa..1182ab987 160000 --- a/plugins/zynaddsubfx/zynaddsubfx +++ b/plugins/zynaddsubfx/zynaddsubfx @@ -1 +1 @@ -Subproject commit 0d76dc8aa6e4bfc2b4ca6e670b905e7d2d7293f2 +Subproject commit 1182ab9877d076ccdd7db61d7479ca2a8ca558ac From 1cf3daed93b1043a789a0debfaf6647fd89e8977 Mon Sep 17 00:00:00 2001 From: Tobias Doerffel Date: Tue, 18 Feb 2014 20:54:39 +0100 Subject: [PATCH 021/647] ZynAddSubFX: update submodule reference --- plugins/zynaddsubfx/zynaddsubfx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/zynaddsubfx/zynaddsubfx b/plugins/zynaddsubfx/zynaddsubfx index 1182ab987..acc9d0832 160000 --- a/plugins/zynaddsubfx/zynaddsubfx +++ b/plugins/zynaddsubfx/zynaddsubfx @@ -1 +1 @@ -Subproject commit 1182ab9877d076ccdd7db61d7479ca2a8ca558ac +Subproject commit acc9d08326eb5a80e06d388a9d9c5023e616e31b From 7d6f661590a0f4d1aceb1a0b1f5e6cd292e3fba2 Mon Sep 17 00:00:00 2001 From: Tobias Doerffel Date: Tue, 18 Feb 2014 23:00:54 +0100 Subject: [PATCH 022/647] ZynAddSubFX: update submodule reference --- plugins/zynaddsubfx/zynaddsubfx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/zynaddsubfx/zynaddsubfx b/plugins/zynaddsubfx/zynaddsubfx index acc9d0832..2ffc12005 160000 --- a/plugins/zynaddsubfx/zynaddsubfx +++ b/plugins/zynaddsubfx/zynaddsubfx @@ -1 +1 @@ -Subproject commit acc9d08326eb5a80e06d388a9d9c5023e616e31b +Subproject commit 2ffc12005865855add8fa7f3129e563e34215c06 From 84f1e1a6da79f475f76d180b7c0c8f9cf68132bc Mon Sep 17 00:00:00 2001 From: "Raine M. Ekman" Date: Sun, 9 Mar 2014 14:51:19 +0200 Subject: [PATCH 023/647] AutomationEditor: fix grid drawing, now both time signatures other than 4/4 and scrolling should work quite a bit better. --- src/gui/AutomationEditor.cpp | 116 ++++++++++++++++++----------------- 1 file changed, 60 insertions(+), 56 deletions(-) diff --git a/src/gui/AutomationEditor.cpp b/src/gui/AutomationEditor.cpp index aa360d730..6026d9648 100644 --- a/src/gui/AutomationEditor.cpp +++ b/src/gui/AutomationEditor.cpp @@ -39,7 +39,7 @@ #include #include - +#include #ifndef __USE_XOPEN #define __USE_XOPEN @@ -63,7 +63,7 @@ #include "bb_track_container.h" #include "piano_roll.h" #include "debug.h" - +#include "MeterModel.h" QPixmap * AutomationEditor::s_toolDraw = NULL; @@ -104,7 +104,8 @@ AutomationEditor::AutomationEditor() : connect( this, SIGNAL( currentPatternChanged() ), this, SLOT( updateAfterPatternChange() ), Qt::QueuedConnection ); - + connect( engine::getSong(), SIGNAL( timeSignatureChanged( int, int ) ), + this, SLOT( update() ) ); // init pixmaps if( s_toolDraw == NULL ) { @@ -820,7 +821,7 @@ void AutomationEditor::mousePressEvent( QMouseEvent * _me ) x -= VALUES_WIDTH; // get tick in which the user clicked - int pos_ticks = x * DefaultTicksPerTact / m_ppt + + int pos_ticks = x * MidiTime::ticksPerTact() / m_ppt + m_currentPosition; // get time map of current pattern @@ -840,7 +841,7 @@ void AutomationEditor::mousePressEvent( QMouseEvent * _me ) len > 0 && ( it+1==time_map.end() || pos_ticks <= (it+1).key() ) && - ( pos_ticks<= it.key() + DefaultTicksPerTact *4 / m_ppt ) && + ( pos_ticks<= it.key() + MidiTime::ticksPerTact() *4 / m_ppt ) && level <= it.value() ) { break; @@ -884,7 +885,7 @@ void AutomationEditor::mousePressEvent( QMouseEvent * _me ) int aligned_x = (int)( (float)( ( it.key() - m_currentPosition ) * - m_ppt ) / DefaultTicksPerTact ); + m_ppt ) / MidiTime::ticksPerTact() ); m_moveXOffset = x - aligned_x - 1; // set move-cursor QCursor c( Qt::SizeAllCursor ); @@ -993,7 +994,7 @@ void AutomationEditor::mouseMoveEvent( QMouseEvent * _me ) x -= m_moveXOffset; } - int pos_ticks = x * DefaultTicksPerTact / m_ppt + + int pos_ticks = x * MidiTime::ticksPerTact() / m_ppt + m_currentPosition; if( _me->buttons() & Qt::LeftButton && m_editMode == DRAW ) { @@ -1117,7 +1118,7 @@ void AutomationEditor::mouseMoveEvent( QMouseEvent * _me ) } // get tick in which the cursor is posated - int pos_ticks = x * DefaultTicksPerTact / m_ppt + + int pos_ticks = x * MidiTime::ticksPerTact() / m_ppt + m_currentPosition; m_selectedTick = pos_ticks - m_selectStartTick; @@ -1138,7 +1139,7 @@ void AutomationEditor::mouseMoveEvent( QMouseEvent * _me ) // move selection + selected values // do horizontal move-stuff - int pos_ticks = x * DefaultTicksPerTact / m_ppt + + int pos_ticks = x * MidiTime::ticksPerTact() / m_ppt + m_currentPosition; int ticks_diff = pos_ticks - m_moveStartTick; @@ -1163,8 +1164,8 @@ void AutomationEditor::mouseMoveEvent( QMouseEvent * _me ) } m_selectStartTick += ticks_diff; - int tact_diff = ticks_diff / DefaultTicksPerTact; - ticks_diff = ticks_diff % DefaultTicksPerTact; + int tact_diff = ticks_diff / MidiTime::ticksPerTact(); + ticks_diff = ticks_diff % MidiTime::ticksPerTact(); // do vertical move-stuff @@ -1214,19 +1215,19 @@ void AutomationEditor::mouseMoveEvent( QMouseEvent * _me ) { int value_tact = ( it.key() / - DefaultTicksPerTact ) + MidiTime::ticksPerTact() ) + tact_diff; int value_ticks = ( it.key() % - DefaultTicksPerTact ) + MidiTime::ticksPerTact() ) + ticks_diff; // ensure value_ticks range - if( value_ticks / DefaultTicksPerTact ) + if( value_ticks / MidiTime::ticksPerTact() ) { value_tact += value_ticks - / DefaultTicksPerTact; + / MidiTime::ticksPerTact(); value_ticks %= - DefaultTicksPerTact; + MidiTime::ticksPerTact(); } m_pattern->removeValue( it.key() ); new_value_pos = MidiTime( value_tact, @@ -1277,7 +1278,7 @@ void AutomationEditor::mouseMoveEvent( QMouseEvent * _me ) } // get tick in which the cursor is posated - int pos_ticks = x * DefaultTicksPerTact / m_ppt + + int pos_ticks = x * MidiTime::ticksPerTact() / m_ppt + m_currentPosition; m_selectedTick = pos_ticks - @@ -1443,43 +1444,46 @@ void AutomationEditor::paintEvent( QPaintEvent * _pe ) grid_height ); // draw vertical raster - int tact_16th = m_currentPosition / ( DefaultTicksPerTact / 16 ); - const int offset = ( m_currentPosition % (DefaultTicksPerTact/16) ) * - m_ppt / DEFAULT_STEPS_PER_TACT / 8; - if( m_pattern ) { + int tick, x; int x_line_end = (int)( m_y_auto || m_topLevel < m_maxLevel ? TOP_MARGIN : grid_bottom - ( m_topLevel - m_bottomLevel ) * m_y_delta ); - - for( int x = VALUES_WIDTH - offset; x < width(); - x += m_ppt / DEFAULT_STEPS_PER_TACT, ++tact_16th ) - { - if( x >= VALUES_WIDTH ) - { - // every tact-start needs to be a bright line - if( tact_16th % 16 == 0 ) - { - p.setPen( QColor( 0x7F, 0x7F, 0x7F ) ); - } - // normal line - else if( tact_16th % 4 == 0 ) - { - p.setPen( QColor( 0x5F, 0x5F, 0x5F ) ); - } - // weak line - else - { - p.setPen( QColor( 0x3F, 0x3F, 0x3F ) ); - } - p.drawLine( x, grid_bottom, x, x_line_end ); - } + // 3 independent loops, because quantization might not divide evenly into + // exotic denominators (e.g. 7/11 time), which are allowed ATM. + // First quantization grid... + for( tick = m_currentPosition - m_currentPosition % quantization(), + x = xCoordOfTick( tick ); + x<=width(); + tick += quantization(), x = xCoordOfTick( tick ) ) + { + p.setPen( QColor( 0x2F, 0x2F, 0x2F ) ); + p.drawLine( x, grid_bottom, x, x_line_end ); } - - // TODO: move this horizontal line drawing code into the same loop as - // the value ticks? + // Then beat grid + int ticksPerBeat = DefaultTicksPerTact / + engine::getSong()->getTimeSigModel().getDenominator(); + for( tick = m_currentPosition - m_currentPosition % ticksPerBeat, + x = xCoordOfTick( tick ); + x<=width(); + tick += ticksPerBeat, x = xCoordOfTick( tick ) ) + { + p.setPen( QColor( 0x5F, 0x5F, 0x5F ) ); + p.drawLine( x, grid_bottom, x, x_line_end ); + } + // and finally bars + for( tick = m_currentPosition - m_currentPosition % MidiTime::ticksPerTact(), + x = xCoordOfTick( tick ); + x<=width(); + tick += MidiTime::ticksPerTact(), x = xCoordOfTick( tick ) ) + { + p.setPen( QColor( 0x7F, 0x7F, 0x7F ) ); + p.drawLine( x, grid_bottom, x, x_line_end ); + } + + /// \todo move this horizontal line drawing code into the same loop as the value ticks? if( m_y_auto ) { QPen pen( QColor( 0x4F, 0x4F, 0x4F ) ); @@ -1626,8 +1630,8 @@ void AutomationEditor::paintEvent( QPaintEvent * _pe ) // now draw selection-frame int x = ( sel_pos_start - m_currentPosition ) * m_ppt / - DefaultTicksPerTact; - int w = ( sel_pos_end - sel_pos_start ) * m_ppt / DefaultTicksPerTact; + MidiTime::ticksPerTact(); + int w = ( sel_pos_end - sel_pos_start ) * m_ppt / MidiTime::ticksPerTact(); int y, h; if( m_y_auto ) { @@ -1681,7 +1685,7 @@ void AutomationEditor::paintEvent( QPaintEvent * _pe ) int AutomationEditor::xCoordOfTick( int _tick ) { return VALUES_WIDTH + ( ( _tick - m_currentPosition ) - * m_ppt / DefaultTicksPerTact ); + * m_ppt / MidiTime::ticksPerTact() ); } @@ -2126,7 +2130,7 @@ void AutomationEditor::getSelectedValues( timeMap & _selected_values ) ++it ) { //TODO: Add constant - tick_t len_ticks = DefaultTicksPerTact / 16; + tick_t len_ticks = MidiTime::ticksPerTact() / 16; float level = it.value(); tick_t pos_ticks = it.key(); @@ -2260,17 +2264,17 @@ void AutomationEditor::updatePosition( const MidiTime & _t ) m_scrollBack == TRUE ) { const int w = width() - VALUES_WIDTH; - if( _t > m_currentPosition + w * DefaultTicksPerTact / m_ppt ) + if( _t > m_currentPosition + w * MidiTime::ticksPerTact() / m_ppt ) { m_leftRightScroll->setValue( _t.getTact() * - DefaultTicksPerTact ); + MidiTime::ticksPerTact() ); } else if( _t < m_currentPosition ) { - MidiTime t = qMax( _t - w * DefaultTicksPerTact * - DefaultTicksPerTact / m_ppt, 0 ); + MidiTime t = qMax( _t - w * MidiTime::ticksPerTact() * + MidiTime::ticksPerTact() / m_ppt, 0 ); m_leftRightScroll->setValue( t.getTact() * - DefaultTicksPerTact ); + MidiTime::ticksPerTact() ); } m_scrollBack = FALSE; } From 194088db5fc2248c7ecf61abad504e13197a356f Mon Sep 17 00:00:00 2001 From: "Raine M. Ekman" Date: Tue, 18 Mar 2014 21:26:08 +0200 Subject: [PATCH 024/647] basic_filters.h: Saner limits for frequency --- include/basic_filters.h | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/include/basic_filters.h b/include/basic_filters.h index 2462978ee..aee960a71 100644 --- a/include/basic_filters.h +++ b/include/basic_filters.h @@ -69,7 +69,7 @@ public: static inline float minFreq() { - return( 0.01f ); + return( 10.0f ); } static inline float minQ() @@ -488,8 +488,9 @@ public: /*, const bool _q_is_bandwidth = false*/ ) { // temp coef vars - _freq = qMax( _freq, minFreq() );// limit freq and q for not getting - // bad noise out of the filter... + _freq = qMax( _freq, minFreq() ); // limit freq and q for not getting + _freq = qMin(_freq, m_sampleRate/2); // bad noise out of the filter... + _q = qMax( _q, minQ() ); if( m_type == Lowpass_RC12 || From 9ab6699a263a176dd1b41bb527820a9d6e6bafa8 Mon Sep 17 00:00:00 2001 From: Hannu Haahti Date: Wed, 19 Mar 2014 00:31:29 +0200 Subject: [PATCH 025/647] sf2_player: fix #481 --- plugins/sf2_player/sf2_player.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/sf2_player/sf2_player.cpp b/plugins/sf2_player/sf2_player.cpp index a5b9e36d1..4fba5c648 100644 --- a/plugins/sf2_player/sf2_player.cpp +++ b/plugins/sf2_player/sf2_player.cpp @@ -607,7 +607,7 @@ void sf2Instrument::playNote( NotePlayHandle * _n, sampleFrame * ) } #endif - const float currentVelocity = _n->volumeLevel( tfp ) * MidiMaxVelocity * DefaultVolume / MaxVolume; + const float currentVelocity = _n->volumeLevel( tfp ) * instrumentTrack()->midiPort()->baseVelocity(); if( pluginData->fluidVoice && pluginData->lastVelocity != currentVelocity ) { From 0b46aa4506ddbd032d3bf5df56dceb5b6beb00f3 Mon Sep 17 00:00:00 2001 From: Vesa Date: Wed, 19 Mar 2014 03:19:02 +0200 Subject: [PATCH 026/647] Dual Filter fix: make more efficient - don't calculate coefficients unnecessarily --- plugins/DualFilter/DualFilter.cpp | 27 ++++++++++++++--- plugins/DualFilter/DualFilter.h | 4 +++ plugins/DualFilter/DualFilterControls.cpp | 35 +++++++++++++---------- plugins/DualFilter/DualFilterControls.h | 3 +- 4 files changed, 49 insertions(+), 20 deletions(-) diff --git a/plugins/DualFilter/DualFilter.cpp b/plugins/DualFilter/DualFilter.cpp index 12ac79436..de6932a02 100644 --- a/plugins/DualFilter/DualFilter.cpp +++ b/plugins/DualFilter/DualFilter.cpp @@ -55,6 +55,10 @@ DualFilterEffect::DualFilterEffect( Model* parent, const Descriptor::SubPluginFe { m_filter1 = new basicFilters<2>( engine::mixer()->processingSampleRate() ); m_filter2 = new basicFilters<2>( engine::mixer()->processingSampleRate() ); + + // ensure filters get updated + m_filter1changed = true; + m_filter2changed = true; } @@ -82,10 +86,23 @@ bool DualFilterEffect::processAudioBuffer( sampleFrame* buf, const fpp_t frames m_filter1->setFilterType( m_dfControls.m_filter1Model.value() ); m_filter2->setFilterType( m_dfControls.m_filter2Model.value() ); + + const bool enabled1 = m_dfControls.m_enabled1Model.value(); + const bool enabled2 = m_dfControls.m_enabled2Model.value(); - if( m_dfControls.m_enabled1Model.value() ) m_filter1->calcFilterCoeffs( m_dfControls.m_cut1Model.value(), m_dfControls.m_res1Model.value() ); - if( m_dfControls.m_enabled2Model.value() ) m_filter2->calcFilterCoeffs( m_dfControls.m_cut2Model.value(), m_dfControls.m_res2Model.value() ); + // recalculate only when necessary + if( enabled1 && m_filter1changed ) + { + m_filter1->calcFilterCoeffs( m_dfControls.m_cut1Model.value(), m_dfControls.m_res1Model.value() ); + m_filter1changed = false; + } + if( enabled2 && m_filter2changed ) + { + m_filter2->calcFilterCoeffs( m_dfControls.m_cut2Model.value(), m_dfControls.m_res2Model.value() ); + m_filter2changed = false; + } + // buffer processing loop for( fpp_t f = 0; f < frames; ++f ) { @@ -98,7 +115,7 @@ bool DualFilterEffect::processAudioBuffer( sampleFrame* buf, const fpp_t frames const float mix2 = ( ( m_dfControls.m_mixModel.value( f ) + 1.0f ) / 2.0f ); // update filter 1 - if( m_dfControls.m_enabled1Model.value() ) + if( enabled1 ) { s1[0] = m_filter1->update( s1[0], 0 ); s1[1] = m_filter1->update( s1[1], 1 ); @@ -113,7 +130,7 @@ bool DualFilterEffect::processAudioBuffer( sampleFrame* buf, const fpp_t frames } // update filter 2 - if( m_dfControls.m_enabled2Model.value() ) + if( enabled2 ) { s2[0] = m_filter2->update( s2[0], 0 ); s2[1] = m_filter2->update( s2[1], 1 ); @@ -140,6 +157,8 @@ bool DualFilterEffect::processAudioBuffer( sampleFrame* buf, const fpp_t frames + + extern "C" { diff --git a/plugins/DualFilter/DualFilter.h b/plugins/DualFilter/DualFilter.h index 7949f84ab..d0bdd2aea 100644 --- a/plugins/DualFilter/DualFilter.h +++ b/plugins/DualFilter/DualFilter.h @@ -43,11 +43,15 @@ public: return &m_dfControls; } + private: DualFilterControls m_dfControls; basicFilters<2> * m_filter1; basicFilters<2> * m_filter2; + + bool m_filter1changed; + bool m_filter2changed; friend class DualFilterControls; diff --git a/plugins/DualFilter/DualFilterControls.cpp b/plugins/DualFilter/DualFilterControls.cpp index 5fbefa8f8..06ead0b31 100644 --- a/plugins/DualFilter/DualFilterControls.cpp +++ b/plugins/DualFilter/DualFilterControls.cpp @@ -51,19 +51,13 @@ DualFilterControls::DualFilterControls( DualFilterEffect* effect ) : m_res2Model( 0.5, basicFilters<0>::minQ(), 10.0, 0.01, this, tr( "Q/Resonance 2" ) ), m_gain2Model( 100.0f, 0.0f, 200.0f, 0.1f, this, tr( "Gain 2" ) ) { - connect( &m_enabled1Model, SIGNAL( dataChanged() ), this, SLOT( changeControl() ) ); - connect( &m_filter1Model, SIGNAL( dataChanged() ), this, SLOT( changeControl() ) ); - connect( &m_cut1Model, SIGNAL( dataChanged() ), this, SLOT( changeControl() ) ); - connect( &m_res1Model, SIGNAL( dataChanged() ), this, SLOT( changeControl() ) ); - connect( &m_gain1Model, SIGNAL( dataChanged() ), this, SLOT( changeControl() ) ); + connect( &m_filter1Model, SIGNAL( dataChanged() ), this, SLOT( updateFilter1() ) ); + connect( &m_cut1Model, SIGNAL( dataChanged() ), this, SLOT( updateFilter1() ) ); + connect( &m_res1Model, SIGNAL( dataChanged() ), this, SLOT( updateFilter1() ) ); - connect( &m_mixModel, SIGNAL( dataChanged() ), this, SLOT( changeControl() ) ); - - connect( &m_enabled2Model, SIGNAL( dataChanged() ), this, SLOT( changeControl() ) ); - connect( &m_filter2Model, SIGNAL( dataChanged() ), this, SLOT( changeControl() ) ); - connect( &m_cut2Model, SIGNAL( dataChanged() ), this, SLOT( changeControl() ) ); - connect( &m_res2Model, SIGNAL( dataChanged() ), this, SLOT( changeControl() ) ); - connect( &m_gain2Model, SIGNAL( dataChanged() ), this, SLOT( changeControl() ) ); + connect( &m_filter2Model, SIGNAL( dataChanged() ), this, SLOT( updateFilter2() ) ); + connect( &m_cut2Model, SIGNAL( dataChanged() ), this, SLOT( updateFilter2() ) ); + connect( &m_res2Model, SIGNAL( dataChanged() ), this, SLOT( updateFilter2() ) ); m_filter1Model.addItem( tr( "LowPass" ), new PixmapLoader( "filter_lp" ) ); m_filter1Model.addItem( tr( "HiPass" ), new PixmapLoader( "filter_hp" ) ); @@ -102,19 +96,30 @@ DualFilterControls::DualFilterControls( DualFilterEffect* effect ) : - -void DualFilterControls::changeControl() +void DualFilterControls::updateFilter1() { - engine::getSong()->setModified(); + m_effect->m_filter1changed = true; +} + +void DualFilterControls::updateFilter2() +{ + m_effect->m_filter2changed = true; } void DualFilterControls::updateFilters() { + // swap filters to new ones + delete m_effect->m_filter1; delete m_effect->m_filter2; m_effect->m_filter1 = new basicFilters<2>( engine::mixer()->processingSampleRate() ); m_effect->m_filter2 = new basicFilters<2>( engine::mixer()->processingSampleRate() ); + + // flag filters as needing recalculation + + updateFilter1(); + updateFilter2(); } diff --git a/plugins/DualFilter/DualFilterControls.h b/plugins/DualFilter/DualFilterControls.h index 69c2571e8..8f02eb051 100644 --- a/plugins/DualFilter/DualFilterControls.h +++ b/plugins/DualFilter/DualFilterControls.h @@ -62,7 +62,8 @@ public: private slots: - void changeControl(); + void updateFilter1(); + void updateFilter2(); void updateFilters(); private: From 34ba29cfcd134222bce58941375490bf62791a6d Mon Sep 17 00:00:00 2001 From: Vesa Date: Wed, 19 Mar 2014 03:26:36 +0200 Subject: [PATCH 027/647] Change Linux Multimedia etc. to LMMS in desktop/package files --- data/lmms | 2 +- data/lmms.desktop | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/data/lmms b/data/lmms index cd921eaa5..274886185 100644 --- a/data/lmms +++ b/data/lmms @@ -1,4 +1,4 @@ ?package(lmms):needs="X11" section="Apps/Sound" \ title="LMMS" hints="Audio" command="/usr/bin/lmms" \ - longtitle="Linux MultiMedia Studio" \ + longtitle="LMMS" \ icon="/usr/share/pixmaps/lmms.png" diff --git a/data/lmms.desktop b/data/lmms.desktop index c374b7e66..807ed54f6 100644 --- a/data/lmms.desktop +++ b/data/lmms.desktop @@ -1,5 +1,5 @@ [Desktop Entry] -Name=Linux MultiMedia Studio +Name=LMMS GenericName=music production suite GenericName[ca]=Programari de producció musical GenericName[de]=Software zur Musik-Produktion From 450bf3a35a3e02581284d044fbcffc6fbe873c6c Mon Sep 17 00:00:00 2001 From: "Raine M. Ekman" Date: Wed, 19 Mar 2014 23:21:48 +0200 Subject: [PATCH 028/647] basic_filters.h: Tweaked limits for cutoff. --- include/basic_filters.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/include/basic_filters.h b/include/basic_filters.h index aee960a71..e41046e61 100644 --- a/include/basic_filters.h +++ b/include/basic_filters.h @@ -69,7 +69,7 @@ public: static inline float minFreq() { - return( 10.0f ); + return( 3.0f ); } static inline float minQ() @@ -488,8 +488,8 @@ public: /*, const bool _q_is_bandwidth = false*/ ) { // temp coef vars - _freq = qMax( _freq, minFreq() ); // limit freq and q for not getting - _freq = qMin(_freq, m_sampleRate/2); // bad noise out of the filter... + _freq = qBound(minFreq(), _freq, 20000.0f); // limit freq and q for not getting + // bad noise out of the filter... _q = qMax( _q, minQ() ); From 7a7c9abd9b3913f2d805f99d4fa1be7d4ee23b17 Mon Sep 17 00:00:00 2001 From: Vesa Date: Thu, 20 Mar 2014 12:19:55 +0200 Subject: [PATCH 029/647] GraphModel: fix/improve normalize() function - remove bias before maximizing, also add some new slots for future use (which I plan to use for something neat in the future ;) ) --- include/graph.h | 20 +++++++------- src/gui/widgets/graph.cpp | 55 +++++++++++++++++++++++++++++++-------- 2 files changed, 55 insertions(+), 20 deletions(-) diff --git a/include/graph.h b/include/graph.h index 411224e1f..025e15a7b 100644 --- a/include/graph.h +++ b/include/graph.h @@ -3,7 +3,7 @@ * * Copyright (c) 2006-2007 Andreas Brandmaier * 2008 Paul Giblock - * + * * This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net * * This program is free software; you can redistribute it and/or @@ -24,8 +24,8 @@ */ -#ifndef _GRAPH_H -#define _GRAPH_H +#ifndef GRAPH_H +#define GRAPH_H #include #include @@ -71,7 +71,7 @@ public: { return m_graphStyle; } - + inline void setGraphStyle( graphStyle _s ) { @@ -101,10 +101,10 @@ private: QPixmap m_foreground; QColor m_graphColor; - + graphModel * m_graphModel; graphStyle m_graphStyle; - + bool m_mouseDown; int m_lastCursorX; @@ -125,7 +125,7 @@ public: virtual ~graphModel(); // TODO: saveSettings, loadSettings? - + inline float minValue() const { return( m_minValue ); @@ -140,7 +140,7 @@ public: { return( m_samples.count() ); } - + inline const float * samples() const { return( m_samples.data() ); @@ -160,10 +160,12 @@ public slots: void setWaveToSquare(); void setWaveToNoise(); QString setWaveToUser( ); - + void smooth(); void smoothNonCyclic(); void normalize(); + void invert(); + void shiftPhase( int _deg ); signals: void lengthChanged(); diff --git a/src/gui/widgets/graph.cpp b/src/gui/widgets/graph.cpp index f336434fa..a7011537c 100644 --- a/src/gui/widgets/graph.cpp +++ b/src/gui/widgets/graph.cpp @@ -629,28 +629,61 @@ void graphModel::smoothNonCyclic() emit samplesChanged(0, length()-1); } + + void graphModel::normalize() { float max = 0.0001f; + float avg = 0.0f; + + // first correct dc offset by normalizing to average for( int i = 0; i < length(); i++ ) - { - if( fabsf(m_samples[i]) > max && m_samples[i] != 0.0f ) - { - max = fabs( m_samples[i] ); - } - } + avg += m_samples[i]; + avg /= length(); + for( int i = 0; i < length(); i++ ) + m_samples[i] -= avg; + + // then maximize + for( int i = 0; i < length(); i++ ) + max = qMax( max, qAbs( m_samples[i] ) ); for( int i = 0; i < length(); i++ ) - { - m_samples[i] /= max; - } + m_samples[i] = qBound( m_minValue, m_samples[i] / max, m_maxValue ); - if( max != 1.0f ) { + // signal changes if any + if( max != 1.0f || avg != 0.0f ) emit samplesChanged( 0, length()-1 ); - } } +void graphModel::invert() +{ + const float range = m_maxValue - m_minValue; + + for( int i = 0; i < length(); i++ ) + m_samples[i] = m_minValue + ( range - ( m_samples[i] - m_minValue ) ); + + emit samplesChanged( 0, length()-1 ); +} + + + +void graphModel::shiftPhase( int _deg ) +{ + // calculate offset in samples + int offset = ( _deg * length() ) / 360; //multiply first because integers + + // store values in temporary array + QVector temp = m_samples; + + // shift phase + for( int i = 0; i < length(); i++ ) + m_samples[i] = temp[ ( i + offset ) % length() ]; + + emit samplesChanged( 0, length()-1 ); +} + + #include "moc_graph.cxx" From 9c107f386081e8c8b6041d1b3c40b75076022992 Mon Sep 17 00:00:00 2001 From: Vesa Date: Thu, 20 Mar 2014 16:44:35 +0200 Subject: [PATCH 030/647] Desktop file modification to correct ubuntu behavior, icon file copied to data/ as lmms.png because it's needed for packaging --- data/lmms.desktop | 2 +- data/lmms.png | Bin 0 -> 95342 bytes 2 files changed, 1 insertion(+), 1 deletion(-) create mode 100644 data/lmms.png diff --git a/data/lmms.desktop b/data/lmms.desktop index 807ed54f6..aad1005bd 100644 --- a/data/lmms.desktop +++ b/data/lmms.desktop @@ -6,7 +6,7 @@ GenericName[de]=Software zur Musik-Produktion Comment=easy music production for everyone! Comment[ca]=Producció fàcil de música per a tothom! Icon=lmms -Exec=lmms +Exec=env QT_X11_NO_NATIVE_MENUBAR=1 lmms Terminal=false Type=Application Categories=Qt;AudioVideo;Audio;Midi; diff --git a/data/lmms.png b/data/lmms.png new file mode 100644 index 0000000000000000000000000000000000000000..ae9fe6a2a9f329fb005f8a5bedcf55874bba3b92 GIT binary patch literal 95342 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 U&9n^i#Q*>R07*qoM6N<$f@CRPtN;K2 literal 0 HcmV?d00001 From e1bebbfcad85e2300c8ba0a5e919d6f8bd006d94 Mon Sep 17 00:00:00 2001 From: Tobias Doerffel Date: Fri, 21 Mar 2014 10:08:02 +0100 Subject: [PATCH 031/647] Removed obsolete pch.h include --- include/pch.h | 36 ------------------------------------ 1 file changed, 36 deletions(-) delete mode 100644 include/pch.h diff --git a/include/pch.h b/include/pch.h deleted file mode 100644 index aa334c07d..000000000 --- a/include/pch.h +++ /dev/null @@ -1,36 +0,0 @@ -/* - * pch.h - file which is used for precompiled headers - * - * Copyright (c) 2008 Tobias Doerffel - * - * This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net - * - * 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 _PCH_H -#define _PCH_H - -#include -#include -#include - -#include - -#include "Mixer.h" - -#endif From 6f5a47342bdcbdf37b83839e88fa605ad6fb886d Mon Sep 17 00:00:00 2001 From: Tobias Doerffel Date: Fri, 21 Mar 2014 10:43:07 +0100 Subject: [PATCH 032/647] AutomatableModel: coding style improvements --- include/AutomatableModel.h | 42 +++++++++++++++++------------------ src/core/AutomatableModel.cpp | 2 +- 2 files changed, 22 insertions(+), 22 deletions(-) diff --git a/include/AutomatableModel.h b/include/AutomatableModel.h index 40a4484ba..59fee5215 100644 --- a/include/AutomatableModel.h +++ b/include/AutomatableModel.h @@ -22,8 +22,8 @@ * */ -#ifndef _AUTOMATABLE_MODEL_H -#define _AUTOMATABLE_MODEL_H +#ifndef AUTOMATABLE_MODEL_H +#define AUTOMATABLE_MODEL_H #include @@ -34,24 +34,24 @@ // simple way to map a property of a view to a model #define mapPropertyFromModelPtr(type,getfunc,setfunc,modelname) \ public: \ - inline type getfunc() const \ + type getfunc() const \ { \ return (type) modelname->value(); \ } \ public slots: \ - inline void setfunc( const type val ) \ + void setfunc( const type val ) \ { \ modelname->setValue( val ); \ } #define mapPropertyFromModel(type,getfunc,setfunc,modelname) \ public: \ - inline type getfunc() const \ + type getfunc() const \ { \ return (type) modelname.value(); \ } \ public slots: \ - inline void setfunc( const type val ) \ + void setfunc( const type val ) \ { \ modelname.setValue( (float) val ); \ } @@ -80,8 +80,8 @@ public: const float max = 0, const float step = 0, Model* parent = NULL, - const QString& display_name = QString(), - bool default_constructed = false ); + const QString& displayName = QString(), + bool defaultConstructed = false ); virtual ~AutomatableModel(); @@ -93,7 +93,7 @@ public: bool isAutomated() const; - inline ControllerConnection* controllerConnection() const + ControllerConnection* controllerConnection() const { return m_controllerConnection; } @@ -103,13 +103,13 @@ public: template - static inline T castValue( const float v ) + static T castValue( const float v ) { return (T)( v ); } template - static inline bool castValue( const float v ) + static bool castValue( const float v ) { return ( qRound( v ) != 0 ); } @@ -130,7 +130,7 @@ public: template - inline T initValue() const + T initValue() const { return castValue( m_initValue ); } @@ -141,19 +141,19 @@ public: } template - inline T minValue() const + T minValue() const { return castValue( m_minValue ); } template - inline T maxValue() const + T maxValue() const { return castValue( m_maxValue ); } template - inline T step() const + T step() const { return castValue( m_step ); } @@ -164,12 +164,12 @@ public: void setAutomatedValue( const float value ); void setValue( const float value ); - inline void incValue( int steps ) + void incValue( int steps ) { setValue( m_value + steps * m_step ); } - inline float range() const + float range() const { return m_range; } @@ -280,22 +280,22 @@ signals: #define defaultTypedMethods(type) \ - inline type value( int frameOffset = 0 ) const \ + type value( int frameOffset = 0 ) const \ { \ return AutomatableModel::value( frameOffset ); \ } \ \ - inline type initValue() const \ + type initValue() const \ { \ return AutomatableModel::initValue(); \ } \ \ - inline type minValue() const \ + type minValue() const \ { \ return AutomatableModel::minValue(); \ } \ \ - inline type maxValue() const \ + type maxValue() const \ { \ return AutomatableModel::maxValue(); \ } \ diff --git a/src/core/AutomatableModel.cpp b/src/core/AutomatableModel.cpp index 7dbd752d5..671fb5aa7 100644 --- a/src/core/AutomatableModel.cpp +++ b/src/core/AutomatableModel.cpp @@ -495,7 +495,7 @@ void AutomatableModel::copyValue() -void AutomatableModel::pasteValue() +void AutomatableModel::pasteValue() { setValue( copiedValue() ); } From 9ffeae441d26df8ed240937f4b3985dece11b48f Mon Sep 17 00:00:00 2001 From: Tobias Doerffel Date: Fri, 21 Mar 2014 10:43:26 +0100 Subject: [PATCH 033/647] AutomatableModel: avoid hiding virtual functions by overload --- include/AutomatableModel.h | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/include/AutomatableModel.h b/include/AutomatableModel.h index 59fee5215..7e9c9e891 100644 --- a/include/AutomatableModel.h +++ b/include/AutomatableModel.h @@ -193,10 +193,13 @@ public: void unlinkAllModels(); - virtual void saveSettings( QDomDocument& doc, QDomElement& element, - const QString& name = QString( "value" ) ); + /*! \brief Saves settings (value, automation links and controller connections) of AutomatableModel into + specified DOM element using as attribute/node name */ + void saveSettings( QDomDocument& doc, QDomElement& element, const QString& name ); - virtual void loadSettings( const QDomElement& element, const QString& name = QString( "value" ) ); + /*! \brief Loads settings (value, automation links and controller connections) of AutomatableModel from + specified DOM element using as attribute/node name */ + void loadSettings( const QDomElement& element, const QString& name ); virtual QString nodeName() const { @@ -233,6 +236,16 @@ public slots: protected: + virtual void saveSettings( QDomDocument& doc, QDomElement& element ) + { + saveSettings( doc, element, "value" ); + } + + virtual void loadSettings( const QDomElement& element ) + { + loadSettings( element, "value" ); + } + virtual void redoStep( JournalEntry& je ); virtual void undoStep( JournalEntry& je ); From 585f95741cc1a1b3347d31d2e878742174e5ba0c Mon Sep 17 00:00:00 2001 From: Tobias Doerffel Date: Fri, 21 Mar 2014 10:44:22 +0100 Subject: [PATCH 034/647] AutomationPattern: define constants outside class declarations --- include/AutomationPattern.h | 6 +++--- src/core/AutomationPattern.cpp | 3 +++ 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/include/AutomationPattern.h b/include/AutomationPattern.h index 8f9869f33..39dd0cf2a 100644 --- a/include/AutomationPattern.h +++ b/include/AutomationPattern.h @@ -2,7 +2,7 @@ * AutomationPattern.h - declaration of class AutomationPattern, which contains * all information about an automation pattern * - * Copyright (c) 2008-2013 Tobias Doerffel + * Copyright (c) 2008-2014 Tobias Doerffel * Copyright (c) 2006-2008 Javier Serrano Polo * * This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net @@ -179,8 +179,8 @@ private: bool m_dragging; - static const float DEFAULT_MIN_VALUE = 0; - static const float DEFAULT_MAX_VALUE = 1; + static const float DEFAULT_MIN_VALUE; + static const float DEFAULT_MAX_VALUE; friend class AutomationPatternView; diff --git a/src/core/AutomationPattern.cpp b/src/core/AutomationPattern.cpp index 76d2d2b16..0f38b34d9 100644 --- a/src/core/AutomationPattern.cpp +++ b/src/core/AutomationPattern.cpp @@ -37,6 +37,9 @@ #include "song.h" +const float AutomationPattern::DEFAULT_MIN_VALUE = 0; +const float AutomationPattern::DEFAULT_MAX_VALUE = 1; + AutomationPattern::AutomationPattern( AutomationTrack * _auto_track ) : trackContentObject( _auto_track ), From b5eb4f1f7a145d80faaad0f42482846e8b59bfee Mon Sep 17 00:00:00 2001 From: Tobias Doerffel Date: Fri, 21 Mar 2014 10:44:56 +0100 Subject: [PATCH 035/647] ControllerView: remove unused member variable --- include/ControllerView.h | 1 - 1 file changed, 1 deletion(-) diff --git a/include/ControllerView.h b/include/ControllerView.h index 44805bdc1..c86b47c70 100644 --- a/include/ControllerView.h +++ b/include/ControllerView.h @@ -77,7 +77,6 @@ protected: private: QPixmap m_bg; - ledCheckBox * m_bypass; QMdiSubWindow * m_subWindow; ControllerDialog * m_controllerDlg; bool m_show; From 729838fa0853b5529a702a3c7c099feeaa5ea3e1 Mon Sep 17 00:00:00 2001 From: Tobias Doerffel Date: Fri, 21 Mar 2014 10:46:42 +0100 Subject: [PATCH 036/647] ModelView, Model: coding style improvements --- include/Model.h | 14 +++++++------- include/ModelView.h | 26 +++++++++++++------------- src/gui/ModelView.cpp | 28 +++++++++++++--------------- 3 files changed, 33 insertions(+), 35 deletions(-) diff --git a/include/Model.h b/include/Model.h index dc2ea3895..94883c65d 100644 --- a/include/Model.h +++ b/include/Model.h @@ -1,7 +1,7 @@ /* * Model.h - declaration of Model base class * - * Copyright (c) 2007-2009 Tobias Doerffel + * Copyright (c) 2007-2014 Tobias Doerffel * * This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net * @@ -22,8 +22,8 @@ * */ -#ifndef _MODEL_H -#define _MODEL_H +#ifndef MODEL_H +#define MODEL_H #include #include @@ -47,12 +47,12 @@ public: { } - inline bool defaultConstructed() + bool isDefaultConstructed() { return m_defaultConstructed; } - inline Model * parentModel() const + Model* parentModel() const { return static_cast( parent() ); } @@ -62,9 +62,9 @@ public: return m_displayName; } - virtual void setDisplayName( const QString & _display_name ) + virtual void setDisplayName( const QString& displayName ) { - m_displayName = _display_name; + m_displayName = displayName; } virtual QString fullDisplayName() const; diff --git a/include/ModelView.h b/include/ModelView.h index 437c7bd5d..9f8cd9e1e 100644 --- a/include/ModelView.h +++ b/include/ModelView.h @@ -1,7 +1,7 @@ /* * ModelView.h - declaration of ModelView base class * - * Copyright (c) 2007-2009 Tobias Doerffel + * Copyright (c) 2007-2014 Tobias Doerffel * * This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net * @@ -22,8 +22,8 @@ * */ -#ifndef _MODEL_VIEW_H -#define _MODEL_VIEW_H +#ifndef MODEL_VIEW_H +#define MODEL_VIEW_H #include "Model.h" @@ -31,31 +31,31 @@ class EXPORT ModelView { public: - ModelView( Model * _model, QWidget * _this ); + ModelView( Model* model, QWidget* widget ); virtual ~ModelView(); - virtual void setModel( Model * _model, bool _old_model_valid = true ); + virtual void setModel( Model* model, bool isOldModelValid = true ); - inline Model * model() + Model* model() { return m_model; } - inline const Model * model() const + const Model* model() const { return m_model; } template - T * castModel() + T* castModel() { - return dynamic_cast( model() ); + return dynamic_cast( model() ); } template - const T * castModel() const + const T* castModel() const { - return dynamic_cast( model() ); + return dynamic_cast( model() ); } @@ -65,7 +65,7 @@ protected: { } - QWidget * widget() + QWidget* widget() { return m_widget; } @@ -74,7 +74,7 @@ protected: private: - QWidget * m_widget; + QWidget* m_widget; QPointer m_model; } ; diff --git a/src/gui/ModelView.cpp b/src/gui/ModelView.cpp index c8be075f4..3d22b09e2 100644 --- a/src/gui/ModelView.cpp +++ b/src/gui/ModelView.cpp @@ -1,7 +1,7 @@ /* - * ModelView.cpp - implementation of ModelView.cpp + * ModelView.cpp - implementation of ModelView * - * Copyright (c) 2007-2009 Tobias Doerffel + * Copyright (c) 2007-2014 Tobias Doerffel * * This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net * @@ -28,9 +28,9 @@ -ModelView::ModelView( Model * _model, QWidget * _this ) : - m_widget( _this ), - m_model( _model ) +ModelView::ModelView( Model* model, QWidget* widget ) : + m_widget( widget ), + m_model( model ) { } @@ -39,7 +39,7 @@ ModelView::ModelView( Model * _model, QWidget * _this ) : ModelView::~ModelView() { - if( m_model != NULL && m_model->defaultConstructed() ) + if( m_model != NULL && m_model->isDefaultConstructed() ) { delete m_model; } @@ -48,11 +48,11 @@ ModelView::~ModelView() -void ModelView::setModel( Model * _model, bool _old_model_valid ) +void ModelView::setModel( Model* model, bool isOldModelValid ) { - if( _old_model_valid && m_model != NULL ) + if( isOldModelValid && m_model != NULL ) { - if( m_model->defaultConstructed() ) + if( m_model->isDefaultConstructed() ) { delete m_model; } @@ -61,7 +61,8 @@ void ModelView::setModel( Model * _model, bool _old_model_valid ) m_model->disconnect( widget() ); } } - m_model = _model; + + m_model = model; doConnections(); @@ -77,11 +78,8 @@ void ModelView::doConnections() { if( m_model != NULL ) { - QObject::connect( m_model, SIGNAL( dataChanged() ), - widget(), SLOT( update() ) ); - - QObject::connect( m_model, SIGNAL( propertiesChanged() ), - widget(), SLOT( update() ) ); + QObject::connect( m_model, SIGNAL( dataChanged() ), widget(), SLOT( update() ) ); + QObject::connect( m_model, SIGNAL( propertiesChanged() ), widget(), SLOT( update() ) ); } } From d4bbaa58b4a1471631a3fbfdec35620653c4e038 Mon Sep 17 00:00:00 2001 From: Tobias Doerffel Date: Fri, 21 Mar 2014 10:47:05 +0100 Subject: [PATCH 037/647] SerializingObject: made saveSettings() and loadSettings() pure virtual All classes inheriting from SerializingObject should also provide according functionality, therefore ensure, they implement methods for loading and saving settings. --- include/LadspaControl.h | 22 ++++++++++--- include/SerializingObject.h | 6 ++-- include/TempoSyncKnobModel.h | 7 ++--- include/track.h | 22 +++++++++++++ plugins/ladspa_browser/ladspa_browser.h | 14 ++++++++- src/core/SerializingObject.cpp | 41 +++++++++++++++---------- 6 files changed, 81 insertions(+), 31 deletions(-) diff --git a/include/LadspaControl.h b/include/LadspaControl.h index 1b0eae471..8180ce721 100644 --- a/include/LadspaControl.h +++ b/include/LadspaControl.h @@ -3,7 +3,7 @@ * * Copyright (c) 2008-2014 Tobias Doerffel * Copyright (c) 2006-2008 Danny McRae - * + * * This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net * * This program is free software; you can redistribute it and/or @@ -23,8 +23,8 @@ * */ -#ifndef _LADSPA_CONTROL_H -#define _LADSPA_CONTROL_H +#ifndef LADSPA_CONTROL_H +#define LADSPA_CONTROL_H #include @@ -70,8 +70,7 @@ public: return m_port; } - virtual void saveSettings( QDomDocument & _doc, QDomElement & _parent, - const QString & _name ); + virtual void saveSettings( QDomDocument & _doc, QDomElement & _parent, const QString & _name ); virtual void loadSettings( const QDomElement & _this, const QString & _name ); inline virtual QString nodeName() const { @@ -90,6 +89,19 @@ protected slots: void tempoKnobChanged(); void linkStateChanged(); +protected: + virtual void saveSettings( QDomDocument& doc, QDomElement& element ) + { + Q_UNUSED(doc) + Q_UNUSED(element) + } + + virtual void loadSettings( const QDomElement& element ) + { + Q_UNUSED(element) + } + + private: bool m_link; diff --git a/include/SerializingObject.h b/include/SerializingObject.h index e647ad31f..28442e2bd 100644 --- a/include/SerializingObject.h +++ b/include/SerializingObject.h @@ -52,7 +52,7 @@ public: void setHook( SerializingObjectHook * _hook ); - SerializingObjectHook * getHook() + SerializingObjectHook* hook() { return m_hook; } @@ -60,8 +60,8 @@ public: protected: // to be implemented by sub-objects - virtual void saveSettings( QDomDocument & _doc, QDomElement & _this ); - virtual void loadSettings( const QDomElement & _this ); + virtual void saveSettings( QDomDocument& doc, QDomElement& element ) = 0; + virtual void loadSettings( const QDomElement& element ) = 0; private: diff --git a/include/TempoSyncKnobModel.h b/include/TempoSyncKnobModel.h index 54a2befe6..0bb9c261f 100644 --- a/include/TempoSyncKnobModel.h +++ b/include/TempoSyncKnobModel.h @@ -53,11 +53,8 @@ public: const QString & _display_name = QString() ); virtual ~TempoSyncKnobModel(); - virtual void saveSettings( QDomDocument & _doc, - QDomElement & _this, - const QString & _name ); - virtual void loadSettings( const QDomElement & _this, - const QString & _name ); + virtual void saveSettings( QDomDocument & _doc, QDomElement & _this, const QString& name = "value" ); + virtual void loadSettings( const QDomElement & _this, const QString& name = "value" ); TempoSyncMode syncMode() const { diff --git a/include/track.h b/include/track.h index 5fc92f2f2..273c77710 100644 --- a/include/track.h +++ b/include/track.h @@ -277,6 +277,17 @@ protected: return "trackcontentwidget"; } + virtual void saveSettings( QDomDocument& doc, QDomElement& element ) + { + Q_UNUSED(doc) + Q_UNUSED(element) + } + + virtual void loadSettings( const QDomElement& element ) + { + Q_UNUSED(element) + } + virtual void undoStep( JournalEntry & _je ); virtual void redoStep( JournalEntry & _je ); @@ -544,6 +555,17 @@ protected: virtual void undoStep( JournalEntry & _je ); virtual void redoStep( JournalEntry & _je ); + virtual void saveSettings( QDomDocument& doc, QDomElement& element ) + { + Q_UNUSED(doc) + Q_UNUSED(element) + } + + virtual void loadSettings( const QDomElement& element ) + { + Q_UNUSED(element) + } + virtual QString nodeName() const { return "trackview"; diff --git a/plugins/ladspa_browser/ladspa_browser.h b/plugins/ladspa_browser/ladspa_browser.h index 5d2a9b943..b105862da 100644 --- a/plugins/ladspa_browser/ladspa_browser.h +++ b/plugins/ladspa_browser/ladspa_browser.h @@ -1,6 +1,6 @@ /* * ladspa_browser.h - dialog to display information about installed LADSPA - * plugins + * plugins * * Copyright (c) 2006-2008 Danny McRae * Copyright (c) 2009 Tobias Doerffel @@ -68,6 +68,18 @@ public: virtual QString nodeName() const; + virtual void saveSettings( QDomDocument& doc, QDomElement& element ) + { + Q_UNUSED(doc) + Q_UNUSED(element) + } + + virtual void loadSettings( const QDomElement& element ) + { + Q_UNUSED(element) + } + + } ; diff --git a/src/core/SerializingObject.cpp b/src/core/SerializingObject.cpp index 2ed0e1c7a..da1b7a5cb 100644 --- a/src/core/SerializingObject.cpp +++ b/src/core/SerializingObject.cpp @@ -47,41 +47,46 @@ SerializingObject::~SerializingObject() -QDomElement SerializingObject::saveState( QDomDocument & _doc, - QDomElement & _parent ) +QDomElement SerializingObject::saveState( QDomDocument& doc, QDomElement& parent ) { - QDomElement _this = _doc.createElement( nodeName() ); - _parent.appendChild( _this ); - saveSettings( _doc, _this ); - if( getHook() ) + QDomElement element = doc.createElement( nodeName() ); + parent.appendChild( element ); + + saveSettings( doc, element ); + + if( hook() ) { - getHook()->saveSettings( _doc, _this ); + hook()->saveSettings( doc, element ); } - return _this; + + return element; } -void SerializingObject::restoreState( const QDomElement & _this ) +void SerializingObject::restoreState( const QDomElement& element ) { - loadSettings( _this ); - if( getHook() ) + loadSettings( element ); + + if( hook() ) { - getHook()->loadSettings( _this ); + hook()->loadSettings( element ); } } -void SerializingObject::setHook( SerializingObjectHook * _hook ) +void SerializingObject::setHook( SerializingObjectHook* hook ) { if( m_hook ) { m_hook->m_hookedIn = NULL; } - m_hook = _hook; + + m_hook = hook; + if( m_hook ) { m_hook->m_hookedIn = this; @@ -91,16 +96,18 @@ void SerializingObject::setHook( SerializingObjectHook * _hook ) -void SerializingObject::saveSettings( QDomDocument &/* _doc*/, - QDomElement &/* _this*/ ) +void SerializingObject::saveSettings( QDomDocument& doc, QDomElement& element ) { + Q_UNUSED(doc) + Q_UNUSED(element) } -void SerializingObject::loadSettings( const QDomElement & /* _this*/ ) +void SerializingObject::loadSettings( const QDomElement& element ) { + Q_UNUSED(element) } From cce942e5d54b594b8c710fcc3b8c61bc7be498de Mon Sep 17 00:00:00 2001 From: Tobias Doerffel Date: Fri, 21 Mar 2014 10:48:43 +0100 Subject: [PATCH 038/647] Graph: removed unused member variable --- include/graph.h | 1 - 1 file changed, 1 deletion(-) diff --git a/include/graph.h b/include/graph.h index 025e15a7b..b2041c6e9 100644 --- a/include/graph.h +++ b/include/graph.h @@ -102,7 +102,6 @@ private: QPixmap m_foreground; QColor m_graphColor; - graphModel * m_graphModel; graphStyle m_graphStyle; bool m_mouseDown; From bdf234aeb88d98f8ca832ced49ce91c93ff3cbc9 Mon Sep 17 00:00:00 2001 From: Tobias Doerffel Date: Fri, 21 Mar 2014 11:11:15 +0100 Subject: [PATCH 039/647] ZynAddSubFX: fixed various CLANG compiler warnings --- plugins/zynaddsubfx/src/DSP/AnalogFilter.h | 1 - plugins/zynaddsubfx/src/Effects/EffectLFO.h | 1 - plugins/zynaddsubfx/src/Effects/Reverb.h | 4 ++-- plugins/zynaddsubfx/src/UI/EffUI.fl | 2 +- plugins/zynaddsubfx/src/UI/EffUI.h | 2 +- plugins/zynaddsubfx/src/UI/EnvelopeUI.fl | 2 +- plugins/zynaddsubfx/src/UI/EnvelopeUI.h | 2 +- plugins/zynaddsubfx/src/UI/FilterUI.fl | 2 +- plugins/zynaddsubfx/src/UI/FilterUI.h | 2 +- plugins/zynaddsubfx/src/UI/PartUI.cc | 2 +- 10 files changed, 9 insertions(+), 11 deletions(-) diff --git a/plugins/zynaddsubfx/src/DSP/AnalogFilter.h b/plugins/zynaddsubfx/src/DSP/AnalogFilter.h index aeca9f1a3..cd7efbc2d 100644 --- a/plugins/zynaddsubfx/src/DSP/AnalogFilter.h +++ b/plugins/zynaddsubfx/src/DSP/AnalogFilter.h @@ -71,7 +71,6 @@ class AnalogFilter:public Filter_ REALTYPE oldc[3], oldd[3]; //old coefficients(used only if some filter paremeters changes very fast, and it needs interpolation) - REALTYPE xd[3], yd[3]; //used if the filter is applied more times int needsinterpolation, firsttime; /**\todo see if bool works for these*/ int abovenq; //this is 1 if the frequency is above the nyquist int oldabovenq; //if the last time was above nyquist (used to see if it needs interpolation) diff --git a/plugins/zynaddsubfx/src/Effects/EffectLFO.h b/plugins/zynaddsubfx/src/Effects/EffectLFO.h index cc14d6652..cd54463a9 100644 --- a/plugins/zynaddsubfx/src/Effects/EffectLFO.h +++ b/plugins/zynaddsubfx/src/Effects/EffectLFO.h @@ -43,7 +43,6 @@ class EffectLFO REALTYPE xl, xr; REALTYPE incx; REALTYPE ampl1, ampl2, ampr1, ampr2; //necessary for "randomness" - REALTYPE lfointensity; REALTYPE lfornd; char lfotype; /**\todo GET RID OF CHAR (replace with short or enum)*/ }; diff --git a/plugins/zynaddsubfx/src/Effects/Reverb.h b/plugins/zynaddsubfx/src/Effects/Reverb.h index e84c56d88..a505a8fda 100644 --- a/plugins/zynaddsubfx/src/Effects/Reverb.h +++ b/plugins/zynaddsubfx/src/Effects/Reverb.h @@ -102,10 +102,10 @@ class Reverb:public Effect void setroomsize(unsigned char Proomsize); void setbandwidth(unsigned char Pbandwidth); - REALTYPE pan, erbalance; + REALTYPE pan; //Parameters int lohidamptype; /**<0=disable,1=highdamp(lowpass),2=lowdamp(highpass)*/ - int idelaylen, rdelaylen; + int idelaylen; int idelayk; REALTYPE lohifb, idelayfb, roomsize, rs; //rs is used to "normalise" the volume according to the roomsize int comblen[REV_COMBS * 2]; diff --git a/plugins/zynaddsubfx/src/UI/EffUI.fl b/plugins/zynaddsubfx/src/UI/EffUI.fl index 69ebac180..d82099c3e 100644 --- a/plugins/zynaddsubfx/src/UI/EffUI.fl +++ b/plugins/zynaddsubfx/src/UI/EffUI.fl @@ -148,7 +148,7 @@ return(20.0*pow((REALTYPE)1000.0,x));} {} code {if (freq<0.00001) freq=0.00001; return(log(freq/20.0)/log(1000.0));} {} } - decl {int oldx,oldy;} {} + decl {int oldx;} {} decl {REALTYPE khzval;} {public } decl {EffectMgr *eff;} {} diff --git a/plugins/zynaddsubfx/src/UI/EffUI.h b/plugins/zynaddsubfx/src/UI/EffUI.h index be2f5f4a8..92af395a9 100644 --- a/plugins/zynaddsubfx/src/UI/EffUI.h +++ b/plugins/zynaddsubfx/src/UI/EffUI.h @@ -24,7 +24,7 @@ public: REALTYPE getfreqx(REALTYPE x); REALTYPE getfreqpos(REALTYPE freq); private: - int oldx,oldy; + int oldx; public: REALTYPE khzval; private: diff --git a/plugins/zynaddsubfx/src/UI/EnvelopeUI.fl b/plugins/zynaddsubfx/src/UI/EnvelopeUI.fl index eef5ad643..3b49da3b5 100644 --- a/plugins/zynaddsubfx/src/UI/EnvelopeUI.fl +++ b/plugins/zynaddsubfx/src/UI/EnvelopeUI.fl @@ -189,7 +189,7 @@ return(1);} {} } decl {Fl_Box *pair;} {} decl {EnvelopeParams *env;} {} - decl {int oldx,oldy;} {} + decl {int oldx;} {} decl {int currentpoint,cpx,cpdt;} {} decl {int lastpoint;} {public } diff --git a/plugins/zynaddsubfx/src/UI/EnvelopeUI.h b/plugins/zynaddsubfx/src/UI/EnvelopeUI.h index 0450433b3..724745c57 100644 --- a/plugins/zynaddsubfx/src/UI/EnvelopeUI.h +++ b/plugins/zynaddsubfx/src/UI/EnvelopeUI.h @@ -29,7 +29,7 @@ public: private: Fl_Box *pair; EnvelopeParams *env; - int oldx,oldy; + int oldx; int currentpoint,cpx,cpdt; public: int lastpoint; diff --git a/plugins/zynaddsubfx/src/UI/FilterUI.fl b/plugins/zynaddsubfx/src/UI/FilterUI.fl index e2da82e12..298d1403d 100644 --- a/plugins/zynaddsubfx/src/UI/FilterUI.fl +++ b/plugins/zynaddsubfx/src/UI/FilterUI.fl @@ -144,7 +144,7 @@ for (i=1;iadd(tmp); - if ((val==-1)){ + if (val==-1){ if (klimits[k]>part->Pkeylimit) val=k; }; k++; From 9aa6a3fbebac4c59b4a6c997a23dbac6575d1e32 Mon Sep 17 00:00:00 2001 From: Tobias Doerffel Date: Fri, 21 Mar 2014 11:11:39 +0100 Subject: [PATCH 040/647] AudioFileProcessor: fixed various CLANG compiler warnings --- plugins/audio_file_processor/audio_file_processor.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/audio_file_processor/audio_file_processor.cpp b/plugins/audio_file_processor/audio_file_processor.cpp index e6ec7b906..ff8ffdd0b 100644 --- a/plugins/audio_file_processor/audio_file_processor.cpp +++ b/plugins/audio_file_processor/audio_file_processor.cpp @@ -303,7 +303,7 @@ void audioFileProcessor::loopPointChanged( void ) //check if start & end overlap and nudge end up if so if( m_startPointModel.value() == m_endPointModel.value() ) { - m_endPointModel.setValue( qMin( m_endPointModel.value() + 0.001, 1.0d ) ); + m_endPointModel.setValue( qMin( m_endPointModel.value() + 0.001f, 1.0f ) ); } const f_cnt_t f_start = static_cast( m_startPointModel.value() * From 117ca99c8592f1bee9014c342148157ceb2d42db Mon Sep 17 00:00:00 2001 From: Tobias Doerffel Date: Fri, 21 Mar 2014 11:11:50 +0100 Subject: [PATCH 041/647] BitInvader: fixed various CLANG compiler warnings --- plugins/bit_invader/bit_invader.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/plugins/bit_invader/bit_invader.h b/plugins/bit_invader/bit_invader.h index 39fc747ee..9aa8c8d58 100644 --- a/plugins/bit_invader/bit_invader.h +++ b/plugins/bit_invader/bit_invader.h @@ -101,8 +101,6 @@ private: float m_normalizeFactor; - oscillator * m_osc; - friend class bitInvaderView; } ; From 33ea001c3137a787d21ca84fbe28e0ce5cc37a55 Mon Sep 17 00:00:00 2001 From: Tobias Doerffel Date: Fri, 21 Mar 2014 11:12:08 +0100 Subject: [PATCH 042/647] LB302: fixed various CLANG compiler warnings --- plugins/lb302/lb302.h | 4 ---- 1 file changed, 4 deletions(-) diff --git a/plugins/lb302/lb302.h b/plugins/lb302/lb302.h index f12129176..b909b2710 100644 --- a/plugins/lb302/lb302.h +++ b/plugins/lb302/lb302.h @@ -200,8 +200,6 @@ private: vco_slideinc, //* Slide base to use in next node. Nonzero=slide next note vco_slidebase; //* The base vco_inc while sliding. - float vco_detune; - enum vco_shape_t { SAWTOOTH, SQUARE, TRIANGLE, MOOG, ROUND_SQUARE, SINE, EXPONENTIAL, WHITE_NOISE }; vco_shape_t vco_shape; @@ -262,8 +260,6 @@ private: knob * m_vcfDecKnob; knob * m_vcfModKnob; - knob * m_vcoFineDetuneKnob; - knob * m_distKnob; knob * m_slideDecKnob; automatableButtonGroup * m_waveBtnGrp; From b2c1a04df85d310c2fe8f536b7397d9e933f0ef8 Mon Sep 17 00:00:00 2001 From: Tobias Doerffel Date: Fri, 21 Mar 2014 11:12:17 +0100 Subject: [PATCH 043/647] OPL2: fixed various CLANG compiler warnings --- plugins/opl2/fmopl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/opl2/fmopl.c b/plugins/opl2/fmopl.c index db5180189..f6382b6cb 100644 --- a/plugins/opl2/fmopl.c +++ b/plugins/opl2/fmopl.c @@ -229,7 +229,7 @@ INT32 *ams_table; INT32 *vib_table; static INT32 amsIncr; static INT32 vibIncr; -static INT32 feedback2; /* connect for SLOT 2 */ +INT32 feedback2; /* connect for SLOT 2 */ /* log output level */ #define LOG_ERR 3 /* ERROR */ From 6e4fbbed87c098aef0ab0cb9fe7ef0a975cbb542 Mon Sep 17 00:00:00 2001 From: Tobias Doerffel Date: Fri, 21 Mar 2014 11:12:29 +0100 Subject: [PATCH 044/647] Papu: fixed various CLANG compiler warnings --- plugins/papu/papu_instrument.h | 3 --- 1 file changed, 3 deletions(-) diff --git a/plugins/papu/papu_instrument.h b/plugins/papu/papu_instrument.h index f462306a7..dad2d0b70 100644 --- a/plugins/papu/papu_instrument.h +++ b/plugins/papu/papu_instrument.h @@ -129,15 +129,12 @@ private: pixmapButton * m_ch2VolSweepDirButton; knob * m_ch2SweepStepLengthKnob; - pixmapButton * m_ch3OnButton; knob * m_ch3VolumeKnob; knob * m_ch4VolumeKnob; pixmapButton * m_ch4VolSweepDirButton; knob * m_ch4SweepStepLengthKnob; - knob * m_ch4ShiftClockFreqKnob; pixmapButton * m_ch4ShiftRegWidthButton; - knob * m_ch4FreqDivRatioKnob; knob * m_so1VolumeKnob; knob * m_so2VolumeKnob; From 1153e85c0cc7cda46a09a251b0cebd638ed93862 Mon Sep 17 00:00:00 2001 From: Tobias Doerffel Date: Fri, 21 Mar 2014 11:12:39 +0100 Subject: [PATCH 045/647] StereoEnhancer: fixed various CLANG compiler warnings --- plugins/stereo_enhancer/stereo_enhancer.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/plugins/stereo_enhancer/stereo_enhancer.cpp b/plugins/stereo_enhancer/stereo_enhancer.cpp index 442d49ccd..d12a8eb1e 100644 --- a/plugins/stereo_enhancer/stereo_enhancer.cpp +++ b/plugins/stereo_enhancer/stereo_enhancer.cpp @@ -69,10 +69,9 @@ stereoEnhancerEffect::~stereoEnhancerEffect() { if( m_delayBuffer ) { - //delete [] m_delayBuffer; - delete m_delayBuffer; - + delete [] m_delayBuffer; } + m_currFrame = 0; } From 71eaa4f5e346aa4c53dc279ef73c8a50c58a99f6 Mon Sep 17 00:00:00 2001 From: Tobias Doerffel Date: Fri, 21 Mar 2014 11:12:52 +0100 Subject: [PATCH 046/647] TripleOscillator: fixed various CLANG compiler warnings --- plugins/triple_oscillator/TripleOscillator.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/plugins/triple_oscillator/TripleOscillator.h b/plugins/triple_oscillator/TripleOscillator.h index bcddcf9e2..a0e670528 100644 --- a/plugins/triple_oscillator/TripleOscillator.h +++ b/plugins/triple_oscillator/TripleOscillator.h @@ -119,8 +119,6 @@ protected slots: private: - InstrumentTrack * m_InstrumentTrack; - OscillatorObject * m_osc[NUM_OF_OSCILLATORS]; struct oscPtr From 890993bff005213825e696978f75e8955c26732a Mon Sep 17 00:00:00 2001 From: Tobias Doerffel Date: Fri, 21 Mar 2014 11:13:05 +0100 Subject: [PATCH 047/647] Vibed: fixed various CLANG compiler warnings --- plugins/vibed/nine_button_selector.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/plugins/vibed/nine_button_selector.h b/plugins/vibed/nine_button_selector.h index bd8eacbc2..f17e36ace 100644 --- a/plugins/vibed/nine_button_selector.h +++ b/plugins/vibed/nine_button_selector.h @@ -87,8 +87,6 @@ private: pixmapButton * m_button; pixmapButton * m_lastBtn; - int m_selected; - } ; typedef IntModel nineButtonSelectorModel; From 8e4417e5d9e17ca79f3adf330a8207197a6f0ed6 Mon Sep 17 00:00:00 2001 From: Tobias Doerffel Date: Fri, 21 Mar 2014 11:13:20 +0100 Subject: [PATCH 048/647] Mixer: fixed various CLANG compiler warnings --- src/core/Mixer.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/core/Mixer.cpp b/src/core/Mixer.cpp index b853c9d80..d922f63d0 100644 --- a/src/core/Mixer.cpp +++ b/src/core/Mixer.cpp @@ -164,6 +164,11 @@ public: void processJobQueue(); + int workerNum() const + { + return m_workerNum; + } + private: virtual void run() From 6bb16951ad6e3460d178784ec210d16bde8921cf Mon Sep 17 00:00:00 2001 From: Tobias Doerffel Date: Fri, 21 Mar 2014 11:13:30 +0100 Subject: [PATCH 049/647] Main: fixed various CLANG compiler warnings --- src/core/main.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/core/main.cpp b/src/core/main.cpp index aa2df2077..92631874b 100644 --- a/src/core/main.cpp +++ b/src/core/main.cpp @@ -181,10 +181,12 @@ int main( int argc, char * * argv ) else if( argc > i+1 && ( QString( argv[i] ) == "--upgrade" || QString( argv[i] ) == "-u" ) ) { - DataFile dataFile( QString( argv[i + 1] ) ); + QString inFile( argv[i + 1] ); + DataFile dataFile( inFile ); if (argc > i+2) { - dataFile.writeFile( argv[i + 2] ); + const QString outFile = argv[i + 2]; + dataFile.writeFile( outFile ); } else { From 6a1a295cecf922415acd13119021910fcc89b2f8 Mon Sep 17 00:00:00 2001 From: Tobias Doerffel Date: Fri, 21 Mar 2014 11:14:22 +0100 Subject: [PATCH 050/647] More CLANG compiler warning fixes --- include/AudioPortAudio.h | 1 - include/AutomatableModel.h | 18 ++++++------ include/ControllerRackView.h | 3 -- include/DummyInstrument.h | 4 +-- include/RemotePlugin.h | 2 -- include/TempoSyncKnobModel.h | 4 +-- include/shared_object.h | 38 ++++++++++++++------------ include/track.h | 2 -- src/gui/widgets/ControllerRackView.cpp | 5 ++-- 9 files changed, 36 insertions(+), 41 deletions(-) diff --git a/include/AudioPortAudio.h b/include/AudioPortAudio.h index 93e86f13d..04b0d3590 100644 --- a/include/AudioPortAudio.h +++ b/include/AudioPortAudio.h @@ -88,7 +88,6 @@ public: private: comboBox * m_backend; comboBox * m_device; - LcdSpinBox * m_channels; AudioPortAudioSetupUtil m_setupUtil; } ; diff --git a/include/AutomatableModel.h b/include/AutomatableModel.h index 7e9c9e891..f390d2531 100644 --- a/include/AutomatableModel.h +++ b/include/AutomatableModel.h @@ -195,11 +195,11 @@ public: /*! \brief Saves settings (value, automation links and controller connections) of AutomatableModel into specified DOM element using as attribute/node name */ - void saveSettings( QDomDocument& doc, QDomElement& element, const QString& name ); + virtual void saveSettings( QDomDocument& doc, QDomElement& element, const QString& name ); /*! \brief Loads settings (value, automation links and controller connections) of AutomatableModel from specified DOM element using as attribute/node name */ - void loadSettings( const QDomElement& element, const QString& name ); + virtual void loadSettings( const QDomElement& element, const QString& name ); virtual QString nodeName() const { @@ -236,6 +236,13 @@ public slots: protected: + virtual void redoStep( JournalEntry& je ); + virtual void undoStep( JournalEntry& je ); + + float fittedValue( float value ) const; + + +private: virtual void saveSettings( QDomDocument& doc, QDomElement& element ) { saveSettings( doc, element, "value" ); @@ -246,13 +253,6 @@ protected: loadSettings( element, "value" ); } - virtual void redoStep( JournalEntry& je ); - virtual void undoStep( JournalEntry& je ); - - float fittedValue( float value ) const; - - -private: void linkModel( AutomatableModel* model ); void unlinkModel( AutomatableModel* model ); diff --git a/include/ControllerRackView.h b/include/ControllerRackView.h index f7a3282be..60c8f0735 100644 --- a/include/ControllerRackView.h +++ b/include/ControllerRackView.h @@ -65,11 +65,8 @@ private slots: private: QVector m_controllerViews; - QVBoxLayout * m_mainLayout; QScrollArea * m_scrollArea; QPushButton * m_addButton; - - int m_lastY; } ; diff --git a/include/DummyInstrument.h b/include/DummyInstrument.h index 091fedc0e..ee9e5d31a 100644 --- a/include/DummyInstrument.h +++ b/include/DummyInstrument.h @@ -2,7 +2,7 @@ * DummyInstrument.h - instrument used as fallback if an instrument couldn't * be loaded * - * Copyright (c) 2005-2009 Tobias Doerffel + * Copyright (c) 2005-2014 Tobias Doerffel * * This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net * @@ -42,7 +42,7 @@ public: { } - virtual void playNote( NotePlayHandle *, bool, sampleFrame * ) + virtual void playNote( NotePlayHandle *, sampleFrame * ) { } diff --git a/include/RemotePlugin.h b/include/RemotePlugin.h index 0da674289..edf09efbe 100644 --- a/include/RemotePlugin.h +++ b/include/RemotePlugin.h @@ -474,7 +474,6 @@ private: #else int m_shmID; #endif - size_t m_shmSize; shmData * m_data; #ifdef USE_QT_SEMAPHORES QSystemSemaphore m_dataSem; @@ -780,7 +779,6 @@ private: void resizeSharedProcessingMemory(); - bool m_initialized; bool m_failed; QProcess m_process; diff --git a/include/TempoSyncKnobModel.h b/include/TempoSyncKnobModel.h index 0bb9c261f..4c0461e24 100644 --- a/include/TempoSyncKnobModel.h +++ b/include/TempoSyncKnobModel.h @@ -53,8 +53,8 @@ public: const QString & _display_name = QString() ); virtual ~TempoSyncKnobModel(); - virtual void saveSettings( QDomDocument & _doc, QDomElement & _this, const QString& name = "value" ); - virtual void loadSettings( const QDomElement & _this, const QString& name = "value" ); + void saveSettings( QDomDocument & _doc, QDomElement & _this, const QString& name ); + void loadSettings( const QDomElement & _this, const QString& name ); TempoSyncMode syncMode() const { diff --git a/include/shared_object.h b/include/shared_object.h index a02e933f4..a0d461539 100644 --- a/include/shared_object.h +++ b/include/shared_object.h @@ -2,8 +2,8 @@ * shared_object.h - class sharedObject for use among other objects * * Copyright (c) 2006-2007 Javier Serrano Polo - * Copyright (c) 2008 Tobias Doerffel - * + * Copyright (c) 2008-2014 Tobias Doerffel + * * This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net * * This program is free software; you can redistribute it and/or @@ -23,10 +23,8 @@ * */ - -#ifndef _SHARED_OBJECT_H -#define _SHARED_OBJECT_H - +#ifndef SHARED_OBJECT_H +#define SHARED_OBJECT_H #include @@ -45,27 +43,33 @@ public: } template - static T * ref( T * _object ) + static T* ref( T* object ) { - _object->m_lock.lock(); + object->m_lock.lock(); // TODO: Use QShared - ++_object->m_referenceCount; - _object->m_lock.unlock(); - return( _object ); + ++object->m_referenceCount; + object->m_lock.unlock(); + return object; } template - static void unref( T * _object ) + static void unref( T* object ) { - _object->m_lock.lock(); - bool delete_object = --_object->m_referenceCount <= 0; - _object->m_lock.unlock(); - if ( delete_object ) + object->m_lock.lock(); + bool deleteObject = --object->m_referenceCount <= 0; + object->m_lock.unlock(); + + if ( deleteObject ) { - delete _object; + delete object; } } + // keep clang happy which complaines about unused member variable + void dummy() + { + m_referenceCount = 0; + } private: int m_referenceCount; diff --git a/include/track.h b/include/track.h index 273c77710..b5a4b3e67 100644 --- a/include/track.h +++ b/include/track.h @@ -307,8 +307,6 @@ private: typedef QVector tcoViewVector; tcoViewVector m_tcoViews; - int m_pixelsPerTact; - QPixmap m_background; } ; diff --git a/src/gui/widgets/ControllerRackView.cpp b/src/gui/widgets/ControllerRackView.cpp index 85116f7ac..97ce687fe 100644 --- a/src/gui/widgets/ControllerRackView.cpp +++ b/src/gui/widgets/ControllerRackView.cpp @@ -2,7 +2,7 @@ * ControllerRackView.cpp - view for song's controllers * * Copyright (c) 2008-2009 Paul Giblock - * Copyright (c) 2010-2011 Tobias Doerffel + * Copyright (c) 2010-2014 Tobias Doerffel * * This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net * @@ -42,8 +42,7 @@ ControllerRackView::ControllerRackView( ) : - QWidget(), - m_lastY( 0 ) + QWidget() { setMinimumWidth( 250 ); setMaximumWidth( 250 ); From 13a41b5bff2c90e66bdf2ca5632d45039fc74275 Mon Sep 17 00:00:00 2001 From: Tobias Doerffel Date: Fri, 21 Mar 2014 11:16:45 +0100 Subject: [PATCH 051/647] VstEffectControlDialog: remove unused variable --- plugins/VstEffect/VstEffectControlDialog.h | 1 - 1 file changed, 1 deletion(-) diff --git a/plugins/VstEffect/VstEffectControlDialog.h b/plugins/VstEffect/VstEffectControlDialog.h index de8b748dd..0912c906d 100644 --- a/plugins/VstEffect/VstEffectControlDialog.h +++ b/plugins/VstEffect/VstEffectControlDialog.h @@ -55,7 +55,6 @@ private: pixmapButton * m_openPresetButton; pixmapButton * m_rolLPresetButton; pixmapButton * m_rolRPresetButton; - pixmapButton * m_selPresetButton; pixmapButton * m_managePluginButton; pixmapButton * m_savePresetButton; From e4dd6938cc69e43918248d41e3ae32d0b663482c Mon Sep 17 00:00:00 2001 From: Tobias Doerffel Date: Fri, 21 Mar 2014 17:22:38 +0100 Subject: [PATCH 052/647] CMakeLists: updated libpng DLL file name --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index ba1536076..95d71c851 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -439,7 +439,7 @@ IF(LMMS_BUILD_WIN32) "${MINGW_PREFIX}/bin/libfftw3f-3.dll" "${MINGW_PREFIX}/bin/libFLAC-8.dll" "${MINGW_PREFIX}/bin/libportaudio-2.dll" - "${MINGW_PREFIX}/bin/libpng15-15.dll" + "${MINGW_PREFIX}/bin/libpng16-16.dll" "${MINGW_PREFIX}/bin/SDL.dll" "${MINGW_PREFIX}/bin/libglib-2.0-0.dll" "${MINGW_PREFIX}/bin/libgthread-2.0-0.dll" From 69e02fc37d0744af1c59618bf7432a354fefb3a6 Mon Sep 17 00:00:00 2001 From: Tobias Doerffel Date: Fri, 21 Mar 2014 17:23:25 +0100 Subject: [PATCH 053/647] VeSTige: removed unused array --- plugins/vestige/vestige.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/plugins/vestige/vestige.h b/plugins/vestige/vestige.h index b4b063a6a..8a5ce639e 100644 --- a/plugins/vestige/vestige.h +++ b/plugins/vestige/vestige.h @@ -78,8 +78,6 @@ protected slots: private: void closePlugin( void ); - int m_runningNotes[NumKeys]; - VstPlugin * m_plugin; QMutex m_pluginMutex; From 25f2eae67fc650bfe60944f9f1e1acbd23aeb213 Mon Sep 17 00:00:00 2001 From: Paul Giblock Date: Sat, 22 Mar 2014 01:03:28 -0400 Subject: [PATCH 054/647] Revert LB302 db24 switch Invert it so 3-pole is used for DB24 mode again. Fixes #477 --- plugins/lb302/lb302.cpp | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/plugins/lb302/lb302.cpp b/plugins/lb302/lb302.cpp index 1891bee3b..28628a27d 100644 --- a/plugins/lb302/lb302.cpp +++ b/plugins/lb302/lb302.cpp @@ -337,8 +337,8 @@ lb302Synth::lb302Synth( InstrumentTrack * _instrumentTrack ) : vca_a = 9; vca_mode = 3; - vcfs[0] = new lb302Filter3Pole(&fs); - vcfs[1] = new lb302FilterIIR2(&fs); + vcfs[0] = new lb302FilterIIR2(&fs); + vcfs[1] = new lb302Filter3Pole(&fs); db24Toggled(); sample_cnt = 0; @@ -346,18 +346,16 @@ lb302Synth::lb302Synth( InstrumentTrack * _instrumentTrack ) : catch_frame = 0; catch_decay = 0; - recalcFilter(); - last_offset = 0; new_freq = -1; current_freq = -1; delete_freq = -1; + filterChanged(); + InstrumentPlayHandle * iph = new InstrumentPlayHandle( this ); engine::mixer()->addPlayHandle( iph ); - - filterChanged(); } From 22cb12d0663d447408761cd5830d7c1c87a76e20 Mon Sep 17 00:00:00 2001 From: Vesa Date: Sat, 22 Mar 2014 12:31:34 +0200 Subject: [PATCH 055/647] Increase the volume of OpulenZ, because it is very very quiet and it's better to correct this now before 1.0.0 is released --- plugins/opl2/opl2instrument.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/opl2/opl2instrument.cpp b/plugins/opl2/opl2instrument.cpp index 26c3ae10a..a1b58a7e7 100644 --- a/plugins/opl2/opl2instrument.cpp +++ b/plugins/opl2/opl2instrument.cpp @@ -395,7 +395,7 @@ void opl2instrument::play( sampleFrame * _working_buffer ) sample_t s = float(renderbuffer[frame])/32768.0; for( ch_cnt_t ch = 0; ch < DEFAULT_CHANNELS; ++ch ) { - _working_buffer[frame][ch] = s; + _working_buffer[frame][ch] = s * 4.0; } } emulatorMutex.unlock(); From f986f099da12ce71bf7ee79ceef5aded043ddf84 Mon Sep 17 00:00:00 2001 From: Vesa Date: Sat, 22 Mar 2014 12:32:43 +0200 Subject: [PATCH 056/647] Piano widget: make keypresses (gui and keyboard) based on the MIDI base velocity spinner --- include/Piano.h | 6 +++--- src/core/Piano.cpp | 8 ++++++-- src/gui/PianoView.cpp | 16 ++++++++-------- 3 files changed, 17 insertions(+), 13 deletions(-) diff --git a/include/Piano.h b/include/Piano.h index b1487095f..8e86622fc 100644 --- a/include/Piano.h +++ b/include/Piano.h @@ -22,8 +22,8 @@ * */ -#ifndef _PIANO_H -#define _PIANO_H +#ifndef PIANO_H +#define PIANO_H #include "note.h" #include "Model.h" @@ -50,7 +50,7 @@ public: return m_pressedKeys[key]; } - void handleKeyPress( int key, int midiVelocity = MidiDefaultVelocity ); + void handleKeyPress( int key, int midiVelocity = -1 ); void handleKeyRelease( int key ); InstrumentTrack* instrumentTrack() const diff --git a/src/core/Piano.cpp b/src/core/Piano.cpp index 584362f46..93fa34869 100644 --- a/src/core/Piano.cpp +++ b/src/core/Piano.cpp @@ -3,7 +3,7 @@ * for testing + according model class * * Copyright (c) 2004-2014 Tobias Doerffel - * + * * This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net * * This program is free software; you can redistribute it and/or @@ -31,7 +31,7 @@ * \mainpage Instrument plugin keyboard display classes * * \section introduction Introduction - * + * * \todo fill this out * \todo write isWhite inline function and replace throughout */ @@ -95,6 +95,10 @@ void Piano::setKeyState( int key, bool state ) */ void Piano::handleKeyPress( int key, int midiVelocity ) { + if( midiVelocity == -1 ) + { + midiVelocity = m_instrumentTrack->midiPort()->baseVelocity(); + } if( isValidKey( key ) ) { m_midiEvProc->processInEvent( MidiEvent( MidiNoteOn, 0, key, midiVelocity ) ); diff --git a/src/gui/PianoView.cpp b/src/gui/PianoView.cpp index ce945ec5f..3bd43f8e6 100644 --- a/src/gui/PianoView.cpp +++ b/src/gui/PianoView.cpp @@ -3,7 +3,7 @@ * for testing + according model class * * Copyright (c) 2004-2014 Tobias Doerffel - * + * * This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net * * This program is free software; you can redistribute it and/or @@ -31,7 +31,7 @@ * \mainpage Instrument plugin keyboard display classes * * \section introduction Introduction - * + * * \todo fill this out * \todo write isWhite inline function and replace throughout */ @@ -160,7 +160,7 @@ PianoView::~PianoView() -/*! \brief Map a keyboard key being pressed to a note in our keyboard view +/*! \brief Map a keyboard key being pressed to a note in our keyboard view * * \param _k The keyboard scan code of the key being pressed. * \todo check the scan codes for ',' = c, 'L' = c#, '.' = d, ':' = d#, @@ -255,7 +255,7 @@ int PianoView::getKeyFromKeyEvent( QKeyEvent * _ke ) case 19: return 27; // 0 = d'# case 33: return 28; // P = e' case 34: return 29; // [ - case 21: return 30; // = + case 21: return 30; // = case 35: return 31; // ] } #endif @@ -459,7 +459,7 @@ void PianoView::mousePressEvent( QMouseEvent * _me ) ( ( KEY_ORDER[key_num % KeysPerOctave] == Piano::WhiteKey ) ? PW_WHITE_KEY_HEIGHT : PW_BLACK_KEY_HEIGHT ) * - (float) MidiDefaultVelocity ); + (float) m_piano->instrumentTrack()->midiPort()->baseVelocity() ); if( y_diff < 0 ) { velocity = 0; @@ -469,7 +469,7 @@ void PianoView::mousePressEvent( QMouseEvent * _me ) Piano::WhiteKey ) ? PW_WHITE_KEY_HEIGHT : PW_BLACK_KEY_HEIGHT ) ) { - velocity = MidiDefaultVelocity; + velocity = m_piano->instrumentTrack()->midiPort()->baseVelocity() ); } // set note on m_piano->midiEventProcessor()->processInEvent( MidiEvent( MidiNoteOn, 0, key_num, velocity ) ); @@ -557,7 +557,7 @@ void PianoView::mouseMoveEvent( QMouseEvent * _me ) int velocity = (int)( (float) y_diff / ( ( KEY_ORDER[key_num % KeysPerOctave] == Piano::WhiteKey ) ? PW_WHITE_KEY_HEIGHT : PW_BLACK_KEY_HEIGHT ) * - (float) MidiDefaultVelocity ); + (float) m_piano->instrumentTrack()->midiPort()->baseVelocity() ); // maybe the user moved the mouse-cursor above or under the // piano-widget while holding left button so check that and // correct volume if necessary @@ -569,7 +569,7 @@ void PianoView::mouseMoveEvent( QMouseEvent * _me ) ( ( KEY_ORDER[key_num % KeysPerOctave] == Piano::WhiteKey ) ? PW_WHITE_KEY_HEIGHT : PW_BLACK_KEY_HEIGHT ) ) { - velocity = MidiDefaultVelocity; + velocity = m_piano->instrumentTrack()->midiPort()->baseVelocity(); } // is the calculated key different from current key? (could be the From e4340c630d208131af491dd44bcf2f811e07ad05 Mon Sep 17 00:00:00 2001 From: Vesa Date: Sat, 22 Mar 2014 13:33:42 +0200 Subject: [PATCH 057/647] Do the opl amplification smarter --- plugins/opl2/opl2instrument.cpp | 38 ++++++++++++++++----------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/plugins/opl2/opl2instrument.cpp b/plugins/opl2/opl2instrument.cpp index a1b58a7e7..4704f0147 100644 --- a/plugins/opl2/opl2instrument.cpp +++ b/plugins/opl2/opl2instrument.cpp @@ -22,7 +22,7 @@ * */ -// TODO: +// TODO: // - Better voice allocation: long releases get cut short :( // - .sbi (or similar) file loading into models // - RT safety = get rid of mutex = make emulator code thread-safe @@ -36,9 +36,9 @@ // - SBI file import? // - Envelope times in ms for UI: t[0] = 0, t[n] = ( 1<write(0x40+adlib_opadd[voice], + theEmulator->write(0x40+adlib_opadd[voice], ( (int)op1_scale_mdl.value() & 0x03 << 6) + ( vel_adjusted & 0x3f ) ); - + vel_adjusted = 63 - ( op2_lvl_mdl.value() * vel/127.0 ); // vel_adjusted = 63 - op2_lvl_mdl.value(); - theEmulator->write(0x43+adlib_opadd[voice], + theEmulator->write(0x43+adlib_opadd[voice], ( (int)op2_scale_mdl.value() & 0x03 << 6) + ( vel_adjusted & 0x3f ) ); } @@ -293,10 +293,10 @@ bool opl2instrument::handleMidiEvent( const MidiEvent& event, const MidiTime& ti // to get us in line with MIDI(?) key = event.key() +12; vel = event.velocity(); - + voice = popVoice(); if( voice != OPL2_NO_VOICE ) { - // Turn voice on, NB! the frequencies are straight by voice number, + // Turn voice on, NB! the frequencies are straight by voice number, // not by the adlib_opadd table! theEmulator->write(0xA0+voice, fnums[key] & 0xff); theEmulator->write(0xB0+voice, 32 + ((fnums[key] & 0x1f00) >> 8) ); @@ -306,7 +306,7 @@ bool opl2instrument::handleMidiEvent( const MidiEvent& event, const MidiTime& ti } break; case MidiNoteOff: - key = event.key() +12; + key = event.key() +12; for(voice=0; voice<9; ++voice) { if( voiceNote[voice] == key ) { theEmulator->write(0xA0+voice, fnums[key] & 0xff); @@ -331,12 +331,12 @@ bool opl2instrument::handleMidiEvent( const MidiEvent& event, const MidiTime& ti break; case MidiPitchBend: // Update fnumber table - // Pitchbend should be in the range 0...16383 but the new range knob gets it wrong. + // Pitchbend should be in the range 0...16383 but the new range knob gets it wrong. // tmp_pb = (2*BEND_CENTS)*((float)event.m_data.m_param[0]/16383)-BEND_CENTS; // Something like 100 cents = 8192, but offset by 8192 so the +/-100 cents range goes from 0...16383? tmp_pb = ( event.pitchBend()-8192 ) * pitchBendRange / 8192; - + if( tmp_pb != pitchbend ) { pitchbend = tmp_pb; tuneEqual(69, 440.0); @@ -349,7 +349,7 @@ bool opl2instrument::handleMidiEvent( const MidiEvent& event, const MidiTime& ti } } break; - case MidiControlChange: + case MidiControlChange: switch (event.controllerNumber()) { case MidiControllerRegisteredParameterNumberLSB: RPNfine = event.controllerValue(); @@ -385,17 +385,17 @@ PluginView * opl2instrument::instantiateView( QWidget * _parent ) } -void opl2instrument::play( sampleFrame * _working_buffer ) +void opl2instrument::play( sampleFrame * _working_buffer ) { emulatorMutex.lock(); theEmulator->update(renderbuffer, frameCount); for( fpp_t frame = 0; frame < frameCount; ++frame ) { - sample_t s = float(renderbuffer[frame])/32768.0; + sample_t s = float(renderbuffer[frame]) / 8192.0; for( ch_cnt_t ch = 0; ch < DEFAULT_CHANNELS; ++ch ) { - _working_buffer[frame][ch] = s * 4.0; + _working_buffer[frame][ch] = s; } } emulatorMutex.unlock(); @@ -406,7 +406,7 @@ void opl2instrument::play( sampleFrame * _working_buffer ) } -void opl2instrument::saveSettings( QDomDocument & _doc, QDomElement & _this ) +void opl2instrument::saveSettings( QDomDocument & _doc, QDomElement & _this ) { op1_a_mdl.saveSettings( _doc, _this, "op1_a" ); op1_d_mdl.saveSettings( _doc, _this, "op1_d" ); @@ -577,11 +577,11 @@ opl2instrumentView::opl2instrumentView( Instrument * _instrument, QWidget * _parent ) : InstrumentView( _instrument, _parent ) { - /* Unnecessary? + /* Unnecessary? m_patch = new LcdSpinBox( 3, this , "PRESET"); m_patch->setLabel( "PRESET" ); m_patch->move( 100, 1 ); - m_patch->setEnabled( true ); + m_patch->setEnabled( true ); */ #define KNOB_GEN(knobname, hinttext, hintunit,xpos,ypos) \ @@ -608,7 +608,7 @@ opl2instrumentView::opl2instrumentView( Instrument * _instrument, toolTip::add( buttname, tr( tooltip ) );\ buttname->move( xpos, ypos );\ buttgroup->addButton(buttname); - + // OP1 knobs & buttons... KNOB_GEN(op1_a_kn, "Attack", "", 6, 48); From 33b9524346066baa40578b3e4df1f9fc7a74d76a Mon Sep 17 00:00:00 2001 From: Vesa Date: Sat, 22 Mar 2014 19:09:42 +0200 Subject: [PATCH 058/647] Envelope: fix drawing of envelope graph, scale to fit view if graph gets too long (also fix typo in last pianoview commit) --- include/EnvelopeAndLfoView.h | 4 +- src/gui/PianoView.cpp | 2 +- src/gui/widgets/EnvelopeAndLfoView.cpp | 61 ++++++++++++++------------ 3 files changed, 37 insertions(+), 30 deletions(-) diff --git a/include/EnvelopeAndLfoView.h b/include/EnvelopeAndLfoView.h index dec4a5bb8..8df71b0ed 100644 --- a/include/EnvelopeAndLfoView.h +++ b/include/EnvelopeAndLfoView.h @@ -23,8 +23,8 @@ * */ -#ifndef _ENVELOPE_AND_LFO_VIEW_H -#define _ENVELOPE_AND_LFO_VIEW_H +#ifndef ENVELOPE_AND_LFO_VIEW_H +#define ENVELOPE_AND_LFO_VIEW_H #include diff --git a/src/gui/PianoView.cpp b/src/gui/PianoView.cpp index 3bd43f8e6..af4b07339 100644 --- a/src/gui/PianoView.cpp +++ b/src/gui/PianoView.cpp @@ -469,7 +469,7 @@ void PianoView::mousePressEvent( QMouseEvent * _me ) Piano::WhiteKey ) ? PW_WHITE_KEY_HEIGHT : PW_BLACK_KEY_HEIGHT ) ) { - velocity = m_piano->instrumentTrack()->midiPort()->baseVelocity() ); + velocity = m_piano->instrumentTrack()->midiPort()->baseVelocity(); } // set note on m_piano->midiEventProcessor()->processInEvent( MidiEvent( MidiNoteOn, 0, key_num, velocity ) ); diff --git a/src/gui/widgets/EnvelopeAndLfoView.cpp b/src/gui/widgets/EnvelopeAndLfoView.cpp index 712f48ac5..034e00d76 100644 --- a/src/gui/widgets/EnvelopeAndLfoView.cpp +++ b/src/gui/widgets/EnvelopeAndLfoView.cpp @@ -62,8 +62,7 @@ const int SUSTAIN_KNOB_X = DECAY_KNOB_X+KNOB_X_SPACING; const int RELEASE_KNOB_X = SUSTAIN_KNOB_X+KNOB_X_SPACING; const int AMOUNT_KNOB_X = RELEASE_KNOB_X+KNOB_X_SPACING; -const float TIME_UNIT_WIDTH = 24.0; - +const int TIME_UNIT_WIDTH = 40; const int LFO_GRAPH_X = 6; const int LFO_GRAPH_Y = ENV_KNOBS_LBL_Y+14; @@ -425,48 +424,56 @@ void EnvelopeAndLfoView::paintEvent( QPaintEvent * ) const int y_base = ENV_GRAPH_Y + s_envGraph->height() - 3; const int avail_height = s_envGraph->height() - 6; - int x1 = ENV_GRAPH_X + 2 + static_cast( m_predelayKnob->value() * - TIME_UNIT_WIDTH ); - int x2 = x1 + static_cast( m_attackKnob->value() * - TIME_UNIT_WIDTH ); + int x1 = static_cast( m_predelayKnob->value() * TIME_UNIT_WIDTH ); + int x2 = x1 + static_cast( m_attackKnob->value() * TIME_UNIT_WIDTH ); + int x3 = x2 + static_cast( m_holdKnob->value() * TIME_UNIT_WIDTH ); + int x4 = x3 + static_cast( ( m_decayKnob->value() * + ( 1 - m_sustainKnob->value() ) ) * TIME_UNIT_WIDTH ); + int x5 = x4 + static_cast( m_releaseKnob->value() * TIME_UNIT_WIDTH ); + + if( x5 > 174 ) + { + x1 = ( x1 * 174 ) / x5; + x2 = ( x2 * 174 ) / x5; + x3 = ( x3 * 174 ) / x5; + x4 = ( x4 * 174 ) / x5; + x5 = ( x5 * 174 ) / x5; + } + x1 += ENV_GRAPH_X + 2; + x2 += ENV_GRAPH_X + 2; + x3 += ENV_GRAPH_X + 2; + x4 += ENV_GRAPH_X + 2; + x5 += ENV_GRAPH_X + 2; p.drawLine( x1, y_base, x2, y_base - avail_height ); p.fillRect( x1 - 1, y_base - 2, 4, 4, end_points_bg_color ); p.fillRect( x1, y_base - 1, 2, 2, end_points_color ); - x1 = x2; - x2 = x1 + static_cast( m_holdKnob->value() * TIME_UNIT_WIDTH ); - p.drawLine( x1, y_base - avail_height, x2, y_base - avail_height ); - p.fillRect( x1 - 1, y_base - 2 - avail_height, 4, 4, + p.drawLine( x2, y_base - avail_height, x3, y_base - avail_height ); + p.fillRect( x2 - 1, y_base - 2 - avail_height, 4, 4, end_points_bg_color ); - p.fillRect( x1, y_base - 1 - avail_height, 2, 2, end_points_color ); - x1 = x2; - x2 = x1 + static_cast( ( m_decayKnob->value() * - ( 1 - m_sustainKnob->value() ) ) * - TIME_UNIT_WIDTH ); + p.fillRect( x2, y_base - 1 - avail_height, 2, 2, end_points_color ); - p.drawLine( x1, y_base-avail_height, x2, static_cast( y_base - + p.drawLine( x3, y_base-avail_height, x4, static_cast( y_base - avail_height + ( 1 - m_sustainKnob->value() ) * avail_height ) ); - p.fillRect( x1 - 1, y_base - 2 - avail_height, 4, 4, + p.fillRect( x3 - 1, y_base - 2 - avail_height, 4, 4, end_points_bg_color ); - p.fillRect( x1, y_base - 1 - avail_height, 2, 2, end_points_color ); - x1 = x2; - x2 = x1 + static_cast( m_releaseKnob->value() * TIME_UNIT_WIDTH ); - - p.drawLine( x1, static_cast( y_base - avail_height + + p.fillRect( x3, y_base - 1 - avail_height, 2, 2, end_points_color ); + + p.drawLine( x4, static_cast( y_base - avail_height + ( 1 - m_sustainKnob->value() ) * - avail_height ), x2, y_base ); - p.fillRect( x1 - 1, static_cast( y_base - avail_height + + avail_height ), x5, y_base ); + p.fillRect( x4 - 1, static_cast( y_base - avail_height + ( 1 - m_sustainKnob->value() ) * avail_height ) - 2, 4, 4, end_points_bg_color ); - p.fillRect( x1, static_cast( y_base - avail_height + + p.fillRect( x4, static_cast( y_base - avail_height + ( 1 - m_sustainKnob->value() ) * avail_height ) - 1, 2, 2, end_points_color ); - p.fillRect( x2 - 1, y_base - 2, 4, 4, end_points_bg_color ); - p.fillRect( x2, y_base - 1, 2, 2, end_points_color ); + p.fillRect( x5 - 1, y_base - 2, 4, 4, end_points_bg_color ); + p.fillRect( x5, y_base - 1, 2, 2, end_points_color ); int LFO_GRAPH_W = s_lfoGraph->width() - 6; // substract border From 752f48f51cce73115903455fbda3ff3b8315772f Mon Sep 17 00:00:00 2001 From: Tobias Doerffel Date: Sun, 23 Mar 2014 23:44:30 +0100 Subject: [PATCH 059/647] Revert "Do not display ENV/LFO tab in plugin window if controls are disabled in it (SF2 Player and OpulenZ)" This does not work well if you open an instrument window of a single streamed instrument, close it afterwards and open an instrument window of a regular instrument due to widget caching/reuse. We therefore have to find a better solution which allows dynamically showing/hiding tabs in the TabWidget class. Until then restore the previous behaviour. This reverts commit ed29f2b6f6aa8e93817dfc1c14ccf49de40b800f. --- src/tracks/InstrumentTrack.cpp | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/src/tracks/InstrumentTrack.cpp b/src/tracks/InstrumentTrack.cpp index 66dbb29fb..c6df21662 100644 --- a/src/tracks/InstrumentTrack.cpp +++ b/src/tracks/InstrumentTrack.cpp @@ -1238,15 +1238,10 @@ InstrumentTrackWindow::InstrumentTrackWindow( InstrumentTrackView * _itv ) : // FX tab m_effectView = new EffectRackView( m_track->m_audioPort.effects(), m_tabWidget ); - // Do not add ENV/LFO tab for the plugin window for SF2 Player and OpulenZ bcause it has no effecton them - int i = 1; - if (!m_track->m_instrument->flags().testFlag( Instrument::IsSingleStreamed )) - { - m_tabWidget->addTab( m_ssView, tr( "ENV/LFO" ), i++ ); - } - m_tabWidget->addTab( instrumentFunctions, tr( "FUNC" ), i++ ); - m_tabWidget->addTab( m_effectView, tr( "FX" ), i++ ); - m_tabWidget->addTab( m_midiView, tr( "MIDI" ), i++ ); + m_tabWidget->addTab( m_ssView, tr( "ENV/LFO" ), 1 ); + m_tabWidget->addTab( instrumentFunctions, tr( "FUNC" ), 2 ); + m_tabWidget->addTab( m_effectView, tr( "FX" ), 3 ); + m_tabWidget->addTab( m_midiView, tr( "MIDI" ), 4 ); // setup piano-widget m_pianoView = new PianoView( this ); @@ -1259,9 +1254,6 @@ InstrumentTrackWindow::InstrumentTrackWindow( InstrumentTrackView * _itv ) : setModel( _itv->model() ); - // Let the window know we may have a tab removed from the regular model - modelChanged(); // Get the instrument window to refresh - updateInstrumentView(); setFixedWidth( INSTRUMENT_WIDTH ); From 2f4d9c6c66b220270fdb102da48ee2b1c1e2f06d Mon Sep 17 00:00:00 2001 From: Tobias Doerffel Date: Sun, 23 Mar 2014 23:52:04 +0100 Subject: [PATCH 060/647] InstrumentSoundShapingView: display info about single-streamed instruments Until we have a solution for hiding the ENV/LFO tab, display a sensible message at least. --- include/InstrumentSoundShapingView.h | 6 +++++- src/gui/widgets/InstrumentSoundShapingView.cpp | 15 ++++++++++++++- 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/include/InstrumentSoundShapingView.h b/include/InstrumentSoundShapingView.h index 587b574c2..ff0152d5b 100644 --- a/include/InstrumentSoundShapingView.h +++ b/include/InstrumentSoundShapingView.h @@ -1,7 +1,7 @@ /* * InstrumentSoundShapingView.h - view for InstrumentSoundShaping class * - * Copyright (c) 2004-2009 Tobias Doerffel + * Copyright (c) 2004-2014 Tobias Doerffel * * This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net * @@ -30,6 +30,8 @@ #include "InstrumentSoundShaping.h" #include "ModelView.h" +class QLabel; + class EnvelopeAndLfoView; class comboBox; class groupBox; @@ -61,6 +63,8 @@ private: knob * m_filterCutKnob; knob * m_filterResKnob; + QLabel* m_singleStreamInfoLabel; + } ; #endif diff --git a/src/gui/widgets/InstrumentSoundShapingView.cpp b/src/gui/widgets/InstrumentSoundShapingView.cpp index 0ee39c29b..8bd9b2d04 100644 --- a/src/gui/widgets/InstrumentSoundShapingView.cpp +++ b/src/gui/widgets/InstrumentSoundShapingView.cpp @@ -1,7 +1,7 @@ /* * InstrumentSoundShapingView.cpp - view for InstrumentSoundShaping class * - * Copyright (c) 2004-2009 Tobias Doerffel + * Copyright (c) 2004-2014 Tobias Doerffel * * This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net * @@ -22,6 +22,8 @@ * */ +#include + #include "InstrumentSoundShapingView.h" #include "EnvelopeAndLfoParameters.h" #include "EnvelopeAndLfoView.h" @@ -115,6 +117,16 @@ InstrumentSoundShapingView::InstrumentSoundShapingView( QWidget * _parent ) : tr( "Use this knob for setting Q/Resonance for the selected " "filter. Q/Resonance tells the filter how much it " "should amplify frequencies near Cutoff-frequency." ) ); + + + m_singleStreamInfoLabel = new QLabel( tr( "Envelopes, LFOs and filters are not supported by the current instrument." ), this ); + m_singleStreamInfoLabel->setWordWrap( true ); + m_singleStreamInfoLabel->setFont( pointSize<8>( m_singleStreamInfoLabel->font() ) ); + + m_singleStreamInfoLabel->setGeometry( TARGETS_TABWIDGET_X, + TARGETS_TABWIDGET_Y, + TARGETS_TABWIDGET_WIDTH, + TARGETS_TABWIDGET_HEIGTH ); } @@ -131,6 +143,7 @@ void InstrumentSoundShapingView::setFunctionsHidden( bool hidden ) { m_targetsTabWidget->setHidden( hidden ); m_filterGroupBox->setHidden( hidden ); + m_singleStreamInfoLabel->setHidden( !hidden ); } From 794e697e229bdc5811207f305842b172b1d5dcb1 Mon Sep 17 00:00:00 2001 From: Tobias Doerffel Date: Sun, 23 Mar 2014 23:53:03 +0100 Subject: [PATCH 061/647] Made 1.0.0 release After almost exactly 10 years of development, we proudly bump the version number to 1.0.0. --- CMakeLists.txt | 6 +++--- README | 2 +- lmms.rc.in | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 95d71c851..7e933c69b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -13,9 +13,9 @@ INCLUDE(AddFileDependencies) INCLUDE(CheckIncludeFiles) INCLUDE(FindPkgConfig) -SET(VERSION_MAJOR "0") -SET(VERSION_MINOR "9") -SET(VERSION_PATCH "92") +SET(VERSION_MAJOR "1") +SET(VERSION_MINOR "0") +SET(VERSION_PATCH "0") #SET(VERSION_SUFFIX "") SET(VERSION "${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}") IF(VERSION_SUFFIX) diff --git a/README b/README index 00f4d80cb..095e55a4d 100644 --- a/README +++ b/README @@ -1,4 +1,4 @@ -LMMS 0.9.92 +LMMS 1.0.0 =========== Copyright (c) 2004-2014 by LMMS developers diff --git a/lmms.rc.in b/lmms.rc.in index 783c84096..b86fb503c 100644 --- a/lmms.rc.in +++ b/lmms.rc.in @@ -2,7 +2,7 @@ lmmsicon ICON data/lmms.ico #include VS_VERSION_INFO VERSIONINFO - FILEVERSION 0,9,92,0 + FILEVERSION 1,0,0,0 FILEFLAGSMASK VS_FFI_FILEFLAGSMASK FILEOS VOS_NT_WINDOWS32 FILETYPE VFT_APP From 11a76c45fc194bf78ca6eb3e726fba2ad4ec9911 Mon Sep 17 00:00:00 2001 From: Vesa Date: Mon, 24 Mar 2014 17:11:42 +0200 Subject: [PATCH 062/647] Compat code to make LMMS compile on Qt <4.8 --- src/core/timeline.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/core/timeline.cpp b/src/core/timeline.cpp index 3120dacc1..42d976884 100644 --- a/src/core/timeline.cpp +++ b/src/core/timeline.cpp @@ -40,6 +40,10 @@ #include "text_float.h" +#if QT_VERSION < 0x040800 +#define MiddleButton MidButton +#endif + QPixmap * timeLine::s_timeLinePixmap = NULL; QPixmap * timeLine::s_posMarkerPixmap = NULL; @@ -283,14 +287,14 @@ void timeLine::mousePressEvent( QMouseEvent* event ) m_moveXOff = s_posMarkerPixmap->width() / 2; } } - else if( event->button() == Qt::RightButton || event->button() == Qt::MiddleButton ) + else if( event->button() == Qt::RightButton || event->button() == Qt:: MiddleButton ) { const MidiTime t = m_begin + static_cast( event->x() * MidiTime::ticksPerTact() / m_ppt ); if( m_loopPos[0] > m_loopPos[1] ) { qSwap( m_loopPos[0], m_loopPos[1] ); } - if( ( event->modifiers() & Qt::ShiftModifier ) || event->button() == Qt::MiddleButton ) + if( ( event->modifiers() & Qt::ShiftModifier ) || event->button() == Qt:: MiddleButton ) { m_action = MoveLoopBegin; } From d80a8436c0fde933c6f90cf8af4b8435dc4bcdeb Mon Sep 17 00:00:00 2001 From: Vesa Date: Mon, 24 Mar 2014 19:49:33 +0200 Subject: [PATCH 063/647] Remove spaces --- src/core/timeline.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/core/timeline.cpp b/src/core/timeline.cpp index 42d976884..6a417f57e 100644 --- a/src/core/timeline.cpp +++ b/src/core/timeline.cpp @@ -287,14 +287,14 @@ void timeLine::mousePressEvent( QMouseEvent* event ) m_moveXOff = s_posMarkerPixmap->width() / 2; } } - else if( event->button() == Qt::RightButton || event->button() == Qt:: MiddleButton ) + else if( event->button() == Qt::RightButton || event->button() == Qt::MiddleButton ) { const MidiTime t = m_begin + static_cast( event->x() * MidiTime::ticksPerTact() / m_ppt ); if( m_loopPos[0] > m_loopPos[1] ) { qSwap( m_loopPos[0], m_loopPos[1] ); } - if( ( event->modifiers() & Qt::ShiftModifier ) || event->button() == Qt:: MiddleButton ) + if( ( event->modifiers() & Qt::ShiftModifier ) || event->button() == Qt::MiddleButton ) { m_action = MoveLoopBegin; } From 2ab5b1da0ceb05ed9001ff06b1da9453b28c17db Mon Sep 17 00:00:00 2001 From: Tobias Doerffel Date: Mon, 24 Mar 2014 19:18:14 +0100 Subject: [PATCH 064/647] AutomatableModel: always fit value from linked model When using value from linked model, make sure to fit it into own range as otherwise this can cause out-of-boundary accesses e.g. in ComboBoxModel. Closes #505. --- src/core/AutomatableModel.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/core/AutomatableModel.cpp b/src/core/AutomatableModel.cpp index 671fb5aa7..7a7bc74c4 100644 --- a/src/core/AutomatableModel.cpp +++ b/src/core/AutomatableModel.cpp @@ -445,10 +445,10 @@ float AutomatableModel::controllerValue( int frameOffset ) const AutomatableModel* lm = m_linkedModels.first(); if( lm->controllerConnection() ) { - return lm->controllerValue( frameOffset ); + return fittedValue( lm->controllerValue( frameOffset ) ); } - return lm->m_value; + return fittedValue( lm->m_value ); } From d32377845bf718c03c9305f705788d774eec1073 Mon Sep 17 00:00:00 2001 From: Tobias Doerffel Date: Mon, 24 Mar 2014 19:19:18 +0100 Subject: [PATCH 065/647] ComboBoxModel: coding style fixes --- include/ComboBoxModel.h | 30 +++++++++++++++--------------- src/core/ComboBoxModel.cpp | 19 ++++++++++--------- 2 files changed, 25 insertions(+), 24 deletions(-) diff --git a/include/ComboBoxModel.h b/include/ComboBoxModel.h index 436fd50cf..b11af8832 100644 --- a/include/ComboBoxModel.h +++ b/include/ComboBoxModel.h @@ -1,7 +1,7 @@ /* * ComboBoxModel.h - declaration of class ComboBoxModel * - * Copyright (c) 2008-2011 Tobias Doerffel + * Copyright (c) 2008-2014 Tobias Doerffel * * This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net * @@ -38,11 +38,10 @@ class EXPORT ComboBoxModel : public IntModel { Q_OBJECT public: - ComboBoxModel( Model * _parent = NULL, - const QString & _display_name = QString(), - bool _default_constructed = false ) : - IntModel( 0, 0, 0, _parent, _display_name, - _default_constructed ) + ComboBoxModel( Model* parent = NULL, + const QString& displayName = QString(), + bool isDefaultConstructed = false ) : + IntModel( 0, 0, 0, parent, displayName, isDefaultConstructed ) { } @@ -51,37 +50,38 @@ public: clear(); } - void addItem( const QString & _item, PixmapLoader * _loader = NULL ); + void addItem( const QString& item, PixmapLoader* loader = NULL ); void clear(); - int findText( const QString & _txt ) const; + int findText( const QString& txt ) const; - inline QString currentText() const + QString currentText() const { return ( size() > 0 && value() < size() ) ? m_items[value()].first : QString(); } - inline const PixmapLoader * currentData() const + const PixmapLoader* currentData() const { return m_items[value()].second; } - inline const QString & itemText( int _i ) const + const QString & itemText( int i ) const { - return m_items[tLimit( _i, minValue(), maxValue() )].first; + return m_items[qBound( minValue(), i, maxValue() )].first; } - inline const PixmapLoader * itemPixmap( int _i ) const + const PixmapLoader* itemPixmap( int i ) const { - return m_items[tLimit( _i, minValue(), maxValue() )].second; + return m_items[qBound( minValue(), i, maxValue() )].second; } - inline int size() const + int size() const { return m_items.size(); } + private: typedef QPair Item; diff --git a/src/core/ComboBoxModel.cpp b/src/core/ComboBoxModel.cpp index 1b8efb3fc..8206f3c37 100644 --- a/src/core/ComboBoxModel.cpp +++ b/src/core/ComboBoxModel.cpp @@ -1,7 +1,7 @@ /* * ComboBoxModel.cpp - implementation of ComboBoxModel * - * Copyright (c) 2008-2009 Tobias Doerffel + * Copyright (c) 2008-2014 Tobias Doerffel * * This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net * @@ -27,9 +27,9 @@ -void ComboBoxModel::addItem( const QString & _item, PixmapLoader * _pl ) +void ComboBoxModel::addItem( const QString& item, PixmapLoader* loader ) { - m_items.push_back( qMakePair( _item, _pl ) ); + m_items.push_back( qMakePair( item, loader ) ); setRange( 0, m_items.size() - 1 ); } @@ -39,23 +39,24 @@ void ComboBoxModel::addItem( const QString & _item, PixmapLoader * _pl ) void ComboBoxModel::clear() { setRange( 0, 0 ); - foreach( const Item & _i, m_items ) + foreach( const Item& i, m_items ) { - delete _i.second; + delete i.second; } + m_items.clear(); + emit propertiesChanged(); } -int ComboBoxModel::findText( const QString & _txt ) const +int ComboBoxModel::findText( const QString& txt ) const { - for( QVector::ConstIterator it = m_items.begin(); - it != m_items.end(); ++it ) + for( QVector::ConstIterator it = m_items.begin(); it != m_items.end(); ++it ) { - if( ( *it ).first == _txt ) + if( ( *it ).first == txt ) { return it - m_items.begin(); } From 0fa2908f7f76bbf5ac71bfc93ded0e2155c20eb6 Mon Sep 17 00:00:00 2001 From: Vesa Date: Thu, 20 Mar 2014 11:46:47 +0200 Subject: [PATCH 066/647] Start wavetable synth --- plugins/CMakeLists.txt | 1 + plugins/wtsynth/CMakeLists.txt | 3 +++ plugins/wtsynth/WTSynth.h | 38 ++++++++++++++++++++++++++++++++++ 3 files changed, 42 insertions(+) create mode 100644 plugins/wtsynth/CMakeLists.txt create mode 100644 plugins/wtsynth/WTSynth.h diff --git a/plugins/CMakeLists.txt b/plugins/CMakeLists.txt index 59aadfbe3..aba116025 100644 --- a/plugins/CMakeLists.txt +++ b/plugins/CMakeLists.txt @@ -29,5 +29,6 @@ ADD_SUBDIRECTORY(vestige) ADD_SUBDIRECTORY(vst_base) ADD_SUBDIRECTORY(VstEffect) ADD_SUBDIRECTORY(waveshaper) +ADD_SUBDIRECTORY(wtsynth) ADD_SUBDIRECTORY(vibed) ADD_SUBDIRECTORY(zynaddsubfx) diff --git a/plugins/wtsynth/CMakeLists.txt b/plugins/wtsynth/CMakeLists.txt new file mode 100644 index 000000000..82e03fcd9 --- /dev/null +++ b/plugins/wtsynth/CMakeLists.txt @@ -0,0 +1,3 @@ +INCLUDE(BuildPlugin) + +BUILD_PLUGIN(wtsynth WTSynth.cpp WTSynth.h MOCFILES WTSynth.h EMBEDDED_RESOURCES ${CMAKE_CURRENT_SOURCE_DIR}/*.png) diff --git a/plugins/wtsynth/WTSynth.h b/plugins/wtsynth/WTSynth.h new file mode 100644 index 000000000..286c23cb7 --- /dev/null +++ b/plugins/wtsynth/WTSynth.h @@ -0,0 +1,38 @@ +/* + * WTSynth.h - work in process, name pending + * + * Copyright (c) 2014 Vesa Kivimäki + * + * This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net + * + * 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 WTSYNTH_H +#define WTSYNTH_H + +#include "Instrument.h" +#include "InstrumentView.h" +#include "graph.h" +#include "knob.h" +#include "pixmap_button.h" + + + + +#endif From 23b3179e1f55703e2ea5647ca98ca9a640f31d82 Mon Sep 17 00:00:00 2001 From: Vesa Date: Fri, 21 Mar 2014 10:53:11 +0200 Subject: [PATCH 067/647] WTSynth files --- data/themes/default/style.css | 25 + plugins/wtsynth/WTSynth.cpp | 1096 +++++++++++++++++++++++++++ plugins/wtsynth/WTSynth.h | 220 ++++++ plugins/wtsynth/a1_active.png | Bin 0 -> 169 bytes plugins/wtsynth/a1_inactive.png | Bin 0 -> 169 bytes plugins/wtsynth/a2_active.png | Bin 0 -> 169 bytes plugins/wtsynth/a2_inactive.png | Bin 0 -> 169 bytes plugins/wtsynth/am_active.png | Bin 0 -> 169 bytes plugins/wtsynth/am_inactive.png | Bin 0 -> 169 bytes plugins/wtsynth/artwork.png | Bin 0 -> 625 bytes plugins/wtsynth/b1_active.png | Bin 0 -> 169 bytes plugins/wtsynth/b1_inactive.png | Bin 0 -> 169 bytes plugins/wtsynth/b2_active.png | Bin 0 -> 169 bytes plugins/wtsynth/b2_inactive.png | Bin 0 -> 169 bytes plugins/wtsynth/inv_active.png | Bin 0 -> 305 bytes plugins/wtsynth/inv_inactive.png | Bin 0 -> 308 bytes plugins/wtsynth/logo.png | Bin 0 -> 174 bytes plugins/wtsynth/mix_active.png | Bin 0 -> 169 bytes plugins/wtsynth/mix_inactive.png | Bin 0 -> 169 bytes plugins/wtsynth/norm_active.png | Bin 0 -> 305 bytes plugins/wtsynth/norm_inactive.png | Bin 0 -> 308 bytes plugins/wtsynth/phl_active.png | Bin 0 -> 305 bytes plugins/wtsynth/phl_inactive.png | Bin 0 -> 308 bytes plugins/wtsynth/phr_active.png | Bin 0 -> 305 bytes plugins/wtsynth/phr_inactive.png | Bin 0 -> 308 bytes plugins/wtsynth/pm_active.png | Bin 0 -> 169 bytes plugins/wtsynth/pm_inactive.png | Bin 0 -> 169 bytes plugins/wtsynth/rm_active.png | Bin 0 -> 169 bytes plugins/wtsynth/rm_inactive.png | Bin 0 -> 169 bytes plugins/wtsynth/saw_active.png | Bin 0 -> 305 bytes plugins/wtsynth/saw_inactive.png | Bin 0 -> 308 bytes plugins/wtsynth/sin_active.png | Bin 0 -> 305 bytes plugins/wtsynth/sin_inactive.png | Bin 0 -> 308 bytes plugins/wtsynth/smooth_active.png | Bin 0 -> 305 bytes plugins/wtsynth/smooth_inactive.png | Bin 0 -> 308 bytes plugins/wtsynth/sqr_active.png | Bin 0 -> 305 bytes plugins/wtsynth/sqr_inactive.png | Bin 0 -> 308 bytes plugins/wtsynth/tri_active.png | Bin 0 -> 305 bytes plugins/wtsynth/tri_inactive.png | Bin 0 -> 308 bytes plugins/wtsynth/wavegraph.png | Bin 0 -> 351 bytes 40 files changed, 1341 insertions(+) create mode 100644 plugins/wtsynth/WTSynth.cpp create mode 100644 plugins/wtsynth/a1_active.png create mode 100644 plugins/wtsynth/a1_inactive.png create mode 100644 plugins/wtsynth/a2_active.png create mode 100644 plugins/wtsynth/a2_inactive.png create mode 100644 plugins/wtsynth/am_active.png create mode 100644 plugins/wtsynth/am_inactive.png create mode 100644 plugins/wtsynth/artwork.png create mode 100644 plugins/wtsynth/b1_active.png create mode 100644 plugins/wtsynth/b1_inactive.png create mode 100644 plugins/wtsynth/b2_active.png create mode 100644 plugins/wtsynth/b2_inactive.png create mode 100644 plugins/wtsynth/inv_active.png create mode 100644 plugins/wtsynth/inv_inactive.png create mode 100644 plugins/wtsynth/logo.png create mode 100644 plugins/wtsynth/mix_active.png create mode 100644 plugins/wtsynth/mix_inactive.png create mode 100644 plugins/wtsynth/norm_active.png create mode 100644 plugins/wtsynth/norm_inactive.png create mode 100644 plugins/wtsynth/phl_active.png create mode 100644 plugins/wtsynth/phl_inactive.png create mode 100644 plugins/wtsynth/phr_active.png create mode 100644 plugins/wtsynth/phr_inactive.png create mode 100644 plugins/wtsynth/pm_active.png create mode 100644 plugins/wtsynth/pm_inactive.png create mode 100644 plugins/wtsynth/rm_active.png create mode 100644 plugins/wtsynth/rm_inactive.png create mode 100644 plugins/wtsynth/saw_active.png create mode 100644 plugins/wtsynth/saw_inactive.png create mode 100644 plugins/wtsynth/sin_active.png create mode 100644 plugins/wtsynth/sin_inactive.png create mode 100644 plugins/wtsynth/smooth_active.png create mode 100644 plugins/wtsynth/smooth_inactive.png create mode 100644 plugins/wtsynth/sqr_active.png create mode 100644 plugins/wtsynth/sqr_inactive.png create mode 100644 plugins/wtsynth/tri_active.png create mode 100644 plugins/wtsynth/tri_inactive.png create mode 100644 plugins/wtsynth/wavegraph.png diff --git a/data/themes/default/style.css b/data/themes/default/style.css index 63f007fe1..98437e2e7 100644 --- a/data/themes/default/style.css +++ b/data/themes/default/style.css @@ -608,6 +608,31 @@ sidInstrumentView knob { qproperty-lineWidth: 2; } +WTSynthView knob#aKnob { + color: rgb( 255, 255, 255 ); + qproperty-outerColor: rgb( 255, 255, 255 ); + qproperty-innerRadius: 1; + qproperty-outerRadius: 9; + qproperty-lineWidth: 2; +} + +WTSynthView knob#bKnob { + color: rgb( 255, 255, 255 ); + qproperty-outerColor: rgb( 255, 255, 255 ); + qproperty-innerRadius: 1; + qproperty-outerRadius: 9; + qproperty-lineWidth: 2; +} + +WTSynthView knob#mixKnob { + color: rgb( 255, 255, 255 ); + qproperty-outerColor: rgb( 255, 255, 255 ); + qproperty-innerRadius: 1; + qproperty-outerRadius: 15; + qproperty-lineWidth: 2; +} + + /* palette information - each colour definition must be on a single line, and the line must begin with "palette:", with no leading whitespace * colour codes MUST be of the form #RRGGBB */ diff --git a/plugins/wtsynth/WTSynth.cpp b/plugins/wtsynth/WTSynth.cpp new file mode 100644 index 000000000..85a9f8d6e --- /dev/null +++ b/plugins/wtsynth/WTSynth.cpp @@ -0,0 +1,1096 @@ +/* + * WTSynth.cpp - work in process, name pending + * + * Copyright (c) 2014 Vesa Kivimäki + * + * This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net + * + * 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 "WTSynth.h" +#include "engine.h" +#include "InstrumentTrack.h" +#include "templates.h" +#include "tooltip.h" +#include "song.h" +#include "lmms_math.h" + +#include "embed.h" + + +extern "C" +{ + +Plugin::Descriptor PLUGIN_EXPORT wtsynth_plugin_descriptor = +{ + STRINGIFY( PLUGIN_NAME ), + "wtsynth", + QT_TRANSLATE_NOOP( "pluginBrowser", + "4-oscillator modulatable wavetable synth" ), + "Vesa Kivimäki ", + 0x0100, + Plugin::Instrument, + new PluginPixmapLoader( "logo" ), + NULL, + NULL +} ; + +} + + +WTSynthObject::WTSynthObject( float * _A1wave, float * _A2wave, + float * _B1wave, float * _B2wave, + int _amod, int _bmod, const sample_rate_t _samplerate, NotePlayHandle * _nph ) : + m_A1wave( _A1wave ), + m_A2wave( _A2wave ), + m_B1wave( _B1wave ), + m_B2wave( _B2wave ), + m_amod( _amod ), + m_bmod( _bmod ), + m_samplerate( _samplerate ), + m_nph( _nph ) +{ + m_lphase[A1_OSC] = 0.0f; + m_lphase[A2_OSC] = 0.0f; + m_lphase[B1_OSC] = 0.0f; + m_lphase[B2_OSC] = 0.0f; + m_rphase[A1_OSC] = 0.0f; + m_rphase[A2_OSC] = 0.0f; + m_rphase[B1_OSC] = 0.0f; + m_rphase[B2_OSC] = 0.0f; + updateFrequencies(); +} + + + +WTSynthObject::~WTSynthObject() +{ +} + + +void WTSynthObject::renderOutput( sampleFrame * _abuf, sampleFrame * _bbuf, fpp_t _frames ) +{ + for( fpp_t frame = 0; frame < _frames; frame++ ) + { + float frac; + + // A2 + frac = fraction( m_lphase[A2_OSC] ); + sample_t A2_L = ( m_A2wave[ int( m_lphase[A2_OSC] ) % WAVELEN ] * ( 1 - frac ) ) + + ( m_A2wave[ int( m_lphase[A2_OSC] + 1 ) % WAVELEN ] * frac ); + A2_L *= m_lvol[A2_OSC]; + frac = fraction( m_rphase[A2_OSC] ); + sample_t A2_R = ( m_A2wave[ int( m_rphase[A2_OSC] ) % WAVELEN ] * ( 1 - frac ) ) + + ( m_A2wave[ int( m_rphase[A2_OSC] + 1 ) % WAVELEN ] * frac ); + A2_R *= m_rvol[A2_OSC]; + + // B2 + frac = fraction( m_lphase[B2_OSC] ); + sample_t B2_L = ( m_A2wave[ int( m_lphase[B2_OSC] ) % WAVELEN ] * ( 1 - frac ) ) + + ( m_B2wave[ int( m_lphase[B2_OSC] + 1 ) % WAVELEN ] * frac ); + B2_L *= m_lvol[B2_OSC]; + frac = fraction( m_rphase[B2_OSC] ); + sample_t B2_R = ( m_A2wave[ int( m_rphase[B2_OSC] ) % WAVELEN ] * ( 1 - frac ) ) + + ( m_A2wave[ int( m_rphase[B2_OSC] + 1 ) % WAVELEN ] * frac ); + B2_R *= m_rvol[B2_OSC]; + + // put phases of 1-series oscs into variables because phase modulation might happen + float A1_lphase = m_lphase[A1_OSC]; + float A1_rphase = m_rphase[A1_OSC]; + float B1_lphase = m_lphase[B1_OSC]; + float B1_rphase = m_rphase[B1_OSC]; + + // if phase mod, add to phases + if( m_amod == MOD_PM ) + { + A1_lphase = fmodf( A1_lphase + A2_L * WAVELEN, WAVELEN ); + A1_rphase = fmodf( A1_rphase + A2_R * WAVELEN, WAVELEN ); + } + if( m_bmod == MOD_PM ) + { + B1_lphase = fmodf( B1_lphase + B2_L * WAVELEN, WAVELEN ); + B1_rphase = fmodf( B1_rphase + B2_R * WAVELEN, WAVELEN ); + } + + // A1 + frac = fraction( A1_lphase ); + sample_t A1_L = ( m_A1wave[ int( A1_lphase ) % WAVELEN ] * ( 1 - frac ) ) + + ( m_A1wave[ int( A1_lphase + 1 ) % WAVELEN ] * frac ); + frac = fraction( A1_rphase ); + sample_t A1_R = ( m_A1wave[ int( A1_rphase ) % WAVELEN ] * ( 1 - frac ) ) + + ( m_A1wave[ int( A1_rphase + 1 ) % WAVELEN ] * frac ); + + // B1 + frac = fraction( B1_lphase ); + sample_t B1_L = ( m_B1wave[ int( B1_lphase ) % WAVELEN ] * ( 1 - frac ) ) + + ( m_B1wave[ int( B1_lphase + 1 ) % WAVELEN ] * frac ); + frac = fraction( B1_rphase ); + sample_t B1_R = ( m_B1wave[ int( B1_rphase ) % WAVELEN ] * ( 1 - frac ) ) + + ( m_B1wave[ int( B1_rphase + 1 ) % WAVELEN ] * frac ); + + // A-series modulation (other than phase mod) + switch( m_amod ) + { + case MOD_MIX: + A1_L += A2_L; + A1_R += A2_R; + break; + case MOD_AM: + A1_L *= qMax( 0.0f, A2_L + 1.0f ); + A1_R *= qMax( 0.0f, A2_R + 1.0f ); + break; + case MOD_RM: + A1_L *= A2_L; + A1_R *= A2_R; + break; + } + _abuf[frame][0] = A1_L * m_lvol[A1_OSC]; + _abuf[frame][1] = A1_R * m_rvol[B1_OSC]; + + // B-series modulation (other than phase mod) + switch( m_bmod ) + { + case MOD_MIX: + B1_L += B2_L; + B1_R += B2_R; + break; + case MOD_AM: + B1_L *= qAbs( B2_L + 1.0f ); + B1_R *= qAbs( B2_R + 1.0f ); + break; + case MOD_RM: + B1_L *= B2_L; + B1_R *= B2_R; + break; + } + _bbuf[frame][0] = B1_L; + _bbuf[frame][1] = B1_R; + + // update phases + for( int i = 0; i < NUM_OSCS; i++ ) + { + m_lphase[i] += ( static_cast( WAVELEN ) / ( m_samplerate / ( m_nph->frequency() * m_lfreq[i] ) ) ); + m_lphase[i] = fmodf( m_lphase[i], WAVELEN ); + m_rphase[i] += ( static_cast( WAVELEN ) / ( m_samplerate / ( m_nph->frequency() * m_rfreq[i] ) ) ); + m_rphase[i] = fmodf( m_rphase[i], WAVELEN ); + } + } + +} + + +void WTSynthObject::updateFrequencies() +{ + // calculate frequencies + for( int i = 0; i < NUM_OSCS; i++ ) + { + m_lfreq[i] = ( m_mult[i] / 8 ) * powf( 2, m_ltune[i] / 1200 ); + m_rfreq[i] = ( m_mult[i] / 8 ) * powf( 2, m_rtune[i] / 1200 ); + } +} + + + +void WTSynthObject::changeVolume( int _osc, float _lvol, float _rvol ) +{ + m_lvol[_osc] = _lvol; + m_rvol[_osc] = _rvol; +} + + +void WTSynthObject::changeMult( int _osc, int _mul ) +{ + m_mult[_osc] = _mul; + updateFrequencies(); +} + + +void WTSynthObject::changeTune( int _osc, float _ltune, float _rtune ) +{ + m_ltune[_osc] = _ltune; + m_rtune[_osc] = _rtune; + updateFrequencies(); +} + + + +WTSynthInstrument::WTSynthInstrument( InstrumentTrack * _instrument_track ) : + Instrument( _instrument_track, &wtsynth_plugin_descriptor ), + + a1_vol( 100.0f, 0.0f, 200.0f, 0.1f, this, tr( "Volume A1" ) ), + a2_vol( 100.0f, 0.0f, 200.0f, 0.1f, this, tr( "Volume A2" ) ), + b1_vol( 100.0f, 0.0f, 200.0f, 0.1f, this, tr( "Volume B1" ) ), + b2_vol( 100.0f, 0.0f, 200.0f, 0.1f, this, tr( "Volume B2" ) ), + + a1_pan( 0.0f, -100.0f, 100.0f, 0.1f, this, tr( "Panning A1" ) ), + a2_pan( 0.0f, -100.0f, 100.0f, 0.1f, this, tr( "Panning A2" ) ), + b1_pan( 0.0f, -100.0f, 100.0f, 0.1f, this, tr( "Panning B1" ) ), + b2_pan( 0.0f, -100.0f, 100.0f, 0.1f, this, tr( "Panning B2" ) ), + + a1_mult( 8, 1, 16, this, tr( "Freq. multiplier A1" ) ), + a2_mult( 8, 1, 16, this, tr( "Freq. multiplier A2" ) ), + b1_mult( 8, 1, 16, this, tr( "Freq. multiplier B1" ) ), + b2_mult( 8, 1, 16, this, tr( "Freq. multiplier B2" ) ), + + a1_ltune( 0.0f, -600.0f, 600.0f, 1.0f, this, tr( "Left detune A1" ) ), + a2_ltune( 0.0f, -600.0f, 600.0f, 1.0f, this, tr( "Left detune A2" ) ), + b1_ltune( 0.0f, -600.0f, 600.0f, 1.0f, this, tr( "Left detune B1" ) ), + b2_ltune( 0.0f, -600.0f, 600.0f, 1.0f, this, tr( "Left detune B2" ) ), + + a1_rtune( 0.0f, -600.0f, 600.0f, 1.0f, this, tr( "Right detune A1" ) ), + a2_rtune( 0.0f, -600.0f, 600.0f, 1.0f, this, tr( "Right detune A2" ) ), + b1_rtune( 0.0f, -600.0f, 600.0f, 1.0f, this, tr( "Right detune B1" ) ), + b2_rtune( 0.0f, -600.0f, 600.0f, 1.0f, this, tr( "Right detune B2" ) ), + + a1_graph( -1.0f, 1.0f, WAVELEN, this ), + a2_graph( -1.0f, 1.0f, WAVELEN, this ), + b1_graph( -1.0f, 1.0f, WAVELEN, this ), + b2_graph( -1.0f, 1.0f, WAVELEN, this ), + + m_abmix( 0.0f, -100.0f, 100.0f, 0.1f, this, tr( "A-B Mix" ) ), + m_amod( 0, 0, 3, this, tr( "A2-A1 modulation" ) ), + m_bmod( 0, 0, 3, this, tr( "B2-B1 modulation" ) ), + + m_selectedGraph( 0, 0, 3, this, tr( "Selected graph" ) ) +{ + connect( &a1_vol, SIGNAL( dataChanged() ), this, SLOT( updateVolumes( A1_OSC ) ) ); + connect( &a2_vol, SIGNAL( dataChanged() ), this, SLOT( updateVolumes( A2_OSC ) ) ); + connect( &b1_vol, SIGNAL( dataChanged() ), this, SLOT( updateVolumes( B1_OSC ) ) ); + connect( &b2_vol, SIGNAL( dataChanged() ), this, SLOT( updateVolumes( B2_OSC ) ) ); + + connect( &a1_pan, SIGNAL( dataChanged() ), this, SLOT( updateVolumes( A1_OSC ) ) ); + connect( &a2_pan, SIGNAL( dataChanged() ), this, SLOT( updateVolumes( A2_OSC ) ) ); + connect( &b1_pan, SIGNAL( dataChanged() ), this, SLOT( updateVolumes( B1_OSC ) ) ); + connect( &b2_pan, SIGNAL( dataChanged() ), this, SLOT( updateVolumes( B2_OSC ) ) ); + + connect( &a1_mult, SIGNAL( dataChanged() ), this, SLOT( updateMult( A1_OSC ) ) ); + connect( &a2_mult, SIGNAL( dataChanged() ), this, SLOT( updateMult( A2_OSC ) ) ); + connect( &b1_mult, SIGNAL( dataChanged() ), this, SLOT( updateMult( B1_OSC ) ) ); + connect( &b2_mult, SIGNAL( dataChanged() ), this, SLOT( updateMult( B2_OSC ) ) ); + + connect( &a1_ltune, SIGNAL( dataChanged() ), this, SLOT( updateTunes( A1_OSC ) ) ); + connect( &a2_ltune, SIGNAL( dataChanged() ), this, SLOT( updateTunes( A2_OSC ) ) ); + connect( &b1_ltune, SIGNAL( dataChanged() ), this, SLOT( updateTunes( B1_OSC ) ) ); + connect( &b2_ltune, SIGNAL( dataChanged() ), this, SLOT( updateTunes( B2_OSC ) ) ); + + connect( &a1_rtune, SIGNAL( dataChanged() ), this, SLOT( updateTunes( A1_OSC ) ) ); + connect( &a2_rtune, SIGNAL( dataChanged() ), this, SLOT( updateTunes( A2_OSC ) ) ); + connect( &b1_rtune, SIGNAL( dataChanged() ), this, SLOT( updateTunes( B1_OSC ) ) ); + connect( &b2_rtune, SIGNAL( dataChanged() ), this, SLOT( updateTunes( B2_OSC ) ) ); + + a1_graph.setWaveToSine(); + a2_graph.setWaveToSine(); + b1_graph.setWaveToSine(); + b2_graph.setWaveToSine(); +} + + +WTSynthInstrument::~WTSynthInstrument() +{ +} + + +void WTSynthInstrument::playNote( NotePlayHandle * _n, + sampleFrame * _working_buffer ) +{ + if ( _n->totalFramesPlayed() == 0 || _n->m_pluginData == NULL ) + { + WTSynthObject * w = new WTSynthObject( const_cast( a1_graph.samples() ), + const_cast( a2_graph.samples() ), + const_cast( b1_graph.samples() ), + const_cast( b2_graph.samples() ), + m_amod.value(), m_bmod.value(), + engine::mixer()->processingSampleRate(), _n ); + + w -> changeMult( A1_OSC, a1_mult.value() ); + w -> changeMult( A2_OSC, a2_mult.value() ); + w -> changeMult( B1_OSC, b1_mult.value() ); + w -> changeMult( B2_OSC, b2_mult.value() ); + + w -> changeTune( A1_OSC, a1_ltune.value(), a1_rtune.value() ); + w -> changeTune( A2_OSC, a2_ltune.value(), a2_rtune.value() ); + w -> changeTune( B1_OSC, b1_ltune.value(), b1_rtune.value() ); + w -> changeTune( B2_OSC, b2_ltune.value(), b2_rtune.value() ); + + w -> changeVolume( A1_OSC, leftCh( a1_vol.value(), a1_pan.value() ), rightCh( a1_vol.value(), a1_pan.value() ) ); + w -> changeVolume( A2_OSC, leftCh( a2_vol.value(), a2_pan.value() ), rightCh( a2_vol.value(), a2_pan.value() ) ); + w -> changeVolume( B1_OSC, leftCh( b1_vol.value(), b1_pan.value() ), rightCh( b1_vol.value(), b1_pan.value() ) ); + w -> changeVolume( B2_OSC, leftCh( b2_vol.value(), b2_pan.value() ), rightCh( b2_vol.value(), b2_pan.value() ) ); + + _n->m_pluginData = w; + } + + const fpp_t frames = _n->framesLeftForCurrentPeriod(); + + WTSynthObject * w = static_cast( _n->m_pluginData ); + + // update oscs if needed + + if( m_volChanged[A1_OSC] ) w-> changeVolume( A1_OSC, leftCh( a1_vol.value(), a1_pan.value() ), rightCh( a1_vol.value(), a1_pan.value() ) ); + if( m_volChanged[A2_OSC] ) w-> changeVolume( A2_OSC, leftCh( a2_vol.value(), a2_pan.value() ), rightCh( a2_vol.value(), a2_pan.value() ) ); + if( m_volChanged[B1_OSC] ) w-> changeVolume( B1_OSC, leftCh( b1_vol.value(), b1_pan.value() ), rightCh( b1_vol.value(), b1_pan.value() ) ); + if( m_volChanged[B2_OSC] ) w-> changeVolume( B2_OSC, leftCh( b2_vol.value(), b2_pan.value() ), rightCh( b2_vol.value(), b2_pan.value() ) ); + + if( m_tuneChanged[A1_OSC] ) w-> changeTune( A1_OSC, a1_ltune.value(), a1_rtune.value() ); + if( m_tuneChanged[A2_OSC] ) w-> changeTune( A2_OSC, a2_ltune.value(), a2_rtune.value() ); + if( m_tuneChanged[B1_OSC] ) w-> changeTune( B1_OSC, b1_ltune.value(), b1_rtune.value() ); + if( m_tuneChanged[B2_OSC] ) w-> changeTune( B2_OSC, b2_ltune.value(), b2_rtune.value() ); + + if( m_multChanged[A1_OSC] ) w-> changeMult( A1_OSC, a1_mult.value() ); + if( m_multChanged[A2_OSC] ) w-> changeMult( A2_OSC, a2_mult.value() ); + if( m_multChanged[B1_OSC] ) w-> changeMult( B1_OSC, b1_mult.value() ); + if( m_multChanged[B2_OSC] ) w-> changeMult( B2_OSC, b2_mult.value() ); + + sampleFrame * abuf = new sampleFrame[frames]; + + sampleFrame * bbuf = new sampleFrame[frames]; + + w-> renderOutput( abuf, bbuf, frames ); + for( fpp_t f=0; f < frames; f++ ) + { + const float amix = ( ( m_abmix.value( f ) - 100.0 ) / -200.0 ); + const float bmix = 1.0 - amix; + _working_buffer[f][0] = ( abuf[f][0] * amix ) + + ( bbuf[f][0] * bmix ); + _working_buffer[f][1] = ( abuf[f][1] * amix ) + + ( bbuf[f][1] * bmix ); + } + + delete[] abuf; + delete[] bbuf; + + applyRelease( _working_buffer, _n ); + + instrumentTrack()->processAudioBuffer( _working_buffer, frames, _n ); +} + + +void WTSynthInstrument::deleteNotePluginData( NotePlayHandle * _n ) +{ + delete static_cast( _n->m_pluginData ); +} + + +void WTSynthInstrument::saveSettings( QDomDocument & _doc, + QDomElement & _this ) +{ + a1_vol.saveSettings( _doc, _this, "a1_vol" ); + a2_vol.saveSettings( _doc, _this, "a2_vol" ); + b1_vol.saveSettings( _doc, _this, "b1_vol" ); + b2_vol.saveSettings( _doc, _this, "b2_vol" ); + + a1_pan.saveSettings( _doc, _this, "a1_pan" ); + a2_pan.saveSettings( _doc, _this, "a2_pan" ); + b1_pan.saveSettings( _doc, _this, "b1_pan" ); + b2_pan.saveSettings( _doc, _this, "b2_pan" ); + + a1_mult.saveSettings( _doc, _this, "a1_mult" ); + a2_mult.saveSettings( _doc, _this, "a2_mult" ); + b1_mult.saveSettings( _doc, _this, "b1_mult" ); + b2_mult.saveSettings( _doc, _this, "b2_mult" ); + + a1_ltune.saveSettings( _doc, _this, "a1_ltune" ); + a2_ltune.saveSettings( _doc, _this, "a2_ltune" ); + b1_ltune.saveSettings( _doc, _this, "b1_ltune" ); + b2_ltune.saveSettings( _doc, _this, "b2_ltune" ); + + a1_rtune.saveSettings( _doc, _this, "a1_rtune" ); + a2_rtune.saveSettings( _doc, _this, "a2_rtune" ); + b1_rtune.saveSettings( _doc, _this, "b1_rtune" ); + b2_rtune.saveSettings( _doc, _this, "b2_rtune" ); + + // save graphs + QString sampleString; + + base64::encode( (const char *)a1_graph.samples(), a1_graph.length() * sizeof(float), sampleString ); + _this.setAttribute( "a1_wave", sampleString ); + base64::encode( (const char *)a2_graph.samples(), a2_graph.length() * sizeof(float), sampleString ); + _this.setAttribute( "a2_wave", sampleString ); + base64::encode( (const char *)b1_graph.samples(), b1_graph.length() * sizeof(float), sampleString ); + _this.setAttribute( "b1_wave", sampleString ); + base64::encode( (const char *)b2_graph.samples(), b2_graph.length() * sizeof(float), sampleString ); + _this.setAttribute( "b2_wave", sampleString ); + + m_abmix.saveSettings( _doc, _this, "abmix" ); + m_amod.saveSettings( _doc, _this, "amod" ); + m_bmod.saveSettings( _doc, _this, "bmod" ); + m_selectedGraph.saveSettings( _doc, _this, "selgraph" ); +} + + +void WTSynthInstrument::loadSettings( const QDomElement & _this ) +{ + a1_vol.loadSettings( _this, "a1_vol" ); + a2_vol.loadSettings( _this, "a2_vol" ); + b1_vol.loadSettings( _this, "b1_vol" ); + b2_vol.loadSettings( _this, "b2_vol" ); + + a1_pan.loadSettings( _this, "a1_pan" ); + a2_pan.loadSettings( _this, "a2_pan" ); + b1_pan.loadSettings( _this, "b1_pan" ); + b2_pan.loadSettings( _this, "b2_pan" ); + + a1_mult.loadSettings( _this, "a1_mult" ); + a2_mult.loadSettings( _this, "a2_mult" ); + b1_mult.loadSettings( _this, "b1_mult" ); + b2_mult.loadSettings( _this, "b2_mult" ); + + a1_ltune.loadSettings( _this, "a1_ltune" ); + a2_ltune.loadSettings( _this, "a2_ltune" ); + b1_ltune.loadSettings( _this, "b1_ltune" ); + b2_ltune.loadSettings( _this, "b2_ltune" ); + + a1_rtune.loadSettings( _this, "a1_rtune" ); + a2_rtune.loadSettings( _this, "a2_rtune" ); + b1_rtune.loadSettings( _this, "b1_rtune" ); + b2_rtune.loadSettings( _this, "b2_rtune" ); + + // load graphs + int size = 0; + char * dst = 0; + + base64::decode( _this.attribute( "a1_wave"), &dst, &size ); + a1_graph.setSamples( (float*) dst ); + base64::decode( _this.attribute( "a2_wave"), &dst, &size ); + a2_graph.setSamples( (float*) dst ); + base64::decode( _this.attribute( "b1_wave"), &dst, &size ); + b1_graph.setSamples( (float*) dst ); + base64::decode( _this.attribute( "b2_wave"), &dst, &size ); + b2_graph.setSamples( (float*) dst ); + + delete[] dst; + + m_abmix.loadSettings( _this, "abmix" ); + m_amod.loadSettings( _this, "amod" ); + m_bmod.loadSettings( _this, "bmod" ); + m_selectedGraph.loadSettings( _this, "selgraph" ); +} + + +QString WTSynthInstrument::nodeName() const +{ + return( wtsynth_plugin_descriptor.name ); +} + + +PluginView * WTSynthInstrument::instantiateView( QWidget * _parent ) +{ + return( new WTSynthView( this, _parent ) ); +} + + +void WTSynthInstrument::updateVolumes( int _osc ) +{ + m_volChanged[_osc] = true; +} +void WTSynthInstrument::updateMult( int _osc ) +{ + m_multChanged[_osc] = true; +} +void WTSynthInstrument::updateTunes( int _osc ) +{ + m_tuneChanged[_osc] = true; +} + + + + + + +#define makeknob( name, x, y, hint, unit, oname ) \ + name = new knob( knobBright_26, this); \ + name ->move( x, y ); \ + name ->setHintText( tr( hint ) + " ", unit ); \ + name ->setObjectName( oname ); + +#define A1ROW 25 +#define A2ROW 47 +#define B1ROW 69 +#define B2ROW 91 + +WTSynthView::WTSynthView( Instrument * _instrument, + QWidget * _parent ) : + InstrumentView( _instrument, _parent ) +{ + setAutoFillBackground( true ); + QPalette pal; + + pal.setBrush( backgroundRole(), + PLUGIN_NAME::getIconPixmap( "artwork" ) ); + setPalette( pal ); + +// knobs... lots of em + + makeknob( a1_volKnob, 96, A1ROW, "Volume", "%", "aKnob" ) + makeknob( a2_volKnob, 96, A2ROW, "Volume", "%", "aKnob" ) + makeknob( b1_volKnob, 96, B1ROW, "Volume", "%", "bKnob" ) + makeknob( b2_volKnob, 96, B2ROW, "Volume", "%", "bKnob" ) + + makeknob( a1_panKnob, 121, A1ROW, "Panning", "", "aKnob" ) + makeknob( a2_panKnob, 121, A2ROW, "Panning", "", "aKnob" ) + makeknob( b1_panKnob, 121, B1ROW, "Panning", "", "bKnob" ) + makeknob( b2_panKnob, 121, B2ROW, "Panning", "", "bKnob" ) + + makeknob( a1_multKnob, 146, A1ROW, "Freq. multiplier", "/8", "aKnob" ) + makeknob( a2_multKnob, 146, A2ROW, "Freq. multiplier", "/8", "aKnob" ) + makeknob( b1_multKnob, 146, B1ROW, "Freq. multiplier", "/8", "bKnob" ) + makeknob( b2_multKnob, 146, B2ROW, "Freq. multiplier", "/8", "bKnob" ) + + makeknob( a1_ltuneKnob, 171, A1ROW, "Left detune", " cents", "aKnob" ) + makeknob( a2_ltuneKnob, 171, A2ROW, "Left detune", " cents", "aKnob" ) + makeknob( b1_ltuneKnob, 171, B1ROW, "Left detune", " cents", "bKnob" ) + makeknob( b2_ltuneKnob, 171, B2ROW, "Left detune", " cents", "bKnob" ) + + makeknob( a1_rtuneKnob, 196, A1ROW, "Right detune", " cents", "aKnob" ) + makeknob( a2_rtuneKnob, 196, A2ROW, "Right detune", " cents", "aKnob" ) + makeknob( b1_rtuneKnob, 196, B1ROW, "Right detune", " cents", "bKnob" ) + makeknob( b2_rtuneKnob, 196, B2ROW, "Right detune", " cents", "bKnob" ) + + makeknob( m_abmixKnob, 4, 4, "A-B Mix", "", "mixKnob" ) + +// let's set volume knobs + a1_volKnob -> setVolumeKnob( true ); + a2_volKnob -> setVolumeKnob( true ); + b1_volKnob -> setVolumeKnob( true ); + b2_volKnob -> setVolumeKnob( true ); + + +// button groups next. +// graph select buttons + pixmapButton * a1_selectButton = new pixmapButton( this, NULL ); + a1_selectButton -> move( 4, 121 ); + a1_selectButton -> setActiveGraphic( PLUGIN_NAME::getIconPixmap( "a1_active" ) ); + a1_selectButton -> setInactiveGraphic( PLUGIN_NAME::getIconPixmap( "a1_inactive" ) ); + toolTip::add( a1_selectButton, tr( "Select oscillator A1") ); + + pixmapButton * a2_selectButton = new pixmapButton( this, NULL ); + a2_selectButton -> move( 44, 121 ); + a2_selectButton -> setActiveGraphic( PLUGIN_NAME::getIconPixmap( "a2_active" ) ); + a2_selectButton -> setInactiveGraphic( PLUGIN_NAME::getIconPixmap( "a2_inactive" ) ); + toolTip::add( a2_selectButton, tr( "Select oscillator A2") ); + + pixmapButton * b1_selectButton = new pixmapButton( this, NULL ); + b1_selectButton -> move( 84, 121 ); + b1_selectButton -> setActiveGraphic( PLUGIN_NAME::getIconPixmap( "b1_active" ) ); + b1_selectButton -> setInactiveGraphic( PLUGIN_NAME::getIconPixmap( "b1_inactive" ) ); + toolTip::add( b1_selectButton, tr( "Select oscillator B1") ); + + pixmapButton * b2_selectButton = new pixmapButton( this, NULL ); + b2_selectButton -> move( 124, 121 ); + b2_selectButton -> setActiveGraphic( PLUGIN_NAME::getIconPixmap( "b2_active" ) ); + b2_selectButton -> setInactiveGraphic( PLUGIN_NAME::getIconPixmap( "b2_inactive" ) ); + toolTip::add( b2_selectButton, tr( "Select oscillator B2") ); + + m_selectedGraphGroup = new automatableButtonGroup( this ); + m_selectedGraphGroup -> addButton( a1_selectButton ); + m_selectedGraphGroup -> addButton( a2_selectButton ); + m_selectedGraphGroup -> addButton( b1_selectButton ); + m_selectedGraphGroup -> addButton( b2_selectButton ); + +// A-modulation button group + pixmapButton * amod_mixButton = new pixmapButton( this, NULL ); + amod_mixButton -> move( 4, 40 ); + amod_mixButton -> setActiveGraphic( PLUGIN_NAME::getIconPixmap( "mix_active" ) ); + amod_mixButton -> setInactiveGraphic( PLUGIN_NAME::getIconPixmap( "mix_inactive" ) ); + toolTip::add( amod_mixButton, tr( "Mix output of A2 to A1" ) ); + + pixmapButton * amod_amButton = new pixmapButton( this, NULL ); + amod_amButton -> move( 4, 56 ); + amod_amButton -> setActiveGraphic( PLUGIN_NAME::getIconPixmap( "am_active" ) ); + amod_amButton -> setInactiveGraphic( PLUGIN_NAME::getIconPixmap( "am_inactive" ) ); + toolTip::add( amod_amButton, tr( "Modulate amplitude of A1 with output of A2" ) ); + + pixmapButton * amod_rmButton = new pixmapButton( this, NULL ); + amod_rmButton -> move( 4, 72 ); + amod_rmButton -> setActiveGraphic( PLUGIN_NAME::getIconPixmap( "rm_active" ) ); + amod_rmButton -> setInactiveGraphic( PLUGIN_NAME::getIconPixmap( "rm_inactive" ) ); + toolTip::add( amod_rmButton, tr( "Ring-modulate A1 and A2" ) ); + + pixmapButton * amod_pmButton = new pixmapButton( this, NULL ); + amod_pmButton -> move( 4, 104 ); + amod_pmButton -> setActiveGraphic( PLUGIN_NAME::getIconPixmap( "pm_active" ) ); + amod_pmButton -> setInactiveGraphic( PLUGIN_NAME::getIconPixmap( "pm_inactive" ) ); + toolTip::add( amod_pmButton, tr( "Modulate phase of A1 with output of A2" ) ); + + m_aModGroup = new automatableButtonGroup( this ); + m_aModGroup -> addButton( amod_mixButton ); + m_aModGroup -> addButton( amod_amButton ); + m_aModGroup -> addButton( amod_rmButton ); + m_aModGroup -> addButton( amod_pmButton ); + +// B-modulation button group + pixmapButton * bmod_mixButton = new pixmapButton( this, NULL ); + bmod_mixButton -> move( 44, 40 ); + bmod_mixButton -> setActiveGraphic( PLUGIN_NAME::getIconPixmap( "mix_active" ) ); + bmod_mixButton -> setInactiveGraphic( PLUGIN_NAME::getIconPixmap( "mix_inactive" ) ); + toolTip::add( bmod_mixButton, tr( "Mix output of B2 to B1" ) ); + + pixmapButton * bmod_amButton = new pixmapButton( this, NULL ); + bmod_amButton -> move( 44, 56 ); + bmod_amButton -> setActiveGraphic( PLUGIN_NAME::getIconPixmap( "am_active" ) ); + bmod_amButton -> setInactiveGraphic( PLUGIN_NAME::getIconPixmap( "am_inactive" ) ); + toolTip::add( bmod_amButton, tr( "Modulate amplitude of B1 with output of B2" ) ); + + pixmapButton * bmod_rmButton = new pixmapButton( this, NULL ); + bmod_rmButton -> move( 44, 72 ); + bmod_rmButton -> setActiveGraphic( PLUGIN_NAME::getIconPixmap( "rm_active" ) ); + bmod_rmButton -> setInactiveGraphic( PLUGIN_NAME::getIconPixmap( "rm_inactive" ) ); + toolTip::add( bmod_rmButton, tr( "Ring-modulate B1 and B2" ) ); + + pixmapButton * bmod_pmButton = new pixmapButton( this, NULL ); + bmod_pmButton -> move( 44, 104 ); + bmod_pmButton -> setActiveGraphic( PLUGIN_NAME::getIconPixmap( "pm_active" ) ); + bmod_pmButton -> setInactiveGraphic( PLUGIN_NAME::getIconPixmap( "pm_inactive" ) ); + toolTip::add( bmod_pmButton, tr( "Modulate phase of B1 with output of B2" ) ); + + m_bModGroup = new automatableButtonGroup( this ); + m_bModGroup -> addButton( bmod_mixButton ); + m_bModGroup -> addButton( bmod_amButton ); + m_bModGroup -> addButton( bmod_rmButton ); + m_bModGroup -> addButton( bmod_pmButton ); + + +// graph widgets + pal = QPalette(); + pal.setBrush( backgroundRole(), PLUGIN_NAME::getIconPixmap("wavegraph") ); +// a1 graph + a1_graph = new graph( this, graph::LinearStyle, 224, 105 ); + a1_graph->move( 4, 141 ); + a1_graph->setAutoFillBackground( true ); + a1_graph->setGraphColor( QColor( 255, 255, 255 ) ); + toolTip::add( a1_graph, tr ( "Draw your own waveform here by dragging your mouse on this graph." ) ); + a1_graph->setPalette( pal ); + +// a2 graph + a2_graph = new graph( this, graph::LinearStyle, 224, 105 ); + a2_graph->move( 4, 141 ); + a2_graph->setAutoFillBackground( true ); + a2_graph->setGraphColor( QColor( 255, 255, 255 ) ); + toolTip::add( a2_graph, tr ( "Draw your own waveform here by dragging your mouse on this graph." ) ); + a2_graph->setPalette( pal ); + +// b1 graph + b1_graph = new graph( this, graph::LinearStyle, 224, 105 ); + b1_graph->move( 4, 141 ); + b1_graph->setAutoFillBackground( true ); + b1_graph->setGraphColor( QColor( 255, 255, 255 ) ); + toolTip::add( b1_graph, tr ( "Draw your own waveform here by dragging your mouse on this graph." ) ); + b1_graph->setPalette( pal ); + +// b2 graph + b2_graph = new graph( this, graph::LinearStyle, 224, 105 ); + b2_graph->move( 4, 141 ); + b2_graph->setAutoFillBackground( true ); + b2_graph->setGraphColor( QColor( 255, 255, 255 ) ); + toolTip::add( b2_graph, tr ( "Draw your own waveform here by dragging your mouse on this graph." ) ); + b2_graph->setPalette( pal ); + + +// misc pushbuttons + m_sinWaveButton = new pixmapButton( this, tr( "Sine wave" ) ); + m_sinWaveButton -> move ( 232, 182 ); + m_sinWaveButton -> setActiveGraphic( PLUGIN_NAME::getIconPixmap( "sin_active" ) ); + m_sinWaveButton -> setInactiveGraphic( PLUGIN_NAME::getIconPixmap( "sin_inactive" ) ); + toolTip::add( m_sinWaveButton, tr( "Click for sine wave" ) ); + + m_triWaveButton = new pixmapButton( this, tr( "Triangle wave" ) ); + m_triWaveButton -> move ( 232, 198 ); + m_triWaveButton -> setActiveGraphic( PLUGIN_NAME::getIconPixmap( "tri_active" ) ); + m_triWaveButton -> setInactiveGraphic( PLUGIN_NAME::getIconPixmap( "tri_inactive" ) ); + toolTip::add( m_triWaveButton, tr( "Click for triangle wave" ) ); + + m_sawWaveButton = new pixmapButton( this, tr( "Triangle wave" ) ); + m_sawWaveButton -> move ( 232, 214 ); + m_sawWaveButton -> setActiveGraphic( PLUGIN_NAME::getIconPixmap( "saw_active" ) ); + m_sawWaveButton -> setInactiveGraphic( PLUGIN_NAME::getIconPixmap( "saw_inactive" ) ); + toolTip::add( m_sawWaveButton, tr( "Click for saw wave" ) ); + + m_sqrWaveButton = new pixmapButton( this, tr( "Square wave" ) ); + m_sqrWaveButton -> move ( 232, 230 ); + m_sqrWaveButton -> setActiveGraphic( PLUGIN_NAME::getIconPixmap( "sqr_active" ) ); + m_sqrWaveButton -> setInactiveGraphic( PLUGIN_NAME::getIconPixmap( "sqr_inactive" ) ); + toolTip::add( m_sqrWaveButton, tr( "Click for square wave" ) ); + + m_normalizeButton = new pixmapButton( this, tr( "Normalize" ) ); + m_normalizeButton -> move ( 232, 134 ); + m_normalizeButton -> setActiveGraphic( PLUGIN_NAME::getIconPixmap( "norm_active" ) ); + m_normalizeButton -> setInactiveGraphic( PLUGIN_NAME::getIconPixmap( "norm_inactive" ) ); + toolTip::add( m_normalizeButton, tr( "Click to normalize" ) ); + + m_invertButton = new pixmapButton( this, tr( "Invert" ) ); + m_invertButton -> move ( 232, 150 ); + m_invertButton -> setActiveGraphic( PLUGIN_NAME::getIconPixmap( "inv_active" ) ); + m_invertButton -> setInactiveGraphic( PLUGIN_NAME::getIconPixmap( "inv_inactive" ) ); + toolTip::add( m_invertButton, tr( "Click to invert" ) ); + + m_smoothButton = new pixmapButton( this, tr( "Smooth" ) ); + m_smoothButton -> move ( 232, 166 ); + m_smoothButton -> setActiveGraphic( PLUGIN_NAME::getIconPixmap( "smooth_active" ) ); + m_smoothButton -> setInactiveGraphic( PLUGIN_NAME::getIconPixmap( "smooth_inactive" ) ); + toolTip::add( m_smoothButton, tr( "Click to smooth" ) ); + + m_phaseLeftButton = new pixmapButton( this, tr( "Phase left" ) ); + m_phaseLeftButton -> move ( 200, 134 ); + m_phaseLeftButton -> setActiveGraphic( PLUGIN_NAME::getIconPixmap( "phl_active" ) ); + m_phaseLeftButton -> setInactiveGraphic( PLUGIN_NAME::getIconPixmap( "phl_inactive" ) ); + toolTip::add( m_phaseLeftButton, tr( "Click to shift phase by -15 degrees" ) ); + + m_phaseRightButton = new pixmapButton( this, tr( "Phase right" ) ); + m_phaseRightButton -> move ( 216, 134 ); + m_phaseRightButton -> setActiveGraphic( PLUGIN_NAME::getIconPixmap( "phr_active" ) ); + m_phaseRightButton -> setInactiveGraphic( PLUGIN_NAME::getIconPixmap( "phr_inactive" ) ); + toolTip::add( m_phaseRightButton, tr( "Click to shift phase by +15 degrees" ) ); + + connect( m_sinWaveButton, SIGNAL( clicked() ), this, SLOT( sinWaveClicked() ) ); + connect( m_triWaveButton, SIGNAL( clicked() ), this, SLOT( triWaveClicked() ) ); + connect( m_sawWaveButton, SIGNAL( clicked() ), this, SLOT( sawWaveClicked() ) ); + connect( m_sqrWaveButton, SIGNAL( clicked() ), this, SLOT( sqrWaveClicked() ) ); + connect( m_normalizeButton, SIGNAL( clicked() ), this, SLOT( normalizeClicked() ) ); + connect( m_invertButton, SIGNAL( clicked() ), this, SLOT( invertClicked() ) ); + connect( m_phaseLeftButton, SIGNAL( clicked() ), this, SLOT( phaseLeftClicked() ) ); + connect( m_phaseRightButton, SIGNAL( clicked() ), this, SLOT( phaseRightClicked() ) ); + + connect( a1_selectButton, SIGNAL( clicked() ), this, SLOT( updateLayout() ) ); + connect( a2_selectButton, SIGNAL( clicked() ), this, SLOT( updateLayout() ) ); + connect( b1_selectButton, SIGNAL( clicked() ), this, SLOT( updateLayout() ) ); + connect( b2_selectButton, SIGNAL( clicked() ), this, SLOT( updateLayout() ) ); + + updateLayout(); +} + + +WTSynthView::~WTSynthView() +{ +} + + + +void WTSynthView::updateLayout() +{ + switch( m_selectedGraphGroup->model()->value() ) + { + case A1_OSC: + a1_graph->show(); + a2_graph->hide(); + b1_graph->hide(); + b2_graph->hide(); + break; + case A2_OSC: + a1_graph->hide(); + a2_graph->show(); + b1_graph->hide(); + b2_graph->hide(); + break; + case B1_OSC: + a1_graph->hide(); + a2_graph->hide(); + b1_graph->show(); + b2_graph->hide(); + break; + case B2_OSC: + a1_graph->hide(); + a2_graph->hide(); + b1_graph->hide(); + b2_graph->show(); + break; + } +} + + + +void WTSynthView::sinWaveClicked() +{ + switch( m_selectedGraphGroup->model()->value() ) + { + case A1_OSC: + a1_graph->model()->setWaveToSine(); + engine::getSong()->setModified(); + break; + case A2_OSC: + a2_graph->model()->setWaveToSine(); + engine::getSong()->setModified(); + break; + case B1_OSC: + b1_graph->model()->setWaveToSine(); + engine::getSong()->setModified(); + break; + case B2_OSC: + b2_graph->model()->setWaveToSine(); + engine::getSong()->setModified(); + break; + } +} + + +void WTSynthView::triWaveClicked() +{ + switch( m_selectedGraphGroup->model()->value() ) + { + case A1_OSC: + a1_graph->model()->setWaveToTriangle(); + engine::getSong()->setModified(); + break; + case A2_OSC: + a2_graph->model()->setWaveToTriangle(); + engine::getSong()->setModified(); + break; + case B1_OSC: + b1_graph->model()->setWaveToTriangle(); + engine::getSong()->setModified(); + break; + case B2_OSC: + b2_graph->model()->setWaveToTriangle(); + engine::getSong()->setModified(); + break; + } +} + + +void WTSynthView::sawWaveClicked() +{ + switch( m_selectedGraphGroup->model()->value() ) + { + case A1_OSC: + a1_graph->model()->setWaveToSaw(); + engine::getSong()->setModified(); + break; + case A2_OSC: + a2_graph->model()->setWaveToSaw(); + engine::getSong()->setModified(); + break; + case B1_OSC: + b1_graph->model()->setWaveToSaw(); + engine::getSong()->setModified(); + break; + case B2_OSC: + b2_graph->model()->setWaveToSaw(); + engine::getSong()->setModified(); + break; + } +} + + +void WTSynthView::sqrWaveClicked() +{ + switch( m_selectedGraphGroup->model()->value() ) + { + case A1_OSC: + a1_graph->model()->setWaveToSquare(); + engine::getSong()->setModified(); + break; + case A2_OSC: + a2_graph->model()->setWaveToSquare(); + engine::getSong()->setModified(); + break; + case B1_OSC: + b1_graph->model()->setWaveToSquare(); + engine::getSong()->setModified(); + break; + case B2_OSC: + b2_graph->model()->setWaveToSquare(); + engine::getSong()->setModified(); + break; + } +} + + +void WTSynthView::normalizeClicked() +{ + switch( m_selectedGraphGroup->model()->value() ) + { + case A1_OSC: + a1_graph->model()->normalize(); + engine::getSong()->setModified(); + break; + case A2_OSC: + a2_graph->model()->normalize(); + engine::getSong()->setModified(); + break; + case B1_OSC: + b1_graph->model()->normalize(); + engine::getSong()->setModified(); + break; + case B2_OSC: + b2_graph->model()->normalize(); + engine::getSong()->setModified(); + break; + } +} + + +void WTSynthView::invertClicked() +{ + switch( m_selectedGraphGroup->model()->value() ) + { + case A1_OSC: + a1_graph->model()->invert(); + engine::getSong()->setModified(); + break; + case A2_OSC: + a2_graph->model()->invert(); + engine::getSong()->setModified(); + break; + case B1_OSC: + b1_graph->model()->invert(); + engine::getSong()->setModified(); + break; + case B2_OSC: + b2_graph->model()->invert(); + engine::getSong()->setModified(); + break; + } +} + + +void WTSynthView::smoothClicked() +{ + switch( m_selectedGraphGroup->model()->value() ) + { + case A1_OSC: + a1_graph->model()->smooth(); + engine::getSong()->setModified(); + break; + case A2_OSC: + a2_graph->model()->smooth(); + engine::getSong()->setModified(); + break; + case B1_OSC: + b1_graph->model()->smooth(); + engine::getSong()->setModified(); + break; + case B2_OSC: + b2_graph->model()->smooth(); + engine::getSong()->setModified(); + break; + } +} + + +void WTSynthView::phaseLeftClicked() +{ + switch( m_selectedGraphGroup->model()->value() ) + { + case A1_OSC: + a1_graph->model()->shiftPhase( -15 ); + engine::getSong()->setModified(); + break; + case A2_OSC: + a2_graph->model()->shiftPhase( -15 ); + engine::getSong()->setModified(); + break; + case B1_OSC: + b1_graph->model()->shiftPhase( -15 ); + engine::getSong()->setModified(); + break; + case B2_OSC: + b2_graph->model()->shiftPhase( -15 ); + engine::getSong()->setModified(); + break; + } +} + + +void WTSynthView::phaseRightClicked() +{ + switch( m_selectedGraphGroup->model()->value() ) + { + case A1_OSC: + a1_graph->model()->shiftPhase( 15 ); + engine::getSong()->setModified(); + break; + case A2_OSC: + a2_graph->model()->shiftPhase( 15 ); + engine::getSong()->setModified(); + break; + case B1_OSC: + b1_graph->model()->shiftPhase( 15 ); + engine::getSong()->setModified(); + break; + case B2_OSC: + b2_graph->model()->shiftPhase( 15 ); + engine::getSong()->setModified(); + break; + } +} + + +void WTSynthView::modelChanged() +{ + WTSynthInstrument * w = castModel(); + + a1_volKnob -> setModel( &w -> a1_vol ); + a2_volKnob -> setModel( &w -> a2_vol ); + b1_volKnob -> setModel( &w -> b1_vol ); + b2_volKnob -> setModel( &w -> b2_vol ); + + a1_panKnob -> setModel( &w -> a1_pan ); + a2_panKnob -> setModel( &w -> a2_pan ); + b1_panKnob -> setModel( &w -> b1_pan ); + b2_panKnob -> setModel( &w -> b2_pan ); + + a1_multKnob -> setModel( &w -> a1_mult ); + a2_multKnob -> setModel( &w -> a2_mult ); + b1_multKnob -> setModel( &w -> b1_mult ); + b2_multKnob -> setModel( &w -> b2_mult ); + + a1_ltuneKnob -> setModel( &w -> a1_ltune ); + a2_ltuneKnob -> setModel( &w -> a2_ltune ); + b1_ltuneKnob -> setModel( &w -> b1_ltune ); + b2_ltuneKnob -> setModel( &w -> b2_ltune ); + + a1_rtuneKnob -> setModel( &w -> a1_rtune ); + a2_rtuneKnob -> setModel( &w -> a2_rtune ); + b1_rtuneKnob -> setModel( &w -> b1_rtune ); + b2_rtuneKnob -> setModel( &w -> b2_rtune ); + + m_abmixKnob -> setModel( &w -> m_abmix ); + + m_selectedGraphGroup -> setModel( &w -> m_selectedGraph ); + + m_aModGroup -> setModel( &w -> m_amod ); + m_bModGroup -> setModel( &w -> m_bmod ); + + a1_graph -> setModel( &w -> a1_graph ); + a2_graph -> setModel( &w -> a2_graph ); + b1_graph -> setModel( &w -> b1_graph ); + b2_graph -> setModel( &w -> b2_graph ); + +} + + + + + +extern "C" +{ + +// necessary for getting instance out of shared lib +Plugin * PLUGIN_EXPORT lmms_plugin_main( Model *, void * _data ) +{ + return( new WTSynthInstrument( static_cast( _data ) ) ); +} + + +} + + +#include "moc_WTSynth.cxx" diff --git a/plugins/wtsynth/WTSynth.h b/plugins/wtsynth/WTSynth.h index 286c23cb7..b53eb77c5 100644 --- a/plugins/wtsynth/WTSynth.h +++ b/plugins/wtsynth/WTSynth.h @@ -29,10 +29,230 @@ #include "Instrument.h" #include "InstrumentView.h" #include "graph.h" +#include "AutomatableModel.h" +#include "automatable_button.h" #include "knob.h" +#include "NotePlayHandle.h" #include "pixmap_button.h" +const int WAVELEN = 220; +const int MOD_MIX = 0; +const int MOD_AM = 1; +const int MOD_RM = 2; +const int MOD_PM = 3; +const int NUM_MODS = 4; + +const int A1_OSC = 0; +const int A2_OSC = 1; +const int B1_OSC = 2; +const int B2_OSC = 3; +const int NUM_OSCS = 4; + +class WTSynthInstrument; +class WTSynthView; + +class WTSynthObject +{ +public: + WTSynthObject( float * _A1wave, float * _A2wave, + float * _B1wave, float * _B2wave, + int _amod, int _bmod, const sample_rate_t _samplerate, NotePlayHandle * _nph ); + virtual ~WTSynthObject(); + + void renderOutput( sampleFrame * _abuf, sampleFrame * _bbuf, fpp_t _frames ); + + void updateFrequencies(); + + void changeVolume( int _osc, float _lvol, float _rvol ); + void changeMult( int _osc, int _mul ); + void changeTune( int _osc, float _ltune, float _rtune ); + +private: + sample_t * m_A1wave; + sample_t * m_A2wave; + sample_t * m_B1wave; + sample_t * m_B2wave; + + float m_lvol [NUM_OSCS]; + float m_rvol [NUM_OSCS]; + int m_mult [NUM_OSCS]; + float m_ltune [NUM_OSCS]; + float m_rtune [NUM_OSCS]; + + int m_amod; + int m_bmod; + + const sample_rate_t m_samplerate; + NotePlayHandle * m_nph; + + float m_lphase [NUM_OSCS]; + float m_rphase [NUM_OSCS]; + + float m_lfreq [NUM_OSCS]; + float m_rfreq [NUM_OSCS]; +}; + +class WTSynthInstrument : public Instrument +{ + Q_OBJECT +public: + WTSynthInstrument( InstrumentTrack * _instrument_track ); + virtual ~WTSynthInstrument(); + + virtual void playNote( NotePlayHandle * _n, + sampleFrame * _working_buffer ); + virtual void deleteNotePluginData( NotePlayHandle * _n ); + + + virtual void saveSettings( QDomDocument & _doc, + QDomElement & _this ); + virtual void loadSettings( const QDomElement & _this ); + + virtual QString nodeName() const; + + virtual f_cnt_t desiredReleaseFrames() const + { + return( 64 ); + } + + virtual PluginView * instantiateView( QWidget * _parent ); + +protected slots: + void updateVolumes( int _osc ); + void updateMult( int _osc ); + void updateTunes( int _osc ); + +private: + inline float leftCh( float _vol, float _pan ) + { + return ( _pan <= 0 ? 1.0 : 1.0 - ( _pan / 100.0 ) ) * _vol; + } + + inline float rightCh( float _vol, float _pan ) + { + return ( _pan >= 0 ? 1.0 : 1.0 + ( _pan / 100.0 ) ) * _vol; + } + + FloatModel a1_vol; + FloatModel a2_vol; + FloatModel b1_vol; + FloatModel b2_vol; + + FloatModel a1_pan; + FloatModel a2_pan; + FloatModel b1_pan; + FloatModel b2_pan; + + IntModel a1_mult; + IntModel a2_mult; + IntModel b1_mult; + IntModel b2_mult; + + FloatModel a1_ltune; + FloatModel a2_ltune; + FloatModel b1_ltune; + FloatModel b2_ltune; + + FloatModel a1_rtune; + FloatModel a2_rtune; + FloatModel b1_rtune; + FloatModel b2_rtune; + + graphModel a1_graph; + graphModel a2_graph; + graphModel b1_graph; + graphModel b2_graph; + + FloatModel m_abmix; + IntModel m_amod; + IntModel m_bmod; + + IntModel m_selectedGraph; + + bool m_volChanged [NUM_OSCS]; + bool m_multChanged [NUM_OSCS]; + bool m_tuneChanged [NUM_OSCS]; + + friend class WTSynthView; +}; + + +class WTSynthView : public InstrumentView +{ + Q_OBJECT +public: + WTSynthView( Instrument * _instrument, + QWidget * _parent ); + virtual ~WTSynthView(); + +protected slots: + void updateLayout(); + + void sinWaveClicked(); + void triWaveClicked(); + void sawWaveClicked(); + void sqrWaveClicked(); + + void smoothClicked(); + void normalizeClicked(); + void invertClicked(); + void phaseLeftClicked(); + void phaseRightClicked(); + +private: + virtual void modelChanged(); + +// knobs + knob * a1_volKnob; + knob * a2_volKnob; + knob * b1_volKnob; + knob * b2_volKnob; + + knob * a1_panKnob; + knob * a2_panKnob; + knob * b1_panKnob; + knob * b2_panKnob; + + knob * a1_multKnob; + knob * a2_multKnob; + knob * b1_multKnob; + knob * b2_multKnob; + + knob * a1_ltuneKnob; + knob * a2_ltuneKnob; + knob * b1_ltuneKnob; + knob * b2_ltuneKnob; + + knob * a1_rtuneKnob; + knob * a2_rtuneKnob; + knob * b1_rtuneKnob; + knob * b2_rtuneKnob; + + knob * m_abmixKnob; + + automatableButtonGroup * m_selectedGraphGroup; + automatableButtonGroup * m_aModGroup; + automatableButtonGroup * m_bModGroup; + + static QPixmap * s_artwork; + + graph * a1_graph; + graph * a2_graph; + graph * b1_graph; + graph * b2_graph; + + pixmapButton * m_sinWaveButton; + pixmapButton * m_triWaveButton; + pixmapButton * m_sawWaveButton; + pixmapButton * m_sqrWaveButton; + pixmapButton * m_normalizeButton; + pixmapButton * m_invertButton; + pixmapButton * m_smoothButton; + pixmapButton * m_phaseLeftButton; + pixmapButton * m_phaseRightButton; + +}; #endif diff --git a/plugins/wtsynth/a1_active.png b/plugins/wtsynth/a1_active.png new file mode 100644 index 0000000000000000000000000000000000000000..c09789d32e7b2ea636f55e145fe074d4331f88fc GIT binary patch literal 169 zcmeAS@N?(olHy`uVBq!ia0vp^8bB<-!2~24nJa0`PlBg3pY5H=O_Iu1CqN1@b#rmUcvOa4nJa0`PlBg3pY5H=O_Iu1CqN@6;UmhL;3Q3l@MwB?`=jNv7l`uFLr6!i7rYMwWmSiZnd-?{1H}Z)C z6)AhVIEGl9PQG&KQj!G6fg=VE30EEkcDw7!ZLI(?*ykT*u-L#bZ@%>fC7^N!Pgg&e IbxsLQ0E1jG%>V!Z literal 0 HcmV?d00001 diff --git a/plugins/wtsynth/a2_active.png b/plugins/wtsynth/a2_active.png new file mode 100644 index 0000000000000000000000000000000000000000..c09789d32e7b2ea636f55e145fe074d4331f88fc GIT binary patch literal 169 zcmeAS@N?(olHy`uVBq!ia0vp^8bB<-!2~24nJa0`PlBg3pY5H=O_Iu1CqN1@b#rmUcvOa4nJa0`PlBg3pY5H=O_Iu1CqN@6;UmhL;3Q3l@MwB?`=jNv7l`uFLr6!i7rYMwWmSiZnd-?{1H}Z)C z6)AhVIEGl9PQG&KQj!G6fg=VE30EEkcDw7!ZLI(?*ykT*u-L#bZ@%>fC7^N!Pgg&e IbxsLQ0E1jG%>V!Z literal 0 HcmV?d00001 diff --git a/plugins/wtsynth/am_active.png b/plugins/wtsynth/am_active.png new file mode 100644 index 0000000000000000000000000000000000000000..c09789d32e7b2ea636f55e145fe074d4331f88fc GIT binary patch literal 169 zcmeAS@N?(olHy`uVBq!ia0vp^8bB<-!2~24nJa0`PlBg3pY5H=O_Iu1CqN1@b#rmUcvOa4nJa0`PlBg3pY5H=O_Iu1CqN@6;UmhL;3Q3l@MwB?`=jNv7l`uFLr6!i7rYMwWmSiZnd-?{1H}Z)C z6)AhVIEGl9PQG&KQj!G6fg=VE30EEkcDw7!ZLI(?*ykT*u-L#bZ@%>fC7^N!Pgg&e IbxsLQ0E1jG%>V!Z literal 0 HcmV?d00001 diff --git a/plugins/wtsynth/artwork.png b/plugins/wtsynth/artwork.png new file mode 100644 index 0000000000000000000000000000000000000000..26b66f53503e776f05e86d8543410ff2aa8523c0 GIT binary patch literal 625 zcmeAS@N?(olHy`uVBq!ia0vp^zd)FS2}rW{oy`JLoCO|{#S9GG!XV7ZFl&wkNUp@w z*OmPqvxumQl2hCoJD`wciEBiObAE1aYF-J0b5UwyNotBhd1gt5g1e`0KzJjcI0FOY zYfl%)kcwMxFER2mFmN0;IPm4|W9BH%(^j4b`IQ;V*mpPIJ@_u6e1r83**AP(?nVR? zF4Kpu2qXhl4_5@zo{Ve~T!u33m`*(S4(?jG9XM?#R{L?(V1OA+k#=Ikm#++~?Zj#a dg>S)WCese)$ZxZBOn_;F!PC{xWt~$(699_VBnJQh literal 0 HcmV?d00001 diff --git a/plugins/wtsynth/b1_active.png b/plugins/wtsynth/b1_active.png new file mode 100644 index 0000000000000000000000000000000000000000..c09789d32e7b2ea636f55e145fe074d4331f88fc GIT binary patch literal 169 zcmeAS@N?(olHy`uVBq!ia0vp^8bB<-!2~24nJa0`PlBg3pY5H=O_Iu1CqN1@b#rmUcvOa4nJa0`PlBg3pY5H=O_Iu1CqN@6;UmhL;3Q3l@MwB?`=jNv7l`uFLr6!i7rYMwWmSiZnd-?{1H}Z)C z6)AhVIEGl9PQG&KQj!G6fg=VE30EEkcDw7!ZLI(?*ykT*u-L#bZ@%>fC7^N!Pgg&e IbxsLQ0E1jG%>V!Z literal 0 HcmV?d00001 diff --git a/plugins/wtsynth/b2_active.png b/plugins/wtsynth/b2_active.png new file mode 100644 index 0000000000000000000000000000000000000000..c09789d32e7b2ea636f55e145fe074d4331f88fc GIT binary patch literal 169 zcmeAS@N?(olHy`uVBq!ia0vp^8bB<-!2~24nJa0`PlBg3pY5H=O_Iu1CqN1@b#rmUcvOa4nJa0`PlBg3pY5H=O_Iu1CqN@6;UmhL;3Q3l@MwB?`=jNv7l`uFLr6!i7rYMwWmSiZnd-?{1H}Z)C z6)AhVIEGl9PQG&KQj!G6fg=VE30EEkcDw7!ZLI(?*ykT*u-L#bZ@%>fC7^N!Pgg&e IbxsLQ0E1jG%>V!Z literal 0 HcmV?d00001 diff --git a/plugins/wtsynth/inv_active.png b/plugins/wtsynth/inv_active.png new file mode 100644 index 0000000000000000000000000000000000000000..16b72849b221c93898b7a135cf68f3dba7ffb793 GIT binary patch literal 305 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61SBU+%rFB|oCO|{#S9GG!XV7ZFl&wkP>{XE z)7O>#9Z^Zxw#)6UNB^fX=NH4oq2-3{bcR#rxD%elER`S{)4 z<%O9EjVtDvWL`SbDXi%9{@&i;u&`t4&gJFhadC2W%l+qCnd<5Bt!kV*SGIqmfcl+X zrP&u3x$^Mv^vnOSphG+J$kC&o-rmaEstXc1mZ~!RD0JT!`_4HU=xhd0S3j3^P6{XE z)7O>#9!MP|ku_QG`p**uBL&4qCHz2%`PaLRd zou`Xqh{pM=L55r{1_F0vrXR9fa;kaD=CkrSmzR0$o;pF?!{LMCKj$0#5hu2VYdG%M z-EmaZ{H~6*HM6zSQkL=$4YPmjeNd^^;o;(Y`ATW+LkE|RjJ0on*Ud{;(y|n|Xwi3W zXYH1Cs|}YuG2m(5x=p5bmfHKjiW7pw{N4#pOXXB#XsD=<=@DeuweIwknZ*eoKVI%w zG3C~_-kGacW!*M&7r4Lb;oj>}^TYL7>aQ#n_t@#)JG-a-KG5Y1p00i_>zopr0A#Oo AxBvhE literal 0 HcmV?d00001 diff --git a/plugins/wtsynth/logo.png b/plugins/wtsynth/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..4378e3ab4d2db625a31a9ebd03f040c28b72e924 GIT binary patch literal 174 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1SJ1Ryj={WI14-?iy0WWg+Z8+Vb&Z8pdfpR zr>`sfJ!TP66_agUlKDU($r9Iy66gHf+|;}h2Ir#G#FEq$h4Rdj34nJa0`PlBg3pY5H=O_Iu1CqN1@b#rmUcvOa4nJa0`PlBg3pY5H=O_Iu1CqN@6;UmhL;3Q3l@MwB?`=jNv7l`uFLr6!i7rYMwWmSiZnd-?{1H}Z)C z6)AhVIEGl9PQG&KQj!G6fg=VE30EEkcDw7!ZLI(?*ykT*u-L#bZ@%>fC7^N!Pgg&e IbxsLQ0E1jG%>V!Z literal 0 HcmV?d00001 diff --git a/plugins/wtsynth/norm_active.png b/plugins/wtsynth/norm_active.png new file mode 100644 index 0000000000000000000000000000000000000000..16b72849b221c93898b7a135cf68f3dba7ffb793 GIT binary patch literal 305 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61SBU+%rFB|oCO|{#S9GG!XV7ZFl&wkP>{XE z)7O>#9Z^Zxw#)6UNB^fX=NH4oq2-3{bcR#rxD%elER`S{)4 z<%O9EjVtDvWL`SbDXi%9{@&i;u&`t4&gJFhadC2W%l+qCnd<5Bt!kV*SGIqmfcl+X zrP&u3x$^Mv^vnOSphG+J$kC&o-rmaEstXc1mZ~!RD0JT!`_4HU=xhd0S3j3^P6{XE z)7O>#9!MP|ku_QG`p**uBL&4qCHz2%`PaLRd zou`Xqh{pM=L55r{1_F0vrXR9fa;kaD=CkrSmzR0$o;pF?!{LMCKj$0#5hu2VYdG%M z-EmaZ{H~6*HM6zSQkL=$4YPmjeNd^^;o;(Y`ATW+LkE|RjJ0on*Ud{;(y|n|Xwi3W zXYH1Cs|}YuG2m(5x=p5bmfHKjiW7pw{N4#pOXXB#XsD=<=@DeuweIwknZ*eoKVI%w zG3C~_-kGacW!*M&7r4Lb;oj>}^TYL7>aQ#n_t@#)JG-a-KG5Y1p00i_>zopr0A#Oo AxBvhE literal 0 HcmV?d00001 diff --git a/plugins/wtsynth/phl_active.png b/plugins/wtsynth/phl_active.png new file mode 100644 index 0000000000000000000000000000000000000000..16b72849b221c93898b7a135cf68f3dba7ffb793 GIT binary patch literal 305 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61SBU+%rFB|oCO|{#S9GG!XV7ZFl&wkP>{XE z)7O>#9Z^Zxw#)6UNB^fX=NH4oq2-3{bcR#rxD%elER`S{)4 z<%O9EjVtDvWL`SbDXi%9{@&i;u&`t4&gJFhadC2W%l+qCnd<5Bt!kV*SGIqmfcl+X zrP&u3x$^Mv^vnOSphG+J$kC&o-rmaEstXc1mZ~!RD0JT!`_4HU=xhd0S3j3^P6{XE z)7O>#9!MP|ku_QG`p**uBL&4qCHz2%`PaLRd zou`Xqh{pM=L55r{1_F0vrXR9fa;kaD=CkrSmzR0$o;pF?!{LMCKj$0#5hu2VYdG%M z-EmaZ{H~6*HM6zSQkL=$4YPmjeNd^^;o;(Y`ATW+LkE|RjJ0on*Ud{;(y|n|Xwi3W zXYH1Cs|}YuG2m(5x=p5bmfHKjiW7pw{N4#pOXXB#XsD=<=@DeuweIwknZ*eoKVI%w zG3C~_-kGacW!*M&7r4Lb;oj>}^TYL7>aQ#n_t@#)JG-a-KG5Y1p00i_>zopr0A#Oo AxBvhE literal 0 HcmV?d00001 diff --git a/plugins/wtsynth/phr_active.png b/plugins/wtsynth/phr_active.png new file mode 100644 index 0000000000000000000000000000000000000000..16b72849b221c93898b7a135cf68f3dba7ffb793 GIT binary patch literal 305 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61SBU+%rFB|oCO|{#S9GG!XV7ZFl&wkP>{XE z)7O>#9Z^Zxw#)6UNB^fX=NH4oq2-3{bcR#rxD%elER`S{)4 z<%O9EjVtDvWL`SbDXi%9{@&i;u&`t4&gJFhadC2W%l+qCnd<5Bt!kV*SGIqmfcl+X zrP&u3x$^Mv^vnOSphG+J$kC&o-rmaEstXc1mZ~!RD0JT!`_4HU=xhd0S3j3^P6{XE z)7O>#9!MP|ku_QG`p**uBL&4qCHz2%`PaLRd zou`Xqh{pM=L55r{1_F0vrXR9fa;kaD=CkrSmzR0$o;pF?!{LMCKj$0#5hu2VYdG%M z-EmaZ{H~6*HM6zSQkL=$4YPmjeNd^^;o;(Y`ATW+LkE|RjJ0on*Ud{;(y|n|Xwi3W zXYH1Cs|}YuG2m(5x=p5bmfHKjiW7pw{N4#pOXXB#XsD=<=@DeuweIwknZ*eoKVI%w zG3C~_-kGacW!*M&7r4Lb;oj>}^TYL7>aQ#n_t@#)JG-a-KG5Y1p00i_>zopr0A#Oo AxBvhE literal 0 HcmV?d00001 diff --git a/plugins/wtsynth/pm_active.png b/plugins/wtsynth/pm_active.png new file mode 100644 index 0000000000000000000000000000000000000000..c09789d32e7b2ea636f55e145fe074d4331f88fc GIT binary patch literal 169 zcmeAS@N?(olHy`uVBq!ia0vp^8bB<-!2~24nJa0`PlBg3pY5H=O_Iu1CqN1@b#rmUcvOa4nJa0`PlBg3pY5H=O_Iu1CqN@6;UmhL;3Q3l@MwB?`=jNv7l`uFLr6!i7rYMwWmSiZnd-?{1H}Z)C z6)AhVIEGl9PQG&KQj!G6fg=VE30EEkcDw7!ZLI(?*ykT*u-L#bZ@%>fC7^N!Pgg&e IbxsLQ0E1jG%>V!Z literal 0 HcmV?d00001 diff --git a/plugins/wtsynth/rm_active.png b/plugins/wtsynth/rm_active.png new file mode 100644 index 0000000000000000000000000000000000000000..c09789d32e7b2ea636f55e145fe074d4331f88fc GIT binary patch literal 169 zcmeAS@N?(olHy`uVBq!ia0vp^8bB<-!2~24nJa0`PlBg3pY5H=O_Iu1CqN1@b#rmUcvOa4nJa0`PlBg3pY5H=O_Iu1CqN@6;UmhL;3Q3l@MwB?`=jNv7l`uFLr6!i7rYMwWmSiZnd-?{1H}Z)C z6)AhVIEGl9PQG&KQj!G6fg=VE30EEkcDw7!ZLI(?*ykT*u-L#bZ@%>fC7^N!Pgg&e IbxsLQ0E1jG%>V!Z literal 0 HcmV?d00001 diff --git a/plugins/wtsynth/saw_active.png b/plugins/wtsynth/saw_active.png new file mode 100644 index 0000000000000000000000000000000000000000..16b72849b221c93898b7a135cf68f3dba7ffb793 GIT binary patch literal 305 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61SBU+%rFB|oCO|{#S9GG!XV7ZFl&wkP>{XE z)7O>#9Z^Zxw#)6UNB^fX=NH4oq2-3{bcR#rxD%elER`S{)4 z<%O9EjVtDvWL`SbDXi%9{@&i;u&`t4&gJFhadC2W%l+qCnd<5Bt!kV*SGIqmfcl+X zrP&u3x$^Mv^vnOSphG+J$kC&o-rmaEstXc1mZ~!RD0JT!`_4HU=xhd0S3j3^P6{XE z)7O>#9!MP|ku_QG`p**uBL&4qCHz2%`PaLRd zou`Xqh{pM=L55r{1_F0vrXR9fa;kaD=CkrSmzR0$o;pF?!{LMCKj$0#5hu2VYdG%M z-EmaZ{H~6*HM6zSQkL=$4YPmjeNd^^;o;(Y`ATW+LkE|RjJ0on*Ud{;(y|n|Xwi3W zXYH1Cs|}YuG2m(5x=p5bmfHKjiW7pw{N4#pOXXB#XsD=<=@DeuweIwknZ*eoKVI%w zG3C~_-kGacW!*M&7r4Lb;oj>}^TYL7>aQ#n_t@#)JG-a-KG5Y1p00i_>zopr0A#Oo AxBvhE literal 0 HcmV?d00001 diff --git a/plugins/wtsynth/sin_active.png b/plugins/wtsynth/sin_active.png new file mode 100644 index 0000000000000000000000000000000000000000..16b72849b221c93898b7a135cf68f3dba7ffb793 GIT binary patch literal 305 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61SBU+%rFB|oCO|{#S9GG!XV7ZFl&wkP>{XE z)7O>#9Z^Zxw#)6UNB^fX=NH4oq2-3{bcR#rxD%elER`S{)4 z<%O9EjVtDvWL`SbDXi%9{@&i;u&`t4&gJFhadC2W%l+qCnd<5Bt!kV*SGIqmfcl+X zrP&u3x$^Mv^vnOSphG+J$kC&o-rmaEstXc1mZ~!RD0JT!`_4HU=xhd0S3j3^P6{XE z)7O>#9!MP|ku_QG`p**uBL&4qCHz2%`PaLRd zou`Xqh{pM=L55r{1_F0vrXR9fa;kaD=CkrSmzR0$o;pF?!{LMCKj$0#5hu2VYdG%M z-EmaZ{H~6*HM6zSQkL=$4YPmjeNd^^;o;(Y`ATW+LkE|RjJ0on*Ud{;(y|n|Xwi3W zXYH1Cs|}YuG2m(5x=p5bmfHKjiW7pw{N4#pOXXB#XsD=<=@DeuweIwknZ*eoKVI%w zG3C~_-kGacW!*M&7r4Lb;oj>}^TYL7>aQ#n_t@#)JG-a-KG5Y1p00i_>zopr0A#Oo AxBvhE literal 0 HcmV?d00001 diff --git a/plugins/wtsynth/smooth_active.png b/plugins/wtsynth/smooth_active.png new file mode 100644 index 0000000000000000000000000000000000000000..16b72849b221c93898b7a135cf68f3dba7ffb793 GIT binary patch literal 305 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61SBU+%rFB|oCO|{#S9GG!XV7ZFl&wkP>{XE z)7O>#9Z^Zxw#)6UNB^fX=NH4oq2-3{bcR#rxD%elER`S{)4 z<%O9EjVtDvWL`SbDXi%9{@&i;u&`t4&gJFhadC2W%l+qCnd<5Bt!kV*SGIqmfcl+X zrP&u3x$^Mv^vnOSphG+J$kC&o-rmaEstXc1mZ~!RD0JT!`_4HU=xhd0S3j3^P6{XE z)7O>#9!MP|ku_QG`p**uBL&4qCHz2%`PaLRd zou`Xqh{pM=L55r{1_F0vrXR9fa;kaD=CkrSmzR0$o;pF?!{LMCKj$0#5hu2VYdG%M z-EmaZ{H~6*HM6zSQkL=$4YPmjeNd^^;o;(Y`ATW+LkE|RjJ0on*Ud{;(y|n|Xwi3W zXYH1Cs|}YuG2m(5x=p5bmfHKjiW7pw{N4#pOXXB#XsD=<=@DeuweIwknZ*eoKVI%w zG3C~_-kGacW!*M&7r4Lb;oj>}^TYL7>aQ#n_t@#)JG-a-KG5Y1p00i_>zopr0A#Oo AxBvhE literal 0 HcmV?d00001 diff --git a/plugins/wtsynth/sqr_active.png b/plugins/wtsynth/sqr_active.png new file mode 100644 index 0000000000000000000000000000000000000000..16b72849b221c93898b7a135cf68f3dba7ffb793 GIT binary patch literal 305 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61SBU+%rFB|oCO|{#S9GG!XV7ZFl&wkP>{XE z)7O>#9Z^Zxw#)6UNB^fX=NH4oq2-3{bcR#rxD%elER`S{)4 z<%O9EjVtDvWL`SbDXi%9{@&i;u&`t4&gJFhadC2W%l+qCnd<5Bt!kV*SGIqmfcl+X zrP&u3x$^Mv^vnOSphG+J$kC&o-rmaEstXc1mZ~!RD0JT!`_4HU=xhd0S3j3^P6{XE z)7O>#9!MP|ku_QG`p**uBL&4qCHz2%`PaLRd zou`Xqh{pM=L55r{1_F0vrXR9fa;kaD=CkrSmzR0$o;pF?!{LMCKj$0#5hu2VYdG%M z-EmaZ{H~6*HM6zSQkL=$4YPmjeNd^^;o;(Y`ATW+LkE|RjJ0on*Ud{;(y|n|Xwi3W zXYH1Cs|}YuG2m(5x=p5bmfHKjiW7pw{N4#pOXXB#XsD=<=@DeuweIwknZ*eoKVI%w zG3C~_-kGacW!*M&7r4Lb;oj>}^TYL7>aQ#n_t@#)JG-a-KG5Y1p00i_>zopr0A#Oo AxBvhE literal 0 HcmV?d00001 diff --git a/plugins/wtsynth/tri_active.png b/plugins/wtsynth/tri_active.png new file mode 100644 index 0000000000000000000000000000000000000000..16b72849b221c93898b7a135cf68f3dba7ffb793 GIT binary patch literal 305 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61SBU+%rFB|oCO|{#S9GG!XV7ZFl&wkP>{XE z)7O>#9Z^Zxw#)6UNB^fX=NH4oq2-3{bcR#rxD%elER`S{)4 z<%O9EjVtDvWL`SbDXi%9{@&i;u&`t4&gJFhadC2W%l+qCnd<5Bt!kV*SGIqmfcl+X zrP&u3x$^Mv^vnOSphG+J$kC&o-rmaEstXc1mZ~!RD0JT!`_4HU=xhd0S3j3^P6{XE z)7O>#9!MP|ku_QG`p**uBL&4qCHz2%`PaLRd zou`Xqh{pM=L55r{1_F0vrXR9fa;kaD=CkrSmzR0$o;pF?!{LMCKj$0#5hu2VYdG%M z-EmaZ{H~6*HM6zSQkL=$4YPmjeNd^^;o;(Y`ATW+LkE|RjJ0on*Ud{;(y|n|Xwi3W zXYH1Cs|}YuG2m(5x=p5bmfHKjiW7pw{N4#pOXXB#XsD=<=@DeuweIwknZ*eoKVI%w zG3C~_-kGacW!*M&7r4Lb;oj>}^TYL7>aQ#n_t@#)JG-a-KG5Y1p00i_>zopr0A#Oo AxBvhE literal 0 HcmV?d00001 diff --git a/plugins/wtsynth/wavegraph.png b/plugins/wtsynth/wavegraph.png new file mode 100644 index 0000000000000000000000000000000000000000..66d9fdee3c592636342ce5fc950bde9120ba4c83 GIT binary patch literal 351 zcmeAS@N?(olHy`uVBq!ia0vp^4}dt6g9%8k`LJUdkm4-xh%9Dc;1&j9Muu5)B!GhK zC7!;n?Dv>O#5jcFKX|4Bg(OQ{BTAg}b8}PkN*J7rQWHy3QxwWGOEMJPJ$(bh8~Mb6 zif($kIEGZ*dV9%Gkb!~Yh(SW#|0=_S2PSyD*g9FH##AUFz(9kIwYkaBP(wllNF7`t zA;QxIq!I#nxY&*YDX@GJkRnPRWDGw2aCx9IZ02Li1C_Bh!|jL4KRm;vx|ZQv{LfF{ QfSzRVboFyt=akR{045G)G5`Po literal 0 HcmV?d00001 From da2a26572f796d777936eee2b5325727bd8c8991 Mon Sep 17 00:00:00 2001 From: Vesa Date: Fri, 21 Mar 2014 12:30:20 +0200 Subject: [PATCH 068/647] Changes --- plugins/wtsynth/CMakeLists.txt | 1 + plugins/wtsynth/WTSynth.cpp | 21 +++------------------ plugins/wtsynth/WTSynth.h | 33 +++++++++++++++++++++++---------- 3 files changed, 27 insertions(+), 28 deletions(-) diff --git a/plugins/wtsynth/CMakeLists.txt b/plugins/wtsynth/CMakeLists.txt index 82e03fcd9..71085901f 100644 --- a/plugins/wtsynth/CMakeLists.txt +++ b/plugins/wtsynth/CMakeLists.txt @@ -1,3 +1,4 @@ INCLUDE(BuildPlugin) BUILD_PLUGIN(wtsynth WTSynth.cpp WTSynth.h MOCFILES WTSynth.h EMBEDDED_RESOURCES ${CMAKE_CURRENT_SOURCE_DIR}/*.png) + diff --git a/plugins/wtsynth/WTSynth.cpp b/plugins/wtsynth/WTSynth.cpp index 85a9f8d6e..c343c56e3 100644 --- a/plugins/wtsynth/WTSynth.cpp +++ b/plugins/wtsynth/WTSynth.cpp @@ -24,7 +24,8 @@ #include #include -#include +#include +#include #include "WTSynth.h" #include "engine.h" @@ -36,14 +37,13 @@ #include "embed.h" - extern "C" { Plugin::Descriptor PLUGIN_EXPORT wtsynth_plugin_descriptor = { STRINGIFY( PLUGIN_NAME ), - "wtsynth", + "WTSynth", QT_TRANSLATE_NOOP( "pluginBrowser", "4-oscillator modulatable wavetable synth" ), "Vesa Kivimäki ", @@ -512,21 +512,6 @@ void WTSynthInstrument::updateTunes( int _osc ) } - - - - -#define makeknob( name, x, y, hint, unit, oname ) \ - name = new knob( knobBright_26, this); \ - name ->move( x, y ); \ - name ->setHintText( tr( hint ) + " ", unit ); \ - name ->setObjectName( oname ); - -#define A1ROW 25 -#define A2ROW 47 -#define B1ROW 69 -#define B2ROW 91 - WTSynthView::WTSynthView( Instrument * _instrument, QWidget * _parent ) : InstrumentView( _instrument, _parent ) diff --git a/plugins/wtsynth/WTSynth.h b/plugins/wtsynth/WTSynth.h index b53eb77c5..5512d1911 100644 --- a/plugins/wtsynth/WTSynth.h +++ b/plugins/wtsynth/WTSynth.h @@ -36,6 +36,18 @@ #include "pixmap_button.h" +#define makeknob( name, x, y, hint, unit, oname ) \ + name = new knob( knobBright_26, this); \ + name ->move( x, y ); \ + name ->setHintText( tr( hint ) + " ", unit ); \ + name ->setObjectName( oname ); + +#define A1ROW 25 +#define A2ROW 47 +#define B1ROW 69 +#define B2ROW 91 + + const int WAVELEN = 220; const int MOD_MIX = 0; @@ -50,8 +62,6 @@ const int B1_OSC = 2; const int B2_OSC = 3; const int NUM_OSCS = 4; -class WTSynthInstrument; -class WTSynthView; class WTSynthObject { @@ -86,12 +96,15 @@ private: const sample_rate_t m_samplerate; NotePlayHandle * m_nph; - + float m_lphase [NUM_OSCS]; float m_rphase [NUM_OSCS]; - + float m_lfreq [NUM_OSCS]; float m_rfreq [NUM_OSCS]; + + friend class WTSynthInstrument; + friend class WTSynthView; }; class WTSynthInstrument : public Instrument @@ -159,7 +172,7 @@ private: FloatModel a2_rtune; FloatModel b1_rtune; FloatModel b2_rtune; - + graphModel a1_graph; graphModel a2_graph; graphModel b1_graph; @@ -168,9 +181,9 @@ private: FloatModel m_abmix; IntModel m_amod; IntModel m_bmod; - + IntModel m_selectedGraph; - + bool m_volChanged [NUM_OSCS]; bool m_multChanged [NUM_OSCS]; bool m_tuneChanged [NUM_OSCS]; @@ -236,13 +249,11 @@ private: automatableButtonGroup * m_aModGroup; automatableButtonGroup * m_bModGroup; - static QPixmap * s_artwork; - graph * a1_graph; graph * a2_graph; graph * b1_graph; graph * b2_graph; - + pixmapButton * m_sinWaveButton; pixmapButton * m_triWaveButton; pixmapButton * m_sawWaveButton; @@ -253,6 +264,8 @@ private: pixmapButton * m_phaseLeftButton; pixmapButton * m_phaseRightButton; + friend class WTSynthInstrument; + }; #endif From 9b394b3660c2e96d8bfbf76d043d8a4b31b064f4 Mon Sep 17 00:00:00 2001 From: Vesa Date: Fri, 21 Mar 2014 16:33:34 +0200 Subject: [PATCH 069/647] Changes... now it seems to work --- data/themes/default/style.css | 6 ++ plugins/wtsynth/CMakeLists.txt | 3 +- plugins/wtsynth/WTSynth.cpp | 168 ++++++++++++++++++--------------- plugins/wtsynth/WTSynth.h | 31 +++--- 4 files changed, 114 insertions(+), 94 deletions(-) diff --git a/data/themes/default/style.css b/data/themes/default/style.css index 98437e2e7..5e6b6504a 100644 --- a/data/themes/default/style.css +++ b/data/themes/default/style.css @@ -613,6 +613,8 @@ WTSynthView knob#aKnob { qproperty-outerColor: rgb( 255, 255, 255 ); qproperty-innerRadius: 1; qproperty-outerRadius: 9; + qproperty-centerPointX: 9.5; + qproperty-centerPointY: 9.5; qproperty-lineWidth: 2; } @@ -621,6 +623,8 @@ WTSynthView knob#bKnob { qproperty-outerColor: rgb( 255, 255, 255 ); qproperty-innerRadius: 1; qproperty-outerRadius: 9; + qproperty-centerPointX: 9.5; + qproperty-centerPointY: 9.5; qproperty-lineWidth: 2; } @@ -629,6 +633,8 @@ WTSynthView knob#mixKnob { qproperty-outerColor: rgb( 255, 255, 255 ); qproperty-innerRadius: 1; qproperty-outerRadius: 15; + qproperty-centerPointX: 15.5; + qproperty-centerPointY: 15.5; qproperty-lineWidth: 2; } diff --git a/plugins/wtsynth/CMakeLists.txt b/plugins/wtsynth/CMakeLists.txt index 71085901f..eb50e0544 100644 --- a/plugins/wtsynth/CMakeLists.txt +++ b/plugins/wtsynth/CMakeLists.txt @@ -1,4 +1,3 @@ INCLUDE(BuildPlugin) -BUILD_PLUGIN(wtsynth WTSynth.cpp WTSynth.h MOCFILES WTSynth.h EMBEDDED_RESOURCES ${CMAKE_CURRENT_SOURCE_DIR}/*.png) - +BUILD_PLUGIN( wtsynth WTSynth.cpp WTSynth.h MOCFILES WTSynth.h EMBEDDED_RESOURCES ${CMAKE_CURRENT_SOURCE_DIR}/*.png) diff --git a/plugins/wtsynth/WTSynth.cpp b/plugins/wtsynth/WTSynth.cpp index c343c56e3..52adbc7b6 100644 --- a/plugins/wtsynth/WTSynth.cpp +++ b/plugins/wtsynth/WTSynth.cpp @@ -23,9 +23,6 @@ */ #include -#include -#include -#include #include "WTSynth.h" #include "engine.h" @@ -35,7 +32,7 @@ #include "song.h" #include "lmms_math.h" -#include "embed.h" +#include "embed.cpp" extern "C" { @@ -95,22 +92,26 @@ void WTSynthObject::renderOutput( sampleFrame * _abuf, sampleFrame * _bbuf, fpp_ // A2 frac = fraction( m_lphase[A2_OSC] ); - sample_t A2_L = ( m_A2wave[ int( m_lphase[A2_OSC] ) % WAVELEN ] * ( 1 - frac ) ) + - ( m_A2wave[ int( m_lphase[A2_OSC] + 1 ) % WAVELEN ] * frac ); + sample_t A2_L = + ( m_A2wave[ static_cast( m_lphase[A2_OSC] ) % WAVELEN ] * ( 1.0f - frac ) ) + + ( m_A2wave[ static_cast( m_lphase[A2_OSC] + 1 ) % WAVELEN ] * frac ); A2_L *= m_lvol[A2_OSC]; frac = fraction( m_rphase[A2_OSC] ); - sample_t A2_R = ( m_A2wave[ int( m_rphase[A2_OSC] ) % WAVELEN ] * ( 1 - frac ) ) + - ( m_A2wave[ int( m_rphase[A2_OSC] + 1 ) % WAVELEN ] * frac ); + sample_t A2_R = + ( m_A2wave[ static_cast( m_rphase[A2_OSC] ) % WAVELEN ] * ( 1.0f - frac ) ) + + ( m_A2wave[ static_cast( m_rphase[A2_OSC] + 1 ) % WAVELEN ] * frac ); A2_R *= m_rvol[A2_OSC]; // B2 frac = fraction( m_lphase[B2_OSC] ); - sample_t B2_L = ( m_A2wave[ int( m_lphase[B2_OSC] ) % WAVELEN ] * ( 1 - frac ) ) + - ( m_B2wave[ int( m_lphase[B2_OSC] + 1 ) % WAVELEN ] * frac ); + sample_t B2_L = + ( m_A2wave[ static_cast( m_lphase[B2_OSC] ) % WAVELEN ] * ( 1.0f - frac ) ) + + ( m_B2wave[ static_cast( m_lphase[B2_OSC] + 1 ) % WAVELEN ] * frac ); B2_L *= m_lvol[B2_OSC]; frac = fraction( m_rphase[B2_OSC] ); - sample_t B2_R = ( m_A2wave[ int( m_rphase[B2_OSC] ) % WAVELEN ] * ( 1 - frac ) ) + - ( m_A2wave[ int( m_rphase[B2_OSC] + 1 ) % WAVELEN ] * frac ); + sample_t B2_R = + ( m_A2wave[ static_cast( m_rphase[B2_OSC] ) % WAVELEN ] * ( 1.0f - frac ) ) + + ( m_A2wave[ static_cast( m_rphase[B2_OSC] + 1 ) % WAVELEN ] * frac ); B2_R *= m_rvol[B2_OSC]; // put phases of 1-series oscs into variables because phase modulation might happen @@ -133,19 +134,23 @@ void WTSynthObject::renderOutput( sampleFrame * _abuf, sampleFrame * _bbuf, fpp_ // A1 frac = fraction( A1_lphase ); - sample_t A1_L = ( m_A1wave[ int( A1_lphase ) % WAVELEN ] * ( 1 - frac ) ) + - ( m_A1wave[ int( A1_lphase + 1 ) % WAVELEN ] * frac ); + sample_t A1_L = + ( m_A1wave[ static_cast( A1_lphase ) % WAVELEN ] * ( 1.0f - frac ) ) + + ( m_A1wave[ static_cast( A1_lphase + 1 ) % WAVELEN ] * frac ); frac = fraction( A1_rphase ); - sample_t A1_R = ( m_A1wave[ int( A1_rphase ) % WAVELEN ] * ( 1 - frac ) ) + - ( m_A1wave[ int( A1_rphase + 1 ) % WAVELEN ] * frac ); + sample_t A1_R = + ( m_A1wave[ static_cast( A1_rphase ) % WAVELEN ] * ( 1.0f - frac ) ) + + ( m_A1wave[ static_cast( A1_rphase + 1 ) % WAVELEN ] * frac ); // B1 frac = fraction( B1_lphase ); - sample_t B1_L = ( m_B1wave[ int( B1_lphase ) % WAVELEN ] * ( 1 - frac ) ) + - ( m_B1wave[ int( B1_lphase + 1 ) % WAVELEN ] * frac ); + sample_t B1_L = + ( m_B1wave[ static_cast( B1_lphase ) % WAVELEN ] * ( 1.0f - frac ) ) + + ( m_B1wave[ static_cast( B1_lphase + 1 ) % WAVELEN ] * frac ); frac = fraction( B1_rphase ); - sample_t B1_R = ( m_B1wave[ int( B1_rphase ) % WAVELEN ] * ( 1 - frac ) ) + - ( m_B1wave[ int( B1_rphase + 1 ) % WAVELEN ] * frac ); + sample_t B1_R = + ( m_B1wave[ static_cast( B1_rphase ) % WAVELEN ] * ( 1.0f - frac ) ) + + ( m_B1wave[ static_cast( B1_rphase + 1 ) % WAVELEN ] * frac ); // A-series modulation (other than phase mod) switch( m_amod ) @@ -164,7 +169,7 @@ void WTSynthObject::renderOutput( sampleFrame * _abuf, sampleFrame * _bbuf, fpp_ break; } _abuf[frame][0] = A1_L * m_lvol[A1_OSC]; - _abuf[frame][1] = A1_R * m_rvol[B1_OSC]; + _abuf[frame][1] = A1_R * m_rvol[A1_OSC]; // B-series modulation (other than phase mod) switch( m_bmod ) @@ -182,8 +187,8 @@ void WTSynthObject::renderOutput( sampleFrame * _abuf, sampleFrame * _bbuf, fpp_ B1_R *= B2_R; break; } - _bbuf[frame][0] = B1_L; - _bbuf[frame][1] = B1_R; + _bbuf[frame][0] = B1_L * m_lvol[B1_OSC]; + _bbuf[frame][1] = B1_R * m_rvol[B1_OSC]; // update phases for( int i = 0; i < NUM_OSCS; i++ ) @@ -212,15 +217,15 @@ void WTSynthObject::updateFrequencies() void WTSynthObject::changeVolume( int _osc, float _lvol, float _rvol ) { - m_lvol[_osc] = _lvol; - m_rvol[_osc] = _rvol; + m_lvol[_osc] = _lvol / 100.0; + m_rvol[_osc] = _rvol / 100.0; + qDebug( "osc %d vol %f %f", _osc, m_lvol[_osc], m_rvol[_osc] ); } -void WTSynthObject::changeMult( int _osc, int _mul ) +void WTSynthObject::changeMult( int _osc, float _mul ) { m_mult[_osc] = _mul; - updateFrequencies(); } @@ -228,7 +233,6 @@ void WTSynthObject::changeTune( int _osc, float _ltune, float _rtune ) { m_ltune[_osc] = _ltune; m_rtune[_osc] = _rtune; - updateFrequencies(); } @@ -246,10 +250,10 @@ WTSynthInstrument::WTSynthInstrument( InstrumentTrack * _instrument_track ) : b1_pan( 0.0f, -100.0f, 100.0f, 0.1f, this, tr( "Panning B1" ) ), b2_pan( 0.0f, -100.0f, 100.0f, 0.1f, this, tr( "Panning B2" ) ), - a1_mult( 8, 1, 16, this, tr( "Freq. multiplier A1" ) ), - a2_mult( 8, 1, 16, this, tr( "Freq. multiplier A2" ) ), - b1_mult( 8, 1, 16, this, tr( "Freq. multiplier B1" ) ), - b2_mult( 8, 1, 16, this, tr( "Freq. multiplier B2" ) ), + a1_mult( 8.0f, 1.0, 16.0, 1.0, this, tr( "Freq. multiplier A1" ) ), + a2_mult( 8.0f, 1.0, 16.0, 1.0, this, tr( "Freq. multiplier A2" ) ), + b1_mult( 8.0f, 1.0, 16.0, 1.0, this, tr( "Freq. multiplier B1" ) ), + b2_mult( 8.0f, 1.0, 16.0, 1.0, this, tr( "Freq. multiplier B2" ) ), a1_ltune( 0.0f, -600.0f, 600.0f, 1.0f, this, tr( "Left detune A1" ) ), a2_ltune( 0.0f, -600.0f, 600.0f, 1.0f, this, tr( "Left detune A2" ) ), @@ -272,30 +276,30 @@ WTSynthInstrument::WTSynthInstrument( InstrumentTrack * _instrument_track ) : m_selectedGraph( 0, 0, 3, this, tr( "Selected graph" ) ) { - connect( &a1_vol, SIGNAL( dataChanged() ), this, SLOT( updateVolumes( A1_OSC ) ) ); - connect( &a2_vol, SIGNAL( dataChanged() ), this, SLOT( updateVolumes( A2_OSC ) ) ); - connect( &b1_vol, SIGNAL( dataChanged() ), this, SLOT( updateVolumes( B1_OSC ) ) ); - connect( &b2_vol, SIGNAL( dataChanged() ), this, SLOT( updateVolumes( B2_OSC ) ) ); + connect( &a1_vol, SIGNAL( dataChanged() ), this, SLOT( updateVolumes() ) ); + connect( &a2_vol, SIGNAL( dataChanged() ), this, SLOT( updateVolumes() ) ); + connect( &b1_vol, SIGNAL( dataChanged() ), this, SLOT( updateVolumes() ) ); + connect( &b2_vol, SIGNAL( dataChanged() ), this, SLOT( updateVolumes() ) ); - connect( &a1_pan, SIGNAL( dataChanged() ), this, SLOT( updateVolumes( A1_OSC ) ) ); - connect( &a2_pan, SIGNAL( dataChanged() ), this, SLOT( updateVolumes( A2_OSC ) ) ); - connect( &b1_pan, SIGNAL( dataChanged() ), this, SLOT( updateVolumes( B1_OSC ) ) ); - connect( &b2_pan, SIGNAL( dataChanged() ), this, SLOT( updateVolumes( B2_OSC ) ) ); + connect( &a1_pan, SIGNAL( dataChanged() ), this, SLOT( updateVolumes() ) ); + connect( &a2_pan, SIGNAL( dataChanged() ), this, SLOT( updateVolumes() ) ); + connect( &b1_pan, SIGNAL( dataChanged() ), this, SLOT( updateVolumes() ) ); + connect( &b2_pan, SIGNAL( dataChanged() ), this, SLOT( updateVolumes() ) ); - connect( &a1_mult, SIGNAL( dataChanged() ), this, SLOT( updateMult( A1_OSC ) ) ); - connect( &a2_mult, SIGNAL( dataChanged() ), this, SLOT( updateMult( A2_OSC ) ) ); - connect( &b1_mult, SIGNAL( dataChanged() ), this, SLOT( updateMult( B1_OSC ) ) ); - connect( &b2_mult, SIGNAL( dataChanged() ), this, SLOT( updateMult( B2_OSC ) ) ); + connect( &a1_mult, SIGNAL( dataChanged() ), this, SLOT( updateMult() ) ); + connect( &a2_mult, SIGNAL( dataChanged() ), this, SLOT( updateMult() ) ); + connect( &b1_mult, SIGNAL( dataChanged() ), this, SLOT( updateMult() ) ); + connect( &b2_mult, SIGNAL( dataChanged() ), this, SLOT( updateMult() ) ); - connect( &a1_ltune, SIGNAL( dataChanged() ), this, SLOT( updateTunes( A1_OSC ) ) ); - connect( &a2_ltune, SIGNAL( dataChanged() ), this, SLOT( updateTunes( A2_OSC ) ) ); - connect( &b1_ltune, SIGNAL( dataChanged() ), this, SLOT( updateTunes( B1_OSC ) ) ); - connect( &b2_ltune, SIGNAL( dataChanged() ), this, SLOT( updateTunes( B2_OSC ) ) ); + connect( &a1_ltune, SIGNAL( dataChanged() ), this, SLOT( updateTunes() ) ); + connect( &a2_ltune, SIGNAL( dataChanged() ), this, SLOT( updateTunes() ) ); + connect( &b1_ltune, SIGNAL( dataChanged() ), this, SLOT( updateTunes() ) ); + connect( &b2_ltune, SIGNAL( dataChanged() ), this, SLOT( updateTunes() ) ); - connect( &a1_rtune, SIGNAL( dataChanged() ), this, SLOT( updateTunes( A1_OSC ) ) ); - connect( &a2_rtune, SIGNAL( dataChanged() ), this, SLOT( updateTunes( A2_OSC ) ) ); - connect( &b1_rtune, SIGNAL( dataChanged() ), this, SLOT( updateTunes( B1_OSC ) ) ); - connect( &b2_rtune, SIGNAL( dataChanged() ), this, SLOT( updateTunes( B2_OSC ) ) ); + connect( &a1_rtune, SIGNAL( dataChanged() ), this, SLOT( updateTunes() ) ); + connect( &a2_rtune, SIGNAL( dataChanged() ), this, SLOT( updateTunes() ) ); + connect( &b1_rtune, SIGNAL( dataChanged() ), this, SLOT( updateTunes() ) ); + connect( &b2_rtune, SIGNAL( dataChanged() ), this, SLOT( updateTunes() ) ); a1_graph.setWaveToSine(); a2_graph.setWaveToSine(); @@ -345,21 +349,30 @@ void WTSynthInstrument::playNote( NotePlayHandle * _n, // update oscs if needed - if( m_volChanged[A1_OSC] ) w-> changeVolume( A1_OSC, leftCh( a1_vol.value(), a1_pan.value() ), rightCh( a1_vol.value(), a1_pan.value() ) ); - if( m_volChanged[A2_OSC] ) w-> changeVolume( A2_OSC, leftCh( a2_vol.value(), a2_pan.value() ), rightCh( a2_vol.value(), a2_pan.value() ) ); - if( m_volChanged[B1_OSC] ) w-> changeVolume( B1_OSC, leftCh( b1_vol.value(), b1_pan.value() ), rightCh( b1_vol.value(), b1_pan.value() ) ); - if( m_volChanged[B2_OSC] ) w-> changeVolume( B2_OSC, leftCh( b2_vol.value(), b2_pan.value() ), rightCh( b2_vol.value(), b2_pan.value() ) ); - - if( m_tuneChanged[A1_OSC] ) w-> changeTune( A1_OSC, a1_ltune.value(), a1_rtune.value() ); - if( m_tuneChanged[A2_OSC] ) w-> changeTune( A2_OSC, a2_ltune.value(), a2_rtune.value() ); - if( m_tuneChanged[B1_OSC] ) w-> changeTune( B1_OSC, b1_ltune.value(), b1_rtune.value() ); - if( m_tuneChanged[B2_OSC] ) w-> changeTune( B2_OSC, b2_ltune.value(), b2_rtune.value() ); - - if( m_multChanged[A1_OSC] ) w-> changeMult( A1_OSC, a1_mult.value() ); - if( m_multChanged[A2_OSC] ) w-> changeMult( A2_OSC, a2_mult.value() ); - if( m_multChanged[B1_OSC] ) w-> changeMult( B1_OSC, b1_mult.value() ); - if( m_multChanged[B2_OSC] ) w-> changeMult( B2_OSC, b2_mult.value() ); - + if( m_volChanged ) + { + w-> changeVolume( A1_OSC, leftCh( a1_vol.value(), a1_pan.value() ), rightCh( a1_vol.value(), a1_pan.value() ) ); + w-> changeVolume( A2_OSC, leftCh( a2_vol.value(), a2_pan.value() ), rightCh( a2_vol.value(), a2_pan.value() ) ); + w-> changeVolume( B1_OSC, leftCh( b1_vol.value(), b1_pan.value() ), rightCh( b1_vol.value(), b1_pan.value() ) ); + w-> changeVolume( B2_OSC, leftCh( b2_vol.value(), b2_pan.value() ), rightCh( b2_vol.value(), b2_pan.value() ) ); + } + if( m_tuneChanged ) + { + w-> changeTune( A1_OSC, a1_ltune.value(), a1_rtune.value() ); + w-> changeTune( A2_OSC, a2_ltune.value(), a2_rtune.value() ); + w-> changeTune( B1_OSC, b1_ltune.value(), b1_rtune.value() ); + w-> changeTune( B2_OSC, b2_ltune.value(), b2_rtune.value() ); + w-> updateFrequencies(); + } + if( m_multChanged ) + { + w-> changeMult( A1_OSC, a1_mult.value() ); + w-> changeMult( A2_OSC, a2_mult.value() ); + w-> changeMult( B1_OSC, b1_mult.value() ); + w-> changeMult( B2_OSC, b2_mult.value() ); + w-> updateFrequencies(); + } + sampleFrame * abuf = new sampleFrame[frames]; sampleFrame * bbuf = new sampleFrame[frames]; @@ -498,17 +511,17 @@ PluginView * WTSynthInstrument::instantiateView( QWidget * _parent ) } -void WTSynthInstrument::updateVolumes( int _osc ) +void WTSynthInstrument::updateVolumes() { - m_volChanged[_osc] = true; + m_volChanged = true; } -void WTSynthInstrument::updateMult( int _osc ) +void WTSynthInstrument::updateMult() { - m_multChanged[_osc] = true; + m_multChanged = true; } -void WTSynthInstrument::updateTunes( int _osc ) +void WTSynthInstrument::updateTunes() { - m_tuneChanged[_osc] = true; + m_tuneChanged = true; } @@ -519,8 +532,7 @@ WTSynthView::WTSynthView( Instrument * _instrument, setAutoFillBackground( true ); QPalette pal; - pal.setBrush( backgroundRole(), - PLUGIN_NAME::getIconPixmap( "artwork" ) ); + pal.setBrush( backgroundRole(), PLUGIN_NAME::getIconPixmap( "artwork" ) ); setPalette( pal ); // knobs... lots of em @@ -558,6 +570,8 @@ WTSynthView::WTSynthView( Instrument * _instrument, b1_volKnob -> setVolumeKnob( true ); b2_volKnob -> setVolumeKnob( true ); + m_abmixKnob -> setFixedSize( 31, 31 ); + // button groups next. // graph select buttons @@ -611,7 +625,7 @@ WTSynthView::WTSynthView( Instrument * _instrument, toolTip::add( amod_rmButton, tr( "Ring-modulate A1 and A2" ) ); pixmapButton * amod_pmButton = new pixmapButton( this, NULL ); - amod_pmButton -> move( 4, 104 ); + amod_pmButton -> move( 4, 88 ); amod_pmButton -> setActiveGraphic( PLUGIN_NAME::getIconPixmap( "pm_active" ) ); amod_pmButton -> setInactiveGraphic( PLUGIN_NAME::getIconPixmap( "pm_inactive" ) ); toolTip::add( amod_pmButton, tr( "Modulate phase of A1 with output of A2" ) ); @@ -642,7 +656,7 @@ WTSynthView::WTSynthView( Instrument * _instrument, toolTip::add( bmod_rmButton, tr( "Ring-modulate B1 and B2" ) ); pixmapButton * bmod_pmButton = new pixmapButton( this, NULL ); - bmod_pmButton -> move( 44, 104 ); + bmod_pmButton -> move( 44, 88 ); bmod_pmButton -> setActiveGraphic( PLUGIN_NAME::getIconPixmap( "pm_active" ) ); bmod_pmButton -> setInactiveGraphic( PLUGIN_NAME::getIconPixmap( "pm_inactive" ) ); toolTip::add( bmod_pmButton, tr( "Modulate phase of B1 with output of B2" ) ); diff --git a/plugins/wtsynth/WTSynth.h b/plugins/wtsynth/WTSynth.h index 5512d1911..428969c2c 100644 --- a/plugins/wtsynth/WTSynth.h +++ b/plugins/wtsynth/WTSynth.h @@ -37,10 +37,11 @@ #define makeknob( name, x, y, hint, unit, oname ) \ - name = new knob( knobBright_26, this); \ + name = new knob( knobStyled, this); \ name ->move( x, y ); \ name ->setHintText( tr( hint ) + " ", unit ); \ - name ->setObjectName( oname ); + name ->setObjectName( oname ); \ + name ->setFixedSize( 19, 19 ); #define A1ROW 25 #define A2ROW 47 @@ -76,7 +77,7 @@ public: void updateFrequencies(); void changeVolume( int _osc, float _lvol, float _rvol ); - void changeMult( int _osc, int _mul ); + void changeMult( int _osc, float _mul ); void changeTune( int _osc, float _ltune, float _rtune ); private: @@ -87,7 +88,7 @@ private: float m_lvol [NUM_OSCS]; float m_rvol [NUM_OSCS]; - int m_mult [NUM_OSCS]; + float m_mult [NUM_OSCS]; float m_ltune [NUM_OSCS]; float m_rtune [NUM_OSCS]; @@ -132,10 +133,10 @@ public: virtual PluginView * instantiateView( QWidget * _parent ); -protected slots: - void updateVolumes( int _osc ); - void updateMult( int _osc ); - void updateTunes( int _osc ); +public slots: + void updateVolumes(); + void updateMult(); + void updateTunes(); private: inline float leftCh( float _vol, float _pan ) @@ -158,10 +159,10 @@ private: FloatModel b1_pan; FloatModel b2_pan; - IntModel a1_mult; - IntModel a2_mult; - IntModel b1_mult; - IntModel b2_mult; + FloatModel a1_mult; + FloatModel a2_mult; + FloatModel b1_mult; + FloatModel b2_mult; FloatModel a1_ltune; FloatModel a2_ltune; @@ -184,9 +185,9 @@ private: IntModel m_selectedGraph; - bool m_volChanged [NUM_OSCS]; - bool m_multChanged [NUM_OSCS]; - bool m_tuneChanged [NUM_OSCS]; + bool m_volChanged; + bool m_multChanged; + bool m_tuneChanged; friend class WTSynthView; }; From 95bf833aceda0976d85e85a9d302c4ec2e285393 Mon Sep 17 00:00:00 2001 From: Vesa Date: Fri, 21 Mar 2014 17:21:31 +0200 Subject: [PATCH 070/647] Updates, fixes etc --- plugins/wtsynth/WTSynth.cpp | 84 +++++++++++++++++++++---------------- plugins/wtsynth/WTSynth.h | 1 + src/gui/widgets/graph.cpp | 6 ++- 3 files changed, 53 insertions(+), 38 deletions(-) diff --git a/plugins/wtsynth/WTSynth.cpp b/plugins/wtsynth/WTSynth.cpp index 52adbc7b6..63bfb3dbb 100644 --- a/plugins/wtsynth/WTSynth.cpp +++ b/plugins/wtsynth/WTSynth.cpp @@ -123,13 +123,13 @@ void WTSynthObject::renderOutput( sampleFrame * _abuf, sampleFrame * _bbuf, fpp_ // if phase mod, add to phases if( m_amod == MOD_PM ) { - A1_lphase = fmodf( A1_lphase + A2_L * WAVELEN, WAVELEN ); - A1_rphase = fmodf( A1_rphase + A2_R * WAVELEN, WAVELEN ); + A1_lphase = fmodf( A1_lphase + A2_L * PMOD_AMT, WAVELEN ); + A1_rphase = fmodf( A1_rphase + A2_R * PMOD_AMT, WAVELEN ); } if( m_bmod == MOD_PM ) { - B1_lphase = fmodf( B1_lphase + B2_L * WAVELEN, WAVELEN ); - B1_rphase = fmodf( B1_rphase + B2_R * WAVELEN, WAVELEN ); + B1_lphase = fmodf( B1_lphase + B2_L * PMOD_AMT, WAVELEN ); + B1_rphase = fmodf( B1_rphase + B2_R * PMOD_AMT, WAVELEN ); } // A1 @@ -179,8 +179,8 @@ void WTSynthObject::renderOutput( sampleFrame * _abuf, sampleFrame * _bbuf, fpp_ B1_R += B2_R; break; case MOD_AM: - B1_L *= qAbs( B2_L + 1.0f ); - B1_R *= qAbs( B2_R + 1.0f ); + B1_L *= qMax( 0.0f, B2_L + 1.0f ); + B1_R *= qMax( 0.0f, B2_R + 1.0f ); break; case MOD_RM: B1_L *= B2_L; @@ -339,6 +339,8 @@ void WTSynthInstrument::playNote( NotePlayHandle * _n, w -> changeVolume( A2_OSC, leftCh( a2_vol.value(), a2_pan.value() ), rightCh( a2_vol.value(), a2_pan.value() ) ); w -> changeVolume( B1_OSC, leftCh( b1_vol.value(), b1_pan.value() ), rightCh( b1_vol.value(), b1_pan.value() ) ); w -> changeVolume( B2_OSC, leftCh( b2_vol.value(), b2_pan.value() ), rightCh( b2_vol.value(), b2_pan.value() ) ); + + w -> updateFrequencies(); _n->m_pluginData = w; } @@ -705,20 +707,55 @@ WTSynthView::WTSynthView( Instrument * _instrument, // misc pushbuttons +// waveform modifications + + m_phaseLeftButton = new pixmapButton( this, tr( "Phase left" ) ); + m_phaseLeftButton -> move ( 200, 121 ); + m_phaseLeftButton -> setActiveGraphic( PLUGIN_NAME::getIconPixmap( "phl_active" ) ); + m_phaseLeftButton -> setInactiveGraphic( PLUGIN_NAME::getIconPixmap( "phl_inactive" ) ); + toolTip::add( m_phaseLeftButton, tr( "Click to shift phase by -15 degrees" ) ); + + m_phaseRightButton = new pixmapButton( this, tr( "Phase right" ) ); + m_phaseRightButton -> move ( 216, 121 ); + m_phaseRightButton -> setActiveGraphic( PLUGIN_NAME::getIconPixmap( "phr_active" ) ); + m_phaseRightButton -> setInactiveGraphic( PLUGIN_NAME::getIconPixmap( "phr_inactive" ) ); + toolTip::add( m_phaseRightButton, tr( "Click to shift phase by +15 degrees" ) ); + + m_normalizeButton = new pixmapButton( this, tr( "Normalize" ) ); + m_normalizeButton -> move ( 232, 121 ); + m_normalizeButton -> setActiveGraphic( PLUGIN_NAME::getIconPixmap( "norm_active" ) ); + m_normalizeButton -> setInactiveGraphic( PLUGIN_NAME::getIconPixmap( "norm_inactive" ) ); + toolTip::add( m_normalizeButton, tr( "Click to normalize" ) ); + + + m_invertButton = new pixmapButton( this, tr( "Invert" ) ); + m_invertButton -> move ( 232, 138 ); + m_invertButton -> setActiveGraphic( PLUGIN_NAME::getIconPixmap( "inv_active" ) ); + m_invertButton -> setInactiveGraphic( PLUGIN_NAME::getIconPixmap( "inv_inactive" ) ); + toolTip::add( m_invertButton, tr( "Click to invert" ) ); + + m_smoothButton = new pixmapButton( this, tr( "Smooth" ) ); + m_smoothButton -> move ( 232, 155 ); + m_smoothButton -> setActiveGraphic( PLUGIN_NAME::getIconPixmap( "smooth_active" ) ); + m_smoothButton -> setInactiveGraphic( PLUGIN_NAME::getIconPixmap( "smooth_inactive" ) ); + toolTip::add( m_smoothButton, tr( "Click to smooth" ) ); + +// waveforms + m_sinWaveButton = new pixmapButton( this, tr( "Sine wave" ) ); - m_sinWaveButton -> move ( 232, 182 ); + m_sinWaveButton -> move ( 232, 176 ); m_sinWaveButton -> setActiveGraphic( PLUGIN_NAME::getIconPixmap( "sin_active" ) ); m_sinWaveButton -> setInactiveGraphic( PLUGIN_NAME::getIconPixmap( "sin_inactive" ) ); toolTip::add( m_sinWaveButton, tr( "Click for sine wave" ) ); m_triWaveButton = new pixmapButton( this, tr( "Triangle wave" ) ); - m_triWaveButton -> move ( 232, 198 ); + m_triWaveButton -> move ( 232, 194 ); m_triWaveButton -> setActiveGraphic( PLUGIN_NAME::getIconPixmap( "tri_active" ) ); m_triWaveButton -> setInactiveGraphic( PLUGIN_NAME::getIconPixmap( "tri_inactive" ) ); toolTip::add( m_triWaveButton, tr( "Click for triangle wave" ) ); m_sawWaveButton = new pixmapButton( this, tr( "Triangle wave" ) ); - m_sawWaveButton -> move ( 232, 214 ); + m_sawWaveButton -> move ( 232, 212 ); m_sawWaveButton -> setActiveGraphic( PLUGIN_NAME::getIconPixmap( "saw_active" ) ); m_sawWaveButton -> setInactiveGraphic( PLUGIN_NAME::getIconPixmap( "saw_inactive" ) ); toolTip::add( m_sawWaveButton, tr( "Click for saw wave" ) ); @@ -729,35 +766,7 @@ WTSynthView::WTSynthView( Instrument * _instrument, m_sqrWaveButton -> setInactiveGraphic( PLUGIN_NAME::getIconPixmap( "sqr_inactive" ) ); toolTip::add( m_sqrWaveButton, tr( "Click for square wave" ) ); - m_normalizeButton = new pixmapButton( this, tr( "Normalize" ) ); - m_normalizeButton -> move ( 232, 134 ); - m_normalizeButton -> setActiveGraphic( PLUGIN_NAME::getIconPixmap( "norm_active" ) ); - m_normalizeButton -> setInactiveGraphic( PLUGIN_NAME::getIconPixmap( "norm_inactive" ) ); - toolTip::add( m_normalizeButton, tr( "Click to normalize" ) ); - m_invertButton = new pixmapButton( this, tr( "Invert" ) ); - m_invertButton -> move ( 232, 150 ); - m_invertButton -> setActiveGraphic( PLUGIN_NAME::getIconPixmap( "inv_active" ) ); - m_invertButton -> setInactiveGraphic( PLUGIN_NAME::getIconPixmap( "inv_inactive" ) ); - toolTip::add( m_invertButton, tr( "Click to invert" ) ); - - m_smoothButton = new pixmapButton( this, tr( "Smooth" ) ); - m_smoothButton -> move ( 232, 166 ); - m_smoothButton -> setActiveGraphic( PLUGIN_NAME::getIconPixmap( "smooth_active" ) ); - m_smoothButton -> setInactiveGraphic( PLUGIN_NAME::getIconPixmap( "smooth_inactive" ) ); - toolTip::add( m_smoothButton, tr( "Click to smooth" ) ); - - m_phaseLeftButton = new pixmapButton( this, tr( "Phase left" ) ); - m_phaseLeftButton -> move ( 200, 134 ); - m_phaseLeftButton -> setActiveGraphic( PLUGIN_NAME::getIconPixmap( "phl_active" ) ); - m_phaseLeftButton -> setInactiveGraphic( PLUGIN_NAME::getIconPixmap( "phl_inactive" ) ); - toolTip::add( m_phaseLeftButton, tr( "Click to shift phase by -15 degrees" ) ); - - m_phaseRightButton = new pixmapButton( this, tr( "Phase right" ) ); - m_phaseRightButton -> move ( 216, 134 ); - m_phaseRightButton -> setActiveGraphic( PLUGIN_NAME::getIconPixmap( "phr_active" ) ); - m_phaseRightButton -> setInactiveGraphic( PLUGIN_NAME::getIconPixmap( "phr_inactive" ) ); - toolTip::add( m_phaseRightButton, tr( "Click to shift phase by +15 degrees" ) ); connect( m_sinWaveButton, SIGNAL( clicked() ), this, SLOT( sinWaveClicked() ) ); connect( m_triWaveButton, SIGNAL( clicked() ), this, SLOT( triWaveClicked() ) ); @@ -765,6 +774,7 @@ WTSynthView::WTSynthView( Instrument * _instrument, connect( m_sqrWaveButton, SIGNAL( clicked() ), this, SLOT( sqrWaveClicked() ) ); connect( m_normalizeButton, SIGNAL( clicked() ), this, SLOT( normalizeClicked() ) ); connect( m_invertButton, SIGNAL( clicked() ), this, SLOT( invertClicked() ) ); + connect( m_smoothButton, SIGNAL( clicked() ), this, SLOT( smoothClicked() ) ); connect( m_phaseLeftButton, SIGNAL( clicked() ), this, SLOT( phaseLeftClicked() ) ); connect( m_phaseRightButton, SIGNAL( clicked() ), this, SLOT( phaseRightClicked() ) ); diff --git a/plugins/wtsynth/WTSynth.h b/plugins/wtsynth/WTSynth.h index 428969c2c..181576aba 100644 --- a/plugins/wtsynth/WTSynth.h +++ b/plugins/wtsynth/WTSynth.h @@ -50,6 +50,7 @@ const int WAVELEN = 220; +const int PMOD_AMT = 110; const int MOD_MIX = 0; const int MOD_AM = 1; diff --git a/src/gui/widgets/graph.cpp b/src/gui/widgets/graph.cpp index a7011537c..fbf3b5a43 100644 --- a/src/gui/widgets/graph.cpp +++ b/src/gui/widgets/graph.cpp @@ -679,7 +679,11 @@ void graphModel::shiftPhase( int _deg ) // shift phase for( int i = 0; i < length(); i++ ) - m_samples[i] = temp[ ( i + offset ) % length() ]; + { + int o = ( i + offset ) % length(); + while( o < 0 ) o += length(); + m_samples[i] = temp[o]; + } emit samplesChanged( 0, length()-1 ); } From 42e44b739f50f78980655c411f2389db55f926e2 Mon Sep 17 00:00:00 2001 From: Vesa Date: Fri, 21 Mar 2014 18:05:24 +0200 Subject: [PATCH 071/647] Fixed multiplier weirdness --- plugins/wtsynth/WTSynth.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/plugins/wtsynth/WTSynth.cpp b/plugins/wtsynth/WTSynth.cpp index 63bfb3dbb..a710c6956 100644 --- a/plugins/wtsynth/WTSynth.cpp +++ b/plugins/wtsynth/WTSynth.cpp @@ -74,7 +74,6 @@ WTSynthObject::WTSynthObject( float * _A1wave, float * _A2wave, m_rphase[A2_OSC] = 0.0f; m_rphase[B1_OSC] = 0.0f; m_rphase[B2_OSC] = 0.0f; - updateFrequencies(); } @@ -357,6 +356,7 @@ void WTSynthInstrument::playNote( NotePlayHandle * _n, w-> changeVolume( A2_OSC, leftCh( a2_vol.value(), a2_pan.value() ), rightCh( a2_vol.value(), a2_pan.value() ) ); w-> changeVolume( B1_OSC, leftCh( b1_vol.value(), b1_pan.value() ), rightCh( b1_vol.value(), b1_pan.value() ) ); w-> changeVolume( B2_OSC, leftCh( b2_vol.value(), b2_pan.value() ), rightCh( b2_vol.value(), b2_pan.value() ) ); + m_volChanged = false; } if( m_tuneChanged ) { @@ -365,6 +365,7 @@ void WTSynthInstrument::playNote( NotePlayHandle * _n, w-> changeTune( B1_OSC, b1_ltune.value(), b1_rtune.value() ); w-> changeTune( B2_OSC, b2_ltune.value(), b2_rtune.value() ); w-> updateFrequencies(); + m_tuneChanged = false; } if( m_multChanged ) { @@ -373,6 +374,7 @@ void WTSynthInstrument::playNote( NotePlayHandle * _n, w-> changeMult( B1_OSC, b1_mult.value() ); w-> changeMult( B2_OSC, b2_mult.value() ); w-> updateFrequencies(); + m_multChanged = false; } sampleFrame * abuf = new sampleFrame[frames]; @@ -380,10 +382,11 @@ void WTSynthInstrument::playNote( NotePlayHandle * _n, sampleFrame * bbuf = new sampleFrame[frames]; w-> renderOutput( abuf, bbuf, frames ); + + const float bmix = ( ( m_abmix.value() + 100.0 ) / 200.0 ); + const float amix = 1.0 - bmix; for( fpp_t f=0; f < frames; f++ ) { - const float amix = ( ( m_abmix.value( f ) - 100.0 ) / -200.0 ); - const float bmix = 1.0 - amix; _working_buffer[f][0] = ( abuf[f][0] * amix ) + ( bbuf[f][0] * bmix ); _working_buffer[f][1] = ( abuf[f][1] * amix ) + From d8d9ac21cdf2e7437d57bab5d4b155780491d974 Mon Sep 17 00:00:00 2001 From: Vesa Date: Fri, 21 Mar 2014 18:33:29 +0200 Subject: [PATCH 072/647] Move stream buffers to the synth object --- plugins/wtsynth/WTSynth.cpp | 32 ++++++++++++++++++-------------- plugins/wtsynth/WTSynth.h | 24 +++++++++++++++++------- 2 files changed, 35 insertions(+), 21 deletions(-) diff --git a/plugins/wtsynth/WTSynth.cpp b/plugins/wtsynth/WTSynth.cpp index a710c6956..98ba989d8 100644 --- a/plugins/wtsynth/WTSynth.cpp +++ b/plugins/wtsynth/WTSynth.cpp @@ -56,7 +56,7 @@ Plugin::Descriptor PLUGIN_EXPORT wtsynth_plugin_descriptor = WTSynthObject::WTSynthObject( float * _A1wave, float * _A2wave, float * _B1wave, float * _B2wave, - int _amod, int _bmod, const sample_rate_t _samplerate, NotePlayHandle * _nph ) : + int _amod, int _bmod, const sample_rate_t _samplerate, NotePlayHandle * _nph, fpp_t _frames ) : m_A1wave( _A1wave ), m_A2wave( _A2wave ), m_B1wave( _B1wave ), @@ -64,8 +64,12 @@ WTSynthObject::WTSynthObject( float * _A1wave, float * _A2wave, m_amod( _amod ), m_bmod( _bmod ), m_samplerate( _samplerate ), - m_nph( _nph ) + m_nph( _nph ), + m_fpp( _frames ) { + m_abuf = new sampleFrame[_frames]; + m_bbuf = new sampleFrame[_frames]; + m_lphase[A1_OSC] = 0.0f; m_lphase[A2_OSC] = 0.0f; m_lphase[B1_OSC] = 0.0f; @@ -80,10 +84,12 @@ WTSynthObject::WTSynthObject( float * _A1wave, float * _A2wave, WTSynthObject::~WTSynthObject() { + delete[] m_abuf; + delete[] m_bbuf; } -void WTSynthObject::renderOutput( sampleFrame * _abuf, sampleFrame * _bbuf, fpp_t _frames ) +void WTSynthObject::renderOutput( fpp_t _frames ) { for( fpp_t frame = 0; frame < _frames; frame++ ) { @@ -167,8 +173,8 @@ void WTSynthObject::renderOutput( sampleFrame * _abuf, sampleFrame * _bbuf, fpp_ A1_R *= A2_R; break; } - _abuf[frame][0] = A1_L * m_lvol[A1_OSC]; - _abuf[frame][1] = A1_R * m_rvol[A1_OSC]; + m_abuf[frame][0] = A1_L * m_lvol[A1_OSC]; + m_abuf[frame][1] = A1_R * m_rvol[A1_OSC]; // B-series modulation (other than phase mod) switch( m_bmod ) @@ -186,8 +192,8 @@ void WTSynthObject::renderOutput( sampleFrame * _abuf, sampleFrame * _bbuf, fpp_ B1_R *= B2_R; break; } - _bbuf[frame][0] = B1_L * m_lvol[B1_OSC]; - _bbuf[frame][1] = B1_R * m_rvol[B1_OSC]; + m_bbuf[frame][0] = B1_L * m_lvol[B1_OSC]; + m_bbuf[frame][1] = B1_R * m_rvol[B1_OSC]; // update phases for( int i = 0; i < NUM_OSCS; i++ ) @@ -322,7 +328,8 @@ void WTSynthInstrument::playNote( NotePlayHandle * _n, const_cast( b1_graph.samples() ), const_cast( b2_graph.samples() ), m_amod.value(), m_bmod.value(), - engine::mixer()->processingSampleRate(), _n ); + engine::mixer()->processingSampleRate(), _n, + engine::mixer()->framesPerPeriod() ); w -> changeMult( A1_OSC, a1_mult.value() ); w -> changeMult( A2_OSC, a2_mult.value() ); @@ -377,11 +384,11 @@ void WTSynthInstrument::playNote( NotePlayHandle * _n, m_multChanged = false; } - sampleFrame * abuf = new sampleFrame[frames]; + sampleFrame * abuf = w->abuf(); - sampleFrame * bbuf = new sampleFrame[frames]; + sampleFrame * bbuf = w->bbuf(); - w-> renderOutput( abuf, bbuf, frames ); + w-> renderOutput( frames ); const float bmix = ( ( m_abmix.value() + 100.0 ) / 200.0 ); const float amix = 1.0 - bmix; @@ -393,9 +400,6 @@ void WTSynthInstrument::playNote( NotePlayHandle * _n, ( bbuf[f][1] * bmix ); } - delete[] abuf; - delete[] bbuf; - applyRelease( _working_buffer, _n ); instrumentTrack()->processAudioBuffer( _working_buffer, frames, _n ); diff --git a/plugins/wtsynth/WTSynth.h b/plugins/wtsynth/WTSynth.h index 181576aba..fc44abb48 100644 --- a/plugins/wtsynth/WTSynth.h +++ b/plugins/wtsynth/WTSynth.h @@ -70,10 +70,10 @@ class WTSynthObject public: WTSynthObject( float * _A1wave, float * _A2wave, float * _B1wave, float * _B2wave, - int _amod, int _bmod, const sample_rate_t _samplerate, NotePlayHandle * _nph ); + int _amod, int _bmod, const sample_rate_t _samplerate, NotePlayHandle * _nph, fpp_t _frames ); virtual ~WTSynthObject(); - void renderOutput( sampleFrame * _abuf, sampleFrame * _bbuf, fpp_t _frames ); + void renderOutput( fpp_t _frames ); void updateFrequencies(); @@ -81,6 +81,15 @@ public: void changeMult( int _osc, float _mul ); void changeTune( int _osc, float _ltune, float _rtune ); + inline sampleFrame * abuf() const + { + return m_abuf; + } + inline sampleFrame * bbuf() const + { + return m_bbuf; + } + private: sample_t * m_A1wave; sample_t * m_A2wave; @@ -99,14 +108,17 @@ private: const sample_rate_t m_samplerate; NotePlayHandle * m_nph; + fpp_t m_fpp; + + sampleFrame * m_abuf; + sampleFrame * m_bbuf; + float m_lphase [NUM_OSCS]; float m_rphase [NUM_OSCS]; float m_lfreq [NUM_OSCS]; float m_rfreq [NUM_OSCS]; - - friend class WTSynthInstrument; - friend class WTSynthView; + }; class WTSynthInstrument : public Instrument @@ -265,8 +277,6 @@ private: pixmapButton * m_smoothButton; pixmapButton * m_phaseLeftButton; pixmapButton * m_phaseRightButton; - - friend class WTSynthInstrument; }; From 861a7d1ce110b1fc2c0727ba6154815fa80ebe23 Mon Sep 17 00:00:00 2001 From: Vesa Date: Fri, 21 Mar 2014 19:04:02 +0200 Subject: [PATCH 073/647] Fix mixing / modulation behaviour, add some more buffer safeguards --- plugins/wtsynth/WTSynth.cpp | 37 +++++++++++++++++++++++-------------- 1 file changed, 23 insertions(+), 14 deletions(-) diff --git a/plugins/wtsynth/WTSynth.cpp b/plugins/wtsynth/WTSynth.cpp index 98ba989d8..e6f393464 100644 --- a/plugins/wtsynth/WTSynth.cpp +++ b/plugins/wtsynth/WTSynth.cpp @@ -74,6 +74,7 @@ WTSynthObject::WTSynthObject( float * _A1wave, float * _A2wave, m_lphase[A2_OSC] = 0.0f; m_lphase[B1_OSC] = 0.0f; m_lphase[B2_OSC] = 0.0f; + m_rphase[A1_OSC] = 0.0f; m_rphase[A2_OSC] = 0.0f; m_rphase[B1_OSC] = 0.0f; @@ -91,6 +92,11 @@ WTSynthObject::~WTSynthObject() void WTSynthObject::renderOutput( fpp_t _frames ) { + if( m_abuf == NULL ) + m_abuf = new sampleFrame[m_fpp]; + if( m_bbuf == NULL ) + m_bbuf = new sampleFrame[m_fpp]; + for( fpp_t frame = 0; frame < _frames; frame++ ) { float frac; @@ -110,13 +116,13 @@ void WTSynthObject::renderOutput( fpp_t _frames ) // B2 frac = fraction( m_lphase[B2_OSC] ); sample_t B2_L = - ( m_A2wave[ static_cast( m_lphase[B2_OSC] ) % WAVELEN ] * ( 1.0f - frac ) ) + + ( m_B2wave[ static_cast( m_lphase[B2_OSC] ) % WAVELEN ] * ( 1.0f - frac ) ) + ( m_B2wave[ static_cast( m_lphase[B2_OSC] + 1 ) % WAVELEN ] * frac ); B2_L *= m_lvol[B2_OSC]; frac = fraction( m_rphase[B2_OSC] ); sample_t B2_R = - ( m_A2wave[ static_cast( m_rphase[B2_OSC] ) % WAVELEN ] * ( 1.0f - frac ) ) + - ( m_A2wave[ static_cast( m_rphase[B2_OSC] + 1 ) % WAVELEN ] * frac ); + ( m_B2wave[ static_cast( m_rphase[B2_OSC] ) % WAVELEN ] * ( 1.0f - frac ) ) + + ( m_B2wave[ static_cast( m_rphase[B2_OSC] + 1 ) % WAVELEN ] * frac ); B2_R *= m_rvol[B2_OSC]; // put phases of 1-series oscs into variables because phase modulation might happen @@ -142,27 +148,31 @@ void WTSynthObject::renderOutput( fpp_t _frames ) sample_t A1_L = ( m_A1wave[ static_cast( A1_lphase ) % WAVELEN ] * ( 1.0f - frac ) ) + ( m_A1wave[ static_cast( A1_lphase + 1 ) % WAVELEN ] * frac ); + A1_L *= m_lvol[A1_OSC]; frac = fraction( A1_rphase ); sample_t A1_R = ( m_A1wave[ static_cast( A1_rphase ) % WAVELEN ] * ( 1.0f - frac ) ) + ( m_A1wave[ static_cast( A1_rphase + 1 ) % WAVELEN ] * frac ); + A1_R *= m_rvol[A1_OSC]; // B1 frac = fraction( B1_lphase ); sample_t B1_L = ( m_B1wave[ static_cast( B1_lphase ) % WAVELEN ] * ( 1.0f - frac ) ) + ( m_B1wave[ static_cast( B1_lphase + 1 ) % WAVELEN ] * frac ); + B1_L *= m_lvol[B1_OSC]; frac = fraction( B1_rphase ); sample_t B1_R = ( m_B1wave[ static_cast( B1_rphase ) % WAVELEN ] * ( 1.0f - frac ) ) + ( m_B1wave[ static_cast( B1_rphase + 1 ) % WAVELEN ] * frac ); - - // A-series modulation (other than phase mod) + B1_R *= m_rvol[B1_OSC]; + + // A-series modulation) switch( m_amod ) { case MOD_MIX: - A1_L += A2_L; - A1_R += A2_R; + A1_L = ( A1_L + A2_L ) / 2.0; + A1_R = ( A1_R + A2_R ) / 2.0; break; case MOD_AM: A1_L *= qMax( 0.0f, A2_L + 1.0f ); @@ -173,15 +183,15 @@ void WTSynthObject::renderOutput( fpp_t _frames ) A1_R *= A2_R; break; } - m_abuf[frame][0] = A1_L * m_lvol[A1_OSC]; - m_abuf[frame][1] = A1_R * m_rvol[A1_OSC]; + m_abuf[frame][0] = A1_L; + m_abuf[frame][1] = A1_R; // B-series modulation (other than phase mod) switch( m_bmod ) { case MOD_MIX: - B1_L += B2_L; - B1_R += B2_R; + B1_L = ( B1_L + B2_L ) / 2.0; + B1_R = ( B1_R + B2_R ) / 2.0; break; case MOD_AM: B1_L *= qMax( 0.0f, B2_L + 1.0f ); @@ -192,8 +202,8 @@ void WTSynthObject::renderOutput( fpp_t _frames ) B1_R *= B2_R; break; } - m_bbuf[frame][0] = B1_L * m_lvol[B1_OSC]; - m_bbuf[frame][1] = B1_R * m_rvol[B1_OSC]; + m_bbuf[frame][0] = B1_L; + m_bbuf[frame][1] = B1_R; // update phases for( int i = 0; i < NUM_OSCS; i++ ) @@ -385,7 +395,6 @@ void WTSynthInstrument::playNote( NotePlayHandle * _n, } sampleFrame * abuf = w->abuf(); - sampleFrame * bbuf = w->bbuf(); w-> renderOutput( frames ); From 89089886faff81abba7a0d9546d0a1b8b4f4784d Mon Sep 17 00:00:00 2001 From: Vesa Date: Fri, 21 Mar 2014 19:22:47 +0200 Subject: [PATCH 074/647] Correct phase mod algo (add below-bounds check) --- plugins/wtsynth/WTSynth.cpp | 51 +++++++++++++++++++++---------------- plugins/wtsynth/WTSynth.h | 8 +++--- 2 files changed, 33 insertions(+), 26 deletions(-) diff --git a/plugins/wtsynth/WTSynth.cpp b/plugins/wtsynth/WTSynth.cpp index e6f393464..8fe84293a 100644 --- a/plugins/wtsynth/WTSynth.cpp +++ b/plugins/wtsynth/WTSynth.cpp @@ -135,12 +135,16 @@ void WTSynthObject::renderOutput( fpp_t _frames ) if( m_amod == MOD_PM ) { A1_lphase = fmodf( A1_lphase + A2_L * PMOD_AMT, WAVELEN ); + while( A1_lphase < 0 ) A1_lphase += WAVELEN; A1_rphase = fmodf( A1_rphase + A2_R * PMOD_AMT, WAVELEN ); + while( A1_rphase < 0 ) A1_rphase += WAVELEN; } if( m_bmod == MOD_PM ) { B1_lphase = fmodf( B1_lphase + B2_L * PMOD_AMT, WAVELEN ); + while( B1_lphase < 0 ) B1_lphase += WAVELEN; B1_rphase = fmodf( B1_rphase + B2_R * PMOD_AMT, WAVELEN ); + while( B1_rphase < 0 ) B1_rphase += WAVELEN; } // A1 @@ -399,10 +403,13 @@ void WTSynthInstrument::playNote( NotePlayHandle * _n, w-> renderOutput( frames ); - const float bmix = ( ( m_abmix.value() + 100.0 ) / 200.0 ); - const float amix = 1.0 - bmix; for( fpp_t f=0; f < frames; f++ ) { + // get knob values in sample-exact way + const float bmix = ( ( m_abmix.value( f ) + 100.0 ) / 200.0 ); + const float amix = 1.0 - bmix; + + // mix a/b streams according to mixing knob _working_buffer[f][0] = ( abuf[f][0] * amix ) + ( bbuf[f][0] * bmix ); _working_buffer[f][1] = ( abuf[f][1] * amix ) + @@ -555,30 +562,30 @@ WTSynthView::WTSynthView( Instrument * _instrument, // knobs... lots of em - makeknob( a1_volKnob, 96, A1ROW, "Volume", "%", "aKnob" ) - makeknob( a2_volKnob, 96, A2ROW, "Volume", "%", "aKnob" ) - makeknob( b1_volKnob, 96, B1ROW, "Volume", "%", "bKnob" ) - makeknob( b2_volKnob, 96, B2ROW, "Volume", "%", "bKnob" ) + makeknob( a1_volKnob, 118, A1ROW, "Volume", "%", "aKnob" ) + makeknob( a2_volKnob, 118, A2ROW, "Volume", "%", "aKnob" ) + makeknob( b1_volKnob, 118, B1ROW, "Volume", "%", "bKnob" ) + makeknob( b2_volKnob, 118, B2ROW, "Volume", "%", "bKnob" ) - makeknob( a1_panKnob, 121, A1ROW, "Panning", "", "aKnob" ) - makeknob( a2_panKnob, 121, A2ROW, "Panning", "", "aKnob" ) - makeknob( b1_panKnob, 121, B1ROW, "Panning", "", "bKnob" ) - makeknob( b2_panKnob, 121, B2ROW, "Panning", "", "bKnob" ) + makeknob( a1_panKnob, 146, A1ROW, "Panning", "", "aKnob" ) + makeknob( a2_panKnob, 146, A2ROW, "Panning", "", "aKnob" ) + makeknob( b1_panKnob, 146, B1ROW, "Panning", "", "bKnob" ) + makeknob( b2_panKnob, 146, B2ROW, "Panning", "", "bKnob" ) - makeknob( a1_multKnob, 146, A1ROW, "Freq. multiplier", "/8", "aKnob" ) - makeknob( a2_multKnob, 146, A2ROW, "Freq. multiplier", "/8", "aKnob" ) - makeknob( b1_multKnob, 146, B1ROW, "Freq. multiplier", "/8", "bKnob" ) - makeknob( b2_multKnob, 146, B2ROW, "Freq. multiplier", "/8", "bKnob" ) + makeknob( a1_multKnob, 172, A1ROW, "Freq. multiplier", "/8", "aKnob" ) + makeknob( a2_multKnob, 172, A2ROW, "Freq. multiplier", "/8", "aKnob" ) + makeknob( b1_multKnob, 172, B1ROW, "Freq. multiplier", "/8", "bKnob" ) + makeknob( b2_multKnob, 172, B2ROW, "Freq. multiplier", "/8", "bKnob" ) - makeknob( a1_ltuneKnob, 171, A1ROW, "Left detune", " cents", "aKnob" ) - makeknob( a2_ltuneKnob, 171, A2ROW, "Left detune", " cents", "aKnob" ) - makeknob( b1_ltuneKnob, 171, B1ROW, "Left detune", " cents", "bKnob" ) - makeknob( b2_ltuneKnob, 171, B2ROW, "Left detune", " cents", "bKnob" ) + makeknob( a1_ltuneKnob, 200, A1ROW, "Left detune", " cents", "aKnob" ) + makeknob( a2_ltuneKnob, 200, A2ROW, "Left detune", " cents", "aKnob" ) + makeknob( b1_ltuneKnob, 200, B1ROW, "Left detune", " cents", "bKnob" ) + makeknob( b2_ltuneKnob, 200, B2ROW, "Left detune", " cents", "bKnob" ) - makeknob( a1_rtuneKnob, 196, A1ROW, "Right detune", " cents", "aKnob" ) - makeknob( a2_rtuneKnob, 196, A2ROW, "Right detune", " cents", "aKnob" ) - makeknob( b1_rtuneKnob, 196, B1ROW, "Right detune", " cents", "bKnob" ) - makeknob( b2_rtuneKnob, 196, B2ROW, "Right detune", " cents", "bKnob" ) + makeknob( a1_rtuneKnob, 228, A1ROW, "Right detune", " cents", "aKnob" ) + makeknob( a2_rtuneKnob, 228, A2ROW, "Right detune", " cents", "aKnob" ) + makeknob( b1_rtuneKnob, 228, B1ROW, "Right detune", " cents", "bKnob" ) + makeknob( b2_rtuneKnob, 228, B2ROW, "Right detune", " cents", "bKnob" ) makeknob( m_abmixKnob, 4, 4, "A-B Mix", "", "mixKnob" ) diff --git a/plugins/wtsynth/WTSynth.h b/plugins/wtsynth/WTSynth.h index fc44abb48..37d3cec0e 100644 --- a/plugins/wtsynth/WTSynth.h +++ b/plugins/wtsynth/WTSynth.h @@ -43,10 +43,10 @@ name ->setObjectName( oname ); \ name ->setFixedSize( 19, 19 ); -#define A1ROW 25 -#define A2ROW 47 -#define B1ROW 69 -#define B2ROW 91 +#define A1ROW 26 +#define A2ROW 49 +#define B1ROW 72 +#define B2ROW 95 const int WAVELEN = 220; From 4924dadaa5e279ca738c6d2a011923bf9deec75a Mon Sep 17 00:00:00 2001 From: Vesa Date: Fri, 21 Mar 2014 21:37:18 +0200 Subject: [PATCH 075/647] Graphics --- data/themes/default/style.css | 18 +++---- plugins/wtsynth/WTSynth.cpp | 72 ++++++++++++++-------------- plugins/wtsynth/a1_active.png | Bin 169 -> 767 bytes plugins/wtsynth/a1_inactive.png | Bin 169 -> 462 bytes plugins/wtsynth/a2_active.png | Bin 169 -> 815 bytes plugins/wtsynth/a2_inactive.png | Bin 169 -> 500 bytes plugins/wtsynth/aam_active.png | Bin 0 -> 830 bytes plugins/wtsynth/aam_inactive.png | Bin 0 -> 480 bytes plugins/wtsynth/am_active.png | Bin 169 -> 0 bytes plugins/wtsynth/am_inactive.png | Bin 169 -> 0 bytes plugins/wtsynth/amix_active.png | Bin 0 -> 1006 bytes plugins/wtsynth/amix_inactive.png | Bin 0 -> 619 bytes plugins/wtsynth/apm_active.png | Bin 0 -> 829 bytes plugins/wtsynth/apm_inactive.png | Bin 0 -> 476 bytes plugins/wtsynth/arm_active.png | Bin 0 -> 889 bytes plugins/wtsynth/arm_inactive.png | Bin 0 -> 569 bytes plugins/wtsynth/artwork.png | Bin 625 -> 94710 bytes plugins/wtsynth/b1_active.png | Bin 169 -> 712 bytes plugins/wtsynth/b1_inactive.png | Bin 169 -> 431 bytes plugins/wtsynth/b2_active.png | Bin 169 -> 764 bytes plugins/wtsynth/b2_inactive.png | Bin 169 -> 490 bytes plugins/wtsynth/bam_active.png | Bin 0 -> 712 bytes plugins/wtsynth/bam_inactive.png | Bin 0 -> 451 bytes plugins/wtsynth/bmix_active.png | Bin 0 -> 931 bytes plugins/wtsynth/bmix_inactive.png | Bin 0 -> 630 bytes plugins/wtsynth/bpm_active.png | Bin 0 -> 729 bytes plugins/wtsynth/bpm_inactive.png | Bin 0 -> 443 bytes plugins/wtsynth/brm_active.png | Bin 0 -> 792 bytes plugins/wtsynth/brm_inactive.png | Bin 0 -> 540 bytes plugins/wtsynth/inv_active.png | Bin 305 -> 581 bytes plugins/wtsynth/inv_inactive.png | Bin 308 -> 489 bytes plugins/wtsynth/load_active.png | Bin 0 -> 628 bytes plugins/wtsynth/load_inactive.png | Bin 0 -> 537 bytes plugins/wtsynth/mix_active.png | Bin 169 -> 0 bytes plugins/wtsynth/mix_inactive.png | Bin 169 -> 0 bytes plugins/wtsynth/norm_active.png | Bin 305 -> 603 bytes plugins/wtsynth/norm_inactive.png | Bin 308 -> 502 bytes plugins/wtsynth/phl_active.png | Bin 305 -> 667 bytes plugins/wtsynth/phl_inactive.png | Bin 308 -> 517 bytes plugins/wtsynth/phr_active.png | Bin 305 -> 667 bytes plugins/wtsynth/phr_inactive.png | Bin 308 -> 536 bytes plugins/wtsynth/pm_active.png | Bin 169 -> 0 bytes plugins/wtsynth/pm_inactive.png | Bin 169 -> 0 bytes plugins/wtsynth/rm_active.png | Bin 169 -> 0 bytes plugins/wtsynth/rm_inactive.png | Bin 169 -> 0 bytes plugins/wtsynth/saw_active.png | Bin 305 -> 590 bytes plugins/wtsynth/saw_inactive.png | Bin 308 -> 426 bytes plugins/wtsynth/sin_active.png | Bin 305 -> 698 bytes plugins/wtsynth/sin_inactive.png | Bin 308 -> 585 bytes plugins/wtsynth/smooth_active.png | Bin 305 -> 653 bytes plugins/wtsynth/smooth_inactive.png | Bin 308 -> 567 bytes plugins/wtsynth/sqr_active.png | Bin 305 -> 611 bytes plugins/wtsynth/sqr_inactive.png | Bin 308 -> 506 bytes plugins/wtsynth/tri_active.png | Bin 305 -> 655 bytes plugins/wtsynth/tri_inactive.png | Bin 308 -> 532 bytes plugins/wtsynth/wavegraph.png | Bin 351 -> 612 bytes 56 files changed, 45 insertions(+), 45 deletions(-) create mode 100644 plugins/wtsynth/aam_active.png create mode 100644 plugins/wtsynth/aam_inactive.png delete mode 100644 plugins/wtsynth/am_active.png delete mode 100644 plugins/wtsynth/am_inactive.png create mode 100644 plugins/wtsynth/amix_active.png create mode 100644 plugins/wtsynth/amix_inactive.png create mode 100644 plugins/wtsynth/apm_active.png create mode 100644 plugins/wtsynth/apm_inactive.png create mode 100644 plugins/wtsynth/arm_active.png create mode 100644 plugins/wtsynth/arm_inactive.png create mode 100644 plugins/wtsynth/bam_active.png create mode 100644 plugins/wtsynth/bam_inactive.png create mode 100644 plugins/wtsynth/bmix_active.png create mode 100644 plugins/wtsynth/bmix_inactive.png create mode 100644 plugins/wtsynth/bpm_active.png create mode 100644 plugins/wtsynth/bpm_inactive.png create mode 100644 plugins/wtsynth/brm_active.png create mode 100644 plugins/wtsynth/brm_inactive.png create mode 100644 plugins/wtsynth/load_active.png create mode 100644 plugins/wtsynth/load_inactive.png delete mode 100644 plugins/wtsynth/mix_active.png delete mode 100644 plugins/wtsynth/mix_inactive.png delete mode 100644 plugins/wtsynth/pm_active.png delete mode 100644 plugins/wtsynth/pm_inactive.png delete mode 100644 plugins/wtsynth/rm_active.png delete mode 100644 plugins/wtsynth/rm_inactive.png diff --git a/data/themes/default/style.css b/data/themes/default/style.css index 5e6b6504a..bba01399d 100644 --- a/data/themes/default/style.css +++ b/data/themes/default/style.css @@ -609,30 +609,30 @@ sidInstrumentView knob { } WTSynthView knob#aKnob { - color: rgb( 255, 255, 255 ); - qproperty-outerColor: rgb( 255, 255, 255 ); + color: #43b2ff; + qproperty-outerColor: #43b2ff; qproperty-innerRadius: 1; - qproperty-outerRadius: 9; + qproperty-outerRadius: 8; qproperty-centerPointX: 9.5; qproperty-centerPointY: 9.5; qproperty-lineWidth: 2; } WTSynthView knob#bKnob { - color: rgb( 255, 255, 255 ); - qproperty-outerColor: rgb( 255, 255, 255 ); + color: #fc5431; + qproperty-outerColor: #fc5431; qproperty-innerRadius: 1; - qproperty-outerRadius: 9; + qproperty-outerRadius: 8; qproperty-centerPointX: 9.5; qproperty-centerPointY: 9.5; qproperty-lineWidth: 2; } WTSynthView knob#mixKnob { - color: rgb( 255, 255, 255 ); - qproperty-outerColor: rgb( 255, 255, 255 ); + color: #43ff82; + qproperty-outerColor: #43ff82; qproperty-innerRadius: 1; - qproperty-outerRadius: 15; + qproperty-outerRadius: 14; qproperty-centerPointX: 15.5; qproperty-centerPointY: 15.5; qproperty-lineWidth: 2; diff --git a/plugins/wtsynth/WTSynth.cpp b/plugins/wtsynth/WTSynth.cpp index 8fe84293a..e51c0ff96 100644 --- a/plugins/wtsynth/WTSynth.cpp +++ b/plugins/wtsynth/WTSynth.cpp @@ -567,10 +567,10 @@ WTSynthView::WTSynthView( Instrument * _instrument, makeknob( b1_volKnob, 118, B1ROW, "Volume", "%", "bKnob" ) makeknob( b2_volKnob, 118, B2ROW, "Volume", "%", "bKnob" ) - makeknob( a1_panKnob, 146, A1ROW, "Panning", "", "aKnob" ) - makeknob( a2_panKnob, 146, A2ROW, "Panning", "", "aKnob" ) - makeknob( b1_panKnob, 146, B1ROW, "Panning", "", "bKnob" ) - makeknob( b2_panKnob, 146, B2ROW, "Panning", "", "bKnob" ) + makeknob( a1_panKnob, 142, A1ROW, "Panning", "", "aKnob" ) + makeknob( a2_panKnob, 142, A2ROW, "Panning", "", "aKnob" ) + makeknob( b1_panKnob, 142, B1ROW, "Panning", "", "bKnob" ) + makeknob( b2_panKnob, 142, B2ROW, "Panning", "", "bKnob" ) makeknob( a1_multKnob, 172, A1ROW, "Freq. multiplier", "/8", "aKnob" ) makeknob( a2_multKnob, 172, A2ROW, "Freq. multiplier", "/8", "aKnob" ) @@ -582,10 +582,10 @@ WTSynthView::WTSynthView( Instrument * _instrument, makeknob( b1_ltuneKnob, 200, B1ROW, "Left detune", " cents", "bKnob" ) makeknob( b2_ltuneKnob, 200, B2ROW, "Left detune", " cents", "bKnob" ) - makeknob( a1_rtuneKnob, 228, A1ROW, "Right detune", " cents", "aKnob" ) - makeknob( a2_rtuneKnob, 228, A2ROW, "Right detune", " cents", "aKnob" ) - makeknob( b1_rtuneKnob, 228, B1ROW, "Right detune", " cents", "bKnob" ) - makeknob( b2_rtuneKnob, 228, B2ROW, "Right detune", " cents", "bKnob" ) + makeknob( a1_rtuneKnob, 224, A1ROW, "Right detune", " cents", "aKnob" ) + makeknob( a2_rtuneKnob, 224, A2ROW, "Right detune", " cents", "aKnob" ) + makeknob( b1_rtuneKnob, 224, B1ROW, "Right detune", " cents", "bKnob" ) + makeknob( b2_rtuneKnob, 224, B2ROW, "Right detune", " cents", "bKnob" ) makeknob( m_abmixKnob, 4, 4, "A-B Mix", "", "mixKnob" ) @@ -632,27 +632,27 @@ WTSynthView::WTSynthView( Instrument * _instrument, // A-modulation button group pixmapButton * amod_mixButton = new pixmapButton( this, NULL ); - amod_mixButton -> move( 4, 40 ); - amod_mixButton -> setActiveGraphic( PLUGIN_NAME::getIconPixmap( "mix_active" ) ); - amod_mixButton -> setInactiveGraphic( PLUGIN_NAME::getIconPixmap( "mix_inactive" ) ); + amod_mixButton -> move( 4, 50 ); + amod_mixButton -> setActiveGraphic( PLUGIN_NAME::getIconPixmap( "amix_active" ) ); + amod_mixButton -> setInactiveGraphic( PLUGIN_NAME::getIconPixmap( "amix_inactive" ) ); toolTip::add( amod_mixButton, tr( "Mix output of A2 to A1" ) ); pixmapButton * amod_amButton = new pixmapButton( this, NULL ); - amod_amButton -> move( 4, 56 ); - amod_amButton -> setActiveGraphic( PLUGIN_NAME::getIconPixmap( "am_active" ) ); - amod_amButton -> setInactiveGraphic( PLUGIN_NAME::getIconPixmap( "am_inactive" ) ); + amod_amButton -> move( 4, 66 ); + amod_amButton -> setActiveGraphic( PLUGIN_NAME::getIconPixmap( "aam_active" ) ); + amod_amButton -> setInactiveGraphic( PLUGIN_NAME::getIconPixmap( "aam_inactive" ) ); toolTip::add( amod_amButton, tr( "Modulate amplitude of A1 with output of A2" ) ); pixmapButton * amod_rmButton = new pixmapButton( this, NULL ); - amod_rmButton -> move( 4, 72 ); - amod_rmButton -> setActiveGraphic( PLUGIN_NAME::getIconPixmap( "rm_active" ) ); - amod_rmButton -> setInactiveGraphic( PLUGIN_NAME::getIconPixmap( "rm_inactive" ) ); + amod_rmButton -> move( 4, 82 ); + amod_rmButton -> setActiveGraphic( PLUGIN_NAME::getIconPixmap( "arm_active" ) ); + amod_rmButton -> setInactiveGraphic( PLUGIN_NAME::getIconPixmap( "arm_inactive" ) ); toolTip::add( amod_rmButton, tr( "Ring-modulate A1 and A2" ) ); pixmapButton * amod_pmButton = new pixmapButton( this, NULL ); - amod_pmButton -> move( 4, 88 ); - amod_pmButton -> setActiveGraphic( PLUGIN_NAME::getIconPixmap( "pm_active" ) ); - amod_pmButton -> setInactiveGraphic( PLUGIN_NAME::getIconPixmap( "pm_inactive" ) ); + amod_pmButton -> move( 4, 98 ); + amod_pmButton -> setActiveGraphic( PLUGIN_NAME::getIconPixmap( "apm_active" ) ); + amod_pmButton -> setInactiveGraphic( PLUGIN_NAME::getIconPixmap( "apm_inactive" ) ); toolTip::add( amod_pmButton, tr( "Modulate phase of A1 with output of A2" ) ); m_aModGroup = new automatableButtonGroup( this ); @@ -663,27 +663,27 @@ WTSynthView::WTSynthView( Instrument * _instrument, // B-modulation button group pixmapButton * bmod_mixButton = new pixmapButton( this, NULL ); - bmod_mixButton -> move( 44, 40 ); - bmod_mixButton -> setActiveGraphic( PLUGIN_NAME::getIconPixmap( "mix_active" ) ); - bmod_mixButton -> setInactiveGraphic( PLUGIN_NAME::getIconPixmap( "mix_inactive" ) ); + bmod_mixButton -> move( 44, 50 ); + bmod_mixButton -> setActiveGraphic( PLUGIN_NAME::getIconPixmap( "bmix_active" ) ); + bmod_mixButton -> setInactiveGraphic( PLUGIN_NAME::getIconPixmap( "bmix_inactive" ) ); toolTip::add( bmod_mixButton, tr( "Mix output of B2 to B1" ) ); pixmapButton * bmod_amButton = new pixmapButton( this, NULL ); - bmod_amButton -> move( 44, 56 ); - bmod_amButton -> setActiveGraphic( PLUGIN_NAME::getIconPixmap( "am_active" ) ); - bmod_amButton -> setInactiveGraphic( PLUGIN_NAME::getIconPixmap( "am_inactive" ) ); + bmod_amButton -> move( 44, 66 ); + bmod_amButton -> setActiveGraphic( PLUGIN_NAME::getIconPixmap( "bam_active" ) ); + bmod_amButton -> setInactiveGraphic( PLUGIN_NAME::getIconPixmap( "bam_inactive" ) ); toolTip::add( bmod_amButton, tr( "Modulate amplitude of B1 with output of B2" ) ); pixmapButton * bmod_rmButton = new pixmapButton( this, NULL ); - bmod_rmButton -> move( 44, 72 ); - bmod_rmButton -> setActiveGraphic( PLUGIN_NAME::getIconPixmap( "rm_active" ) ); - bmod_rmButton -> setInactiveGraphic( PLUGIN_NAME::getIconPixmap( "rm_inactive" ) ); + bmod_rmButton -> move( 44, 82 ); + bmod_rmButton -> setActiveGraphic( PLUGIN_NAME::getIconPixmap( "brm_active" ) ); + bmod_rmButton -> setInactiveGraphic( PLUGIN_NAME::getIconPixmap( "brm_inactive" ) ); toolTip::add( bmod_rmButton, tr( "Ring-modulate B1 and B2" ) ); pixmapButton * bmod_pmButton = new pixmapButton( this, NULL ); - bmod_pmButton -> move( 44, 88 ); - bmod_pmButton -> setActiveGraphic( PLUGIN_NAME::getIconPixmap( "pm_active" ) ); - bmod_pmButton -> setInactiveGraphic( PLUGIN_NAME::getIconPixmap( "pm_inactive" ) ); + bmod_pmButton -> move( 44, 98 ); + bmod_pmButton -> setActiveGraphic( PLUGIN_NAME::getIconPixmap( "bpm_active" ) ); + bmod_pmButton -> setInactiveGraphic( PLUGIN_NAME::getIconPixmap( "bpm_inactive" ) ); toolTip::add( bmod_pmButton, tr( "Modulate phase of B1 with output of B2" ) ); m_bModGroup = new automatableButtonGroup( this ); @@ -700,7 +700,7 @@ WTSynthView::WTSynthView( Instrument * _instrument, a1_graph = new graph( this, graph::LinearStyle, 224, 105 ); a1_graph->move( 4, 141 ); a1_graph->setAutoFillBackground( true ); - a1_graph->setGraphColor( QColor( 255, 255, 255 ) ); + a1_graph->setGraphColor( QColor( 0x43, 0xb2, 0xff ) ); toolTip::add( a1_graph, tr ( "Draw your own waveform here by dragging your mouse on this graph." ) ); a1_graph->setPalette( pal ); @@ -708,7 +708,7 @@ WTSynthView::WTSynthView( Instrument * _instrument, a2_graph = new graph( this, graph::LinearStyle, 224, 105 ); a2_graph->move( 4, 141 ); a2_graph->setAutoFillBackground( true ); - a2_graph->setGraphColor( QColor( 255, 255, 255 ) ); + a2_graph->setGraphColor( QColor( 0x43, 0xb2, 0xff ) ); toolTip::add( a2_graph, tr ( "Draw your own waveform here by dragging your mouse on this graph." ) ); a2_graph->setPalette( pal ); @@ -716,7 +716,7 @@ WTSynthView::WTSynthView( Instrument * _instrument, b1_graph = new graph( this, graph::LinearStyle, 224, 105 ); b1_graph->move( 4, 141 ); b1_graph->setAutoFillBackground( true ); - b1_graph->setGraphColor( QColor( 255, 255, 255 ) ); + b1_graph->setGraphColor( QColor( 0xfc, 0x54, 0x31 ) ); toolTip::add( b1_graph, tr ( "Draw your own waveform here by dragging your mouse on this graph." ) ); b1_graph->setPalette( pal ); @@ -724,7 +724,7 @@ WTSynthView::WTSynthView( Instrument * _instrument, b2_graph = new graph( this, graph::LinearStyle, 224, 105 ); b2_graph->move( 4, 141 ); b2_graph->setAutoFillBackground( true ); - b2_graph->setGraphColor( QColor( 255, 255, 255 ) ); + b2_graph->setGraphColor( QColor( 0xfc, 0x54, 0x31 ) ); toolTip::add( b2_graph, tr ( "Draw your own waveform here by dragging your mouse on this graph." ) ); b2_graph->setPalette( pal ); diff --git a/plugins/wtsynth/a1_active.png b/plugins/wtsynth/a1_active.png index c09789d32e7b2ea636f55e145fe074d4331f88fc..06dbee18579a0db54d887d6b3eec1800a35f45f5 100644 GIT binary patch delta 691 zcmV;k0!;m>0sjS%85#xv003myJ*@x$00v@9M??T003QG!fq_z#ks%-m6%q#olL;?E zkx3_i0%u7?K~zY`&6dAw6j2bzKQnLlHfIuIf|Z3J7B*fH0@?~z+W8j*5p07N3jP4G zFoh@$5aUtS@ju|#HFayb|VP;sGU}+5AcSj@wqG(v5Ha(AX0p7U+U>+!q zNw>aZNfYT%PjZAioPZ%dW#rgNG>m9|{fwCr42?2$WP)&b zlz4p&(iE*!**|`o_1CkIG$F3{1c+)`ITb}!(K2rSC~yg#Zp#9QAT9)8>EU^nW+vHq zH<$TP2R`M?^IO@w3rgpLb@7|WloASml2atuEt!wrc-3A6pJGV^AJ_LzX8y(sJ{Bu0 ztg*HX7{TxXTy+>R1M_*dDY+~~ih49jtM6<~UgBNY$43`fo;kp;=dL0_rEHMSI_a``b=%*6T!2&t zQ0-kX4F`Gy)UbjMjkR=Ehiy+32|`w$UE7u&4OpGM%j)bsFpoz25K-RWJOvn9sb<~$ zN1+xph&lkwIa8aS@0+d8aw-J1S`8mJSeUBeT!5&csu^qk)4{FdgVk6A=iRrAbr zm+up!)h!v6JzX3_EKVoeNIXAhAkfg6*l=LQ(Zyo@Q8rm0K@5JoZbl(z#N9mJ9xkE0JJ4CsOUDIKi!dp-! z4KfWbENvqf&0O z+4KPc*6TH@iikW_y(CF+9OoQRReON{L55*}$b3FWRROTpQdJdso&&I0Ebx6FV+>_k z-VE6T?8cmkT&3c4Iz?4E9*+Qco<|S_OePafr&D`L6h#~khnoSLhig~Cu5#BjfbDim zmSwF<&Et$Qz4@)@He>hEc!}fq;<~kVxGcWL{&II+*R6|P*S#1T_at1i=V1kRyB*d} zT4u8uQ4|fH(aOke^niD}c)#EG=0#CZ6h&_>P19iklO!3Rg3INyt$mK;oK=%&e;mYo de~tRP^#fCyOiYz^9FdgVk6A=iRbTbX z!$T9J)h!v6JzX3_EKVn1xpXN>g5$su1BZkwj{>{hb>+5JfEeuak1|+nV3;@G`hpVB O3 diff --git a/plugins/wtsynth/a2_active.png b/plugins/wtsynth/a2_active.png index c09789d32e7b2ea636f55e145fe074d4331f88fc..cd8963a4121cccfe8f6a1accdb33c070603d0028 100644 GIT binary patch delta 739 zcmV<90v!FR0j~y-85#xv003myJ*@x$00v@9M??T003QG!fq_z#ks%-m6%q#$XWg0; zkx3_i0+&fdK~zY`&6c}sR6!KRf9K51?k3qa4;3GvUe}E!_tq>Fu z5y3`56fG33Qi!N+3PB4I3(GVq1Q8Qofy4(96SKSbF&1}slg-|ZV4A%!F!!FB^L_K3 z$6UGn=%J^DAITNEyv_HZE{BM;1S#)5aZn_GT>Oc(E`!UpGk9mJrIedII{>9ctT6^- zEC5p%hlztS_!xXjlbgdwdk)qY&aKC6)rBsLL>L?G46QVq>tX z1~rjKhF` z`4{*3_Hvx~&#y#;H2;|_VtNuSjG}5#RYj#j5FiX7SWX{d8Hpo0`$tfhrTpUyrSG4K zOH1VU4&e&jh=31D#O38=gk{t^HuWDw@DP^Q@gGptT}4qr0Pz0$5u)NE;PG*k-WmRXrC>v; z*Ak*JNu*Ltt9l1M4x2jf9eYxn7iZrwbN3V?iWg0-;(88E2&&69zjkbGV%`_KpAm002ovPDHLkV1hupS$O~e delta 116 zcmZ3_wvuszqyZBH1HFdgVk6A=iRrAbr zm+up!)h!v6JzX3_EKVoeNIXAhAkfg6*l=LQ(Zyo@Q8rm0K@5JoZbl(z#S(muk zY=)W9Znp`7098dq2*WTF-|zR+z1-bn P00000NkvXXu0mjf2*$(q delta 116 zcmeyuypnN(qyZBH1HFdgVk6A=iRbTbX z!$T9J)h!v6JzX3_EKVn1xpXN>g5$su1BZkwj{>{hb>+5JfEeuak1|+nV3;@G`hpVB O3P)e zSad^gZEa<4bO1wgWnpw>WFU8GbZ8()Nlj2!fese{00O2-L_t(Y$IX^qh)q!xfWNi& zxqsbzWril1CqMaVC`l8U{N%wKFW!_Wk)o9R6iHr0kuoJulEfhN)ZZ!5uhZ~thn%!sU)wCbb@LO zNEDgphgKp!M8%@*9UDPaG)N*Y0AyUhF^ls+z&vI?(ydyX3(J@viT)icA|QeWDHfi* zS7i$7OoSyyh6iD!g2wqLu|WwE1lj3K@7&C+O$X6LDq3U4aPKqvuN=U9Nc+}PWaoGC z_Vi|aVGx|7b@f)-HtylW<^2r3xQj1-$ILgmsEIV>TI%NN0lmj6C9M1dv>s4>8cSEm zFJ6NtQk1{+gBdQ@LU!(QT(*Vq+dyO}NRnUF#kZ%oK^^%e>th3k56k%S56p)Rcu~Y$ zLu9onJ-J(zqE_K z?i~#E+#lb8fp@g5+CqBv0!p8I{}y1aC`QXZ8j46`y4pC2UX!8M4@kAm!OSSUepoAn zxP8^@ms;y;I1K8xSX7ZjDn9C(+stTzOzdvWi9*i6~@TF>8gCry~6StX3 z0fQ7lZpNgI`s4MZvA2e3z`(7u4BR?begAahcr_YtPHd>^9(;Tg%;PfC&{THPM%@Hx zafvTG^JvN(b)!rXV7bVXeH~NpvfzCLSSftP7o+QzpJLaopR8#6Tb=CAC;$Ke07*qo IM6N<$f>{1^CIA2c literal 0 HcmV?d00001 diff --git a/plugins/wtsynth/aam_inactive.png b/plugins/wtsynth/aam_inactive.png new file mode 100644 index 0000000000000000000000000000000000000000..979e48b937071770713ec129f66c43d9b62ffd11 GIT binary patch literal 480 zcmV<60U!Q}P)e zSad^gZEa<4bO1wgWnpw>WFU8GbZ8()Nlj2!fese{00BrzL_t(Y$L*HQYQjJig}=E` zL4}FgWD^j416_;nQu+>kkG@0clLXf;vM_=_i);lW0SyS5E=p2^ZK(|nS@f*#Fbte~ z&ixtn{Q6>^9v%@9Lecaa|A^j#eJbX0t{STPzl3f&laRyb%^pCX-tQ ze+tKO7!HSsyjO=Yh9pVYY&HOlMkBP=1VKQSWdOLYi|2W)*K3j_`P&*C3?Ov_|$&KaRBIaI`sSf>P>Pl#^dp~_gZT# z%c`VaC4%Sk8Gv@XU9$IDY1_67C2OC9tJR7y42k3T%LH84rPu2f$uw$E$8k)z+r=2e z@px<=!JO3TbmDTk)K`Ps?Y4A|qKGJpit}!_yV(W+`~AK;!Rd6`++FPZ{{L_0H+Tbu WB4`KX3qm*m00004nJa0`PlBg3pY5H=O_Iu1CqN1@b#rmUcvOa4nJa0`PlBg3pY5H=O_Iu1CqN@6;UmhL;3Q3l@MwB?`=jNv7l`uFLr6!i7rYMwWmSiZnd-?{1H}Z)C z6)AhVIEGl9PQG&KQj!G6fg=VE30EEkcDw7!ZLI(?*ykT*u-L#bZ@%>fC7^N!Pgg&e IbxsLQ0E1jG%>V!Z diff --git a/plugins/wtsynth/amix_active.png b/plugins/wtsynth/amix_active.png new file mode 100644 index 0000000000000000000000000000000000000000..6c76d44ff5d48534f982bbf2d3ac71cb429e8fa6 GIT binary patch literal 1006 zcmVe zSad^gZEa<4bO1wgWnpw>WFU8GbZ8()Nlj2!fese{00UM@L_t(Y$IX^aXdP7)$A9PC znK$nxX;Mv^szm$_Buz!7R=Y@0BZ3PTq6?*n6x_HFapA@fP$2}ma#L_$rS7DzRM15e zVyU8nU}6?3Xsafq&Btrsn>RD}xS01Q?lfBxrx&mDRHqm#xi9s$4` zuf2tfDu5s&#bo>U^&Dn~PwJ%Ai#b3SRXBWNepfN~-Kz&7uI2zCXX^Xc4`XQqX?jEi zR1p^}1#;K!kbb_&|8TL;egGLQsT_M|8-n8{)thS2y6aaOKY7<~vs*uL` z_zKpz0*xA^4a8@Nfd(b|Mkml9#JPaJgO3$j6%nLa2@zrKn@@?Ceq&(bC|ZixH+hU? zZHbjLA41lEqz*}~)6#?%|0;^AZUKmGvJD7U_*y%A?|mE%N|gGCs0@vCRH*ni!_t_g z&rT5T-Otc-?@_+#ZkE6J0AE|jk{EopDWz6SDZ&&<>rTbneb*seS1)@GJn|p6&|_(X z>f+Z_7thi&{4llOe`4*2&+$o&WsO|N*V<-wGQh0${v(*Ul1Uw zn^M?%nOf^b+RkL>490)|!VO2BrF_dU@zSqXPeKF@BYH;0>Av#;)_?qp^3B8a-Tx#S zMo18XTwCZZt6CXITN}}iY&RBWi3ab$%&0ER{R_>Cgk=Vwc$wtVpZxX7H1!LM3{1X+ ztMsC!3gUt`;mM}Rw=k=n=PD9LXt^7Wa+6XSaba;lb$%9r`XBS8)s-T#&RZhvJ@gc% zfm>ObJ%wc{D`!p;_6>65_|ZH@)K$dDtqTpy+W>ZGP=bh{rymt7v?9(SF68{jZ|7_R zKfg0s>{&f`8Zbly&Yya-NM!Zg>E>JxxVkWx?=z1p_n={=^P)7F)F9dp(3-8}zT;mjO&cMefSo9}EV!0Sk% c_xLpCABBM__OQ7v9RL6T07*qoM6N<$f|Zrbv;Y7A literal 0 HcmV?d00001 diff --git a/plugins/wtsynth/amix_inactive.png b/plugins/wtsynth/amix_inactive.png new file mode 100644 index 0000000000000000000000000000000000000000..846cbf6e7b3fbf7bc2eea40800b3a5fc63216491 GIT binary patch literal 619 zcmV-x0+juUP)e zSad^gZEa<4bO1wgWnpw>WFU8GbZ8()Nlj2!fese{00GlUL_t(Y$IX^Os^UNphX3jw zqPA#a)QARjp}B+L#*;kW9p)l)hha`4?u4w}h=LJ=L5*U93i?)^NyJg|V9p#_ioGuhZ#3RaMxwjmzZ%0I1b!Xf~S|kH^^UcCai9nx?0&z8@B2_y6^FwCo6Y8Xt2m7j5j0Ip0NztjTD+FiEV`&% z(gKEI2*WTSgg_XEPt`6I3Rth#5JEuL_0$Tc2HbA9$mMdlUa#brGjiW3)gi40L$ePilV?UjQ>-ElgT8Sy=~i(-}Agg zOxz#u^L;-t?puJpUhh2*3-UL|7z5`#u{po`@WAlq_63}ZhvdAU_!IyD002ovPDHLk FV1jVX3p4-# literal 0 HcmV?d00001 diff --git a/plugins/wtsynth/apm_active.png b/plugins/wtsynth/apm_active.png new file mode 100644 index 0000000000000000000000000000000000000000..3011bfee40403a734cb5d538a4282da2af356a5b GIT binary patch literal 829 zcmV-D1H$}?P)e zSad^gZEa<4bO1wgWnpw>WFU8GbZ8()Nlj2!fese{00N~+L_t(Y$IX^sh)iJ^#((eo zeRF1~owY3O%|<2)E#*S8QAl#(Ldq3Ixsjq=p_HU3N{L(LLc%52lnW%eP{R5XC6vvd zkr`&rob!Dy&Y3wgJFHq^-+Jrxopavve9!y5&v)eX#S8wxu00r=Lsc=xAgZV+B7%s} zjJC_aAI{;TIu;;T9KhrYs4*BdhzhETFdpE)LFn=LMhzxEIa#%sT7Y7E(g^V zAPF-M_OC!(go;nv+s>dWY6HYrK)Uvvg@AW>?~=Nz*;*9hT@2oLBN71-)aF@m^kxf_ z?f6VoC;nE3xPhknO8^RDbJ*VL%-MN{;)0P(DpAOX>*x4%=L$nxkI_4SIWJCZ!d1#( z3%$wkS{3izPg&Dk4-{u~u5|!(4&SKbYE@jlGksXY$BhhF_#GF8 zs14{FUejVlZ9w0`RfsC6p>Ofpw7ADbVe($R`jh;IYt*{f)h>B@pR~-kr|a7Fi<6sq zetaV?3e&b{(YItBVgrJKAqqnaGZ}b~@2Z_E>*~7_(3r135pktV^ks~w`WYXGt$SZbZ;>A?;k~CadMC4=)Vexr zr`fcwafd+%gQAM$^6636Z8KtWzx1zm1}jf)F>Cd9YHywpRX(-z+`t7Adt!XpG=}C)45R>EG<-;u|o*r4(s$0Hy6}-a~rlI-X-x_rnK%WYH>B+lO z=BR68N&tp6?(ZF*dOr)!Vf*|0xpM6irMV??>D2fs^waPIM%*3DD~zPx00000NkvXX Hu0mjf`a*w* literal 0 HcmV?d00001 diff --git a/plugins/wtsynth/apm_inactive.png b/plugins/wtsynth/apm_inactive.png new file mode 100644 index 0000000000000000000000000000000000000000..2ecea068373ca6c254a55aee726da25d00a0b576 GIT binary patch literal 476 zcmV<20VDp2P)e zSad^gZEa<4bO1wgWnpw>WFU8GbZ8()Nlj2!fese{00BfvL_t(Y$IX_pZo)7ShCg2@ zk_C!k$&#f(yZ|%eU8=rA-=ptPb?-YwnE_=*u(7}ZLLvjg?$XdkX{A=6)cYA_PHjiIq|)r6~0^Zc2jZYL&rcGVuy*I-OPl0kSOfqQs-osP5oz zH5d#q#$49cTGs0|o6UwKNeIJ`JkPP#0uV(JaU8Q)EI1qv&Gq2`a+?QH84 literal 0 HcmV?d00001 diff --git a/plugins/wtsynth/arm_active.png b/plugins/wtsynth/arm_active.png new file mode 100644 index 0000000000000000000000000000000000000000..cd70a1fd4f63fae0bea41aa05ac958832e7ed154 GIT binary patch literal 889 zcmV-<1BU#GP)e zSad^gZEa<4bO1wgWnpw>WFU8GbZ8()Nlj2!fese{00QAjL_t(Y$IX^aXk1kkfWLF@ z`?%W8mAR?uR z-3jeNB#WZmv}q!Zl-6R138~G`do%Cd>*7r&nM`LGgq9q*a3Am7bG~!#z2{sxe__P+ z9X*Eed{h-<45EsPA|i+g%d%?v_{Cam65|2*`KK{q6KV`b4WfdoBCG{`GK3C?D@HIs zmjOzUW9OGQSWj}Z|20r80g`3r`ia*Oo1o%QHK-pT#xL*fvL3iqrlcx;x5{D_aIVXme!Zv zK>ZM#6f!%dL7LzS5jI}TMlq_g>s6)Qm9~gV#XpAM0cY7Za2ZikbK^F3A7$y!-&Y+6 zprn8M%t36tn0ZPQa1Q4zIJ;6J>I2r6j>G3b4eA9f{WVroPt@@2!H27Q>;;EP4s;M_S`U4A-zad^VK(a8)_~2gBXujccvj(tKm}`^>XH#67)IEbZ z$KRKRNtYh3>Ix|UFMN2BZ391Ha`~0kBm$x<{?;@Dtvo-9_#q~2L4#cVZK%^#l7FX} z`tfY}`{Au$$`wF^rt*4G4+(N;*qjYNS7leuUl?(xPJYI&uWmF@s2@rC{~KDJLOs^M zo8p71?2@?BJ$mKy(RI`6mYFiZLd3P>UF+|$U~L9ioS(%;*>lUTv**@-kyRc_y&Ays P00000NkvXXu0mjf+P|28 literal 0 HcmV?d00001 diff --git a/plugins/wtsynth/arm_inactive.png b/plugins/wtsynth/arm_inactive.png new file mode 100644 index 0000000000000000000000000000000000000000..8fed339262a176957e4c3ee507ae90366c269a9e GIT binary patch literal 569 zcmV-90>=G`P)e zSad^gZEa<4bO1wgWnpw>WFU8GbZ8()Nlj2!fese{00E&%L_t(Y$L*HQiXt%-g}vY$D47>tzJ>uSVgSM_& z582lYFqurQax2PqgCGb9g5YDV4xrU)J#R1WbUOckGk=3$*AJR1&^@fd00000NkvXX Hu0mjfbbIeh literal 0 HcmV?d00001 diff --git a/plugins/wtsynth/artwork.png b/plugins/wtsynth/artwork.png index 26b66f53503e776f05e86d8543410ff2aa8523c0..819f322c73eb4ccaea14fd555c23e6c10e675174 100644 GIT binary patch literal 94710 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 diff --git a/plugins/wtsynth/b1_active.png b/plugins/wtsynth/b1_active.png index c09789d32e7b2ea636f55e145fe074d4331f88fc..5788f45c06267b9ba6f48cfff2bc10c11b07e76b 100644 GIT binary patch delta 635 zcmV->0)+jk0mucA85#xv003myJ*@x$00v@9M??T003QG!fq_z#ks%-m6%q#^uL{eP zkx3_i0x(HLK~zY`&6d4uR6!KQf9KA7`;mwyCJ`*e!p2~e#zMp*h#LrbI-l+%$cWWFJCxQJT%v= z`+OQ`1Vd9o%7IQ6Y4i|jGWN2J!|05{5|Em>kcjo= zC2q|(t9RY#JpZxBt6#qXSYKXb<$RqdTW#L#?6a3Sy)n2YcHP9qU;sJ6;F!!X<-Kr! zi7w*6$Iq^dOe!GZAd7UPQ!}x;I0I(5jLe}KjQdNoL>XP5jCF zetIz_RUr>QZ}VWIMK?O3Sj&LNTe|=xWi3T4C(TkgMV{oeVt#skfdJG@eErj-@6d@( zBc6?WB`TQaq>pxIw3x-<@wjoWRz3fJ>|{71!*O(E|B1K*`3Je!X)9dYXtB1@q92{R z3ym|kn`Eepe<~PRJLwdU%AFkdxQ40nv{4{6%gL0ZS=d4^ zIv?5{5IG1f(<(wH$<>zVm>vZj|VD^`q5^)(o1F3?$k}BMWTC3pIW#( zGbYkBx1LEFH02zI2$pegZ(g37tFDsEm8C_WOO5)7tLuM~JB-e5FQRWd+f)6!^%val V#s&oOVkZCq002ovPDHLkV1j7UEiM26 delta 116 zcmX@Xx{`5%qyZBH1HFdgVk6A=iRrAbr zm+up!)h!v6JzX3_EKVoeNIXAhAkfg6*l=LQ(Zyo@Q8rm0K@5JoZbl(z#Mu zkx3_i0T)R`K~zY`&6YiihA+?gxU?Yy>7!7D!mIVMPioz(cvMi5)08mwx5pa2)LvbAd z_xj9|B!TbydM<=O*LCRoUaxze2hKUhal8zFsR1da+PT-K#Y+ePVB0njLO>}+7={>z z;gBSbW6bk>8BnoMLWoYL^gBaY(==d=K?reJ=bYCmu1m@DW7Q$ z_Wm{Y`dxEfSL=0M|BUgUxathOdqc(;7-Nu9A_#)#`{3OGX`243OQQf)I}k!(nkI8E y0Nb`b-BZ`~vw&HanfFFdgVk6A=iRbTbX z!$T9J)h!v6JzX3_EKVn1xpXN>g5$su1BZkwj{>{hb>+5JfEeuak1|+nV3;@G`hpVB O3C?QQ%wEbL8T z9UDOu1RKFx!9=i;SXc;A#E2o$BCH0J{hDVnA8eA@Ag0+11H;_+&O7(qk9oTP_)%a$ zEskS!uoj20ilgcb4G6ISY;_anUN7Jy?-{OtINr~k7%26oUwx)tuj8FLoO1wNe)E-P z5=ekhl6VtD65g~+?a;GFqSW6>0__m!mS9U@Kx|_E(s7(~48>Kvb5;=S$Y^xCG?Tzi z3;`7r2fUb_n&9GCt?;#yz=P!mPgZ^dFgrEA&EHM}bIT1Le*ZKR)i;l$EI)Y)B_tKgZ!WIU3Gm|F5u8AXpupWv>$q%@SL*kc*BJr{mwalS2Yz) zu@fM&luT~5Y$UXkz(STn$8JBQxL%@W>PxU{!n6m$$i!I1NcyBBAJli2){7b`x;zAY z_Nkx0YQj~ld{F23I~e+2wO*b-IxxSwoRd!iG?T!Ew<`m6S!gCHMSc0PHn7(%fWI4Q V+3@vWoTUH&002ovPDHLkV1lVnK%oEt delta 116 zcmeyvx{`5%qyZBH1HFdgVk6A=iRrAbr zm+up!)h!v6JzX3_EKVoeNIXAhAkfg6*l=LQ(Zyo@Q8rm0K@5JoZbl(z#sI`Kw54%@g2>h@CvO zFG(o{K%VC)r4SK1oerDL1^{CWd7j(YbAJ_y2m*M;VW$UIRgxqaV~C;%rIcNtrfDfI ziXuehs{M;tuTHImVQ4e7+wJUp5Cru5{huuS4r6X>7PT@M1c9{=hl5?;>-A_ho243R z+-|pz&){OQ0AMs4(QdbGjTM_GNn&g9R@DL=4u_@MJJ(<^u=akxXSrNH7O-eb#TEYN zzotXn1#q=m)$-pAI3ACk`yX4t`F!r=gF&TVnX|7MfNw=FdgVk6A=iRbTbX z!$T9J)h!v6JzX3_EKVn1xpXN>g5$su1BZkwj{>{hb>+5JfEeuak1|+nV3;@G`hpVB O3e zSad^gZEa<4bO1wgWnpw>WFU8GbZ8()Nlj2!fese{00J;cL_t(Y$IX^YYg17W$A5Ej zZ|_a2X_J=FM8s|s*Oov;rP41Tg1B?zM%^lY1iy@XahFAX1q2IXe5~w3B5F+n(&l}} z#l5LFH;LNlA_KEIkN^DVab}L>R#(&$!3c9DR$;qZ#qmT~b`72p=7pmI9jgF1M!+*d zrBs-!2$m|ffFN)fxviI<=~~5V;6+r7z=8+~0g>@ot122|i3nB$91$>)wVs83cs43B zv|)sDF@MO(i5}`&rO~sr?I?f{TueKLE4dW+)|c?YqE%IPessD2q0T_z!RZXeC6B8+ zUugC%4#M^PBDYVbx%>V*<$9a_fn}iM1bri9Tr;xn#0#@+m4m@JL9385%B75tXM|7f zJ_=+V!@0Ca#x;EHSO}fDnDKf1t%U(DXZ^$4>RP2WQ2G-H4mpfuE?%6I)P@S+hDf)n zd)$1p$9AI)Kq8j*t*no0;Dn#x?BYTg?ddk6IyHhvkw+VAzun(Rd!!x1W+wShk7Z_p zyRAN;thfn|J7yf%2p5)pHpBGJDrVM;cisjmeiEiQE*}qiTw6EwQ*0!7>con5*k+tR%){vRvqqa6g=4(i?@{mC z5u9W~rnZ^52|1Np)!agY7p20H8nvoo`PGEuje7EY{rg6JzEb1itJgsUhlk6>{M?MX uAt%RbFqlh~+I)T%I;u2#b}qkL06zhN740u4+v^Je0000e zSad^gZEa<4bO1wgWnpw>WFU8GbZ8()Nlj2!fese{00ApWL_t(Y$IX?^ii0o|Mvu`J zRERAFH-gYNsPF#@11<`qg|;r-3MxV?2xb<8j>7!lI5>W*+=NTc{c@9Nhr>a!QoTg4 z2v#nm8w5eHDzGpN$AH7h|JKkfV`}n#zsL7|gm~``r4&_Fal73BI3ABkDLJ3dv~3H3 z>$-TJ$Mt%ps;Wu*P42-sGBW&u8*PXIQX&FFZCPCJg%JGs~qce-3I z#Boef6kitLx-OPw^~Ed-_>+pFz%)&iQj}%6KEMv@@p#ZQ&2l|>zu!l3nx>>_+Q&(f teERTbSvDVVZQtDpa4p~5Vme zSad^gZEa<4bO1wgWnpw>WFU8GbZ8()Nlj2!fese{00Rq2L_t(Y$IX_{Yg|EyNgqW#vW$5rl4(Zu}2iyD8|-o!~+Qsp8gU7i~bR0YSut zf*`FTjg+)bLX(*{@69_d-kX`sbc%L27Y^@n?z!iCe%GMLaEX8dp$gwTe;Vf;^?Dt3PKN>JqU`lyH#2r~ z<4$h0`;a1BI=jG?wH1=Uk)sr%ymhL<*7_>vnlXhcA3VLl*7_=;cf7G&?!CTLM^)LF zpJQu%mA6-qb7;cd9CmXXNoMTz%NPKhbA(}tiYh8)ekMW>p<^TInb5EHYbv}rpWvMm zIAwD_8Ky5H!#as5U*A6DW+&sqa-GmQ-dSmIJMHtu&H)+FHO6o{R$^O)rK6{m^(|dj zeJaIdaA0J!IUiF~;ZziG_E@btRR%b4V?fW~<3IO#B=o$0rpc2@z$bt0v!5H?0{RnJ zLm3Q%NLj&$9o}<|kcL-YZbc8YDS)&vw%aM&?JjF4B7V8oD2nhh zY!3|HMUD>dXdl3exX{irH%1bo`qv{=#vBYuw@D;pqnDOSL2~W)h z-0WmiZ4`)9*l0#P+X%UKr^A`KfLBk(L@H&l{{zc2VJ8!!l^jj>+jh$1ae$feT|1o~ zppL0#)V&a^;N^ZinZWWD{+Q!Pg~W{{aw84|xc*NUfL{+X z?)HkY#EvHV+CsugNPugP5@%`E| zn?LN(D@p=2#);YqV{o@QfaLw#XJZro4Q11uG;o?qg*?OS~HJP)$I02y>e zSad^gZEa<4bO1wgWnpw>WFU8GbZ8()Nlj2!fese{00G`fL_t(Y$IX^q&*4BAhOe2C zmI|tZ?qrg?GtbO(%`?-c z;>(Y3C*D{>)3mn*{QC1dA*B=m^?LoS;2MnvmSz0`1ZXy!Zvj`U)lfC$ zl?sVO0>^PU9*+QIvssG8BJFmY)oMkxTE#R?TCEnDOomdaM6cIlI-O#gCe><{;c&=k zG)%ys0ksEQes(_-(E9;Fn8LV^8$ z&tx+BG|x2)fD}Ub3t#-Bc9CUS2qDmQooFyIGs+ouKQ_h zp-^DA+tKg$*>1Pwa=AcN3_)AxOxUH4{QkShB6`1p9QABAhcf7#vtkmSwv3!}G+PwKJ| Qx&QzG07*qoM6N<$f{)-6(f|Me literal 0 HcmV?d00001 diff --git a/plugins/wtsynth/bpm_active.png b/plugins/wtsynth/bpm_active.png new file mode 100644 index 0000000000000000000000000000000000000000..250b5ff0c97bf685e7a5084335063ec9b2276e26 GIT binary patch literal 729 zcmV;~0w(>5P)e zSad^gZEa<4bO1wgWnpw>WFU8GbZ8()Nlj2!fese{00KctL_t(Y$IX^cYZGA*#((o> zH`%l$CQ-yxgj~deM+pQJDh0ud2cdZL?%A{8#gjKbfM39yUmyoj30TxiQLvx~sr`dZ zK$?G>eaFLY(%nr`A%bRLF1znM`^>!0%&eS0cUE&E7-6BzD!kg>#>t6LbPYKpEDA>j z`c?sOj6lu^&HCy>Rj}UN4G99{%5A*+!N4k3!z|)v1hOJz1VoaxRy{c_B3KPEM8L$J z`4)z%6WAjTMj&g1My)dD$6J_-tNSqMCR4*7d38-MI;xbSF)7lRgOesWRzHaxa=3P|7>W1TIHh$V?R?tY;>ZHUv8Z*w6eJF$*DBdS;T0QQsuJGyD z=V)LP82OBxI%d+JND$0MbLg}|{pd?;oIuGj1RB0`MR>f^8V~VXTYKZ!mxmp!Dus+; z$;clE^#s9DK%-V!m{m98e zSad^gZEa<4bO1wgWnpw>WFU8GbZ8()Nlj2!fese{00AROL_t(Y$IX__YJ@Npg-_xj z1SKkh8&`@i;QPNqK}Bdc;_QT}E)>Bm#MqVXq@A`n4vuG)gDYf z6bIL7X~c1SD6k|+RKV-OXY1Om)7r^l7{aow&%TrrRaK#`YXm_6&N=cthm;Zk;CUW= z-$zjt==**(?AjJB1mFTS3e zSad^gZEa<4bO1wgWnpw>WFU8GbZ8()Nlj2!fese{00MwXL_t(Y$IX^IXcSQthQD)X zACtsnHxD-?M1l%YurWel1q%rXVk*JLMzFB9vd}{80t$k?m8GWAK7}AIn8X(W38E=t zTocIC%|7QIi`h)}kj+yj@%*6cr&JHbjlk zE*KTaTLmCw1foVrC5PLpg2~jX4-g0{H~HZ=1*=#E5r~N32#8eIR#k)fVQX5BS-V#2 z=P4A+PXUZT#0aw!Ljk5xg+5QnCk?%6gW9RU$^X+~*!zm5ErC>w{g?7Vc8qC2E9%RkEHX>sfME@l?rL zWzX|RuDpAd7OEwu0;-@jNp5^vqonZW!XVBOTX$!qn~yt%ssrc9L5w}m0^sREE?cI= ze*T64kFv*S`f$n|`Iad(^m7CroQm-yTdG^@a)jxzegKxUB_4g>Y^oeB13Y&u63ka} zUPHeZzy5N2q?;3Nedwr>AWleH6E)K+z^VB(SLf2?JY}*02LWdOWLVhA6Fx-wH;R@k zb7?Xq+p^qL0hB-+u9#AydxhCo+|}j{<1K zKkA)Ea2@eg{6B2H;PG^MJ9vM$l?xQ0!!bcI9DxoabUOZUO?}Ii(ZqlzA`b79!%c;{ zQlJ|Nb<6FniBMlmt@3i=i+@P=)6Px|wN0zr#}u;aH|At&wLLEjc~!QGwk@w)0RI3j Wl@LW;7Suri0000e zSad^gZEa<4bO1wgWnpw>WFU8GbZ8()Nlj2!fese{00D$aL_t(Y$IX?^i|Q~G#eYc) zZqy>`rcm%};YP&&|6h2}Vr2#w3Mwcl6iV?6P4ZTDbVf(z`DS`nx%Zyj9Fjw>D3{BI zjN;Gx8~#Y3`Fy(G@Ao%(i^T%hb;;#&SH++Docr-59t?s2 z-}lj4-}E5Ba=9c)lB)ua$0NS)qm+966Q5v=`PPE~lgWg3yNzwz=^lVir-LyD%d#Fm z@4rlv!{NYmI!)s^j?*9D8F3HY;CMW~i2MEi)!JuX9LMR$A4L&S6#d(%%i_4Z5SW!Q e_ah#BCH?~2r<`6T2Q!EO0000uQ785#xv001BJ|6u?C00v@9M??Vs0RI60puMM)ks%-m6%!-?D-ZS! zkx3_i0j)_yK~y-)ZIaPVBS8>EU-j&cZG0d6Ac4eXzy-kl69NH|2O*FHgg^}bAp*`` z?@af7tarUDGg3=4(o|PckPfQSer@%{Zx6A|QpoVmHVK@vG<%xqF3#OX>Ym0ByM6e5EC zzx|+KyZtq>NMg6!@$vDo80q%*mZzsDBAjrLi9@%?0M_f(1eO{1zwdc|ex_|(B7#2; z4?O;Tr0;ubbwZ4PMizVDF?ua~ARo1EDf@8j`E zgySc6li}{{_xq_yDTU+lIDzMDx2vm0D>myj9)3!q`1<005AYXf^-<010qNS#tmY3ljhU3ljkVnw%H_000McNliru z-UAdC4G%$q(fN^ECw~B|NklX&bLI>KDS(NAL_lW^`T6-iK0eEqEhDVq?%lij z`T2Qyd0Vz@*|B5C-Me>jX<&h)cV1o|ey2~JIyEjX z4yu8jogI&n5GUNab!*Y0MGOoKjF=HuSy{=zz|h{_4(ERR_CgKrU`DJlou8jCAtCYU z)2DCWzHxDJrKF_5oxq4IX~f0FNlQy3D0?@WCqi1V6=NOO27-Q<)#u!2flu{_=zip#ex0X_>aUld^jI};6 z{S~aLs45~-SN;jV9H6Szs0Z{62C$F39}*El2zc+`!oN09)f!Vu=`B1MkaH%bg!lew zV;I0bqWO9ECoq6@&QVGsrG$voO>VbaZHh6{_xI*4TL1t6 delta 256 zcmV+b0ssE#1GEB=8889>005AYXf^-<010qNS#tmY3ljhU3ljkVnw%H_000McNliru z-UAdC4I5iq1%#1XCw~C0Nkl!ak(RgS4~FA8ga6NV}Dg7f3+x zA^te zSad^gZEa<4bO1wgWnpw>WFU8GbZ8()Nlj2!fese{00G=dL_t(I%XO1IQY0}9g+IxS zXJFWZgkS;|;w7LUA?FSd&Rw_%7a=9&1OxO}!XO_z)IcH*wgb)ZJpsJIFpn%}+ zhzOsbpET}HjFF?GBSeH4BdR(v5rp+8DP?lbq?B-X+COb!uvqL*C~e#F@bJLL$H%vp z&d<*|JNtzjhzecbq5$*xY(oA0{!Z6*?Ck7tb92M(?JcLLrwqfu>+35y8!lBgp{dnH z1QFrq@iD8_3IQBQDIrq&o`goG_-_R&<(fQ>Bko2OqWCwuG_%Njf*`mXDJ8nD zWf(?sHgGR~smUe2ad%WU464d6FE2bkK5nlFKlb+#kttq9XzIKH%nY-F{`U3;z`?-* zS65f4>NM&CUUs6X)xs>(Py1_f<~- O0000e zSad^gZEa<4bO1wgWnpw>WFU8GbZ8()Nlj2!fese{00DtXL_t(I%axNcj_NQJMUO+0 z5{Zh25(;W+8fvz|9#{?=U^$4Q7?BS%lhMrSEakr3cYUpn z$D`+kAP4|(&H-SpC5j@Pb2#T{wOVMc(OLr#20?(emNZTI4bC}41n)h!+l|mU_a?sI z?<^Jz(lo{U|K`FlWIP@-8ja9eBO+v3_Tk`_^Z87k=frW$Y&IhdLsqL5Ns_SLZW#`T zSZe_&ih}U7#lc{}d_J$wB7#y15kW+-*1kJy+SPlHwHB>4#+W+PS8?Njr#R1ZvMj?G z^R2jXfVGw+NmwqIZ+~vL+g}GfKX~0)Yt89&!Z}B$(_u21pp>H9?f&e*T8l9Tt#zGr z9LMx}y~bVyuLY^9in1)JstTplTQi$b`~BW$S%!#E6a`vqoO9m>_L=MTN*F~E-g~O5 zLPTouX0u_vUeoXQnNFw8D?AHgj6p>BD{8mfd1DNh%cXuKzah_a9*@VzEgTL9%CfAJ b{|o;BO;Z(J@#uk100000NkvXXu0mjfrjOqZ literal 0 HcmV?d00001 diff --git a/plugins/wtsynth/mix_active.png b/plugins/wtsynth/mix_active.png deleted file mode 100644 index c09789d32e7b2ea636f55e145fe074d4331f88fc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 169 zcmeAS@N?(olHy`uVBq!ia0vp^8bB<-!2~24nJa0`PlBg3pY5H=O_Iu1CqN1@b#rmUcvOa4nJa0`PlBg3pY5H=O_Iu1CqN@6;UmhL;3Q3l@MwB?`=jNv7l`uFLr6!i7rYMwWmSiZnd-?{1H}Z)C z6)AhVIEGl9PQG&KQj!G6fg=VE30EEkcDw7!ZLI(?*ykT*u-L#bZ@%>fC7^N!Pgg&e IbxsLQ0E1jG%>V!Z diff --git a/plugins/wtsynth/norm_active.png b/plugins/wtsynth/norm_active.png index 16b72849b221c93898b7a135cf68f3dba7ffb793..bbf45313a992b822dfc0e1efa86c4b1902d6d555 100644 GIT binary patch delta 525 zcmV+o0`mQ_0^0D9%`F!Td%<$fSGn>s25xn=P>WxGY8kf2bgb=9f8Z+ba z?~(|{;|Z$D@pxpj*&rhPetYA`^D~$7!pENv%#77)#mmc2EP|*|lou3WFzDZ_Hs$_) zej*}ROgglcLx`BPvPnwN?Nb^d_xn9nRZ-P7Aq33sTBo*>JtSxk&5WWbQj+Vn9ZzR} zN_Snf-|wUDP5|j P00000NkvXXu0mjfL8toH delta 253 zcmV005AYXf^-<010qNS#tmY3ljhU3ljkVnw%H_000McNliru z-UAdC4G%$q(fN^ECw~B|NklX&bLI>KDS(NAL_lW^`T6-iK0eEqEhDVq?%lij z`T2Qyd0Vz@*|B5C-Me>jX<&h)cV1o|ey2~JIyEjX z4yu8jogI&n5GUNab!*Y0MGOoKjF=HuSy{=zz|h{_4(ERR_CgKrU`DJlou8jCAtCYU z)2DCWzHxDJrKF_5oxq4IX~f0FNlQy3D diff --git a/plugins/wtsynth/norm_inactive.png b/plugins/wtsynth/norm_inactive.png index d712c722a04f407aad3ce2dda983aeb727edfeea..7a0bd937d634aae0f48d86a04ed4721889419bb4 100644 GIT binary patch delta 423 zcmV;Y0a*UD0`>!t85#xv001BJ|6u?C00v@9M??Vs0RI60puMM)ks%-m6%!#3#>XGo zkx3_i0bWT&K~y-)jgvi&;!qHTzcDr`7eEMs2+Vyr0oUOq90rj9mL(!W0ubPzXI^(t zu<{ej4&JHA$yX|O)%!Y~PR5I(C;~uL0T2V;mNZR+s#2CE(Wj{U{T}ZW`9oi(V#3#vMdX6RrN10 z9Q`NQ%oq#?Y&IL}x(?7g+-Z=eDS4iAzu!N?08!ibYfY-kbUH;u$n*Ro{7-@wZpSlr z8jaZPcAdM3-UlKgVTJSgoZIczZQz{4%n*^#Z~M=a$%KBt-))d231${Lemz(m$INE4 zZUgT<-g}y+2?no9)3npzE6Xx#nuhcF93IJUR1^hORS^Rmk4Ngd{xQM-^bMhJ8IrPt Rk-z`|002ovPDHLkV1lI5zOVoQ delta 256 zcmV+b0ssE?1GEB=8889>005AYXf^-<010qNS#tmY3ljhU3ljkVnw%H_000McNliru z-UAdC4I5iq1%#1XCw~C0Nkl!ak(RgS4~FA8ga6NV}Dg7f3+x zA^t3;TXB;F7kcIea7*W$8BvVjQKu3_Mf@Hez4IGg8 zJV6RRBr4~8-0n__J)aFpRvPUV^WMCfc`N7V=f>I*5dc&bGb4mRp67%RNRouDtu5-h z#yLm7Uyv>V-g|a;ck$kn=Q&A|kR%DJ+C`FoC?J>_BEoz=Cp9zjJZEQT2N5C9b5ylc zA_(mh=RDqfoO75N)$b}Q7!1C2RYc@NpkM~hH8f3wS-=8_3X8fT1t^N%3iOF2xPT9y z#x(>V+8jX;KqA5C%BsqIKF7=`ih`zbgy5;F1tPGyx!L9ZlK|l6<_0t4=;(+n%McNN zZg0NQ09vBfrDMM#(X2DqC{0NCH(Cxn2ibl}lwv}#d6Bzi*E*LQYy z#`g9$)9IA5ECFRa9y1&cd3boBoR!^wkX55UbTAkoB3SFj(P%`LWjsDU^7p_0!B-T(jq07*qoM6N<$f^kO>Hvj+t delta 253 zcmV005AYXf^-<010qNS#tmY3ljhU3ljkVnw%H_000McNliru z-UAdC4G%$q(fN^ECw~B|NklX&bLI>KDS(NAL_lW^`T6-iK0eEqEhDVq?%lij z`T2Qyd0Vz@*|B5C-Me>jX<&h)cV1o|ey2~JIyEjX z4yu8jogI&n5GUNab!*Y0MGOoKjF=HuSy{=zz|h{_4(ERR_CgKrU`DJlou8jCAtCYU z)2DCWzHxDJrKF_5oxq4IX~f0FNlQy3Dxt)>vzQx!rDG6O?f+iUOq+#u%J)06ZQK;&;&X zdIg|fuLn5Kb3}wjqY>)fHt6^JhzPUU3;<&cqtOU}@pw$FR{L7|E4bZmBO)voivSM> z0|2JeX@LK0kYyR2PA9-hDbh6k0spJ$`@I1slL_8?hQnc4*nB<*pxf=fyy}k$mdho7 ztyYWGYDJo+!L`|Jve|4n9*^%Ec<(XB(ChVx?k6$QVPlS`8nhto!|b|C7Ys hZiiATWc)Y!1lhI*Doxi}od5s;07*p#PDHLkV1oE9&3XU; delta 256 zcmV+b0ssDm1hfK>8889>005AYXf^-<010qNS#tmY3ljhU3ljkVnw%H_000McNliru z-UAdC4I5iq1%#1XCw~C0Nkl!ak(RgS4~FA8ga6NV}Dg7f3+x zA^t^zv}(57oQLbScq3!BtHTo;w~eC#7BTY!~{Hnh0yUj zwve140%I>TJ9EK$y*76%wRVE3>aMODU0z;BwmwM!m>DrfLI~t}P6&Y{NjNw-psFgo z_Y_5+v<1|4&GGRubzPI^IZ2X`Bnf7=sU$IfK*Si4#A2}^jWLqvIfsXbNFvX3%xp7> z5bGn}*VJ{5_nsId%g<#q!C>%X(?!xwVGtvD?{Ll$V;}~QiB+{E1?cyC9q1cL@PRti zIPVB`Sl5XN&H%XieX}L4nF9%nF=ATV zWX8qC1u;ghudjJ~dqXnL&(A?H9*>#N=a?GFCSlutx4|jP5`d?tCnS)J)6-KV@%Z?- zZr)@fZS8Bp)9IASWWv$Wkg_Z>6Z83hoag6fhQlGF(P(XXBPAUS28~@YGMmkqOeSPm zMp>3f9XQJ}Mx)Wr9wd=E=a7t0dtP2%$g*rRt|b1vzV3j#u&w{&@i?BGoKUSQzT8*i zpSp+D1x(%Y)+F!m@1%QsdldaX%jL51_2z4SDLkNGXMYp07*qoM6N<$f|(K<6951J delta 253 zcmV005AYXf^-<010qNS#tmY3ljhU3ljkVnw%H_000McNliru z-UAdC4G%$q(fN^ECw~B|NklX&bLI>KDS(NAL_lW^`T6-iK0eEqEhDVq?%lij z`T2Qyd0Vz@*|B5C-Me>jX<&h)cV1o|ey2~JIyEjX z4yu8jogI&n5GUNab!*Y0MGOoKjF=HuSy{=zz|h{_4(ERR_CgKrU`DJlou8jCAtCYU z)2DCWzHxDJrKF_5oxq4IX~f0FNlQy3DOc@g&ki<-h#Wo-5rYKyBftr{35ZDeBpe{*jHhI<$Mfh7 zuJEpfuEbU}8g*6mRQG%xk4NDblu`hA?*VYm5r!e&d%X9wS}nBJXsrPVlu|h7xL&V( z0`EQ6T114~?MC3e|A;IiSZk@O3avHPTJk)9|JT7Mu2of0mLUL$}){ zNfH2t!y(Q&lv2cTjEFFw&)>)mffruxqtS@{evdJR<#Gu?6h&lN))aWn`vq$)Q54~S zoFk6oy6y3J48Ur&YScGEbk32cDeLu`e!tITGC@ShvW)F^%V035h28|b_oQh`k|YE{ zz<4}vki#&1BLgU{H6ns@j?HG%AOq}nyZ@2_z7B_jTrL;NvZN@Ade)!dbULA|we^Zx zYxygbF@{d3Q-6?8-5-y~Pl#!nQkG>Iz2kquH+P*Ecdfl1djJ3c07*qoM6N<$g7}8f A!vFvP delta 256 zcmV+b0ssD(1hfK>8889>005AYXf^-<010qNS#tmY3ljhU3ljkVnw%H_000McNliru z-UAdC4I5iq1%#1XCw~C0Nkl!ak(RgS4~FA8ga6NV}Dg7f3+x zA^t4nJa0`PlBg3pY5H=O_Iu1CqN1@b#rmUcvOa4nJa0`PlBg3pY5H=O_Iu1CqN@6;UmhL;3Q3l@MwB?`=jNv7l`uFLr6!i7rYMwWmSiZnd-?{1H}Z)C z6)AhVIEGl9PQG&KQj!G6fg=VE30EEkcDw7!ZLI(?*ykT*u-L#bZ@%>fC7^N!Pgg&e IbxsLQ0E1jG%>V!Z diff --git a/plugins/wtsynth/rm_active.png b/plugins/wtsynth/rm_active.png deleted file mode 100644 index c09789d32e7b2ea636f55e145fe074d4331f88fc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 169 zcmeAS@N?(olHy`uVBq!ia0vp^8bB<-!2~24nJa0`PlBg3pY5H=O_Iu1CqN1@b#rmUcvOa4nJa0`PlBg3pY5H=O_Iu1CqN@6;UmhL;3Q3l@MwB?`=jNv7l`uFLr6!i7rYMwWmSiZnd-?{1H}Z)C z6)AhVIEGl9PQG&KQj!G6fg=VE30EEkcDw7!ZLI(?*ykT*u-L#bZ@%>fC7^N!Pgg&e IbxsLQ0E1jG%>V!Z diff --git a/plugins/wtsynth/saw_active.png b/plugins/wtsynth/saw_active.png index 16b72849b221c93898b7a135cf68f3dba7ffb793..c5fd4dba635b220a7378c9a628941a5c154b6007 100644 GIT binary patch delta 512 zcmV+b0{{K70?q`G85#xv001BJ|6u?C00v@9M??Vs0RI60puMM)ks%-m6%!*D=bhyZ zkx3_i0k%m*K~y-)ZIUrkBS8#B-`7ly4c>r+qI@_`K;|(Aa71Jb1Z=_)muO+_ad%4_ zjAv{EU8Sl{{+HgDv|6o#lP3uPGb18!cbcZb-KnaItE(%zt|RBn#l@6*5R_7w&*zj< zXqtwqs;H_8GaIX_3=k24BtAbssUw1>X}G?BzD5#F(_m)fBtjg%+5fBZf=Ie zupzLqq<#{>-AOsob$fEktk-L9Z*Rx2rJoGU00p!5$Dyq8|3mf!V$9?(Qez@7t03 zo2Uow;p%#3XS3O`ShScOMZ=_hZas?4W-}xahii-o9v>fR+b?1hvQvZ}qfRLy8D9Fa z*XuRQ005AYXf^-<010qNS#tmY3ljhU3ljkVnw%H_000McNliru z-UAdC4G%$q(fN^ECw~B|NklX&bLI>KDS(NAL_lW^`T6-iK0eEqEhDVq?%lij z`T2Qyd0Vz@*|B5C-Me>jX<&h)cV1o|ey2~JIyEjX z4yu8jogI&n5GUNab!*Y0MGOoKjF=HuSy{=zz|h{_4(ERR_CgKrU`DJlou8jCAtCYU z)2DCWzHxDJrKF_5oxq4IX~f0FNlQy3DK~y-)m6I`!!axi~9|O4r_oF3gkf=BST#$x}28jZYAQ?|=&lX70vTSyT z-@ora-=4|wc+7lL2mt_h2f)mzstR|<-I-3OhzKGAz$}D-nQ^&XD3QCPs^pxxUatgq zFM@N<^nK6ibYihsaJ${O-|x=^B~w#M#28tBuh-1ybKIS_ZTXj0Rbq^^ZOd}Gq^|2B z5io9$b4FDW5xTCUu4}g2?Ens?kHKb!h!A6>X&QFB-5We=PznRjE&P0QDg2he%t$FA zB1Q0vfxFZ9eevYMKtx_jYntZQwnq)Bsv6F6Y*l|6s4A+;YPDjs+3=|*`~5zrlsKO% t&%-Av(c|%;>pErthr@vwBWCt-f-e#=03P898xa5i002ovPDHLkV1mdAotFRr delta 256 zcmV+b0ssE01GEB=8889>005AYXf^-<010qNS#tmY3ljhU3ljkVnw%H_000McNliru z-UAdC4I5iq1%#1XCw~C0Nkl!ak(RgS4~FA8ga6NV}Dg7f3+x zA^t9 diff --git a/plugins/wtsynth/sin_active.png b/plugins/wtsynth/sin_active.png index 16b72849b221c93898b7a135cf68f3dba7ffb793..de78b98773a0bb37f5ad5fdf9004452e94a4e093 100644 GIT binary patch delta 621 zcmV-z0+Ri)0=fl|85#xv001BJ|6u?C00v@9M??Vs0RI60puMM)ks%-m6%!){jV;Ch zkx3_i0wPI7K~y-)Ws^@%+fWe3e={adAWahqkO*CeEf*lL=Lqx!NL+$DlpSKvJ&3bI zqHEX(Hh?0UIPblgF6!`;dAoZa1BM1(xgQPoC? zAk??Sm`EuRW5nHA{8>~Ay4`OL%XC`s@bH__XvFF1DJZx@jDZjW?uHwP3d?eV0(3g< zYPl#7Q7$enczu24?(PnY#%i@H zWw|1T_!%^UNHq;WQ54NGfCKaSoag6f%+hBjA{9iPi?-WsG*h0Qo){e*Afk0(kzTLI z+uK{i_BoXfL{N7}MTs%;V}BoaBgRMwfxW#w=JR>Oyq=qzn@YY2y8hlG(iA7gh?y}Q z4w=nni0D566=2l~T?cr6evX+DLcq*_5E1(Q0khc*)jBXyUS3{kwOaKv*ywhLZq^#Ap}GeONN;>epQv7ogI3;Ufs;f#$+;Ke0C-q+vy{|005AYXf^-<010qNS#tmY3ljhU3ljkVnw%H_000McNliru z-UAdC4G%$q(fN^ECw~B|NklX&bLI>KDS(NAL_lW^`T6-iK0eEqEhDVq?%lij z`T2Qyd0Vz@*|B5C-Me>jX<&h)cV1o|ey2~JIyEjX z4yu8jogI&n5GUNab!*Y0MGOoKjF=HuSy{=zz|h{_4(ERR_CgKrU`DJlou8jCAtCYU z)2DCWzHxDJrKF_5oxq4IX~f0FNlQy3D3=ZTjc;DPvFsp(Ftrn;5kW+#R4OQ?P)Y$% z4T1n`Ew|f^-#|n##^9Xee!o){kvH;Uv0$}-TG8+K8IQ-l@0`OJgVq|Q6vh}Hj|V|% zxg-P3W;0HwldnYtr4&h$kfteGYea-JO$lD@Efxz#qY(g;$%OTKO_pWkc}|+9D5bF0 z;+(^|ztIKX$ff1$^-3JaWLbvR`iQ=r^;31bXODe^q0-EMO@9KQbi;UJ14thIhkMN!abG>GH) zjc`033B&MHKtw2tf;`Xt%(YsL>-G93u-$Iy^?FYMrIZh?JdiT&R;xv=R(lgzE|(04 z!>2$PhB)UaiUMN{BI0MRR;vsK1LpHe`BySPV2tr6YK-{^X*e9xY&MCa$k(s<+3j{t xYt7|y@%Dd%BuU7!j4Hr>zbDUgthM|v{s4PUMl54YMLPfh002ovPDHLkV1lxZ=8889>005AYXf^-<010qNS#tmY3ljhU3ljkVnw%H_000McNliru z-UAdC4I5iq1%#1XCw~C0Nkl!ak(RgS4~FA8ga6NV}Dg7f3+x zA^tAyS0*wWb85#xv001BJ|6u?C00v@9M??Vs0RI60puMM)ks%-m6%!*eteG)N zkx3_i0rg2lK~y-)ZIZ!G8$l36U-b-wu`L1zkeoYk$4SILaPlYdAN&G2aO6flfZT|L z6eOe&gv2Evyk5LBlf&3+Td-1VS3A>H)m5#NlatKSBMAUABj-#?i4X!QC7g3?ZEaE4 zHBHm7vC+ZL8)A$M1_NS@gb;Af;he+F+H%f+0FiS>60fhX_?$B#1a@|IkVFUpGi#Ly zG5e%xA~8mqrXlA{HLi++Ua#M>yu7?{adAOaRqsYRI5=Q9JR~QOiAi1I0Xm&^Bq51^ z&(Dmo*REL(FV{ zX{=K30j!u*W^PC+ky2WCqQX4)#jmfgW6p{s31MxdlSzeHNy2--L{xMjl@v@11>4(O zgb=8zinFutEtvP7qoX7C_V(KQCgJCK1EiGb_xp@SBc7g~+Ptr?e{p~Rhnt%l_V@Q^ z&j*EMxrf3ProFuPWi{09zQ%g2!q0yew= O0000005AYXf^-<010qNS#tmY3ljhU3ljkVnw%H_000McNliru z-UAdC4G%$q(fN^ECw~B|NklX&bLI>KDS(NAL_lW^`T6-iK0eEqEhDVq?%lij z`T2Qyd0Vz@*|B5C-Me>jX<&h)cV1o|ey2~JIyEjX z4yu8jogI&n5GUNab!*Y0MGOoKjF=HuSy{=zz|h{_4(ERR_CgKrU`DJlou8jCAtCYU z)2DCWzHxDJrKF_5oxq4IX~f0FNlQy3DlB-Q{sU_ERB*1!hHiAbDa37O3N z1lai5?=wNGJ-F!}F%>@5ty{NVSy2=jo?zQH09tDRlu~$}ht?XcHICyTgg^)ZfNR?} zN-56gGw(oajg%5&442CVS8H7vJ|2(E=W}jXY7-LA11Y-#Y{00000NkvXXu0mjf8W!L8 delta 256 zcmV+b0ssED1hfK>8889>005AYXf^-<010qNS#tmY3ljhU3ljkVnw%H_000McNliru z-UAdC4I5iq1%#1XCw~C0Nkl!ak(RgS4~FA8ga6NV}Dg7f3+x zA^t^zv{Kd2K#{*#5sf`1j_*s2#F8@3GhS|PU-xBkvMGc z&QIUN>?}T5sioEYR998k=;`Unx%eajU}m^Gr4&L4lv3!rj+>hs`o1Tn#MRY;S-X&P zX1!jMb0&m9*L8GVhnY>)bp{A`M-rc(pUm8Uoe%=Ix3@?lgn*e%OoSMJNhy_a|lmi^UvCJUl!g37Ie% zyWNgb3d1lEQ>5fF?F#{_0A>b)^?Hq@Dgg)~Ac?*oC?(f(ldM|S0E8y9035i#|4mAN ziBj@^(zx)&=JPq$jmTz5HX4@r`1s2(3{$sO`~4q4AYtx~sk+{o;a*57jfOdIZ*NoQ zR_~$D(!06@pwdIgH{!=X2P28$HzxXDa073%dNB7XqfCGsnrKtE|*B+ z*O+5T-77I?NQ`M)h1FO}F!{NYgw;SjFCE005AYXf^-<010qNS#tmY3ljhU3ljkVnw%H_000McNliru z-UAdC4G%$q(fN^ECw~B|NklX&bLI>KDS(NAL_lW^`T6-iK0eEqEhDVq?%lij z`T2Qyd0Vz@*|B5C-Me>jX<&h)cV1o|ey2~JIyEjX z4yu8jogI&n5GUNab!*Y0MGOoKjF=HuSy{=zz|h{_4(ERR_CgKrU`DJlou8jCAtCYU z)2DCWzHxDJrKF_5oxq4IX~f0FNlQy3DX zkx3_i0b)r+K~y-)m69=z;y@5Z-xw^Ba0K8OoB?qN60X4^xB@W;A|XN$0Fo_%vAesf zYl4w`U>Wbu{?P6J`uDH;I2;bfld>!WAjSxQs*>k9F-BsH^m;v#b(SbUG!3KwZ~( z@88Uw05d~XDa(?ost6&Z?*PZ+@$Udt#W_a^fz#>qVg^{R*WZA4-mOFg=NwJbpsL(@ zZnwACKR#i#TA`|GOl|CcDFH^K5g~-s_Mfpk0nWKpTDu@WwcVwDp68euAp}H(7-KTG zeLT1R1`v_7q9XEgI2;bSUaxGo+fKm8Znrb}002ovPDHLkV1mwY$2$N3 delta 256 zcmV+b0ssE`1GEB=8889>005AYXf^-<010qNS#tmY3ljhU3ljkVnw%H_000McNliru z-UAdC4I5iq1%#1XCw~C0Nkl!ak(RgS4~FA8ga6NV}Dg7f3+x zA^tOc@iPj{?=C8j#{f)f5ycnHNL;z4#%#08MaU2suAc`WcudgYJ0_Pl;mwhhI2fX(r zNrLyDIF5;;h$xCs)h41y0l~}=5e|m~7iLC(9LL<<-60~xag3@qN(7-E;+)5Ok8=() z1l(_|5mCYH-3BEs|YGtQNiWr|Am<956FZrxT?s z2|m<&1VI2n&%l}xK~>poHatB&@%Z@2YPG_Zt_4l2^7jR*0PJ=<(lli{owDEWTP9L} zWj=G!UayBnb^WS{C~t3XWLd^=IAk;$k)|nmo_F|EIuJq443)Y~s+a|KyB*W%6z@GE z%4{~{^YgQnEn5Et?e^Quczu24{{EiZ+gnttY~%5S*=)vkyRAwP5UD(&-S&kL`1trB zP1Cy8GZ*=$;yfn;Iv5NP5e!(b*JN3L#&|rgH@38sWWszt=l%V?;UFStS(b<>!3XyH zJz17@vQ%KThC83nn~unt!|8OwEU;d!$g+%Nl6-TdHU<-tB;n!Vfz4*qu3ueUaoO*a z|IN9%8CEXqC}IVzIEIC@6}85W)|`@a=8<3{~YngAutA$g1ax Qg8%>k07*qoM6N<$f|EcJ*Z=?k delta 253 zcmV005AYXf^-<010qNS#tmY3ljhU3ljkVnw%H_000McNliru z-UAdC4G%$q(fN^ECw~B|NklX&bLI>KDS(NAL_lW^`T6-iK0eEqEhDVq?%lij z`T2Qyd0Vz@*|B5C-Me>jX<&h)cV1o|ey2~JIyEjX z4yu8jogI&n5GUNab!*Y0MGOoKjF=HuSy{=zz|h{_4(ERR_CgKrU`DJlou8jCAtCYU z)2DCWzHxDJrKF_5oxq4IX~f0FNlQy3D)@ow2 zkx3_i0eneBK~y-)m6JP;;y@Hd4+d|bg=NVs0DlmhU`?!o#TW=p#0n}yBt(b^OMt}3 zRj$tjEv#;}J=1fu3QoOKuion&k4MLsc%BD!yZns-gRVhVP zRn&EjF$RF=^GWY?I=Qkef57YYy6J(|n%QhdUDr70aPG5hWm(c$UI@WtG9gJ4gb*mD zzQIk?+u+q|#dJC)3`2q-AdX{-qWA%KULb@ZNs{KxS(dTe?OIK}_kX{W=Q&xH5d;B$ zbzK7xMGyD%IM*>1PZxwqf%ol=VP w`P?kYZ}NCNc)eZ>01k%(RaG@J{y+H@1I{P|Punp(p8x;=07*qoM6N<$f=ZUpEdT%j delta 256 zcmV+b0ssD#1hfK>8889>005AYXf^-<010qNS#tmY3ljhU3ljkVnw%H_000McNliru z-UAdC4I5iq1%#1XCw~C0Nkl!ak(RgS4~FA8ga6NV}Dg7f3+x zA^t|gW!U_%O?XxI14-? ziy0WWg+Z8+Vb&Z8pdfpRr>`sfJ!Vm1L5W#GYu*BdBuiW)N}Tg^b5rw57@Uhz6H8K4 z6v{J8G8EiBeFMT9`NSC*7|(dRIEGZ*dVAg1>#&1F!^8L9SsQj~zTCH6`27RbJ9dAI=3+{_9yY zoByz|lFYRVo4EH4u_N@;@Wxv z)j0|5EG!&M1TiBM6AMweiJ`GrqIB}Eb&GXQuMHG&O-V~hb8-34^6j$8*>?=Lx4m^f zea3E2VhIzAdw_s~f&+HUAt0cDAK%yjQlWQgI>SL(0TvDpEcng)sD=dgmTuEmYNfI6 zk<+3VYjmABbK*=#$3MO#5jcFKX|4Bg(OQ{BTAg}b8}PkN*J7rQWHy3QxwWGOEMJPJ$(bh8~Mb6 zif($kIEGZ*dV9%Gkb!~Yh(SW#|0=_S2PSyD*g9FH##AUFz(9kIwYkaBP(wllNF7`t zA;QxIq!I#nxY&*YDX@GJkRnPRWDGw2aCx9IZ02Li1C_Bh!|jL4KRm;vx|ZQv{LfF{ QfSzRVboFyt=akR{045G)G5`Po From f7e107ea2cd71415304438e253cc34cd8d6cca98 Mon Sep 17 00:00:00 2001 From: Vesa Date: Fri, 21 Mar 2014 23:45:53 +0200 Subject: [PATCH 076/647] Add some mixer locks --- plugins/wtsynth/WTSynth.cpp | 48 ++++++++++++++++++++++++++++--------- 1 file changed, 37 insertions(+), 11 deletions(-) diff --git a/plugins/wtsynth/WTSynth.cpp b/plugins/wtsynth/WTSynth.cpp index e51c0ff96..8b533ed4b 100644 --- a/plugins/wtsynth/WTSynth.cpp +++ b/plugins/wtsynth/WTSynth.cpp @@ -238,7 +238,7 @@ void WTSynthObject::changeVolume( int _osc, float _lvol, float _rvol ) { m_lvol[_osc] = _lvol / 100.0; m_rvol[_osc] = _rvol / 100.0; - qDebug( "osc %d vol %f %f", _osc, m_lvol[_osc], m_rvol[_osc] ); +// qDebug( "osc %d vol %f %f", _osc, m_lvol[_osc], m_rvol[_osc] ); } @@ -402,18 +402,34 @@ void WTSynthInstrument::playNote( NotePlayHandle * _n, sampleFrame * bbuf = w->bbuf(); w-> renderOutput( frames ); - - for( fpp_t f=0; f < frames; f++ ) + + if( engine::mixer()->currentQualitySettings().sampleExactControllers ) { - // get knob values in sample-exact way - const float bmix = ( ( m_abmix.value( f ) + 100.0 ) / 200.0 ); + for( fpp_t f=0; f < frames; f++ ) + { + // get knob values in sample-exact way + const float bmix = ( ( m_abmix.value( f ) + 100.0 ) / 200.0 ); + const float amix = 1.0 - bmix; + + // mix a/b streams according to mixing knob + _working_buffer[f][0] = ( abuf[f][0] * amix ) + + ( bbuf[f][0] * bmix ); + _working_buffer[f][1] = ( abuf[f][1] * amix ) + + ( bbuf[f][1] * bmix ); + } + } + else + { + const float bmix = ( ( m_abmix.value() + 100.0 ) / 200.0 ); const float amix = 1.0 - bmix; - - // mix a/b streams according to mixing knob - _working_buffer[f][0] = ( abuf[f][0] * amix ) + - ( bbuf[f][0] * bmix ); - _working_buffer[f][1] = ( abuf[f][1] * amix ) + - ( bbuf[f][1] * bmix ); + for( fpp_t f=0; f < frames; f++ ) + { + // mix a/b streams according to mixing knob + _working_buffer[f][0] = ( abuf[f][0] * amix ) + + ( bbuf[f][0] * bmix ); + _working_buffer[f][1] = ( abuf[f][1] * amix ) + + ( bbuf[f][1] * bmix ); + } } applyRelease( _working_buffer, _n ); @@ -947,6 +963,7 @@ void WTSynthView::sqrWaveClicked() void WTSynthView::normalizeClicked() { + engine::mixer()->lock(); switch( m_selectedGraphGroup->model()->value() ) { case A1_OSC: @@ -966,11 +983,13 @@ void WTSynthView::normalizeClicked() engine::getSong()->setModified(); break; } + engine::mixer()->unlock(); } void WTSynthView::invertClicked() { + engine::mixer()->lock(); switch( m_selectedGraphGroup->model()->value() ) { case A1_OSC: @@ -990,11 +1009,13 @@ void WTSynthView::invertClicked() engine::getSong()->setModified(); break; } + engine::mixer()->unlock(); } void WTSynthView::smoothClicked() { + engine::mixer()->lock(); switch( m_selectedGraphGroup->model()->value() ) { case A1_OSC: @@ -1014,11 +1035,13 @@ void WTSynthView::smoothClicked() engine::getSong()->setModified(); break; } + engine::mixer()->unlock(); } void WTSynthView::phaseLeftClicked() { + engine::mixer()->lock(); switch( m_selectedGraphGroup->model()->value() ) { case A1_OSC: @@ -1038,11 +1061,13 @@ void WTSynthView::phaseLeftClicked() engine::getSong()->setModified(); break; } + engine::mixer()->unlock(); } void WTSynthView::phaseRightClicked() { + engine::mixer()->lock(); switch( m_selectedGraphGroup->model()->value() ) { case A1_OSC: @@ -1062,6 +1087,7 @@ void WTSynthView::phaseRightClicked() engine::getSong()->setModified(); break; } + engine::mixer()->unlock(); } From b574e1c1ca4a22afee345bee3557f646ccdfdbc2 Mon Sep 17 00:00:00 2001 From: Vesa Date: Fri, 21 Mar 2014 23:53:15 +0200 Subject: [PATCH 077/647] Revert earlier --- plugins/wtsynth/WTSynth.cpp | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/plugins/wtsynth/WTSynth.cpp b/plugins/wtsynth/WTSynth.cpp index 8b533ed4b..98fbab8e2 100644 --- a/plugins/wtsynth/WTSynth.cpp +++ b/plugins/wtsynth/WTSynth.cpp @@ -963,7 +963,6 @@ void WTSynthView::sqrWaveClicked() void WTSynthView::normalizeClicked() { - engine::mixer()->lock(); switch( m_selectedGraphGroup->model()->value() ) { case A1_OSC: @@ -983,13 +982,11 @@ void WTSynthView::normalizeClicked() engine::getSong()->setModified(); break; } - engine::mixer()->unlock(); } void WTSynthView::invertClicked() { - engine::mixer()->lock(); switch( m_selectedGraphGroup->model()->value() ) { case A1_OSC: @@ -1009,13 +1006,11 @@ void WTSynthView::invertClicked() engine::getSong()->setModified(); break; } - engine::mixer()->unlock(); } void WTSynthView::smoothClicked() { - engine::mixer()->lock(); switch( m_selectedGraphGroup->model()->value() ) { case A1_OSC: @@ -1035,13 +1030,11 @@ void WTSynthView::smoothClicked() engine::getSong()->setModified(); break; } - engine::mixer()->unlock(); } void WTSynthView::phaseLeftClicked() { - engine::mixer()->lock(); switch( m_selectedGraphGroup->model()->value() ) { case A1_OSC: @@ -1061,13 +1054,11 @@ void WTSynthView::phaseLeftClicked() engine::getSong()->setModified(); break; } - engine::mixer()->unlock(); } void WTSynthView::phaseRightClicked() { - engine::mixer()->lock(); switch( m_selectedGraphGroup->model()->value() ) { case A1_OSC: @@ -1087,7 +1078,6 @@ void WTSynthView::phaseRightClicked() engine::getSong()->setModified(); break; } - engine::mixer()->unlock(); } From 10994e3ae5c2bb601036461a3e658c194ec32ab9 Mon Sep 17 00:00:00 2001 From: Vesa Date: Sat, 22 Mar 2014 02:37:47 +0200 Subject: [PATCH 078/647] Copy wavegraphs to synthobject at note start, prevent hangups if wave edited while playing --- plugins/wtsynth/WTSynth.cpp | 10 ++++++---- plugins/wtsynth/WTSynth.h | 11 +++++------ 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/plugins/wtsynth/WTSynth.cpp b/plugins/wtsynth/WTSynth.cpp index 98fbab8e2..94ea69093 100644 --- a/plugins/wtsynth/WTSynth.cpp +++ b/plugins/wtsynth/WTSynth.cpp @@ -57,10 +57,6 @@ Plugin::Descriptor PLUGIN_EXPORT wtsynth_plugin_descriptor = WTSynthObject::WTSynthObject( float * _A1wave, float * _A2wave, float * _B1wave, float * _B2wave, int _amod, int _bmod, const sample_rate_t _samplerate, NotePlayHandle * _nph, fpp_t _frames ) : - m_A1wave( _A1wave ), - m_A2wave( _A2wave ), - m_B1wave( _B1wave ), - m_B2wave( _B2wave ), m_amod( _amod ), m_bmod( _bmod ), m_samplerate( _samplerate ), @@ -79,6 +75,12 @@ WTSynthObject::WTSynthObject( float * _A1wave, float * _A2wave, m_rphase[A2_OSC] = 0.0f; m_rphase[B1_OSC] = 0.0f; m_rphase[B2_OSC] = 0.0f; + + // copy wavegraphs to the synth object to prevent race conditions + memcpy( &m_A1wave, _A1wave, sizeof( m_A1wave ) ); + memcpy( &m_A2wave, _A2wave, sizeof( m_A2wave ) ); + memcpy( &m_B1wave, _B1wave, sizeof( m_B1wave ) ); + memcpy( &m_B2wave, _B2wave, sizeof( m_B2wave ) ); } diff --git a/plugins/wtsynth/WTSynth.h b/plugins/wtsynth/WTSynth.h index 37d3cec0e..0484fa7da 100644 --- a/plugins/wtsynth/WTSynth.h +++ b/plugins/wtsynth/WTSynth.h @@ -91,11 +91,6 @@ public: } private: - sample_t * m_A1wave; - sample_t * m_A2wave; - sample_t * m_B1wave; - sample_t * m_B2wave; - float m_lvol [NUM_OSCS]; float m_rvol [NUM_OSCS]; float m_mult [NUM_OSCS]; @@ -118,7 +113,11 @@ private: float m_lfreq [NUM_OSCS]; float m_rfreq [NUM_OSCS]; - + + float m_A1wave [WAVELEN]; + float m_A2wave [WAVELEN]; + float m_B1wave [WAVELEN]; + float m_B2wave [WAVELEN]; }; class WTSynthInstrument : public Instrument From ed2b63b1fffe8d3f6db7736754f2596652b2647c Mon Sep 17 00:00:00 2001 From: Vesa Date: Sat, 22 Mar 2014 22:26:41 +0200 Subject: [PATCH 079/647] Added simple mix envelope --- data/themes/default/style.css | 15 ++- plugins/wtsynth/WTSynth.cpp | 173 ++++++++++++++++++++++++---------- plugins/wtsynth/WTSynth.h | 15 ++- plugins/wtsynth/artwork.png | Bin 94710 -> 95609 bytes 4 files changed, 151 insertions(+), 52 deletions(-) diff --git a/data/themes/default/style.css b/data/themes/default/style.css index bba01399d..c2e91bd05 100644 --- a/data/themes/default/style.css +++ b/data/themes/default/style.css @@ -612,7 +612,7 @@ WTSynthView knob#aKnob { color: #43b2ff; qproperty-outerColor: #43b2ff; qproperty-innerRadius: 1; - qproperty-outerRadius: 8; + qproperty-outerRadius: 7; qproperty-centerPointX: 9.5; qproperty-centerPointY: 9.5; qproperty-lineWidth: 2; @@ -622,7 +622,7 @@ WTSynthView knob#bKnob { color: #fc5431; qproperty-outerColor: #fc5431; qproperty-innerRadius: 1; - qproperty-outerRadius: 8; + qproperty-outerRadius: 7; qproperty-centerPointX: 9.5; qproperty-centerPointY: 9.5; qproperty-lineWidth: 2; @@ -632,12 +632,21 @@ WTSynthView knob#mixKnob { color: #43ff82; qproperty-outerColor: #43ff82; qproperty-innerRadius: 1; - qproperty-outerRadius: 14; + qproperty-outerRadius: 13; qproperty-centerPointX: 15.5; qproperty-centerPointY: 15.5; qproperty-lineWidth: 2; } +WTSynthView knob#mixenvKnob { + color: #43ff82; + qproperty-outerColor: #43ff82; + qproperty-innerRadius: 1; + qproperty-outerRadius: 7; + qproperty-centerPointX: 9.5; + qproperty-centerPointY: 9.5; + qproperty-lineWidth: 2; +} /* palette information - each colour definition must be on a single line, and the line must begin with "palette:", with no leading whitespace * colour codes MUST be of the form #RRGGBB */ diff --git a/plugins/wtsynth/WTSynth.cpp b/plugins/wtsynth/WTSynth.cpp index 94ea69093..82fa8dba6 100644 --- a/plugins/wtsynth/WTSynth.cpp +++ b/plugins/wtsynth/WTSynth.cpp @@ -65,17 +65,17 @@ WTSynthObject::WTSynthObject( float * _A1wave, float * _A2wave, { m_abuf = new sampleFrame[_frames]; m_bbuf = new sampleFrame[_frames]; - + m_lphase[A1_OSC] = 0.0f; m_lphase[A2_OSC] = 0.0f; m_lphase[B1_OSC] = 0.0f; m_lphase[B2_OSC] = 0.0f; - + m_rphase[A1_OSC] = 0.0f; m_rphase[A2_OSC] = 0.0f; m_rphase[B1_OSC] = 0.0f; m_rphase[B2_OSC] = 0.0f; - + // copy wavegraphs to the synth object to prevent race conditions memcpy( &m_A1wave, _A1wave, sizeof( m_A1wave ) ); memcpy( &m_A2wave, _A2wave, sizeof( m_A2wave ) ); @@ -98,31 +98,31 @@ void WTSynthObject::renderOutput( fpp_t _frames ) m_abuf = new sampleFrame[m_fpp]; if( m_bbuf == NULL ) m_bbuf = new sampleFrame[m_fpp]; - + for( fpp_t frame = 0; frame < _frames; frame++ ) { float frac; // A2 frac = fraction( m_lphase[A2_OSC] ); - sample_t A2_L = + sample_t A2_L = ( m_A2wave[ static_cast( m_lphase[A2_OSC] ) % WAVELEN ] * ( 1.0f - frac ) ) + ( m_A2wave[ static_cast( m_lphase[A2_OSC] + 1 ) % WAVELEN ] * frac ); A2_L *= m_lvol[A2_OSC]; frac = fraction( m_rphase[A2_OSC] ); - sample_t A2_R = + sample_t A2_R = ( m_A2wave[ static_cast( m_rphase[A2_OSC] ) % WAVELEN ] * ( 1.0f - frac ) ) + ( m_A2wave[ static_cast( m_rphase[A2_OSC] + 1 ) % WAVELEN ] * frac ); A2_R *= m_rvol[A2_OSC]; // B2 frac = fraction( m_lphase[B2_OSC] ); - sample_t B2_L = + sample_t B2_L = ( m_B2wave[ static_cast( m_lphase[B2_OSC] ) % WAVELEN ] * ( 1.0f - frac ) ) + ( m_B2wave[ static_cast( m_lphase[B2_OSC] + 1 ) % WAVELEN ] * frac ); B2_L *= m_lvol[B2_OSC]; frac = fraction( m_rphase[B2_OSC] ); - sample_t B2_R = + sample_t B2_R = ( m_B2wave[ static_cast( m_rphase[B2_OSC] ) % WAVELEN ] * ( 1.0f - frac ) ) + ( m_B2wave[ static_cast( m_rphase[B2_OSC] + 1 ) % WAVELEN ] * frac ); B2_R *= m_rvol[B2_OSC]; @@ -151,28 +151,28 @@ void WTSynthObject::renderOutput( fpp_t _frames ) // A1 frac = fraction( A1_lphase ); - sample_t A1_L = + sample_t A1_L = ( m_A1wave[ static_cast( A1_lphase ) % WAVELEN ] * ( 1.0f - frac ) ) + ( m_A1wave[ static_cast( A1_lphase + 1 ) % WAVELEN ] * frac ); A1_L *= m_lvol[A1_OSC]; frac = fraction( A1_rphase ); - sample_t A1_R = + sample_t A1_R = ( m_A1wave[ static_cast( A1_rphase ) % WAVELEN ] * ( 1.0f - frac ) ) + ( m_A1wave[ static_cast( A1_rphase + 1 ) % WAVELEN ] * frac ); A1_R *= m_rvol[A1_OSC]; // B1 frac = fraction( B1_lphase ); - sample_t B1_L = + sample_t B1_L = ( m_B1wave[ static_cast( B1_lphase ) % WAVELEN ] * ( 1.0f - frac ) ) + ( m_B1wave[ static_cast( B1_lphase + 1 ) % WAVELEN ] * frac ); B1_L *= m_lvol[B1_OSC]; frac = fraction( B1_rphase ); - sample_t B1_R = + sample_t B1_R = ( m_B1wave[ static_cast( B1_rphase ) % WAVELEN ] * ( 1.0f - frac ) ) + ( m_B1wave[ static_cast( B1_rphase + 1 ) % WAVELEN ] * frac ); B1_R *= m_rvol[B1_OSC]; - + // A-series modulation) switch( m_amod ) { @@ -271,10 +271,10 @@ WTSynthInstrument::WTSynthInstrument( InstrumentTrack * _instrument_track ) : b1_pan( 0.0f, -100.0f, 100.0f, 0.1f, this, tr( "Panning B1" ) ), b2_pan( 0.0f, -100.0f, 100.0f, 0.1f, this, tr( "Panning B2" ) ), - a1_mult( 8.0f, 1.0, 16.0, 1.0, this, tr( "Freq. multiplier A1" ) ), - a2_mult( 8.0f, 1.0, 16.0, 1.0, this, tr( "Freq. multiplier A2" ) ), - b1_mult( 8.0f, 1.0, 16.0, 1.0, this, tr( "Freq. multiplier B1" ) ), - b2_mult( 8.0f, 1.0, 16.0, 1.0, this, tr( "Freq. multiplier B2" ) ), + a1_mult( 8.0f, 1.0, 24.0, 1.0, this, tr( "Freq. multiplier A1" ) ), + a2_mult( 8.0f, 1.0, 24.0, 1.0, this, tr( "Freq. multiplier A2" ) ), + b1_mult( 8.0f, 1.0, 24.0, 1.0, this, tr( "Freq. multiplier B1" ) ), + b2_mult( 8.0f, 1.0, 24.0, 1.0, this, tr( "Freq. multiplier B2" ) ), a1_ltune( 0.0f, -600.0f, 600.0f, 1.0f, this, tr( "Left detune A1" ) ), a2_ltune( 0.0f, -600.0f, 600.0f, 1.0f, this, tr( "Left detune A2" ) ), @@ -292,6 +292,10 @@ WTSynthInstrument::WTSynthInstrument( InstrumentTrack * _instrument_track ) : b2_graph( -1.0f, 1.0f, WAVELEN, this ), m_abmix( 0.0f, -100.0f, 100.0f, 0.1f, this, tr( "A-B Mix" ) ), + m_envAmt( 0.0f, -200.0f, 200.0f, 0.1f, this, tr( "A-B Mix envelope amount" ) ), + m_envAtt( 0.0f, 0.0f, 2000.0f, 1.0f, this, tr( "A-B Mix envelope attack" ) ), + m_envDec( 0.0f, 0.0f, 2000.0f, 1.0f, this, tr( "A-B Mix envelope decay" ) ), + m_amod( 0, 0, 3, this, tr( "A2-A1 modulation" ) ), m_bmod( 0, 0, 3, this, tr( "B2-B1 modulation" ) ), @@ -361,7 +365,7 @@ void WTSynthInstrument::playNote( NotePlayHandle * _n, w -> changeVolume( A2_OSC, leftCh( a2_vol.value(), a2_pan.value() ), rightCh( a2_vol.value(), a2_pan.value() ) ); w -> changeVolume( B1_OSC, leftCh( b1_vol.value(), b1_pan.value() ), rightCh( b1_vol.value(), b1_pan.value() ) ); w -> changeVolume( B2_OSC, leftCh( b2_vol.value(), b2_pan.value() ), rightCh( b2_vol.value(), b2_pan.value() ) ); - + w -> updateFrequencies(); _n->m_pluginData = w; @@ -399,20 +403,42 @@ void WTSynthInstrument::playNote( NotePlayHandle * _n, w-> updateFrequencies(); m_multChanged = false; } - + sampleFrame * abuf = w->abuf(); sampleFrame * bbuf = w->bbuf(); w-> renderOutput( frames ); - + + // envelope parameters + const float envAmt = m_envAmt.value(); + const float envAtt = ( m_envAtt.value() * w->samplerate() ) / 1000.0f; + const float envDec = ( m_envDec.value() * w->samplerate() ) / 1000.0f; + const float envLen = envAtt + envDec; + const float tfp_ = static_cast( _n->totalFramesPlayed() ); + + // if sample-exact is enabled, use sample-exact calculations... if( engine::mixer()->currentQualitySettings().sampleExactControllers ) { for( fpp_t f=0; f < frames; f++ ) { + const float tfp = tfp_ + f; + // handle mixing envelope + float mixvalue = m_abmix.value( f ); + if( envAmt != 0.0f && tfp < envLen ) + { + if( tfp < envAtt ) + { + mixvalue = qBound( -100.0f, mixvalue + ( tfp / envAtt * envAmt ), 100.0f ); + } + else + { + mixvalue = qBound( -100.0f, mixvalue + envAmt - ( ( tfp - envAtt ) / envDec * envAmt ), 100.0f ); + } + } // get knob values in sample-exact way - const float bmix = ( ( m_abmix.value( f ) + 100.0 ) / 200.0 ); + const float bmix = ( ( mixvalue + 100.0 ) / 200.0 ); const float amix = 1.0 - bmix; - + // mix a/b streams according to mixing knob _working_buffer[f][0] = ( abuf[f][0] * amix ) + ( bbuf[f][0] * bmix ); @@ -420,18 +446,52 @@ void WTSynthInstrument::playNote( NotePlayHandle * _n, ( bbuf[f][1] * bmix ); } } - else + + // if sample-exact is not enabled, use simpler calculations: + // if mix envelope is active, and we haven't gone past the envelope end, use envelope-aware calculation... + else if( envAmt != 0.0f && tfp_ < envLen ) { - const float bmix = ( ( m_abmix.value() + 100.0 ) / 200.0 ); - const float amix = 1.0 - bmix; + const float mixvalue_ = m_abmix.value(); for( fpp_t f=0; f < frames; f++ ) - { + { + float mixvalue = mixvalue_; + const float tfp = tfp_ + f; + // handle mixing envelope + if( tfp < envAtt ) + { + mixvalue = qBound( -100.0f, mixvalue + ( tfp / envAtt * envAmt ), 100.0f ); + } + else + { + mixvalue = qBound( -100.0f, mixvalue + envAmt - ( ( tfp - envAtt ) / envDec * envAmt ), 100.0f ); + } + + // get knob values + const float bmix = ( ( mixvalue + 100.0 ) / 200.0 ); + const float amix = 1.0 - bmix; + // mix a/b streams according to mixing knob _working_buffer[f][0] = ( abuf[f][0] * amix ) + ( bbuf[f][0] * bmix ); _working_buffer[f][1] = ( abuf[f][1] * amix ) + ( bbuf[f][1] * bmix ); - } + } + } + + // ... mix envelope is inactive or we've past the end of envelope, so use a faster calculation to save cpu + else + { + // get knob values + const float bmix = ( ( m_abmix.value() + 100.0 ) / 200.0 ); + const float amix = 1.0 - bmix; + for( fpp_t f=0; f < frames; f++ ) + { + // mix a/b streams according to mixing knob + _working_buffer[f][0] = ( abuf[f][0] * amix ) + + ( bbuf[f][0] * bmix ); + _working_buffer[f][1] = ( abuf[f][1] * amix ) + + ( bbuf[f][1] * bmix ); + } } applyRelease( _working_buffer, _n ); @@ -487,6 +547,10 @@ void WTSynthInstrument::saveSettings( QDomDocument & _doc, _this.setAttribute( "b2_wave", sampleString ); m_abmix.saveSettings( _doc, _this, "abmix" ); + m_envAmt.saveSettings( _doc, _this, "envAmt" ); + m_envAtt.saveSettings( _doc, _this, "envAtt" ); + m_envDec.saveSettings( _doc, _this, "envDec" ); + m_amod.saveSettings( _doc, _this, "amod" ); m_bmod.saveSettings( _doc, _this, "bmod" ); m_selectedGraph.saveSettings( _doc, _this, "selgraph" ); @@ -536,6 +600,11 @@ void WTSynthInstrument::loadSettings( const QDomElement & _this ) delete[] dst; m_abmix.loadSettings( _this, "abmix" ); + + m_envAmt.loadSettings( _this, "envAmt" ); + m_envAtt.loadSettings( _this, "envAtt" ); + m_envDec.loadSettings( _this, "envDec" ); + m_amod.loadSettings( _this, "amod" ); m_bmod.loadSettings( _this, "bmod" ); m_selectedGraph.loadSettings( _this, "selgraph" ); @@ -580,32 +649,36 @@ WTSynthView::WTSynthView( Instrument * _instrument, // knobs... lots of em - makeknob( a1_volKnob, 118, A1ROW, "Volume", "%", "aKnob" ) - makeknob( a2_volKnob, 118, A2ROW, "Volume", "%", "aKnob" ) - makeknob( b1_volKnob, 118, B1ROW, "Volume", "%", "bKnob" ) - makeknob( b2_volKnob, 118, B2ROW, "Volume", "%", "bKnob" ) + makeknob( a1_volKnob, 130, A1ROW, "Volume", "%", "aKnob" ) + makeknob( a2_volKnob, 130, A2ROW, "Volume", "%", "aKnob" ) + makeknob( b1_volKnob, 130, B1ROW, "Volume", "%", "bKnob" ) + makeknob( b2_volKnob, 130, B2ROW, "Volume", "%", "bKnob" ) - makeknob( a1_panKnob, 142, A1ROW, "Panning", "", "aKnob" ) - makeknob( a2_panKnob, 142, A2ROW, "Panning", "", "aKnob" ) - makeknob( b1_panKnob, 142, B1ROW, "Panning", "", "bKnob" ) - makeknob( b2_panKnob, 142, B2ROW, "Panning", "", "bKnob" ) + makeknob( a1_panKnob, 154, A1ROW, "Panning", "", "aKnob" ) + makeknob( a2_panKnob, 154, A2ROW, "Panning", "", "aKnob" ) + makeknob( b1_panKnob, 154, B1ROW, "Panning", "", "bKnob" ) + makeknob( b2_panKnob, 154, B2ROW, "Panning", "", "bKnob" ) - makeknob( a1_multKnob, 172, A1ROW, "Freq. multiplier", "/8", "aKnob" ) - makeknob( a2_multKnob, 172, A2ROW, "Freq. multiplier", "/8", "aKnob" ) - makeknob( b1_multKnob, 172, B1ROW, "Freq. multiplier", "/8", "bKnob" ) - makeknob( b2_multKnob, 172, B2ROW, "Freq. multiplier", "/8", "bKnob" ) + makeknob( a1_multKnob, 178, A1ROW, "Freq. multiplier", "/8", "aKnob" ) + makeknob( a2_multKnob, 178, A2ROW, "Freq. multiplier", "/8", "aKnob" ) + makeknob( b1_multKnob, 178, B1ROW, "Freq. multiplier", "/8", "bKnob" ) + makeknob( b2_multKnob, 178, B2ROW, "Freq. multiplier", "/8", "bKnob" ) - makeknob( a1_ltuneKnob, 200, A1ROW, "Left detune", " cents", "aKnob" ) - makeknob( a2_ltuneKnob, 200, A2ROW, "Left detune", " cents", "aKnob" ) - makeknob( b1_ltuneKnob, 200, B1ROW, "Left detune", " cents", "bKnob" ) - makeknob( b2_ltuneKnob, 200, B2ROW, "Left detune", " cents", "bKnob" ) + makeknob( a1_ltuneKnob, 202, A1ROW, "Left detune", " cents", "aKnob" ) + makeknob( a2_ltuneKnob, 202, A2ROW, "Left detune", " cents", "aKnob" ) + makeknob( b1_ltuneKnob, 202, B1ROW, "Left detune", " cents", "bKnob" ) + makeknob( b2_ltuneKnob, 202, B2ROW, "Left detune", " cents", "bKnob" ) - makeknob( a1_rtuneKnob, 224, A1ROW, "Right detune", " cents", "aKnob" ) - makeknob( a2_rtuneKnob, 224, A2ROW, "Right detune", " cents", "aKnob" ) - makeknob( b1_rtuneKnob, 224, B1ROW, "Right detune", " cents", "bKnob" ) - makeknob( b2_rtuneKnob, 224, B2ROW, "Right detune", " cents", "bKnob" ) + makeknob( a1_rtuneKnob, 226, A1ROW, "Right detune", " cents", "aKnob" ) + makeknob( a2_rtuneKnob, 226, A2ROW, "Right detune", " cents", "aKnob" ) + makeknob( b1_rtuneKnob, 226, B1ROW, "Right detune", " cents", "bKnob" ) + makeknob( b2_rtuneKnob, 226, B2ROW, "Right detune", " cents", "bKnob" ) - makeknob( m_abmixKnob, 4, 4, "A-B Mix", "", "mixKnob" ) + makeknob( m_abmixKnob, 4, 3, "A-B Mix", "", "mixKnob" ) + + makeknob( m_envAmtKnob, 88, 3, "Mix envelope amount", "", "mixenvKnob" ) + makeknob( m_envAttKnob, 88, A1ROW, "Mix envelope attack", " ms", "mixenvKnob" ) + makeknob( m_envDecKnob, 88, A2ROW, "Mix envelope decay", " ms", "mixenvKnob" ) // let's set volume knobs a1_volKnob -> setVolumeKnob( true ); @@ -1124,6 +1197,10 @@ void WTSynthView::modelChanged() b1_graph -> setModel( &w -> b1_graph ); b2_graph -> setModel( &w -> b2_graph ); + m_envAmtKnob -> setModel( &w -> m_envAmt ); + m_envAttKnob -> setModel( &w -> m_envAtt ); + m_envDecKnob -> setModel( &w -> m_envDec ); + } diff --git a/plugins/wtsynth/WTSynth.h b/plugins/wtsynth/WTSynth.h index 0484fa7da..3b09d3003 100644 --- a/plugins/wtsynth/WTSynth.h +++ b/plugins/wtsynth/WTSynth.h @@ -89,6 +89,10 @@ public: { return m_bbuf; } + inline sample_rate_t samplerate() const + { + return m_samplerate; + } private: float m_lvol [NUM_OSCS]; @@ -113,7 +117,7 @@ private: float m_lfreq [NUM_OSCS]; float m_rfreq [NUM_OSCS]; - + float m_A1wave [WAVELEN]; float m_A2wave [WAVELEN]; float m_B1wave [WAVELEN]; @@ -192,6 +196,11 @@ private: graphModel b2_graph; FloatModel m_abmix; + + FloatModel m_envAmt; + FloatModel m_envAtt; + FloatModel m_envDec; + IntModel m_amod; IntModel m_bmod; @@ -258,6 +267,10 @@ private: knob * m_abmixKnob; + knob * m_envAmtKnob; + knob * m_envAttKnob; + knob * m_envDecKnob; + automatableButtonGroup * m_selectedGraphGroup; automatableButtonGroup * m_aModGroup; automatableButtonGroup * m_bModGroup; diff --git a/plugins/wtsynth/artwork.png b/plugins/wtsynth/artwork.png index 819f322c73eb4ccaea14fd555c23e6c10e675174..c908695efe8cd6b0eb88effe5fc8805299b45454 100644 GIT binary patch literal 95609 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 Date: Sat, 22 Mar 2014 22:27:26 +0200 Subject: [PATCH 080/647] Adjust previous --- plugins/wtsynth/WTSynth.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/wtsynth/WTSynth.cpp b/plugins/wtsynth/WTSynth.cpp index 82fa8dba6..c59d8d0d4 100644 --- a/plugins/wtsynth/WTSynth.cpp +++ b/plugins/wtsynth/WTSynth.cpp @@ -292,7 +292,7 @@ WTSynthInstrument::WTSynthInstrument( InstrumentTrack * _instrument_track ) : b2_graph( -1.0f, 1.0f, WAVELEN, this ), m_abmix( 0.0f, -100.0f, 100.0f, 0.1f, this, tr( "A-B Mix" ) ), - m_envAmt( 0.0f, -200.0f, 200.0f, 0.1f, this, tr( "A-B Mix envelope amount" ) ), + m_envAmt( 0.0f, -200.0f, 200.0f, 1.0f, this, tr( "A-B Mix envelope amount" ) ), m_envAtt( 0.0f, 0.0f, 2000.0f, 1.0f, this, tr( "A-B Mix envelope attack" ) ), m_envDec( 0.0f, 0.0f, 2000.0f, 1.0f, this, tr( "A-B Mix envelope decay" ) ), From e58e55660a17e1ee01dbb160a7da933327d9f708 Mon Sep 17 00:00:00 2001 From: Vesa Date: Sun, 23 Mar 2014 14:13:53 +0200 Subject: [PATCH 081/647] Add hold knob --- plugins/wtsynth/WTSynth.cpp | 24 +++++++++++++++++++----- plugins/wtsynth/WTSynth.h | 21 ++++++++++++++++----- plugins/wtsynth/artwork.png | Bin 95609 -> 95662 bytes 3 files changed, 35 insertions(+), 10 deletions(-) diff --git a/plugins/wtsynth/WTSynth.cpp b/plugins/wtsynth/WTSynth.cpp index c59d8d0d4..1c7272200 100644 --- a/plugins/wtsynth/WTSynth.cpp +++ b/plugins/wtsynth/WTSynth.cpp @@ -412,8 +412,9 @@ void WTSynthInstrument::playNote( NotePlayHandle * _n, // envelope parameters const float envAmt = m_envAmt.value(); const float envAtt = ( m_envAtt.value() * w->samplerate() ) / 1000.0f; + const float envHold = ( m_envHold.value() * w->samplerate() ) / 1000.0f; const float envDec = ( m_envDec.value() * w->samplerate() ) / 1000.0f; - const float envLen = envAtt + envDec; + const float envLen = envAtt + envDec + envHold; const float tfp_ = static_cast( _n->totalFramesPlayed() ); // if sample-exact is enabled, use sample-exact calculations... @@ -430,9 +431,13 @@ void WTSynthInstrument::playNote( NotePlayHandle * _n, { mixvalue = qBound( -100.0f, mixvalue + ( tfp / envAtt * envAmt ), 100.0f ); } + else if ( tfp >= envAtt && tfp < envAtt + envHold ) + { + mixvalue = qBound( -100.0f, mixvalue + envAmt, 100.0f ); + } else { - mixvalue = qBound( -100.0f, mixvalue + envAmt - ( ( tfp - envAtt ) / envDec * envAmt ), 100.0f ); + mixvalue = qBound( -100.0f, mixvalue + envAmt - ( ( tfp - ( envAtt + envHold ) ) / envDec * envAmt ), 100.0f ); } } // get knob values in sample-exact way @@ -461,9 +466,13 @@ void WTSynthInstrument::playNote( NotePlayHandle * _n, { mixvalue = qBound( -100.0f, mixvalue + ( tfp / envAtt * envAmt ), 100.0f ); } + else if ( tfp >= envAtt && tfp < envAtt + envHold ) + { + mixvalue = qBound( -100.0f, mixvalue + envAmt, 100.0f ); + } else { - mixvalue = qBound( -100.0f, mixvalue + envAmt - ( ( tfp - envAtt ) / envDec * envAmt ), 100.0f ); + mixvalue = qBound( -100.0f, mixvalue + envAmt - ( ( tfp - ( envAtt + envHold ) ) / envDec * envAmt ), 100.0f ); } // get knob values @@ -549,6 +558,7 @@ void WTSynthInstrument::saveSettings( QDomDocument & _doc, m_abmix.saveSettings( _doc, _this, "abmix" ); m_envAmt.saveSettings( _doc, _this, "envAmt" ); m_envAtt.saveSettings( _doc, _this, "envAtt" ); + m_envHold.saveSettings( _doc, _this, "envHold" ); m_envDec.saveSettings( _doc, _this, "envDec" ); m_amod.saveSettings( _doc, _this, "amod" ); @@ -603,6 +613,7 @@ void WTSynthInstrument::loadSettings( const QDomElement & _this ) m_envAmt.loadSettings( _this, "envAmt" ); m_envAtt.loadSettings( _this, "envAtt" ); + m_envHold.loadSettings( _this, "envHold" ); m_envDec.loadSettings( _this, "envDec" ); m_amod.loadSettings( _this, "amod" ); @@ -677,8 +688,10 @@ WTSynthView::WTSynthView( Instrument * _instrument, makeknob( m_abmixKnob, 4, 3, "A-B Mix", "", "mixKnob" ) makeknob( m_envAmtKnob, 88, 3, "Mix envelope amount", "", "mixenvKnob" ) - makeknob( m_envAttKnob, 88, A1ROW, "Mix envelope attack", " ms", "mixenvKnob" ) - makeknob( m_envDecKnob, 88, A2ROW, "Mix envelope decay", " ms", "mixenvKnob" ) + + maketsknob( m_envAttKnob, 88, A1ROW, "Mix envelope attack", " ms", "mixenvKnob" ) + maketsknob( m_envHoldKnob, 88, A2ROW, "Mix envelope hold", " ms", "mixenvKnob" ) + maketsknob( m_envDecKnob, 88, B1ROW, "Mix envelope decay", " ms", "mixenvKnob" ) // let's set volume knobs a1_volKnob -> setVolumeKnob( true ); @@ -1199,6 +1212,7 @@ void WTSynthView::modelChanged() m_envAmtKnob -> setModel( &w -> m_envAmt ); m_envAttKnob -> setModel( &w -> m_envAtt ); + m_envHoldKnob -> setModel( &w -> m_envHold ); m_envDecKnob -> setModel( &w -> m_envDec ); } diff --git a/plugins/wtsynth/WTSynth.h b/plugins/wtsynth/WTSynth.h index 3b09d3003..599d0d487 100644 --- a/plugins/wtsynth/WTSynth.h +++ b/plugins/wtsynth/WTSynth.h @@ -37,7 +37,14 @@ #define makeknob( name, x, y, hint, unit, oname ) \ - name = new knob( knobStyled, this); \ + name = new knob( knobStyled, this ); \ + name ->move( x, y ); \ + name ->setHintText( tr( hint ) + " ", unit ); \ + name ->setObjectName( oname ); \ + name ->setFixedSize( 19, 19 ); + +#define maketsknob( name, x, y, hint, unit, oname ) \ + name = new TempoSyncKnob( knobStyled, this ); \ name ->move( x, y ); \ name ->setHintText( tr( hint ) + " ", unit ); \ name ->setObjectName( oname ); \ @@ -198,8 +205,10 @@ private: FloatModel m_abmix; FloatModel m_envAmt; - FloatModel m_envAtt; - FloatModel m_envDec; + + TempoSyncKnobModel m_envAtt; + TempoSyncKnobModel m_envHold; + TempoSyncKnobModel m_envDec; IntModel m_amod; IntModel m_bmod; @@ -268,8 +277,10 @@ private: knob * m_abmixKnob; knob * m_envAmtKnob; - knob * m_envAttKnob; - knob * m_envDecKnob; + + TempoSyncKnob * m_envAttKnob; + TempoSyncKnob * m_envHoldKnob; + TempoSyncKnob * m_envDecKnob; automatableButtonGroup * m_selectedGraphGroup; automatableButtonGroup * m_aModGroup; diff --git a/plugins/wtsynth/artwork.png b/plugins/wtsynth/artwork.png index c908695efe8cd6b0eb88effe5fc8805299b45454..56413dcea32e35f177f97d88db55b7d9c46b25e1 100644 GIT binary patch delta 77550 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

KTtJkY7M|93 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 N002ovPDHLkV1jQEkqiI; literal 0 HcmV?d00001 diff --git a/plugins/monstro/fm_active.png b/plugins/monstro/fm_active.png new file mode 100644 index 0000000000000000000000000000000000000000..cd4ee859d03bc5cca2f65fe23ad40b603efd2905 GIT binary patch literal 678 zcmV;X0$KfuP)e zSad^gZEa<4bO1wgWnpw>WFU8GbZ8()Nlj2!fese{00It4L_t(I%Z-#jYm`9{#(%SW z(VU#-L~N|Ikq}StL_4_;prw+=Phe$l=O?gGK?Jd|F{dD68U<0&!b&g~0-~r0fe0CONq(Nl!n zF?aSI!OH-7oLYqs;Pju|W%b^*!sE!5TWr34#>R_B%-wlI+_xVbK3+bDjkY*?^CrX4x>*!Y&c+j;W{FM4hIZBukds2TS-4<9{7XS&RQmB zu}1&(A~>vfZxCuzljNuZV&GN)+xCd%`4+tk#~8eO1;Et7L;UK02cZA*G4;cXpOUjP6A literal 0 HcmV?d00001 diff --git a/plugins/monstro/fm_inactive.png b/plugins/monstro/fm_inactive.png new file mode 100644 index 0000000000000000000000000000000000000000..a96128b7db2f1e72ac9d1748d58421947957a1d4 GIT binary patch literal 484 zcmVW02y>e zSad^gZEa<4bO1wgWnpw>WFU8GbZ8()Nlj2!fese{00B%%L_t(I%dM2Xssb?(g}=-D;bhr=PK(}~03z-TnWS_{B(xg^Un27|#9X@&55y%IuTGMN-- zo6Uy%{myo~rQh%4z2|&B6Gc&_P#;T<Q5?wOV1VMMPfS z`BB?+yIpR#8|`-cZH{ryY1t{|m)|)hcSzYOkH>?>V(~M{b$NL#|7E);$$53lgQ0Ff a)Zq&^)wc^~=^|AC0000undR< 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 Am;e9( literal 0 HcmV?d00001 diff --git a/plugins/monstro/moog.png b/plugins/monstro/moog.png new file mode 100644 index 0000000000000000000000000000000000000000..1a657b161324cabb6a67bade9c17f35d366bc4b2 GIT binary patch literal 402 zcmV;D0d4+?P)UyOwITYqUl3@ z`^~&i!R-S}Kme{A8Pz_p4NQSWAZFN`aiChADNiZxQ(r8rSv)q_9oH&+XFsIIht w)2Lt68AAxiY5^Ppmp})#t9BcH&i6rl0^94WKmdLPuK)l507*qoM6N<$f>Z;NXaE2J literal 0 HcmV?d00001 diff --git a/plugins/monstro/noise.png b/plugins/monstro/noise.png new file mode 100644 index 0000000000000000000000000000000000000000..cd22af02b51a24ec51095a77b26008a3855a55f7 GIT binary patch literal 478 zcmV<40U`d0P)_CTR4a#c!5bTb=*}yP|ygMa1Ng<{}xM0rmeO0IUK8la2PwaKUuOz*jIO7 z!@DHc2P{<=ID}8wu8*@__l5H~h4+{YI9=d(%oq5z07*qoM6N<$g49yUp#T5? literal 0 HcmV?d00001 diff --git a/plugins/monstro/opview_active.png b/plugins/monstro/opview_active.png new file mode 100644 index 0000000000000000000000000000000000000000..d993b111b3572d509548e4cb671f5ce36e128950 GIT binary patch literal 2129 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 Xs^G$%TA4L+00000NkvXXu0mjffBDQl literal 0 HcmV?d00001 diff --git a/plugins/monstro/ramp.png b/plugins/monstro/ramp.png new file mode 100644 index 0000000000000000000000000000000000000000..94f23b59f4d3ae623724cea67c983c344ac83f9d GIT binary patch literal 333 zcmeAS@N?(olHy`uVBq!ia0vp^d_XL~!3HGNrubO_Db50q$YKTtZeb8+WSBKa0w~B{ z;_2(kevesJM4dk%t<4lDBw6AbQR1ARo12kkZ7lQxBL zd|)a2XXAI!%p$*`REtmX*bLVO^+|1>1_#&|F#4#PcE8&3tMKCAd)G^RZb{_4V^&|F zojISU*6jf6izBkrosxa{&NM{d*~pqz*Y!ax;+SdVf_KYfn-0%nn4b8JVa3Yyl-Lc^hNe^yeNp zV{=%{?)2J1?HMzV-_Tf?XnH-n@!P2nLd92WE;8gk-oTTu^k`39uuo%HVN0crZ*!fj zsj+xruc(d75zot^uVmM6XnWpq<8O9>>)F+%dmb$~yKK?3tJdF?A1&s6lbR+!duh11 z;KyrEO+{}UWRg>Uv~Fo#&-#-g{tGkTi1HTpU#zb?aVh05Z`>3A8;jprUjcfV!PC{x JWt~$(699#lkk9}C literal 0 HcmV?d00001 diff --git a/plugins/monstro/sin.png b/plugins/monstro/sin.png new file mode 100644 index 0000000000000000000000000000000000000000..f9441bdfbc0d9f2a9efe464ea1aee44d57522b95 GIT binary patch literal 398 zcmV;90df9`P)ABwe#cJ%<8t z2W$aL;D9cY^q@aIN*cO-zYYqLqNGo^gQPe2g*L7NYTyuf2BM#t`|4HT0O$kJ%#xWU zhx;CD1&@GlV3GM3-lSU6UQt$Py1D_(fk_5NAOXjoZgSw(AGoT3A#ek{6yO}#FY4R@ zHk(vOz{t$LnrKU%HLwl504L`@=J&6*RLk@Z|Hn0CpYh sw2DDelCkpKVy07*qoM6N<$f))^%egFUf literal 0 HcmV?d00001 diff --git a/plugins/monstro/sqr.png b/plugins/monstro/sqr.png new file mode 100644 index 0000000000000000000000000000000000000000..47748c66830d3acc5bd245bf6ea27e9e0c633166 GIT binary patch literal 342 zcmeAS@N?(olHy`uVBq!ia0vp^d_XL~!3HGNrubO_Db50q$YKTtZeb8+WSBKa0w~B{ z;_2(kevesJL|xpOOD-8GBw6AbQR1ARo12%J#2SL$jpaJZWLW%oj0wfZ*!5{V}{+aY!zCw>;4DEKTJ+O k-cfPFXX?w)$99LzJ6{-{5?uZk=rslgPgg&ebxsLQ0OxsuO#lD@ literal 0 HcmV?d00001 diff --git a/plugins/monstro/tri.png b/plugins/monstro/tri.png new file mode 100644 index 0000000000000000000000000000000000000000..9764a36e8bdfdfb2eada0673e3e5846cbf1eabc9 GIT binary patch literal 380 zcmV-?0fYXDP)&L#D9n^!8)alC>DYJ06)S{NFn*2 zEv#&{uoP1Stc=})AVkDkun;633*XAByE_GPYG)s_FIR;#N&X{+H!3hNtSYI%^d7fEVDpkJvJ44eY2xVnU{w!+)Y4@n5LJ aX8#WK`s*geiHIEl0000 Date: Sat, 29 Mar 2014 23:08:25 +0200 Subject: [PATCH 113/647] Add applyrelease --- plugins/monstro/Monstro.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/monstro/Monstro.cpp b/plugins/monstro/Monstro.cpp index e3b843891..d74127089 100644 --- a/plugins/monstro/Monstro.cpp +++ b/plugins/monstro/Monstro.cpp @@ -874,7 +874,7 @@ void MonstroInstrument::playNote( NotePlayHandle * _n, ms->renderOutput( frames, _working_buffer ); - //applyRelease( _working_buffer, _n ); + applyRelease( _working_buffer, _n ); instrumentTrack()->processAudioBuffer( _working_buffer, frames, _n ); } From 460bb0420ccab24d7e3f8a3af78350b3631ffa92 Mon Sep 17 00:00:00 2001 From: Vesa Date: Sat, 29 Mar 2014 23:23:04 +0200 Subject: [PATCH 114/647] Negative volume env. fix --- plugins/monstro/Monstro.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/monstro/Monstro.cpp b/plugins/monstro/Monstro.cpp index d74127089..7e5364521 100644 --- a/plugins/monstro/Monstro.cpp +++ b/plugins/monstro/Monstro.cpp @@ -110,9 +110,9 @@ void MonstroSynth::renderOutput( fpp_t _frames, sampleFrame * _buf ) #define modulatevol( car, mod ) \ if( mod##_e1 > 0.0 ) car = qBound( 0.0f, car * ( 1.0f - mod##_e1 + mod##_e1 * m_env1_buf[f] ), MODCLIP ); \ - if( mod##_e1 < 0.0 ) car = qBound( 0.0f, car * ( 0.0f - mod##_e1 + mod##_e1 * m_env1_buf[f] ), MODCLIP ); \ + if( mod##_e1 < 0.0 ) car = qBound( 0.0f, car * ( 1.0f + mod##_e1 * m_env1_buf[f] ), MODCLIP ); \ if( mod##_e2 > 0.0 ) car = qBound( 0.0f, car * ( 1.0f - mod##_e2 + mod##_e2 * m_env2_buf[f] ), MODCLIP ); \ - if( mod##_e2 < 0.0 ) car = qBound( 0.0f, car * ( 0.0f - mod##_e2 + mod##_e2 * m_env2_buf[f] ), MODCLIP ); \ + if( mod##_e2 < 0.0 ) car = qBound( 0.0f, car * ( 1.0f + mod##_e2 * m_env2_buf[f] ), MODCLIP ); \ if( mod##_l1 != 0.0 ) car = qBound( 0.0f, car * ( 1.0f + mod##_l1 * m_lfo1_buf[f] ), MODCLIP ); \ if( mod##_l2 != 0.0 ) car = qBound( 0.0f, car * ( 1.0f + mod##_l2 * m_lfo2_buf[f] ), MODCLIP ); From 8aad594cbd2d7052573cbd821b79d5aae0b4e2e2 Mon Sep 17 00:00:00 2001 From: Vesa Date: Sun, 30 Mar 2014 00:21:07 +0200 Subject: [PATCH 115/647] Monstro: algorithm tweaks, fixes, optimizations --- plugins/monstro/Monstro.cpp | 79 +++++++++++++++++++++---------------- plugins/monstro/Monstro.h | 3 ++ 2 files changed, 48 insertions(+), 34 deletions(-) diff --git a/plugins/monstro/Monstro.cpp b/plugins/monstro/Monstro.cpp index 7e5364521..2940813bc 100644 --- a/plugins/monstro/Monstro.cpp +++ b/plugins/monstro/Monstro.cpp @@ -96,17 +96,24 @@ MonstroSynth::~MonstroSynth() void MonstroSynth::renderOutput( fpp_t _frames, sampleFrame * _buf ) { // macros for modulating with env/lfos -#define modulatefreq( car, mod, min, max ) \ - if( mod##_e1 != 0.0 ) car = qBound( min, car * static_cast( fastPow( 2, m_env1_buf[f] * mod##_e1 ) ), max ); \ - if( mod##_e2 != 0.0 ) car = qBound( min, car * static_cast( fastPow( 2, m_env2_buf[f] * mod##_e2 ) ), max ); \ - if( mod##_l1 != 0.0 ) car = qBound( min, car * static_cast( fastPow( 2, m_lfo1_buf[f] * mod##_l1 ) ), max ); \ - if( mod##_l2 != 0.0 ) car = qBound( min, car * static_cast( fastPow( 2, m_lfo2_buf[f] * mod##_l2 ) ), max ); +#define modulatefreq( car, mod ) \ + if( mod##_e1 != 0.0 ) car = qBound( MIN_FREQ, car * static_cast( fastPow( 10, m_env1_buf[f] * mod##_e1 ) ), MAX_FREQ ); \ + if( mod##_e2 != 0.0 ) car = qBound( MIN_FREQ, car * static_cast( fastPow( 10, m_env2_buf[f] * mod##_e2 ) ), MAX_FREQ ); \ + if( mod##_l1 != 0.0 ) car = qBound( MIN_FREQ, car * static_cast( fastPow( 10, m_lfo1_buf[f] * mod##_l1 ) ), MAX_FREQ ); \ + if( mod##_l2 != 0.0 ) car = qBound( MIN_FREQ, car * static_cast( fastPow( 10, m_lfo2_buf[f] * mod##_l2 ) ), MAX_FREQ ); + +#define modulateabs( car, mod ) \ + if( mod##_e1 != 0.0 ) car = qBound( 0.0f, car + mod##_e1 / 2 * m_env1_buf[f], 1.0f ); \ + if( mod##_e2 != 0.0 ) car = qBound( 0.0f, car + mod##_e2 / 2 * m_env2_buf[f], 1.0f ); \ + if( mod##_l1 != 0.0 ) car = qBound( 0.0f, car + mod##_l1 / 2 * m_lfo1_buf[f], 1.0f ); \ + if( mod##_l2 != 0.0 ) car = qBound( 0.0f, car + mod##_l2 / 2 * m_lfo2_buf[f], 1.0f ); + +#define modulatephs( car, mod ) \ + if( mod##_e1 != 0.0 ) car = fraction( car + mod##_e1 / 2 * m_env1_buf[f] ); \ + if( mod##_e2 != 0.0 ) car = fraction( car + mod##_e2 / 2 * m_env2_buf[f] ); \ + if( mod##_l1 != 0.0 ) car = fraction( car + mod##_l1 / 2 * m_lfo1_buf[f] ); \ + if( mod##_l2 != 0.0 ) car = fraction( car + mod##_l2 / 2 * m_lfo2_buf[f] ); -#define modulateabs( car, mod, min, max ) \ - if( mod##_e1 != 0.0 ) car = qBound( min, car + mod##_e1 / 2 * m_env1_buf[f], max ); \ - if( mod##_e2 != 0.0 ) car = qBound( min, car + mod##_e2 / 2 * m_env2_buf[f], max ); \ - if( mod##_l1 != 0.0 ) car = qBound( min, car + mod##_l1 / 2 * m_lfo1_buf[f], max ); \ - if( mod##_l2 != 0.0 ) car = qBound( min, car + mod##_l2 / 2 * m_lfo2_buf[f], max ); #define modulatevol( car, mod ) \ if( mod##_e1 > 0.0 ) car = qBound( 0.0f, car * ( 1.0f - mod##_e1 + mod##_e1 * m_env1_buf[f] ), MODCLIP ); \ @@ -221,6 +228,10 @@ void MonstroSynth::renderOutput( fpp_t _frames, sampleFrame * _buf ) //o2-o3 modulation const int omod = m_parent->m_o23Mod.value(); + + // frequency helpers + + const int srquot = 1.0 / static_cast( m_samplerate ); /////////////////////////// // // @@ -251,18 +262,18 @@ void MonstroSynth::renderOutput( fpp_t _frames, sampleFrame * _buf ) // calc and mod frequencies float o1l_f = o1lfb; float o1r_f = o1rfb; - modulatefreq( o1l_f, o1f, 20.0f, 20000.0f ) - modulatefreq( o1r_f, o1f, 20.0f, 20000.0f ) + modulatefreq( o1l_f, o1f ) + modulatefreq( o1r_f, o1f ) // calc and modulate phase float o1l_p = m_osc1l_phase + o1lpo; float o1r_p = m_osc1r_phase + o1rpo; - modulateabs( o1l_p, o1p, 0.0f, 1.0f ) - modulateabs( o1r_p, o1p, 0.0f, 1.0f ) + modulatephs( o1l_p, o1p ) + modulatephs( o1r_p, o1p ) // calc and modulate pulse float o1_pw = pw; - modulateabs( o1_pw, o1pw, -1.0f, 1.0f ) + modulateabs( o1_pw, o1pw ) // pulse wave osc sample_t O1L = ( o1l_p < o1_pw ) ? 1.0f : -1.0f; @@ -275,8 +286,8 @@ void MonstroSynth::renderOutput( fpp_t _frames, sampleFrame * _buf ) modulatevol( O1R, o1v ) // update osc1 phases - m_osc1l_phase = fraction( m_osc1l_phase + ( 1.0 / ( static_cast( m_samplerate ) / o1l_f ) ) ); - m_osc1r_phase = fraction( m_osc1r_phase + ( 1.0 / ( static_cast( m_samplerate ) / o1r_f ) ) ); + m_osc1l_phase = fraction( m_osc1l_phase + srquot / o1l_f ); + m_osc1r_phase = fraction( m_osc1r_phase + srquot / o1r_f ); ///////////////////////////// // // @@ -287,14 +298,14 @@ void MonstroSynth::renderOutput( fpp_t _frames, sampleFrame * _buf ) // calc and mod frequencies float o2l_f = o2lfb; float o2r_f = o2rfb; - modulatefreq( o2l_f, o2f, 20.0f, 20000.0f ) - modulatefreq( o2r_f, o2f, 20.0f, 20000.0f ) + modulatefreq( o2l_f, o2f ) + modulatefreq( o2r_f, o2f ) // calc and modulate phase float o2l_p = m_osc2l_phase + o2lpo; float o2r_p = m_osc2r_phase + o2rpo; - modulateabs( o2l_p, o2p, 0.0f, 1.0f ) - modulateabs( o2r_p, o2p, 0.0f, 1.0f ) + modulatephs( o2l_p, o2p ) + modulatephs( o2r_p, o2p ) // multi-wave DC Oscillator sample_t O2L = oscillate( o2w, o2l_p ); @@ -307,8 +318,8 @@ void MonstroSynth::renderOutput( fpp_t _frames, sampleFrame * _buf ) modulatevol( O2R, o2v ) // update osc2 phases - m_osc2l_phase = fraction( m_osc2l_phase + ( 1.0 / ( static_cast( m_samplerate ) / o2l_f ) ) ); - m_osc2r_phase = fraction( m_osc2r_phase + ( 1.0 / ( static_cast( m_samplerate ) / o2r_f ) ) ); + m_osc2l_phase = fraction( m_osc2l_phase + srquot / o2l_f ); + m_osc2r_phase = fraction( m_osc2r_phase + srquot / o2r_f ); ///////////////////////////// // // @@ -319,25 +330,25 @@ void MonstroSynth::renderOutput( fpp_t _frames, sampleFrame * _buf ) // calc and mod frequencies float o3l_f = o3fb; float o3r_f = o3fb; - modulatefreq( o3l_f, o3f, 20.0f, 20000.0f ) - modulatefreq( o3r_f, o3f, 20.0f, 20000.0f ) + modulatefreq( o3l_f, o3f ) + modulatefreq( o3r_f, o3f ) // o2 modulation? if( omod == MOD_FM ) { - o3l_f = qBound( 20.0f, o3l_f * static_cast( fastPow( 2, O2L ) ), 20000.0f ); - o3r_f = qBound( 20.0f, o3r_f * static_cast( fastPow( 2, O2R ) ), 20000.0f ); + o3l_f = qBound( MIN_FREQ, o3l_f * static_cast( fastPow( 4, O2L ) ), MAX_FREQ ); + o3r_f = qBound( MIN_FREQ, o3r_f * static_cast( fastPow( 4, O2R ) ), MAX_FREQ ); } // calc and modulate phase float o3l_p = m_osc3l_phase + o3lpo; float o3r_p = m_osc3r_phase + o3rpo; - modulateabs( o3l_p, o3p, 0.0f, 1.0f ) - modulateabs( o3r_p, o3p, 0.0f, 1.0f ) + modulatephs( o3l_p, o3p ) + modulatephs( o3r_p, o3p ) // o2 modulation? if( omod == MOD_PM ) { - o3l_p = qBound( 0.0f, o3l_p + O2L/2, 1.0f ); - o3r_p = qBound( 0.0f, o3r_p + O2R/2, 1.0f ); + o3l_p = fraction( o3l_p + O2L/2 ); + o3r_p = fraction( o3r_p + O2R/2 ); } // multi-wave DC Oscillator, sub-osc 1 @@ -350,7 +361,7 @@ void MonstroSynth::renderOutput( fpp_t _frames, sampleFrame * _buf ) // calc and modulate sub float sub = o3sub; - modulateabs( sub, o3s, 0.0f, 1.0f ) + modulateabs( sub, o3s ) sample_t O3L = interpolate( O3AL, O3BL, sub ); sample_t O3R = interpolate( O3AR, O3BR, sub ); @@ -368,8 +379,8 @@ void MonstroSynth::renderOutput( fpp_t _frames, sampleFrame * _buf ) } // update osc3 phases - m_osc3l_phase = fraction( m_osc3l_phase + ( 1.0f / ( static_cast( m_samplerate ) / o3l_f ) ) ); - m_osc3r_phase = fraction( m_osc3r_phase + ( 1.0f / ( static_cast( m_samplerate ) / o3r_f ) ) ); + m_osc3l_phase = fraction( m_osc3l_phase + srquot / o3l_f ); + m_osc3r_phase = fraction( m_osc3r_phase + srquot / o3r_f ); _buf[f][0] = O1L + O3L + ( omod == MOD_MIX ? O2L : 0.0f ); _buf[f][1] = O1R + O3R + ( omod == MOD_MIX ? O2R : 0.0f ); diff --git a/plugins/monstro/Monstro.h b/plugins/monstro/Monstro.h index 094859f62..e251b60b2 100644 --- a/plugins/monstro/Monstro.h +++ b/plugins/monstro/Monstro.h @@ -125,6 +125,9 @@ const int NUM_MODS = 4; const float MODCLIP = 2.0; +const float MIN_FREQ = 18.0f; +const float MAX_FREQ = 48000.0f; + class MonstroInstrument; class MonstroView; From c892c7a819473d01e9e65c4f2568669aa44c0ef7 Mon Sep 17 00:00:00 2001 From: Vesa Date: Sun, 30 Mar 2014 00:29:03 +0200 Subject: [PATCH 116/647] Monstro: Fix previous stupidity... --- plugins/monstro/Monstro.cpp | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/plugins/monstro/Monstro.cpp b/plugins/monstro/Monstro.cpp index 2940813bc..554756c97 100644 --- a/plugins/monstro/Monstro.cpp +++ b/plugins/monstro/Monstro.cpp @@ -231,8 +231,6 @@ void MonstroSynth::renderOutput( fpp_t _frames, sampleFrame * _buf ) // frequency helpers - const int srquot = 1.0 / static_cast( m_samplerate ); - /////////////////////////// // // // start buffer loop // @@ -286,8 +284,8 @@ void MonstroSynth::renderOutput( fpp_t _frames, sampleFrame * _buf ) modulatevol( O1R, o1v ) // update osc1 phases - m_osc1l_phase = fraction( m_osc1l_phase + srquot / o1l_f ); - m_osc1r_phase = fraction( m_osc1r_phase + srquot / o1r_f ); + m_osc1l_phase = fraction( m_osc1l_phase + 1.0f / ( static_cast( m_samplerate ) / o1l_f ) ); + m_osc1r_phase = fraction( m_osc1r_phase + 1.0f / ( static_cast( m_samplerate ) / o1r_f ) ); ///////////////////////////// // // @@ -318,8 +316,8 @@ void MonstroSynth::renderOutput( fpp_t _frames, sampleFrame * _buf ) modulatevol( O2R, o2v ) // update osc2 phases - m_osc2l_phase = fraction( m_osc2l_phase + srquot / o2l_f ); - m_osc2r_phase = fraction( m_osc2r_phase + srquot / o2r_f ); + m_osc2l_phase = fraction( m_osc2l_phase + ( 1.0f / static_cast( m_samplerate ) / o2l_f ) ); + m_osc2r_phase = fraction( m_osc2r_phase + ( 1.0f / static_cast( m_samplerate ) / o2r_f ) ); ///////////////////////////// // // @@ -379,8 +377,8 @@ void MonstroSynth::renderOutput( fpp_t _frames, sampleFrame * _buf ) } // update osc3 phases - m_osc3l_phase = fraction( m_osc3l_phase + srquot / o3l_f ); - m_osc3r_phase = fraction( m_osc3r_phase + srquot / o3r_f ); + m_osc3l_phase = fraction( m_osc3l_phase + ( 1.0f / static_cast( m_samplerate ) / o3l_f ) ); + m_osc3r_phase = fraction( m_osc3r_phase + ( 1.0f / static_cast( m_samplerate ) / o3r_f ) ); _buf[f][0] = O1L + O3L + ( omod == MOD_MIX ? O2L : 0.0f ); _buf[f][1] = O1R + O3R + ( omod == MOD_MIX ? O2R : 0.0f ); From 252e0609fa9bf31940f7d3fe96cb2c435b5a7b5a Mon Sep 17 00:00:00 2001 From: Vesa Date: Sun, 30 Mar 2014 00:32:26 +0200 Subject: [PATCH 117/647] Monstro: fix again... --- plugins/monstro/Monstro.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/plugins/monstro/Monstro.cpp b/plugins/monstro/Monstro.cpp index 554756c97..4b1149037 100644 --- a/plugins/monstro/Monstro.cpp +++ b/plugins/monstro/Monstro.cpp @@ -316,8 +316,8 @@ void MonstroSynth::renderOutput( fpp_t _frames, sampleFrame * _buf ) modulatevol( O2R, o2v ) // update osc2 phases - m_osc2l_phase = fraction( m_osc2l_phase + ( 1.0f / static_cast( m_samplerate ) / o2l_f ) ); - m_osc2r_phase = fraction( m_osc2r_phase + ( 1.0f / static_cast( m_samplerate ) / o2r_f ) ); + m_osc2l_phase = fraction( m_osc2l_phase + 1.0f / ( static_cast( m_samplerate ) / o2l_f ) ); + m_osc2r_phase = fraction( m_osc2r_phase + 1.0f / ( static_cast( m_samplerate ) / o2r_f ) ); ///////////////////////////// // // @@ -377,8 +377,8 @@ void MonstroSynth::renderOutput( fpp_t _frames, sampleFrame * _buf ) } // update osc3 phases - m_osc3l_phase = fraction( m_osc3l_phase + ( 1.0f / static_cast( m_samplerate ) / o3l_f ) ); - m_osc3r_phase = fraction( m_osc3r_phase + ( 1.0f / static_cast( m_samplerate ) / o3r_f ) ); + m_osc3l_phase = fraction( m_osc3l_phase + 1.0f / ( static_cast( m_samplerate ) / o3l_f ) ); + m_osc3r_phase = fraction( m_osc3r_phase + 1.0f / ( static_cast( m_samplerate ) / o3r_f ) ); _buf[f][0] = O1L + O3L + ( omod == MOD_MIX ? O2L : 0.0f ); _buf[f][1] = O1R + O3R + ( omod == MOD_MIX ? O2R : 0.0f ); From 9f594268c8fe8cce5f09286a640b3ff9a9facef4 Mon Sep 17 00:00:00 2001 From: Vesa Date: Sun, 30 Mar 2014 01:43:20 +0200 Subject: [PATCH 118/647] Monstro - More fixes.. --- plugins/monstro/Monstro.cpp | 53 ++++++++++++++++++------------------- 1 file changed, 26 insertions(+), 27 deletions(-) diff --git a/plugins/monstro/Monstro.cpp b/plugins/monstro/Monstro.cpp index 4b1149037..708a31cb2 100644 --- a/plugins/monstro/Monstro.cpp +++ b/plugins/monstro/Monstro.cpp @@ -96,21 +96,21 @@ MonstroSynth::~MonstroSynth() void MonstroSynth::renderOutput( fpp_t _frames, sampleFrame * _buf ) { // macros for modulating with env/lfos -#define modulatefreq( car, mod ) \ - if( mod##_e1 != 0.0 ) car = qBound( MIN_FREQ, car * static_cast( fastPow( 10, m_env1_buf[f] * mod##_e1 ) ), MAX_FREQ ); \ - if( mod##_e2 != 0.0 ) car = qBound( MIN_FREQ, car * static_cast( fastPow( 10, m_env2_buf[f] * mod##_e2 ) ), MAX_FREQ ); \ - if( mod##_l1 != 0.0 ) car = qBound( MIN_FREQ, car * static_cast( fastPow( 10, m_lfo1_buf[f] * mod##_l1 ) ), MAX_FREQ ); \ - if( mod##_l2 != 0.0 ) car = qBound( MIN_FREQ, car * static_cast( fastPow( 10, m_lfo2_buf[f] * mod##_l2 ) ), MAX_FREQ ); +#define modulatefreq( car, mod ) \ + if( mod##_e1 != 0.0 ) car = qBound( MIN_FREQ, car * static_cast( fastPow( 10.0, m_env1_buf[f] * mod##_e1 ) ), MAX_FREQ ); \ + if( mod##_e2 != 0.0 ) car = qBound( MIN_FREQ, car * static_cast( fastPow( 10.0, m_env2_buf[f] * mod##_e2 ) ), MAX_FREQ ); \ + if( mod##_l1 != 0.0 ) car = qBound( MIN_FREQ, car * static_cast( fastPow( 5.0, m_lfo1_buf[f] * mod##_l1 ) ), MAX_FREQ ); \ + if( mod##_l2 != 0.0 ) car = qBound( MIN_FREQ, car * static_cast( fastPow( 5.0, m_lfo2_buf[f] * mod##_l2 ) ), MAX_FREQ ); #define modulateabs( car, mod ) \ - if( mod##_e1 != 0.0 ) car = qBound( 0.0f, car + mod##_e1 / 2 * m_env1_buf[f], 1.0f ); \ - if( mod##_e2 != 0.0 ) car = qBound( 0.0f, car + mod##_e2 / 2 * m_env2_buf[f], 1.0f ); \ + if( mod##_e1 != 0.0 ) car = qBound( 0.0f, car + mod##_e1 * m_env1_buf[f], 1.0f ); \ + if( mod##_e2 != 0.0 ) car = qBound( 0.0f, car + mod##_e2 * m_env2_buf[f], 1.0f ); \ if( mod##_l1 != 0.0 ) car = qBound( 0.0f, car + mod##_l1 / 2 * m_lfo1_buf[f], 1.0f ); \ if( mod##_l2 != 0.0 ) car = qBound( 0.0f, car + mod##_l2 / 2 * m_lfo2_buf[f], 1.0f ); #define modulatephs( car, mod ) \ - if( mod##_e1 != 0.0 ) car = fraction( car + mod##_e1 / 2 * m_env1_buf[f] ); \ - if( mod##_e2 != 0.0 ) car = fraction( car + mod##_e2 / 2 * m_env2_buf[f] ); \ + if( mod##_e1 != 0.0 ) car = fraction( car + mod##_e1 * m_env1_buf[f] ); \ + if( mod##_e2 != 0.0 ) car = fraction( car + mod##_e2 * m_env2_buf[f] ); \ if( mod##_l1 != 0.0 ) car = fraction( car + mod##_l1 / 2 * m_lfo1_buf[f] ); \ if( mod##_l2 != 0.0 ) car = fraction( car + mod##_l2 / 2 * m_lfo2_buf[f] ); @@ -176,7 +176,7 @@ void MonstroSynth::renderOutput( fpp_t _frames, sampleFrame * _buf ) const float o2rfb = ( m_parent->m_osc2r_freq * m_nph->frequency() ); const float o2f_e1 = ( m_parent->m_pit2env1.value() ); const float o2f_e2 = ( m_parent->m_pit2env2.value() ); - const float o2f_l1 = ( m_parent->m_pit2lfo2.value() ); + const float o2f_l1 = ( m_parent->m_pit2lfo1.value() ); const float o2f_l2 = ( m_parent->m_pit2lfo2.value() ); // get volumes @@ -229,7 +229,6 @@ void MonstroSynth::renderOutput( fpp_t _frames, sampleFrame * _buf ) const int omod = m_parent->m_o23Mod.value(); - // frequency helpers /////////////////////////// // // @@ -333,8 +332,8 @@ void MonstroSynth::renderOutput( fpp_t _frames, sampleFrame * _buf ) // o2 modulation? if( omod == MOD_FM ) { - o3l_f = qBound( MIN_FREQ, o3l_f * static_cast( fastPow( 4, O2L ) ), MAX_FREQ ); - o3r_f = qBound( MIN_FREQ, o3r_f * static_cast( fastPow( 4, O2R ) ), MAX_FREQ ); + o3l_f = qBound( MIN_FREQ, o3l_f * powf( 5, O2L ), MAX_FREQ ); + o3r_f = qBound( MIN_FREQ, o3r_f * powf( 5, O2R ), MAX_FREQ ); } // calc and modulate phase @@ -1151,17 +1150,17 @@ void MonstroInstrument::updateVolumes() void MonstroInstrument::updateFreq() { - m_osc1l_freq = powf( 2.0d, m_osc1Crs.value() / 12.0d ) * - powf( 2.0d, m_osc1Ftl.value() / 1200.0d ); - m_osc1r_freq = powf( 2.0d, m_osc1Crs.value() / 12.0d ) * - powf( 2.0d, m_osc1Ftr.value() / 1200.0d ); + m_osc1l_freq = powf( 2.0f, m_osc1Crs.value() / 12.0f ) * + powf( 2.0f, m_osc1Ftl.value() / 1200.0f ); + m_osc1r_freq = powf( 2.0f, m_osc1Crs.value() / 12.0f ) * + powf( 2.0f, m_osc1Ftr.value() / 1200.0f ); - m_osc2l_freq = powf( 2.0d, m_osc2Crs.value() / 12.0d ) * - powf( 2.0d, m_osc2Ftl.value() / 1200.0d ); - m_osc2r_freq = powf( 2.0d, m_osc2Crs.value() / 12.0d ) * - powf( 2.0d, m_osc2Ftr.value() / 1200.0d ); + m_osc2l_freq = powf( 2.0f, m_osc2Crs.value() / 12.0f ) * + powf( 2.0f, m_osc2Ftl.value() / 1200.0f ); + m_osc2r_freq = powf( 2.0f, m_osc2Crs.value() / 12.0f ) * + powf( 2.0f, m_osc2Ftr.value() / 1200.0f ); - m_osc3_freq = powf( 2.0d, m_osc3Crs.value() / 12.0d ); + m_osc3_freq = powf( 2.0f, m_osc3Crs.value() / 12.0f ); } @@ -1422,7 +1421,7 @@ QWidget * MonstroView::setupOperatorsView( QWidget * _parent ) makeknob( m_osc1CrsKnob, KNOBCOL3, O1ROW, "Coarse detune", " seminotes", "osc1Knob" ) makeknob( m_osc1FtlKnob, KNOBCOL4, O1ROW, "Finetune left", " cents", "osc1Knob" ) makeknob( m_osc1FtrKnob, KNOBCOL5, O1ROW, "Finetune right", " cents", "osc1Knob" ) - makeknob( m_osc1SpoKnob, KNOBCOL6, O1ROW, "Stereo phase offset", "°", "osc1Knob" ) + makeknob( m_osc1SpoKnob, KNOBCOL6, O1ROW, "Stereo phase offset", " deg", "osc1Knob" ) makeknob( m_osc1PwKnob, KNOBCOL7, O1ROW, "Pulse width", "%", "osc1Knob" ) m_osc1VolKnob -> setVolumeKnob( true ); @@ -1432,7 +1431,7 @@ QWidget * MonstroView::setupOperatorsView( QWidget * _parent ) makeknob( m_osc2CrsKnob, KNOBCOL3, O2ROW, "Coarse detune", " seminotes", "osc2Knob" ) makeknob( m_osc2FtlKnob, KNOBCOL4, O2ROW, "Finetune left", " cents", "osc2Knob" ) makeknob( m_osc2FtrKnob, KNOBCOL5, O2ROW, "Finetune right", " cents", "osc2Knob" ) - makeknob( m_osc2SpoKnob, KNOBCOL6, O2ROW, "Stereo phase offset", "°", "osc2Knob" ) + makeknob( m_osc2SpoKnob, KNOBCOL6, O2ROW, "Stereo phase offset", " deg", "osc2Knob" ) m_osc2VolKnob -> setVolumeKnob( true ); @@ -1443,7 +1442,7 @@ QWidget * MonstroView::setupOperatorsView( QWidget * _parent ) makeknob( m_osc3VolKnob, KNOBCOL1, O3ROW, "Volume", "%", "osc3Knob" ) makeknob( m_osc3PanKnob, KNOBCOL2, O3ROW, "Panning", "", "osc3Knob" ) makeknob( m_osc3CrsKnob, KNOBCOL3, O3ROW, "Coarse detune", " seminotes", "osc3Knob" ) - makeknob( m_osc3SpoKnob, KNOBCOL4, O3ROW, "Stereo phase offset", "°", "osc3Knob" ) + makeknob( m_osc3SpoKnob, KNOBCOL4, O3ROW, "Stereo phase offset", " deg", "osc3Knob" ) makeknob( m_osc3SubKnob, KNOBCOL5, O3ROW, "Sub-osc mix", "", "osc3Knob" ) m_osc3Wave1Box = new comboBox( view ); @@ -1460,7 +1459,7 @@ QWidget * MonstroView::setupOperatorsView( QWidget * _parent ) maketsknob( m_lfo1AttKnob, LFOCOL1, LFOROW, "Attack", " ms", "lfoKnob" ) maketsknob( m_lfo1RateKnob, LFOCOL2, LFOROW, "Rate", " ms", "lfoKnob" ) - makeknob( m_lfo1PhsKnob, LFOCOL3, LFOROW, "Phase", "°", "lfoKnob" ) + makeknob( m_lfo1PhsKnob, LFOCOL3, LFOROW, "Phase", " deg", "lfoKnob" ) m_lfo2WaveBox = new comboBox( view ); m_lfo2WaveBox -> setGeometry( 127, LFOROW + 7, 42, 22 ); @@ -1468,7 +1467,7 @@ QWidget * MonstroView::setupOperatorsView( QWidget * _parent ) maketsknob( m_lfo2AttKnob, LFOCOL4, LFOROW, "Attack", " ms", "lfoKnob" ) maketsknob( m_lfo2RateKnob, LFOCOL5, LFOROW, "Rate", " ms", "lfoKnob" ) - makeknob( m_lfo2PhsKnob, LFOCOL6, LFOROW, "Phase", "°", "lfoKnob" ) + makeknob( m_lfo2PhsKnob, LFOCOL6, LFOROW, "Phase", " deg", "lfoKnob" ) maketsknob( m_env1PreKnob, KNOBCOL1, E1ROW, "Pre-delay", " ms", "envKnob" ) maketsknob( m_env1AttKnob, KNOBCOL2, E1ROW, "Attack", " ms", "envKnob" ) From 32e981a518d8a4df7fcc441c2ed649b089954d41 Mon Sep 17 00:00:00 2001 From: Vesa Date: Sun, 30 Mar 2014 04:08:26 +0300 Subject: [PATCH 119/647] Monstro - more alg. tweaks - getting better --- plugins/monstro/Monstro.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/plugins/monstro/Monstro.cpp b/plugins/monstro/Monstro.cpp index 708a31cb2..28aa4c94e 100644 --- a/plugins/monstro/Monstro.cpp +++ b/plugins/monstro/Monstro.cpp @@ -99,8 +99,8 @@ void MonstroSynth::renderOutput( fpp_t _frames, sampleFrame * _buf ) #define modulatefreq( car, mod ) \ if( mod##_e1 != 0.0 ) car = qBound( MIN_FREQ, car * static_cast( fastPow( 10.0, m_env1_buf[f] * mod##_e1 ) ), MAX_FREQ ); \ if( mod##_e2 != 0.0 ) car = qBound( MIN_FREQ, car * static_cast( fastPow( 10.0, m_env2_buf[f] * mod##_e2 ) ), MAX_FREQ ); \ - if( mod##_l1 != 0.0 ) car = qBound( MIN_FREQ, car * static_cast( fastPow( 5.0, m_lfo1_buf[f] * mod##_l1 ) ), MAX_FREQ ); \ - if( mod##_l2 != 0.0 ) car = qBound( MIN_FREQ, car * static_cast( fastPow( 5.0, m_lfo2_buf[f] * mod##_l2 ) ), MAX_FREQ ); + if( mod##_l1 != 0.0 ) car = qBound( MIN_FREQ, car * static_cast( fastPow( 2.5, m_lfo1_buf[f] * mod##_l1 ) ), MAX_FREQ ); \ + if( mod##_l2 != 0.0 ) car = qBound( MIN_FREQ, car * static_cast( fastPow( 2.5, m_lfo2_buf[f] * mod##_l2 ) ), MAX_FREQ ); #define modulateabs( car, mod ) \ if( mod##_e1 != 0.0 ) car = qBound( 0.0f, car + mod##_e1 * m_env1_buf[f], 1.0f ); \ @@ -332,8 +332,8 @@ void MonstroSynth::renderOutput( fpp_t _frames, sampleFrame * _buf ) // o2 modulation? if( omod == MOD_FM ) { - o3l_f = qBound( MIN_FREQ, o3l_f * powf( 5, O2L ), MAX_FREQ ); - o3r_f = qBound( MIN_FREQ, o3r_f * powf( 5, O2R ), MAX_FREQ ); + o3l_f = qBound( MIN_FREQ, o3l_f * powf( 4.0f, O2L ), MAX_FREQ ); + o3r_f = qBound( MIN_FREQ, o3r_f * powf( 4.0f, O2R ), MAX_FREQ ); } // calc and modulate phase From 445bdb69e39698612b953828dd6099c34e02f906 Mon Sep 17 00:00:00 2001 From: Tobias Doerffel Date: Sun, 30 Mar 2014 12:21:37 +0200 Subject: [PATCH 120/647] Song: cleanup and coding style improvements --- include/song.h | 17 +++++++------- src/core/song.cpp | 56 +++++++++++++---------------------------------- 2 files changed, 24 insertions(+), 49 deletions(-) diff --git a/include/song.h b/include/song.h index 0fb2a2047..dc58a8d94 100644 --- a/include/song.h +++ b/include/song.h @@ -210,26 +210,29 @@ public: void loadProject( const QString & _filename ); bool guiSaveProject(); bool guiSaveProjectAs( const QString & _filename ); - bool saveProjectFile( const QString & _filename ); - inline const QString & projectFileName() const + bool saveProjectFile( const QString & _filename ); + + const QString & projectFileName() const { return m_fileName; } - inline bool isLoadingProject() const + + bool isLoadingProject() const { return m_loadingProject; } - inline bool isModified() const + + bool isModified() const { return m_modified; } - inline virtual QString nodeName() const + virtual QString nodeName() const { return "song"; } - virtual inline bool fixedTCOs() const + virtual bool fixedTCOs() const { return false; } @@ -274,8 +277,6 @@ public slots: void addBBTrack(); - bool isLoadingProject(); - private slots: void insertBar(); diff --git a/src/core/song.cpp b/src/core/song.cpp index 5961a3ea3..612ee3875 100644 --- a/src/core/song.cpp +++ b/src/core/song.cpp @@ -666,8 +666,7 @@ void song::addBBTrack() { engine::mixer()->lock(); track * t = track::create( track::BBTrack, this ); - engine::getBBTrackContainer()->setCurrentBB( - bbTrack::numOfBBTrack( t ) ); + engine::getBBTrackContainer()->setCurrentBB( dynamic_cast( t )->index() ); engine::mixer()->unlock(); } @@ -920,8 +919,7 @@ void song::loadProject( const QString & _file_name ) { if( node.nodeName() == "trackcontainer" ) { - ( (JournallingObject *)( this ) )-> - restoreState( node.toElement() ); + ( (JournallingObject *)( this ) )->restoreState( node.toElement() ); } else if( node.nodeName() == "controllers" ) { @@ -933,37 +931,25 @@ void song::loadProject( const QString & _file_name ) } else if( engine::hasGUI() ) { - if( node.nodeName() == - engine::getControllerRackView()->nodeName() ) + if( node.nodeName() == engine::getControllerRackView()->nodeName() ) { - engine::getControllerRackView()-> - restoreState( node.toElement() ); + engine::getControllerRackView()->restoreState( node.toElement() ); } else if( node.nodeName() == engine::pianoRoll()->nodeName() ) { engine::pianoRoll()->restoreState( node.toElement() ); } - else if( node.nodeName() == - engine::automationEditor()-> - nodeName() ) + else if( node.nodeName() == engine::automationEditor()->nodeName() ) { - engine::automationEditor()-> - restoreState( node.toElement() ); + engine::automationEditor()->restoreState( node.toElement() ); } - else if( node.nodeName() == - engine::getProjectNotes()-> - nodeName() ) + else if( node.nodeName() == engine::getProjectNotes()->nodeName() ) { - engine::getProjectNotes()-> - SerializingObject::restoreState( node.toElement() ); + engine::getProjectNotes()->SerializingObject::restoreState( node.toElement() ); } - else if( node.nodeName() == - m_playPos[Mode_PlaySong]. - m_timeLine->nodeName() ) + else if( node.nodeName() == m_playPos[Mode_PlaySong].m_timeLine->nodeName() ) { - m_playPos[Mode_PlaySong]. - m_timeLine->restoreState( - node.toElement() ); + m_playPos[Mode_PlaySong].m_timeLine->restoreState( node.toElement() ); } } } @@ -1019,15 +1005,13 @@ bool song::saveProjectFile( const QString & _filename ) engine::getControllerRackView()->saveState( dataFile, dataFile.content() ); engine::pianoRoll()->saveState( dataFile, dataFile.content() ); engine::automationEditor()->saveState( dataFile, dataFile.content() ); - engine::getProjectNotes()-> - SerializingObject::saveState( dataFile, dataFile.content() ); - m_playPos[Mode_PlaySong].m_timeLine->saveState( - dataFile, dataFile.content() ); + engine::getProjectNotes()->SerializingObject::saveState( dataFile, dataFile.content() ); + m_playPos[Mode_PlaySong].m_timeLine->saveState( dataFile, dataFile.content() ); } saveControllerStates( dataFile, dataFile.content() ); - return dataFile.writeFile( _filename ); + return dataFile.writeFile( _filename ); } @@ -1172,8 +1156,7 @@ void song::exportProject(bool multiExport) efd.setFileMode( FileDialog::AnyFile ); int idx = 0; QStringList types; - while( __fileEncodeDevices[idx].m_fileFormat != - ProjectRenderer::NumFileFormats ) + while( __fileEncodeDevices[idx].m_fileFormat != ProjectRenderer::NumFileFormats ) { types << tr( __fileEncodeDevices[idx].m_description ); ++idx; @@ -1224,8 +1207,7 @@ void song::setModified() { m_modified = true; if( engine::mainWindow() && - QThread::currentThread() == - engine::mainWindow()->thread() ) + QThread::currentThread() == engine::mainWindow()->thread() ) { engine::mainWindow()->resetWindowTitle(); } @@ -1263,14 +1245,6 @@ void song::removeController( Controller * _controller ) } - - -bool song::isLoadingProject() -{ - return m_loadingProject; -} - - #include "moc_song.cxx" From 1adbac9009764742b46181e953e25ab855a1eecb Mon Sep 17 00:00:00 2001 From: Tobias Doerffel Date: Sun, 30 Mar 2014 12:27:23 +0200 Subject: [PATCH 121/647] Song: revert accidental change --- src/core/song.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/core/song.cpp b/src/core/song.cpp index 612ee3875..a1a27c3d6 100644 --- a/src/core/song.cpp +++ b/src/core/song.cpp @@ -666,7 +666,8 @@ void song::addBBTrack() { engine::mixer()->lock(); track * t = track::create( track::BBTrack, this ); - engine::getBBTrackContainer()->setCurrentBB( dynamic_cast( t )->index() ); + engine::getBBTrackContainer()->setCurrentBB( + bbTrack::numOfBBTrack( t ) ); engine::mixer()->unlock(); } From e924888eb63f406c18f46b8d62e6b6969c4e5349 Mon Sep 17 00:00:00 2001 From: Tobias Doerffel Date: Sun, 30 Mar 2014 12:23:10 +0200 Subject: [PATCH 122/647] BbTrack: replaced static numOfBBTrack() by proper index() method --- include/bb_track.h | 8 +++++++- src/core/song.cpp | 3 +-- src/tracks/bb_track.cpp | 29 ++++++++++------------------- 3 files changed, 18 insertions(+), 22 deletions(-) diff --git a/include/bb_track.h b/include/bb_track.h index d951ea963..f9001f61e 100644 --- a/include/bb_track.h +++ b/include/bb_track.h @@ -58,6 +58,8 @@ public: return qRgb( 128, 182, 175 ); } + int bbTrackIndex(); + virtual trackContentObjectView * createView( trackView * _tv ); private: @@ -122,9 +124,13 @@ public: virtual void loadTrackSpecificSettings( const QDomElement & _this ); static bbTrack * findBBTrack( int _bb_num ); - static int numOfBBTrack( track * _track ); static void swapBBTracks( track * _track1, track * _track2 ); + int index() + { + return s_infoMap[this]; + } + bool automationDisabled( track * _track ) { return( m_disabledTracks.contains( _track ) ); diff --git a/src/core/song.cpp b/src/core/song.cpp index 2d60cbec1..6300c3217 100644 --- a/src/core/song.cpp +++ b/src/core/song.cpp @@ -666,8 +666,7 @@ void song::addBBTrack() { engine::mixer()->lock(); track * t = track::create( track::BBTrack, this ); - engine::getBBTrackContainer()->setCurrentBB( - bbTrack::numOfBBTrack( t ) ); + engine::getBBTrackContainer()->setCurrentBB( dynamic_cast( t )->index() ); engine::mixer()->unlock(); } diff --git a/src/tracks/bb_track.cpp b/src/tracks/bb_track.cpp index ff2b9b76f..cc156599e 100644 --- a/src/tracks/bb_track.cpp +++ b/src/tracks/bb_track.cpp @@ -50,8 +50,7 @@ bbTCO::bbTCO( track * _track, unsigned int _color ) : trackContentObject( _track ), m_color( _color > 0 ? _color : defaultColor() ) { - tact_t t = engine::getBBTrackContainer()->lengthOfBB( - bbTrack::numOfBBTrack( getTrack() ) ); + tact_t t = engine::getBBTrackContainer()->lengthOfBB( bbTrackIndex() ); if( t > 0 ) { saveJournallingState( false ); @@ -110,6 +109,12 @@ void bbTCO::loadSettings( const QDomElement & _this ) +int bbTCO::bbTrackIndex() +{ + return dynamic_cast( getTrack() )->index(); +} + + trackContentObjectView * bbTCO::createView( trackView * _tv ) { @@ -190,8 +195,7 @@ void bbTCOView::paintEvent( QPaintEvent * ) lingrad.setColorAt( 1, col.light( 70 ) ); p.fillRect( rect(), lingrad ); - tact_t t = engine::getBBTrackContainer()->lengthOfBB( - bbTrack::numOfBBTrack( m_bbTCO->getTrack() ) ); + tact_t t = engine::getBBTrackContainer()->lengthOfBB( m_bbTCO->bbTrackIndex() ); if( m_bbTCO->length() > MidiTime::ticksPerTact() && t > 0 ) { for( int x = static_cast( t * pixelsPerTact() ); @@ -230,7 +234,7 @@ void bbTCOView::paintEvent( QPaintEvent * ) void bbTCOView::openInBBEditor() { - engine::getBBTrackContainer()->setCurrentBB( bbTrack::numOfBBTrack( m_bbTCO->getTrack() ) ); + engine::getBBTrackContainer()->setCurrentBB( m_bbTCO->bbTrackIndex() ); engine::mainWindow()->toggleBBEditorWin( true ); } @@ -504,18 +508,6 @@ bbTrack * bbTrack::findBBTrack( int _bb_num ) -int bbTrack::numOfBBTrack( track * _track ) -{ - if( dynamic_cast( _track ) != NULL ) - { - return s_infoMap[dynamic_cast( _track )]; - } - return 0; -} - - - - void bbTrack::swapBBTracks( track * _track1, track * _track2 ) { bbTrack * t1 = dynamic_cast( _track1 ); @@ -577,8 +569,7 @@ bool bbTrackView::close() void bbTrackView::clickedTrackLabel() { - engine::getBBTrackContainer()->setCurrentBB( - bbTrack::numOfBBTrack( m_bbTrack ) ); + engine::getBBTrackContainer()->setCurrentBB( m_bbTrack->index() ); engine::getBBEditor()->show(); /* foreach( bbTrackView * tv, trackContainerView()->findChildren() ) From 083d1889eed7fca5de320b31ae7ad29bcc16e0f9 Mon Sep 17 00:00:00 2001 From: Tobias Doerffel Date: Sun, 30 Mar 2014 12:29:25 +0200 Subject: [PATCH 123/647] BbEditor: use foreach() loop --- src/gui/bb_editor.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/gui/bb_editor.cpp b/src/gui/bb_editor.cpp index 939b8f631..8cd5fd051 100644 --- a/src/gui/bb_editor.cpp +++ b/src/gui/bb_editor.cpp @@ -161,10 +161,9 @@ bbEditor::~bbEditor() void bbEditor::removeBBView( int _bb ) { - QList tl = trackViews(); - for( int i = 0; i < tl.size(); ++i ) + foreach( trackView* view, trackViews() ) { - tl[i]->getTrackContentWidget()->removeTCOView( _bb ); + view->getTrackContentWidget()->removeTCOView( _bb ); } } From bd1d9356b5904db6c2023c4d3eb9c6cecdbeb2aa Mon Sep 17 00:00:00 2001 From: Tobias Doerffel Date: Sun, 30 Mar 2014 12:31:47 +0200 Subject: [PATCH 124/647] TrackContentObjectView: add journal checkpoint in remove() rather than close() The remove() slot is only called upon user interaction (i.e. right click) and thus the correct place where to make checkpoints. --- src/core/track.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/core/track.cpp b/src/core/track.cpp index 5bdf09f7f..82d040eca 100644 --- a/src/core/track.cpp +++ b/src/core/track.cpp @@ -324,8 +324,6 @@ bool trackContentObjectView::fixedTCOs() */ bool trackContentObjectView::close() { - m_trackView->getTrack()->addJournalCheckPoint(); - m_trackView->getTrackContentWidget()->removeTCOView( this ); return QWidget::close(); } @@ -342,6 +340,8 @@ bool trackContentObjectView::close() */ void trackContentObjectView::remove() { + m_trackView->getTrack()->addJournalCheckPoint(); + // delete ourself close(); m_tco->deleteLater(); @@ -2246,7 +2246,6 @@ void trackView::mouseMoveEvent( QMouseEvent * _me ) // a track-widget not equal to ourself? if( track_at_y != NULL && track_at_y != this ) { - addJournalCheckPoint(); // then move us up/down there! if( _me->y() < 0 ) { From 75d8ab54beac813099be39819412203e4bd99f2a Mon Sep 17 00:00:00 2001 From: Tobias Doerffel Date: Sun, 30 Mar 2014 12:39:12 +0200 Subject: [PATCH 125/647] TrackContainerView: add journal checkpoints in view rather than model --- src/core/TrackContainer.cpp | 2 -- src/gui/TrackContainerView.cpp | 6 ++++++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/core/TrackContainer.cpp b/src/core/TrackContainer.cpp index 4c4b69c85..744cac788 100644 --- a/src/core/TrackContainer.cpp +++ b/src/core/TrackContainer.cpp @@ -160,8 +160,6 @@ void TrackContainer::addTrack( track * _track ) { if( _track->type() != track::HiddenAutomationTrack ) { - addJournalCheckPoint(); - m_tracksMutex.lockForWrite(); m_tracks.push_back( _track ); m_tracksMutex.unlock(); diff --git a/src/gui/TrackContainerView.cpp b/src/gui/TrackContainerView.cpp index 775a56ece..72dff7bd5 100644 --- a/src/gui/TrackContainerView.cpp +++ b/src/gui/TrackContainerView.cpp @@ -156,6 +156,8 @@ void TrackContainerView::removeTrackView( trackView * _tv ) void TrackContainerView::moveTrackViewUp( trackView * _tv ) { + m_tc->addJournalCheckPoint(); + for( int i = 1; i < m_trackViews.size(); ++i ) { trackView * t = m_trackViews[i]; @@ -178,6 +180,8 @@ void TrackContainerView::moveTrackViewUp( trackView * _tv ) void TrackContainerView::moveTrackViewDown( trackView * _tv ) { + m_tc->addJournalCheckPoint(); + for( int i = 0; i < m_trackViews.size()-1; ++i ) { trackView * t = m_trackViews[i]; @@ -219,6 +223,8 @@ void TrackContainerView::realignTracks() void TrackContainerView::createTrackView( track * _t ) { + m_tc->addJournalCheckPoint(); + _t->createView( this ); } From d6efd028e1c3cfc1fdb6b5984ede1b9fa963924b Mon Sep 17 00:00:00 2001 From: Tobias Doerffel Date: Sun, 30 Mar 2014 12:40:05 +0200 Subject: [PATCH 126/647] TrackContainerView: disable undo/redo for track creation/removal Due to the complex implementation of BB tracks it's hard to implement a reliable undo/redo journalling for whole TrackContainerViews. Closes #531. --- src/gui/TrackContainerView.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/gui/TrackContainerView.cpp b/src/gui/TrackContainerView.cpp index 72dff7bd5..a55ca4b50 100644 --- a/src/gui/TrackContainerView.cpp +++ b/src/gui/TrackContainerView.cpp @@ -223,7 +223,7 @@ void TrackContainerView::realignTracks() void TrackContainerView::createTrackView( track * _t ) { - m_tc->addJournalCheckPoint(); + //m_tc->addJournalCheckPoint(); _t->createView( this ); } @@ -233,7 +233,7 @@ void TrackContainerView::createTrackView( track * _t ) void TrackContainerView::deleteTrackView( trackView * _tv ) { - m_tc->addJournalCheckPoint(); + //m_tc->addJournalCheckPoint(); track * t = _tv->getTrack(); removeTrackView( _tv ); From 3b80ec74d1cd790a2529a01abfc541cbe4b0c940 Mon Sep 17 00:00:00 2001 From: Vesa Date: Sun, 30 Mar 2014 15:18:29 +0300 Subject: [PATCH 127/647] Monstro - fixes, new waveforms --- plugins/monstro/Monstro.cpp | 57 ++++++++++++++++++++++++++++++++---- plugins/monstro/Monstro.h | 36 +++++++++++++++++++---- plugins/monstro/rand.png | Bin 0 -> 407 bytes plugins/monstro/sinabs.png | Bin 0 -> 399 bytes plugins/monstro/sqrsoft.png | Bin 0 -> 393 bytes 5 files changed, 83 insertions(+), 10 deletions(-) create mode 100644 plugins/monstro/rand.png create mode 100644 plugins/monstro/sinabs.png create mode 100644 plugins/monstro/sqrsoft.png diff --git a/plugins/monstro/Monstro.cpp b/plugins/monstro/Monstro.cpp index 28aa4c94e..1ca3837be 100644 --- a/plugins/monstro/Monstro.cpp +++ b/plugins/monstro/Monstro.cpp @@ -99,8 +99,8 @@ void MonstroSynth::renderOutput( fpp_t _frames, sampleFrame * _buf ) #define modulatefreq( car, mod ) \ if( mod##_e1 != 0.0 ) car = qBound( MIN_FREQ, car * static_cast( fastPow( 10.0, m_env1_buf[f] * mod##_e1 ) ), MAX_FREQ ); \ if( mod##_e2 != 0.0 ) car = qBound( MIN_FREQ, car * static_cast( fastPow( 10.0, m_env2_buf[f] * mod##_e2 ) ), MAX_FREQ ); \ - if( mod##_l1 != 0.0 ) car = qBound( MIN_FREQ, car * static_cast( fastPow( 2.5, m_lfo1_buf[f] * mod##_l1 ) ), MAX_FREQ ); \ - if( mod##_l2 != 0.0 ) car = qBound( MIN_FREQ, car * static_cast( fastPow( 2.5, m_lfo2_buf[f] * mod##_l2 ) ), MAX_FREQ ); + if( mod##_l1 != 0.0 ) car = qBound( MIN_FREQ, car * static_cast( fastPow( 2.0, m_lfo1_buf[f] * mod##_l1 ) ), MAX_FREQ ); \ + if( mod##_l2 != 0.0 ) car = qBound( MIN_FREQ, car * static_cast( fastPow( 2.0, m_lfo2_buf[f] * mod##_l2 ) ), MAX_FREQ ); #define modulateabs( car, mod ) \ if( mod##_e1 != 0.0 ) car = qBound( 0.0f, car + mod##_e1 * m_env1_buf[f], 1.0f ); \ @@ -113,7 +113,6 @@ void MonstroSynth::renderOutput( fpp_t _frames, sampleFrame * _buf ) if( mod##_e2 != 0.0 ) car = fraction( car + mod##_e2 * m_env2_buf[f] ); \ if( mod##_l1 != 0.0 ) car = fraction( car + mod##_l1 / 2 * m_lfo1_buf[f] ); \ if( mod##_l2 != 0.0 ) car = fraction( car + mod##_l2 / 2 * m_lfo2_buf[f] ); - #define modulatevol( car, mod ) \ if( mod##_e1 > 0.0 ) car = qBound( 0.0f, car * ( 1.0f - mod##_e1 + mod##_e1 * m_env1_buf[f] ), MODCLIP ); \ @@ -272,6 +271,10 @@ void MonstroSynth::renderOutput( fpp_t _frames, sampleFrame * _buf ) float o1_pw = pw; modulateabs( o1_pw, o1pw ) + // bounds check for phase + if( o1l_p < 0 ) o1l_p += 1.0f; + if( o1r_p < 0 ) o1r_p += 1.0f; + // pulse wave osc sample_t O1L = ( o1l_p < o1_pw ) ? 1.0f : -1.0f; sample_t O1R = ( o1r_p < o1_pw ) ? 1.0f : -1.0f; @@ -303,6 +306,10 @@ void MonstroSynth::renderOutput( fpp_t _frames, sampleFrame * _buf ) float o2r_p = m_osc2r_phase + o2rpo; modulatephs( o2l_p, o2p ) modulatephs( o2r_p, o2p ) + + // bounds check for phase + if( o2l_p < 0 ) o2l_p += 1.0f; + if( o2r_p < 0 ) o2r_p += 1.0f; // multi-wave DC Oscillator sample_t O2L = oscillate( o2w, o2l_p ); @@ -347,6 +354,10 @@ void MonstroSynth::renderOutput( fpp_t _frames, sampleFrame * _buf ) o3l_p = fraction( o3l_p + O2L/2 ); o3r_p = fraction( o3r_p + O2R/2 ); } + + // bounds check for phase + if( o3l_p < 0 ) o3l_p += 1.0f; + if( o3r_p < 0 ) o3r_p += 1.0f; // multi-wave DC Oscillator, sub-osc 1 sample_t O3AL = oscillate( o3w1, o3l_p ); @@ -449,6 +460,15 @@ void MonstroSynth::renderModulators( fpp_t _frames ) m_lfo1_buf[f] = lfo1_s; } break; + case WAVE_SQRSOFT: + for( f_cnt_t f = 0; f < _frames; f++ ) + { + const f_cnt_t t = f + m_nph->totalFramesPlayed(); + lfo1_s = oscillate( WAVE_SQRSOFT, lfo1_p + static_cast( t ) / lfo1_r ); + if( t < m_parent->m_lfo1_att ) lfo1_s *= ( static_cast( t ) / m_parent->m_lfo1_att ); + m_lfo1_buf[f] = lfo1_s; + } + break; case WAVE_MOOG: for( f_cnt_t f = 0; f < _frames; f++ ) { @@ -458,6 +478,15 @@ void MonstroSynth::renderModulators( fpp_t _frames ) m_lfo1_buf[f] = lfo1_s; } break; + case WAVE_SINABS: + for( f_cnt_t f = 0; f < _frames; f++ ) + { + const f_cnt_t t = f + m_nph->totalFramesPlayed(); + lfo1_s = oscillate( WAVE_SINABS, lfo1_p + static_cast( t ) / lfo1_r ); + if( t < m_parent->m_lfo1_att ) lfo1_s *= ( static_cast( t ) / m_parent->m_lfo1_att ); + m_lfo1_buf[f] = lfo1_s; + } + break; case WAVE_EXP: for( f_cnt_t f = 0; f < _frames; f++ ) { @@ -529,6 +558,15 @@ void MonstroSynth::renderModulators( fpp_t _frames ) m_lfo2_buf[f] = lfo2_s; } break; + case WAVE_SQRSOFT: + for( f_cnt_t f = 0; f < _frames; f++ ) + { + const f_cnt_t t = f + m_nph->totalFramesPlayed(); + lfo2_s = oscillate( WAVE_SQRSOFT, lfo2_p + static_cast( t ) / lfo2_r ); + if( t < m_parent->m_lfo2_att ) lfo2_s *= ( static_cast( t ) / m_parent->m_lfo2_att ); + m_lfo2_buf[f] = lfo2_s; + } + break; case WAVE_MOOG: for( f_cnt_t f = 0; f < _frames; f++ ) { @@ -538,6 +576,15 @@ void MonstroSynth::renderModulators( fpp_t _frames ) m_lfo2_buf[f] = lfo2_s; } break; + case WAVE_SINABS: + for( f_cnt_t f = 0; f < _frames; f++ ) + { + const f_cnt_t t = f + m_nph->totalFramesPlayed(); + lfo2_s = oscillate( WAVE_SINABS, lfo2_p + static_cast( t ) / lfo2_r ); + if( t < m_parent->m_lfo2_att ) lfo2_s *= ( static_cast( t ) / m_parent->m_lfo2_att ); + m_lfo2_buf[f] = lfo2_s; + } + break; case WAVE_EXP: for( f_cnt_t f = 0; f < _frames; f++ ) { @@ -797,8 +844,8 @@ MonstroInstrument::MonstroInstrument( InstrumentTrack * _instrument_track ) : setwavemodel( m_osc2Wave ) setwavemodel( m_osc3Wave1 ) setwavemodel( m_osc3Wave2 ) - setwavemodel( m_lfo1Wave ) - setwavemodel( m_lfo2Wave ) + setlfowavemodel( m_lfo1Wave ) + setlfowavemodel( m_lfo2Wave ) // make connections: diff --git a/plugins/monstro/Monstro.h b/plugins/monstro/Monstro.h index e251b60b2..43dc40b7c 100644 --- a/plugins/monstro/Monstro.h +++ b/plugins/monstro/Monstro.h @@ -59,11 +59,23 @@ name .addItem( tr( "Saw wave" ), static_cast( new PluginPixmapLoader( "saw" ) ) ); \ name .addItem( tr( "Ramp wave" ), static_cast( new PluginPixmapLoader( "ramp" ) ) ); \ name .addItem( tr( "Square wave" ), static_cast( new PluginPixmapLoader( "sqr" ) ) ); \ + name .addItem( tr( "Soft square wave" ), static_cast( new PluginPixmapLoader( "sqrsoft" ) ) ); \ name .addItem( tr( "Moog saw wave" ), static_cast( new PluginPixmapLoader( "moog" ) ) ); \ + name .addItem( tr( "Abs. sine wave" ), static_cast( new PluginPixmapLoader( "sinabs" ) ) ); \ name .addItem( tr( "Exponential wave" ), static_cast( new PluginPixmapLoader( "exp" ) ) ); \ name .addItem( tr( "White noise" ), static_cast( new PluginPixmapLoader( "noise" ) ) ); - +#define setlfowavemodel( name ) \ + name .addItem( tr( "Sine wave" ), static_cast( new PluginPixmapLoader( "sin" ) ) ); \ + name .addItem( tr( "Triangle wave" ), static_cast( new PluginPixmapLoader( "tri" ) ) ); \ + name .addItem( tr( "Saw wave" ), static_cast( new PluginPixmapLoader( "saw" ) ) ); \ + name .addItem( tr( "Ramp wave" ), static_cast( new PluginPixmapLoader( "ramp" ) ) ); \ + name .addItem( tr( "Square wave" ), static_cast( new PluginPixmapLoader( "sqr" ) ) ); \ + name .addItem( tr( "Soft square wave" ), static_cast( new PluginPixmapLoader( "sqrsoft" ) ) ); \ + name .addItem( tr( "Moog saw wave" ), static_cast( new PluginPixmapLoader( "moog" ) ) ); \ + name .addItem( tr( "Abs. sine wave" ), static_cast( new PluginPixmapLoader( "sinabs" ) ) ); \ + name .addItem( tr( "Exponential wave" ), static_cast( new PluginPixmapLoader( "exp" ) ) ); \ + name .addItem( tr( "Random" ), static_cast( new PluginPixmapLoader( "rand" ) ) ); const int O1ROW = 22; @@ -112,10 +124,12 @@ const int WAVE_TRI = 1; const int WAVE_SAW = 2; const int WAVE_RAMP = 3; const int WAVE_SQR = 4; -const int WAVE_MOOG = 5; -const int WAVE_EXP = 6; -const int WAVE_NOISE = 7; -const int NUM_WAVES = 8; +const int WAVE_SQRSOFT = 5; +const int WAVE_MOOG = 6; +const int WAVE_SINABS = 7; +const int WAVE_EXP = 8; +const int WAVE_NOISE = 9; +const int NUM_WAVES = 10; const int MOD_MIX = 0; const int MOD_AM = 1; @@ -206,9 +220,21 @@ private: case WAVE_SQR: return Oscillator::squareSample( _ph ); break; + case WAVE_SQRSOFT: + { + const float ph = fraction( _ph ); + if( ph < 0.1 ) return Oscillator::sinSample( ph * 5 + 0.75 ); + else if( ph < 0.5 ) return 1.0f; + else if( ph < 0.6 ) return Oscillator::sinSample( ph * 5 + 0.75 ); + else return -1.0f; + break; + } case WAVE_MOOG: return Oscillator::moogSawSample( _ph ); break; + case WAVE_SINABS: + return qAbs( Oscillator::sinSample( _ph ) ); + break; case WAVE_EXP: return Oscillator::expSample( _ph ); break; diff --git a/plugins/monstro/rand.png b/plugins/monstro/rand.png new file mode 100644 index 0000000000000000000000000000000000000000..b857b98820cfa9d95ab85e6f7be6a04487de29b4 GIT binary patch literal 407 zcmeAS@N?(olHy`uVBq!ia0vp^d_XL~!3HGNrubO_DYhhUcNZWH1V5d3*8?fe0*}aI z1_o|n5N2eUHAey{$X?><>&kwQS&my=GvZO*44{x?iEBiObAE1aYF-J0b5UwyNotBh zd1gt5g1e`0KzJjcI8f1lPZ!4!jq_6{>Uz5binv}+oR`?-d2qc=6i?XyhWdn6Zh{** zx+?3MeI1XeWo+R}+I&KSg?+NZEVkyZqlJ=t9KYN>KAU%X@!{AvwcmIrUGYt5&N6M} zPuTjAeHIJbfpj)0cDKgcPPxpl4@eiV%t^Z=*6_CEz1RUE1GYJ?N5b?Ldv$R-FqSmD z?zpkKVcDc)VF|{LuJ+=WTQ1FEPZQcKE%|~egW>Z2S#OpJxs|ShalK w6PeQoQn#+>yHZ}7JHs~o%Hf3zcKu=tm^|gQ&g9DFVdQ&MBb@09-|zZvX%Q literal 0 HcmV?d00001 diff --git a/plugins/monstro/sinabs.png b/plugins/monstro/sinabs.png new file mode 100644 index 0000000000000000000000000000000000000000..067fa0ddb04f4f27fd56baac0416ad8553d08c61 GIT binary patch literal 399 zcmeAS@N?(olHy`uVBq!ia0vp^d_XL~!3HGNrubO_DYhhUcNZWH1V5d3*8?fe0*}aI z1_o|n5N2eUHAey{$X?><>&kwQS&mywx>HXs5-22D;u=xnoS&PUnpeW$T$GwvlA5AW zo>`Ki;O^-g5Z=fq4pj8r)5S4FV*9sifkbhOd3^}9&K`&Afgv`{Lsx09Mh)7N!)vS?#}5wjV)En&Ry02y6l4f zRq?OWa#w8K6?FYoyOrjbu(y8>9*cQe&H9GX_<^WJ`0h8njp_+3GOJ5ne6+W+@im%1 zuxj_;bYg+^10`pM8;r+he&aBS{Cvgjr20?3#>@9ASa=%Llx}roT(;5p`p1pE=jvar z>wj3L9o;+4(q*Cff$DSp+6m$j4Ch-nGDaPEVjK1}lz-Ct?LFO1!h)9{UGinUlb*ae o%VkSeen$6!_V_LJezopr0C&opi2wiq literal 0 HcmV?d00001 diff --git a/plugins/monstro/sqrsoft.png b/plugins/monstro/sqrsoft.png new file mode 100644 index 0000000000000000000000000000000000000000..d04a739474efd2a478d60f3b7ed0a43a5ddce2d7 GIT binary patch literal 393 zcmeAS@N?(olHy`uVBq!ia0vp^d_XL~!3HGNrubO_DYhhUcNZWH1V5d3*8?fe0*}aI z1_o|n5N2eUHAey{$X?><>&kwQS&my=>Ab;m0icj%iEBiObAE1aYF-J0b5UwyNotBh zd1gt5g1e`0KzJjcI8f0?PZ!4!jq`IS8G1Q8inyNt{m;oUaKlD{je#3BY%Aq#;?Q&O zSk3XyDW+j Date: Sun, 30 Mar 2014 16:11:12 +0300 Subject: [PATCH 128/647] Monstro - envelope fix --- plugins/monstro/Monstro.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/plugins/monstro/Monstro.cpp b/plugins/monstro/Monstro.cpp index 1ca3837be..8cd069f90 100644 --- a/plugins/monstro/Monstro.cpp +++ b/plugins/monstro/Monstro.cpp @@ -97,8 +97,8 @@ void MonstroSynth::renderOutput( fpp_t _frames, sampleFrame * _buf ) { // macros for modulating with env/lfos #define modulatefreq( car, mod ) \ - if( mod##_e1 != 0.0 ) car = qBound( MIN_FREQ, car * static_cast( fastPow( 10.0, m_env1_buf[f] * mod##_e1 ) ), MAX_FREQ ); \ - if( mod##_e2 != 0.0 ) car = qBound( MIN_FREQ, car * static_cast( fastPow( 10.0, m_env2_buf[f] * mod##_e2 ) ), MAX_FREQ ); \ + if( mod##_e1 != 0.0 ) car = qBound( MIN_FREQ, car * static_cast( fastPow( 2.0, m_env1_buf[f] * mod##_e1 * 2 ) ), MAX_FREQ ); \ + if( mod##_e2 != 0.0 ) car = qBound( MIN_FREQ, car * static_cast( fastPow( 2.0, m_env2_buf[f] * mod##_e2 * 2 ) ), MAX_FREQ ); \ if( mod##_l1 != 0.0 ) car = qBound( MIN_FREQ, car * static_cast( fastPow( 2.0, m_lfo1_buf[f] * mod##_l1 ) ), MAX_FREQ ); \ if( mod##_l2 != 0.0 ) car = qBound( MIN_FREQ, car * static_cast( fastPow( 2.0, m_lfo2_buf[f] * mod##_l2 ) ), MAX_FREQ ); @@ -661,6 +661,7 @@ void MonstroSynth::renderModulators( fpp_t _frames ) { m_env1_buf[f] = calcSlope( s, env1_s ); m_env1_phase = qMin( 4.0f - env1_sus, m_env1_phase + m_parent->m_env1_dec ); + if( m_env1_phase == 4.0f ) m_env1_phase = 5.0f; // jump over release if sustain is zero - fix for clicking } } else if( m_env1_phase < 5.0f ) // release phase @@ -712,6 +713,7 @@ void MonstroSynth::renderModulators( fpp_t _frames ) { m_env2_buf[f] = calcSlope( s, env2_s ); m_env2_phase = qMin( 4.0f - env2_sus, m_env2_phase + m_parent->m_env2_dec ); + if( m_env1_phase == 4.0f ) m_env1_phase = 5.0f; // jump over release if sustain is zero - fix for clicking } } else if( m_env2_phase < 5.0f ) // release phase From d2a0723e14ce4e52b778ff4798bd207fa3d7f9e2 Mon Sep 17 00:00:00 2001 From: Hannu Haahti Date: Sun, 30 Mar 2014 21:59:42 +0300 Subject: [PATCH 129/647] fileBrowser: keep filter after refresh --- src/gui/file_browser.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/gui/file_browser.cpp b/src/gui/file_browser.cpp index 2d5159766..d49d4c04f 100644 --- a/src/gui/file_browser.cpp +++ b/src/gui/file_browser.cpp @@ -225,6 +225,7 @@ bool fileBrowser::filterItems( QTreeWidgetItem * _item, const QString & _filter void fileBrowser::reloadTree( void ) { + const QString text = m_filterEdit->text(); m_filterEdit->clear(); m_l->clear(); QStringList paths = m_directories.split( '*' ); @@ -232,6 +233,8 @@ void fileBrowser::reloadTree( void ) { addItems( *it ); } + m_filterEdit->setText( text ); + filterItems( text ); } From 8f065c198af9e81f5e6e3828604e6f26812195d7 Mon Sep 17 00:00:00 2001 From: Vesa Date: Mon, 31 Mar 2014 01:37:38 +0300 Subject: [PATCH 130/647] Monstro: add sync mechanism, make LFOs running, fix remaining small bugs --- plugins/monstro/Monstro.cpp | 413 ++++++++++++++++++++------------ plugins/monstro/Monstro.h | 47 +++- plugins/monstro/artwork_op.png | Bin 58075 -> 59412 bytes plugins/monstro/tinyled_off.png | Bin 0 -> 397 bytes plugins/monstro/tinyled_on.png | Bin 0 -> 594 bytes 5 files changed, 297 insertions(+), 163 deletions(-) create mode 100644 plugins/monstro/tinyled_off.png create mode 100644 plugins/monstro/tinyled_on.png diff --git a/plugins/monstro/Monstro.cpp b/plugins/monstro/Monstro.cpp index 8cd069f90..900fb4b5d 100644 --- a/plugins/monstro/Monstro.cpp +++ b/plugins/monstro/Monstro.cpp @@ -80,6 +80,12 @@ MonstroSynth::MonstroSynth( MonstroInstrument * _i, NotePlayHandle * _nph, m_env1_phase = 0.0; m_env2_phase = 0.0; + + m_lfo1_phase = 0.0; + m_lfo2_phase = 0.0; + + m_osc1l_last = 0.0; + m_osc1r_last = 0.0; } @@ -100,20 +106,20 @@ void MonstroSynth::renderOutput( fpp_t _frames, sampleFrame * _buf ) if( mod##_e1 != 0.0 ) car = qBound( MIN_FREQ, car * static_cast( fastPow( 2.0, m_env1_buf[f] * mod##_e1 * 2 ) ), MAX_FREQ ); \ if( mod##_e2 != 0.0 ) car = qBound( MIN_FREQ, car * static_cast( fastPow( 2.0, m_env2_buf[f] * mod##_e2 * 2 ) ), MAX_FREQ ); \ if( mod##_l1 != 0.0 ) car = qBound( MIN_FREQ, car * static_cast( fastPow( 2.0, m_lfo1_buf[f] * mod##_l1 ) ), MAX_FREQ ); \ - if( mod##_l2 != 0.0 ) car = qBound( MIN_FREQ, car * static_cast( fastPow( 2.0, m_lfo2_buf[f] * mod##_l2 ) ), MAX_FREQ ); + if( mod##_l2 != 0.0 ) car = qBound( MIN_FREQ, car * static_cast( fastPow( 2.0, m_lfo2_buf[f] * mod##_l2 ) ), MAX_FREQ ); #define modulateabs( car, mod ) \ if( mod##_e1 != 0.0 ) car = qBound( 0.0f, car + mod##_e1 * m_env1_buf[f], 1.0f ); \ if( mod##_e2 != 0.0 ) car = qBound( 0.0f, car + mod##_e2 * m_env2_buf[f], 1.0f ); \ if( mod##_l1 != 0.0 ) car = qBound( 0.0f, car + mod##_l1 / 2 * m_lfo1_buf[f], 1.0f ); \ if( mod##_l2 != 0.0 ) car = qBound( 0.0f, car + mod##_l2 / 2 * m_lfo2_buf[f], 1.0f ); - + #define modulatephs( car, mod ) \ if( mod##_e1 != 0.0 ) car = fraction( car + mod##_e1 * m_env1_buf[f] ); \ if( mod##_e2 != 0.0 ) car = fraction( car + mod##_e2 * m_env2_buf[f] ); \ if( mod##_l1 != 0.0 ) car = fraction( car + mod##_l1 / 2 * m_lfo1_buf[f] ); \ if( mod##_l2 != 0.0 ) car = fraction( car + mod##_l2 / 2 * m_lfo2_buf[f] ); - + #define modulatevol( car, mod ) \ if( mod##_e1 > 0.0 ) car = qBound( 0.0f, car * ( 1.0f - mod##_e1 + mod##_e1 * m_env1_buf[f] ), MODCLIP ); \ if( mod##_e1 < 0.0 ) car = qBound( 0.0f, car * ( 1.0f + mod##_e1 * m_env1_buf[f] ), MODCLIP ); \ @@ -121,7 +127,7 @@ void MonstroSynth::renderOutput( fpp_t _frames, sampleFrame * _buf ) if( mod##_e2 < 0.0 ) car = qBound( 0.0f, car * ( 1.0f + mod##_e2 * m_env2_buf[f] ), MODCLIP ); \ if( mod##_l1 != 0.0 ) car = qBound( 0.0f, car * ( 1.0f + mod##_l1 * m_lfo1_buf[f] ), MODCLIP ); \ if( mod##_l2 != 0.0 ) car = qBound( 0.0f, car * ( 1.0f + mod##_l2 * m_lfo2_buf[f] ), MODCLIP ); - + // pre-render env's and lfo's renderModulators( _frames ); @@ -132,7 +138,7 @@ void MonstroSynth::renderOutput( fpp_t _frames, sampleFrame * _buf ) const float o1pw_e2 = ( m_parent->m_pw1env2.value() ); const float o1pw_l1 = ( m_parent->m_pw1lfo1.value() ); const float o1pw_l2 = ( m_parent->m_pw1lfo2.value() ); - + // get phases const float o1lpo = m_parent->m_osc1l_po; const float o1rpo = m_parent->m_osc1r_po; @@ -140,8 +146,8 @@ void MonstroSynth::renderOutput( fpp_t _frames, sampleFrame * _buf ) const float o1p_e2 = ( m_parent->m_phs1env2.value() ); const float o1p_l1 = ( m_parent->m_phs1lfo1.value() ); const float o1p_l2 = ( m_parent->m_phs1lfo2.value() ); - - // get pitch + + // get pitch const float o1lfb = ( m_parent->m_osc1l_freq * m_nph->frequency() ); const float o1rfb = ( m_parent->m_osc1r_freq * m_nph->frequency() ); const float o1f_e1 = ( m_parent->m_pit1env1.value() ); @@ -157,11 +163,10 @@ void MonstroSynth::renderOutput( fpp_t _frames, sampleFrame * _buf ) const float o1v_l1 = ( m_parent->m_vol1lfo1.value() ); const float o1v_l2 = ( m_parent->m_vol1lfo2.value() ); - // update osc2 // get waveform const int o2w = m_parent->m_osc2Wave.value(); - + // get phases const float o2lpo = m_parent->m_osc2l_po; const float o2rpo = m_parent->m_osc2r_po; @@ -170,9 +175,9 @@ void MonstroSynth::renderOutput( fpp_t _frames, sampleFrame * _buf ) const float o2p_l1 = ( m_parent->m_phs2lfo1.value() ); const float o2p_l2 = ( m_parent->m_phs2lfo2.value() ); - // get pitch + // get pitch const float o2lfb = ( m_parent->m_osc2l_freq * m_nph->frequency() ); - const float o2rfb = ( m_parent->m_osc2r_freq * m_nph->frequency() ); + const float o2rfb = ( m_parent->m_osc2r_freq * m_nph->frequency() ); const float o2f_e1 = ( m_parent->m_pit2env1.value() ); const float o2f_e2 = ( m_parent->m_pit2env2.value() ); const float o2f_l1 = ( m_parent->m_pit2lfo1.value() ); @@ -185,8 +190,8 @@ void MonstroSynth::renderOutput( fpp_t _frames, sampleFrame * _buf ) const float o2v_e2 = ( m_parent->m_vol2env2.value() ); const float o2v_l1 = ( m_parent->m_vol2lfo2.value() ); const float o2v_l2 = ( m_parent->m_vol2lfo2.value() ); - - + + // update osc3 // get waveforms @@ -222,27 +227,33 @@ void MonstroSynth::renderOutput( fpp_t _frames, sampleFrame * _buf ) const float o3s_e2 = ( m_parent->m_sub3env2.value() ); const float o3s_l1 = ( m_parent->m_sub3lfo1.value() ); const float o3s_l2 = ( m_parent->m_sub3lfo2.value() ); - - + + //o2-o3 modulation - + const int omod = m_parent->m_o23Mod.value(); - - + + // sync information + + const bool o1ssr = m_parent->m_osc1SSR.value(); + const bool o1ssf = m_parent->m_osc1SSF.value(); + const bool o2sync = m_parent->m_osc2Sync.value(); + const bool o3sync = m_parent->m_osc3Sync.value(); + /////////////////////////// // // // start buffer loop // // // /////////////////////////// - - - + + + for( f_cnt_t f = 0; f < _frames; f++ ) - { + { /* // debug code - if( f % 10 == 0 ) { + if( f % 10 == 0 ) { qDebug( "env1 %f -- env1 phase %f", m_env1_buf[f], m_env1_phase ); qDebug( "env1 pre %f att %f dec %f rel %f ", m_parent->m_env1_pre, m_parent->m_env1_att, m_parent->m_env1_dec, m_parent->m_env1_rel ); @@ -255,52 +266,80 @@ void MonstroSynth::renderOutput( fpp_t _frames, sampleFrame * _buf ) // // ///////////////////////////// + // sync send "signals" + bool syncl = false; + bool syncr = false; + // calc and mod frequencies float o1l_f = o1lfb; float o1r_f = o1rfb; modulatefreq( o1l_f, o1f ) modulatefreq( o1r_f, o1f ) - + // calc and modulate phase float o1l_p = m_osc1l_phase + o1lpo; float o1r_p = m_osc1r_phase + o1rpo; modulatephs( o1l_p, o1p ) modulatephs( o1r_p, o1p ) - + // calc and modulate pulse float o1_pw = pw; modulateabs( o1_pw, o1pw ) - + // bounds check for phase if( o1l_p < 0 ) o1l_p += 1.0f; if( o1r_p < 0 ) o1r_p += 1.0f; - + // pulse wave osc sample_t O1L = ( o1l_p < o1_pw ) ? 1.0f : -1.0f; sample_t O1R = ( o1r_p < o1_pw ) ? 1.0f : -1.0f; - + + // check for rise/fall, and "send" sync if appropriate + // sync on rise + if( o1ssr ) + { + if( O1L > m_osc1l_last ) syncl = true; + if( O1R > m_osc1r_last ) syncr = true; + } + if( o1ssf ) + { + if( O1L < m_osc1l_last ) syncl = true; + if( O1R < m_osc1r_last ) syncr = true; + } + + // update last before signal is touched + m_osc1l_last = O1L; + m_osc1r_last = O1R; + // modulate volume O1L *= o1lv; O1R *= o1rv; modulatevol( O1L, o1v ) modulatevol( O1R, o1v ) - - // update osc1 phases + + // update osc1 phases m_osc1l_phase = fraction( m_osc1l_phase + 1.0f / ( static_cast( m_samplerate ) / o1l_f ) ); m_osc1r_phase = fraction( m_osc1r_phase + 1.0f / ( static_cast( m_samplerate ) / o1r_f ) ); - + ///////////////////////////// // // // OSC 2 // // // ///////////////////////////// - + // calc and mod frequencies float o2l_f = o2lfb; float o2r_f = o2rfb; modulatefreq( o2l_f, o2f ) modulatefreq( o2r_f, o2f ) - + + // check for sync + if( o2sync ) + { + if( syncl ) m_osc2l_phase = 0.0f; + if( syncr ) m_osc2r_phase = 0.0f; + } + // calc and modulate phase float o2l_p = m_osc2l_phase + o2lpo; float o2r_p = m_osc2r_phase + o2rpo; @@ -310,21 +349,21 @@ void MonstroSynth::renderOutput( fpp_t _frames, sampleFrame * _buf ) // bounds check for phase if( o2l_p < 0 ) o2l_p += 1.0f; if( o2r_p < 0 ) o2r_p += 1.0f; - + // multi-wave DC Oscillator sample_t O2L = oscillate( o2w, o2l_p ); sample_t O2R = oscillate( o2w, o2r_p ); - + // modulate volume O2L *= o2lv; O2R *= o2rv; modulatevol( O2L, o2v ) modulatevol( O2R, o2v ) - - // update osc2 phases + + // update osc2 phases m_osc2l_phase = fraction( m_osc2l_phase + 1.0f / ( static_cast( m_samplerate ) / o2l_f ) ); m_osc2r_phase = fraction( m_osc2r_phase + 1.0f / ( static_cast( m_samplerate ) / o2r_f ) ); - + ///////////////////////////// // // // OSC 3 // @@ -342,7 +381,14 @@ void MonstroSynth::renderOutput( fpp_t _frames, sampleFrame * _buf ) o3l_f = qBound( MIN_FREQ, o3l_f * powf( 4.0f, O2L ), MAX_FREQ ); o3r_f = qBound( MIN_FREQ, o3r_f * powf( 4.0f, O2R ), MAX_FREQ ); } - + + // check for sync + if( o3sync ) + { + if( syncl ) m_osc3l_phase = 0.0f; + if( syncr ) m_osc3r_phase = 0.0f; + } + // calc and modulate phase float o3l_p = m_osc3l_phase + o3lpo; float o3r_p = m_osc3r_phase + o3rpo; @@ -354,7 +400,7 @@ void MonstroSynth::renderOutput( fpp_t _frames, sampleFrame * _buf ) o3l_p = fraction( o3l_p + O2L/2 ); o3r_p = fraction( o3r_p + O2R/2 ); } - + // bounds check for phase if( o3l_p < 0 ) o3l_p += 1.0f; if( o3r_p < 0 ) o3r_p += 1.0f; @@ -366,14 +412,14 @@ void MonstroSynth::renderOutput( fpp_t _frames, sampleFrame * _buf ) // multi-wave DC Oscillator, sub-osc 2 sample_t O3BL = oscillate( o3w2, o3l_p ); sample_t O3BR = oscillate( o3w2, o3r_p ); - + // calc and modulate sub float sub = o3sub; modulateabs( sub, o3s ) - + sample_t O3L = interpolate( O3AL, O3BL, sub ); sample_t O3R = interpolate( O3AR, O3BR, sub ); - + // modulate volume O3L *= o3lv; O3R *= o3rv; @@ -386,10 +432,10 @@ void MonstroSynth::renderOutput( fpp_t _frames, sampleFrame * _buf ) O3R = qBound( -MODCLIP, O3R * qMax( 0.0f, 1.0f + O2R ), MODCLIP ); } - // update osc3 phases + // update osc3 phases m_osc3l_phase = fraction( m_osc3l_phase + 1.0f / ( static_cast( m_samplerate ) / o3l_f ) ); m_osc3r_phase = fraction( m_osc3r_phase + 1.0f / ( static_cast( m_samplerate ) / o3r_f ) ); - + _buf[f][0] = O1L + O3L + ( omod == MOD_MIX ? O2L : 0.0f ); _buf[f][1] = O1R + O3R + ( omod == MOD_MIX ? O2R : 0.0f ); } @@ -399,15 +445,21 @@ void MonstroSynth::renderOutput( fpp_t _frames, sampleFrame * _buf ) void MonstroSynth::renderModulators( fpp_t _frames ) { // LFO phase offsets - const float lfo1_p = m_parent->m_lfo1Phs.value() / 360.0f; - const float lfo2_p = m_parent->m_lfo2Phs.value() / 360.0f; + const float lfo1_po = m_parent->m_lfo1Phs.value() / 360.0f; + const float lfo2_po = m_parent->m_lfo2Phs.value() / 360.0f; + + // remove cruft from phase counters to prevent overflow + m_lfo1_phase = fraction( m_lfo1_phase ); + m_lfo2_phase = fraction( m_lfo2_phase ); // LFO rates const float lfo1_r = m_parent->m_lfo1Rate.value() / 1000.0f * m_samplerate; const float lfo2_r = m_parent->m_lfo2Rate.value() / 1000.0f * m_samplerate; - // LFOs + // frames played before + const f_cnt_t tfp = m_nph->totalFramesPlayed(); + // LFOs sample_t lfo1_s; sample_t lfo2_s; @@ -418,93 +470,112 @@ void MonstroSynth::renderModulators( fpp_t _frames ) case WAVE_SINE: for( f_cnt_t f = 0; f < _frames; f++ ) { - const f_cnt_t t = f + m_nph->totalFramesPlayed(); - lfo1_s = Oscillator::sinSample( lfo1_p + static_cast( t ) / lfo1_r ); + const f_cnt_t t = f + tfp; + const float ph = m_lfo1_phase + lfo1_po; + lfo1_s = Oscillator::sinSample( ph ); if( t < m_parent->m_lfo1_att ) lfo1_s *= ( static_cast( t ) / m_parent-> m_lfo1_att ); m_lfo1_buf[f] = lfo1_s; + m_lfo1_phase += 1.0 / lfo1_r; } break; case WAVE_TRI: for( f_cnt_t f = 0; f < _frames; f++ ) { - const f_cnt_t t = f + m_nph->totalFramesPlayed(); - lfo1_s = Oscillator::triangleSample( lfo1_p + static_cast( t ) / lfo1_r ); + const f_cnt_t t = f + tfp; + const float ph = m_lfo1_phase + lfo1_po; + lfo1_s = Oscillator::triangleSample( ph ); if( t < m_parent->m_lfo1_att ) lfo1_s *= ( static_cast( t ) / m_parent->m_lfo1_att ); m_lfo1_buf[f] = lfo1_s; + m_lfo1_phase += 1.0 / lfo1_r; } break; case WAVE_SAW: for( f_cnt_t f = 0; f < _frames; f++ ) { - const f_cnt_t t = f + m_nph->totalFramesPlayed(); - lfo1_s = Oscillator::sawSample( lfo1_p + static_cast( t ) / lfo1_r ); + const f_cnt_t t = f + tfp; + const float ph = m_lfo1_phase + lfo1_po; + lfo1_s = Oscillator::sawSample( ph ); if( t < m_parent->m_lfo1_att ) lfo1_s *= ( static_cast( t ) / m_parent->m_lfo1_att ); m_lfo1_buf[f] = lfo1_s; + m_lfo1_phase += 1.0 / lfo1_r; } break; case WAVE_RAMP: for( f_cnt_t f = 0; f < _frames; f++ ) { - const f_cnt_t t = f + m_nph->totalFramesPlayed(); - lfo1_s = Oscillator::sawSample( lfo1_p + static_cast( t ) / lfo1_r ) * -1.0f; + const f_cnt_t t = f + tfp; + const float ph = m_lfo1_phase + lfo1_po; + lfo1_s = Oscillator::sawSample( ph ) * -1.0f; if( t < m_parent->m_lfo1_att ) lfo1_s *= ( static_cast( t ) / m_parent->m_lfo1_att ); m_lfo1_buf[f] = lfo1_s; + m_lfo1_phase += 1.0 / lfo1_r; } break; case WAVE_SQR: for( f_cnt_t f = 0; f < _frames; f++ ) { - const f_cnt_t t = f + m_nph->totalFramesPlayed(); - lfo1_s = Oscillator::squareSample( lfo1_p + static_cast( t ) / lfo1_r ); + const f_cnt_t t = f + tfp; + const float ph = m_lfo1_phase + lfo1_po; + lfo1_s = Oscillator::squareSample( ph ); if( t < m_parent->m_lfo1_att ) lfo1_s *= ( static_cast( t ) / m_parent->m_lfo1_att ); m_lfo1_buf[f] = lfo1_s; + m_lfo1_phase += 1.0 / lfo1_r; } break; case WAVE_SQRSOFT: for( f_cnt_t f = 0; f < _frames; f++ ) { - const f_cnt_t t = f + m_nph->totalFramesPlayed(); - lfo1_s = oscillate( WAVE_SQRSOFT, lfo1_p + static_cast( t ) / lfo1_r ); + const f_cnt_t t = f + tfp; + const float ph = m_lfo1_phase + lfo1_po; + lfo1_s = oscillate( WAVE_SQRSOFT, ph ); if( t < m_parent->m_lfo1_att ) lfo1_s *= ( static_cast( t ) / m_parent->m_lfo1_att ); m_lfo1_buf[f] = lfo1_s; + m_lfo1_phase += 1.0 / lfo1_r; } break; case WAVE_MOOG: for( f_cnt_t f = 0; f < _frames; f++ ) { - const f_cnt_t t = f + m_nph->totalFramesPlayed(); - lfo1_s = Oscillator::moogSawSample( lfo1_p + static_cast( t ) / lfo1_r ); + const f_cnt_t t = f + tfp; + const float ph = m_lfo1_phase + lfo1_po; + lfo1_s = Oscillator::moogSawSample( ph ); if( t < m_parent->m_lfo1_att ) lfo1_s *= ( static_cast( t ) / m_parent->m_lfo1_att ); m_lfo1_buf[f] = lfo1_s; + m_lfo1_phase += 1.0 / lfo1_r; } break; case WAVE_SINABS: for( f_cnt_t f = 0; f < _frames; f++ ) { - const f_cnt_t t = f + m_nph->totalFramesPlayed(); - lfo1_s = oscillate( WAVE_SINABS, lfo1_p + static_cast( t ) / lfo1_r ); + const f_cnt_t t = f + tfp; + const float ph = m_lfo1_phase + lfo1_po; + lfo1_s = oscillate( WAVE_SINABS, ph ); if( t < m_parent->m_lfo1_att ) lfo1_s *= ( static_cast( t ) / m_parent->m_lfo1_att ); m_lfo1_buf[f] = lfo1_s; + m_lfo1_phase += 1.0 / lfo1_r; } break; case WAVE_EXP: for( f_cnt_t f = 0; f < _frames; f++ ) { - const f_cnt_t t = f + m_nph->totalFramesPlayed(); - lfo1_s = Oscillator::expSample( lfo1_p + static_cast( t ) / lfo1_r ); + const f_cnt_t t = f + tfp; + const float ph = m_lfo1_phase + lfo1_po; + lfo1_s = Oscillator::expSample( ph ); if( t < m_parent->m_lfo1_att ) lfo1_s *= ( static_cast( t ) / m_parent-> m_lfo1_att ); m_lfo1_buf[f] = lfo1_s; + m_lfo1_phase += 1.0 / lfo1_r; } break; case WAVE_NOISE: default: for( f_cnt_t f = 0; f < _frames; f++ ) { - const f_cnt_t t = f + m_nph->totalFramesPlayed(); + const f_cnt_t t = f + tfp; if( t % static_cast( lfo1_r ) == 0 ) m_lfo1_last = Oscillator::noiseSample( 0.0f ); lfo1_s = m_lfo1_last; if( t < m_parent->m_lfo1_att ) lfo1_s *= ( static_cast( t ) / m_parent->m_lfo1_att ); m_lfo1_buf[f] = lfo1_s; + m_lfo1_phase += 1.0 / lfo1_r; } break; } @@ -516,93 +587,112 @@ void MonstroSynth::renderModulators( fpp_t _frames ) case WAVE_SINE: for( f_cnt_t f = 0; f < _frames; f++ ) { - const f_cnt_t t = f + m_nph->totalFramesPlayed(); - lfo2_s = Oscillator::sinSample( lfo2_p + static_cast( t ) / lfo2_r ); - if( t < m_parent->m_lfo2_att ) lfo2_s *= ( static_cast( t ) / m_parent->m_lfo2_att ); + const f_cnt_t t = f + tfp; + const float ph = m_lfo2_phase + lfo2_po; + lfo2_s = Oscillator::sinSample( ph ); + if( t < m_parent->m_lfo2_att ) lfo2_s *= ( static_cast( t ) / m_parent-> m_lfo2_att ); m_lfo2_buf[f] = lfo2_s; + m_lfo2_phase += 1.0 / lfo2_r; } break; case WAVE_TRI: for( f_cnt_t f = 0; f < _frames; f++ ) { - const f_cnt_t t = f + m_nph->totalFramesPlayed(); - lfo2_s = Oscillator::triangleSample( lfo2_p + static_cast( t ) / lfo2_r ); + const f_cnt_t t = f + tfp; + const float ph = m_lfo2_phase + lfo2_po; + lfo2_s = Oscillator::triangleSample( ph ); if( t < m_parent->m_lfo2_att ) lfo2_s *= ( static_cast( t ) / m_parent->m_lfo2_att ); m_lfo2_buf[f] = lfo2_s; + m_lfo2_phase += 1.0 / lfo2_r; } break; case WAVE_SAW: for( f_cnt_t f = 0; f < _frames; f++ ) { - const f_cnt_t t = f + m_nph->totalFramesPlayed(); - lfo2_s = Oscillator::sawSample( lfo2_p + static_cast( t ) / lfo2_r ); + const f_cnt_t t = f + tfp; + const float ph = m_lfo2_phase + lfo2_po; + lfo2_s = Oscillator::sawSample( ph ); if( t < m_parent->m_lfo2_att ) lfo2_s *= ( static_cast( t ) / m_parent->m_lfo2_att ); m_lfo2_buf[f] = lfo2_s; + m_lfo2_phase += 1.0 / lfo2_r; } break; case WAVE_RAMP: for( f_cnt_t f = 0; f < _frames; f++ ) { - const f_cnt_t t = f + m_nph->totalFramesPlayed(); - lfo2_s = Oscillator::sawSample( lfo2_p + static_cast( t ) / lfo2_r ) * -1.0f; + const f_cnt_t t = f + tfp; + const float ph = m_lfo2_phase + lfo2_po; + lfo2_s = Oscillator::sawSample( ph ) * -1.0f; if( t < m_parent->m_lfo2_att ) lfo2_s *= ( static_cast( t ) / m_parent->m_lfo2_att ); m_lfo2_buf[f] = lfo2_s; + m_lfo2_phase += 1.0 / lfo2_r; } break; case WAVE_SQR: for( f_cnt_t f = 0; f < _frames; f++ ) { - const f_cnt_t t = f + m_nph->totalFramesPlayed(); - lfo2_s = Oscillator::squareSample( lfo2_p + static_cast( t ) / lfo2_r ); + const f_cnt_t t = f + tfp; + const float ph = m_lfo2_phase + lfo2_po; + lfo2_s = Oscillator::squareSample( ph ); if( t < m_parent->m_lfo2_att ) lfo2_s *= ( static_cast( t ) / m_parent->m_lfo2_att ); m_lfo2_buf[f] = lfo2_s; + m_lfo2_phase += 1.0 / lfo2_r; } break; case WAVE_SQRSOFT: for( f_cnt_t f = 0; f < _frames; f++ ) { - const f_cnt_t t = f + m_nph->totalFramesPlayed(); - lfo2_s = oscillate( WAVE_SQRSOFT, lfo2_p + static_cast( t ) / lfo2_r ); + const f_cnt_t t = f + tfp; + const float ph = m_lfo2_phase + lfo2_po; + lfo2_s = oscillate( WAVE_SQRSOFT, ph ); if( t < m_parent->m_lfo2_att ) lfo2_s *= ( static_cast( t ) / m_parent->m_lfo2_att ); m_lfo2_buf[f] = lfo2_s; + m_lfo2_phase += 1.0 / lfo2_r; } break; case WAVE_MOOG: for( f_cnt_t f = 0; f < _frames; f++ ) { - const f_cnt_t t = f + m_nph->totalFramesPlayed(); - lfo2_s = Oscillator::moogSawSample( lfo2_p + static_cast( t ) / lfo2_r ); + const f_cnt_t t = f + tfp; + const float ph = m_lfo2_phase + lfo2_po; + lfo2_s = Oscillator::moogSawSample( ph ); if( t < m_parent->m_lfo2_att ) lfo2_s *= ( static_cast( t ) / m_parent->m_lfo2_att ); m_lfo2_buf[f] = lfo2_s; + m_lfo2_phase += 1.0 / lfo2_r; } break; case WAVE_SINABS: for( f_cnt_t f = 0; f < _frames; f++ ) { - const f_cnt_t t = f + m_nph->totalFramesPlayed(); - lfo2_s = oscillate( WAVE_SINABS, lfo2_p + static_cast( t ) / lfo2_r ); + const f_cnt_t t = f + tfp; + const float ph = m_lfo2_phase + lfo2_po; + lfo2_s = oscillate( WAVE_SINABS, ph ); if( t < m_parent->m_lfo2_att ) lfo2_s *= ( static_cast( t ) / m_parent->m_lfo2_att ); m_lfo2_buf[f] = lfo2_s; + m_lfo2_phase += 1.0 / lfo2_r; } break; case WAVE_EXP: for( f_cnt_t f = 0; f < _frames; f++ ) { - const f_cnt_t t = f + m_nph->totalFramesPlayed(); - lfo2_s = Oscillator::expSample( lfo2_p + static_cast( t ) / lfo2_r ); - if( t < m_parent->m_lfo2_att ) lfo2_s *= ( static_cast( t ) / m_parent->m_lfo2_att ); + const f_cnt_t t = f + tfp; + const float ph = m_lfo2_phase + lfo2_po; + lfo2_s = Oscillator::expSample( ph ); + if( t < m_parent->m_lfo2_att ) lfo2_s *= ( static_cast( t ) / m_parent-> m_lfo2_att ); m_lfo2_buf[f] = lfo2_s; + m_lfo2_phase += 1.0 / lfo2_r; } break; case WAVE_NOISE: default: for( f_cnt_t f = 0; f < _frames; f++ ) { - const f_cnt_t t = f + m_nph->totalFramesPlayed(); + const f_cnt_t t = f + tfp; if( t % static_cast( lfo2_r ) == 0 ) m_lfo2_last = Oscillator::noiseSample( 0.0f ); lfo2_s = m_lfo2_last; if( t < m_parent->m_lfo2_att ) lfo2_s *= ( static_cast( t ) / m_parent->m_lfo2_att ); m_lfo2_buf[f] = lfo2_s; + m_lfo2_phase += 1.0 / lfo2_r; } break; } @@ -617,10 +707,10 @@ void MonstroSynth::renderModulators( fpp_t _frames ) const float env1_s = m_parent-> m_env1Slope.value(); const float env2_s = m_parent-> m_env2Slope.value(); - + const float env1_sus = m_parent-> m_env1Sus.value(); const float env2_sus = m_parent-> m_env2Sus.value(); - + for( f_cnt_t f = 0; f < _frames; f++ ) { // envelope 1 @@ -633,7 +723,7 @@ void MonstroSynth::renderModulators( fpp_t _frames ) else if( m_env1_phase < 3.0f ) m_env1_phase = 4.0f; else m_env1_phase = 4.0f + fraction( m_env1_phase ); } - + // process envelope if( m_env1_phase < 1.0f ) // pre-delay phase { @@ -653,7 +743,7 @@ void MonstroSynth::renderModulators( fpp_t _frames ) else if( m_env1_phase < 4.0f ) // decay phase { const sample_t s = 1.0f - fraction( m_env1_phase ); - if( s <= env1_sus ) + if( s <= env1_sus ) { m_env1_buf[f] = env1_sus; } @@ -685,7 +775,7 @@ void MonstroSynth::renderModulators( fpp_t _frames ) else if( m_env2_phase < 3.0f ) m_env2_phase = 4.0f; else m_env2_phase = 4.0f + fraction( m_env2_phase ); } - + // process envelope if( m_env2_phase < 1.0f ) // pre-delay phase { @@ -705,7 +795,7 @@ void MonstroSynth::renderModulators( fpp_t _frames ) else if( m_env2_phase < 4.0f ) // decay phase { const sample_t s = 1.0f - fraction( m_env2_phase ); - if( s <= env2_sus ) + if( s <= env2_sus ) { m_env2_buf[f] = env2_sus; } @@ -739,6 +829,8 @@ MonstroInstrument::MonstroInstrument( InstrumentTrack * _instrument_track ) : m_osc1Ftr( 0.0, -100.0, 100.0, 1.0, this, tr( "Osc 1 Fine detune right" ) ), m_osc1Spo( 0.0, -180.0, 180.0, 0.1, this, tr( "Osc 1 Stereo phase offset" ) ), m_osc1Pw( 50.0, 0.0, 100.0, 0.01, this, tr( "Osc 1 Pulse width" ) ), + m_osc1SSR( false, this, tr( "Osc 1 Sync send on rise" ) ), + m_osc1SSF( false, this, tr( "Osc 1 Sync send on fall" ) ), m_osc2Vol( 33.0, 0.0, 200.0, 0.1, this, tr( "Osc 2 Volume" ) ), m_osc2Pan( 0.0, -100.0, 100.0, 0.1, this, tr( "Osc 2 Panning" ) ), @@ -747,6 +839,7 @@ MonstroInstrument::MonstroInstrument( InstrumentTrack * _instrument_track ) : m_osc2Ftr( 0.0, -100.0, 100.0, 1.0, this, tr( "Osc 2 Fine detune right" ) ), m_osc2Spo( 0.0, -180.0, 180.0, 0.1, this, tr( "Osc 2 Stereo phase offset" ) ), m_osc2Wave( this, tr( "Osc 2 Waveform" ) ), + m_osc2Sync( false, this, tr( "Osc 2 Sync" ) ), m_osc3Vol( 33.0, 0.0, 200.0, 0.1, this, tr( "Osc 3 Volume" ) ), m_osc3Pan( 0.0, -100.0, 100.0, 0.1, this, tr( "Osc 3 Panning" ) ), @@ -755,15 +848,16 @@ MonstroInstrument::MonstroInstrument( InstrumentTrack * _instrument_track ) : m_osc3Sub( 0.0, -100.0, 100.0, 0.1, this, tr( "Osc 3 Sub-oscillator mix" ) ), m_osc3Wave1( this, tr( "Osc 3 Waveform 1" ) ), m_osc3Wave2( this, tr( "Osc 3 Waveform 2" ) ), + m_osc3Sync( false, this, tr( "Osc 3 Sync" ) ), m_lfo1Wave( this, tr( "LFO 1 Waveform" ) ), m_lfo1Att( 0.0f, 0.0f, 2000.0f, 1.0f, 2000.0f, this, tr( "LFO 1 Attack" ) ), - m_lfo1Rate( 1.0f, 0.1, 20000.0, 0.1, 20000.0f, this, tr( "LFO 1 Rate" ) ), + m_lfo1Rate( 1.0f, 0.1, 10000.0, 0.1, 10000.0f, this, tr( "LFO 1 Rate" ) ), m_lfo1Phs( 0.0, -180.0, 180.0, 0.1, this, tr( "LFO 1 Phase" ) ), m_lfo2Wave( this, tr( "LFO 2 Waveform" ) ), m_lfo2Att( 0.0f, 0.0f, 2000.0f, 1.0f, 2000.0f, this, tr( "LFO 2 Attack" ) ), - m_lfo2Rate( 1.0f, 0.1, 20000.0, 0.1, 20000.0f, this, tr( "LFO 2 Rate" ) ), + m_lfo2Rate( 1.0f, 0.1, 10000.0, 0.1, 10000.0f, this, tr( "LFO 2 Rate" ) ), m_lfo2Phs( 0.0, -180.0, 180.0, 0.1, this, tr( "LFO 2 Phase" ) ), m_env1Pre( 0.0f, 0.0f, 2000.0f, 1.0f, 2000.0f, this, tr( "Env 1 Pre-delay" ) ), @@ -876,7 +970,7 @@ MonstroInstrument::MonstroInstrument( InstrumentTrack * _instrument_track ) : connect( &m_osc1Spo, SIGNAL( dataChanged() ), this, SLOT( updatePO() ) ); connect( &m_osc2Spo, SIGNAL( dataChanged() ), this, SLOT( updatePO() ) ); connect( &m_osc3Spo, SIGNAL( dataChanged() ), this, SLOT( updatePO() ) ); - + // updateEnvelope1 connect( &m_env1Pre, SIGNAL( dataChanged() ), this, SLOT( updateEnvelope1() ) ); @@ -952,6 +1046,8 @@ void MonstroInstrument::saveSettings( QDomDocument & _doc, m_osc1Ftr.saveSettings( _doc, _this, "o1ftr" ); m_osc1Spo.saveSettings( _doc, _this, "o1spo" ); m_osc1Pw.saveSettings( _doc, _this, "o1pw" ); + m_osc1SSR.saveSettings( _doc, _this, "o1ssr" ); + m_osc1SSF.saveSettings( _doc, _this, "o1ssf" ); m_osc2Vol.saveSettings( _doc, _this, "o2vol" ); m_osc2Pan.saveSettings( _doc, _this, "o2pan" ); @@ -960,6 +1056,7 @@ void MonstroInstrument::saveSettings( QDomDocument & _doc, m_osc2Ftr.saveSettings( _doc, _this, "o2ftr" ); m_osc2Spo.saveSettings( _doc, _this, "o2spo" ); m_osc2Wave.saveSettings( _doc, _this, "o2wav" ); + m_osc2Sync.saveSettings( _doc, _this, "o2syn" ); m_osc3Vol.saveSettings( _doc, _this, "o3vol" ); m_osc3Pan.saveSettings( _doc, _this, "o3pan" ); @@ -968,6 +1065,7 @@ void MonstroInstrument::saveSettings( QDomDocument & _doc, m_osc3Sub.saveSettings( _doc, _this, "o3sub" ); m_osc3Wave1.saveSettings( _doc, _this, "o3wav1" ); m_osc3Wave2.saveSettings( _doc, _this, "o3wav2" ); + m_osc3Sync.saveSettings( _doc, _this, "o3syn" ); m_lfo1Wave.saveSettings( _doc, _this, "l1wav" ); m_lfo1Att.saveSettings( _doc, _this, "l1att" ); @@ -995,7 +1093,7 @@ void MonstroInstrument::saveSettings( QDomDocument & _doc, m_env2Rel.saveSettings( _doc, _this, "e2rel" ); m_env2Slope.saveSettings( _doc, _this, "e2slo" ); - m_o23Mod.saveSettings( _doc, _this, "o23mo" ); + m_o23Mod.saveSettings( _doc, _this, "o23mo" ); m_vol1env1.saveSettings( _doc, _this, "v1e1" ); m_vol1env2.saveSettings( _doc, _this, "v1e2" ); @@ -1051,8 +1149,8 @@ void MonstroInstrument::saveSettings( QDomDocument & _doc, m_sub3env2.saveSettings( _doc, _this, "s3e2" ); m_sub3lfo1.saveSettings( _doc, _this, "s3l1" ); m_sub3lfo2.saveSettings( _doc, _this, "s3l2" ); - -} + +} void MonstroInstrument::loadSettings( const QDomElement & _this ) { @@ -1063,6 +1161,8 @@ void MonstroInstrument::loadSettings( const QDomElement & _this ) m_osc1Ftr.loadSettings( _this, "o1ftr" ); m_osc1Spo.loadSettings( _this, "o1spo" ); m_osc1Pw.loadSettings( _this, "o1pw" ); + m_osc1SSR.loadSettings( _this, "o1ssr" ); + m_osc1SSF.loadSettings( _this, "o1ssf" ); m_osc2Vol.loadSettings( _this, "o2vol" ); m_osc2Pan.loadSettings( _this, "o2pan" ); @@ -1071,6 +1171,7 @@ void MonstroInstrument::loadSettings( const QDomElement & _this ) m_osc2Ftr.loadSettings( _this, "o2ftr" ); m_osc2Spo.loadSettings( _this, "o2spo" ); m_osc2Wave.loadSettings( _this, "o2wav" ); + m_osc2Sync.loadSettings( _this, "o2syn" ); m_osc3Vol.loadSettings( _this, "o3vol" ); m_osc3Pan.loadSettings( _this, "o3pan" ); @@ -1079,6 +1180,7 @@ void MonstroInstrument::loadSettings( const QDomElement & _this ) m_osc3Sub.loadSettings( _this, "o3sub" ); m_osc3Wave1.loadSettings( _this, "o3wav1" ); m_osc3Wave2.loadSettings( _this, "o3wav2" ); + m_osc3Sync.loadSettings( _this, "o3syn" ); m_lfo1Wave.loadSettings( _this, "l1wav" ); m_lfo1Att.loadSettings( _this, "l1att" ); @@ -1106,7 +1208,7 @@ void MonstroInstrument::loadSettings( const QDomElement & _this ) m_env2Rel.loadSettings( _this, "e2rel" ); m_env2Slope.loadSettings( _this, "e2slo" ); - m_o23Mod.loadSettings( _this, "o23mo" ); + m_o23Mod.loadSettings( _this, "o23mo" ); m_vol1env1.loadSettings( _this, "v1e1" ); m_vol1env2.loadSettings( _this, "v1e2" ); @@ -1162,7 +1264,7 @@ void MonstroInstrument::loadSettings( const QDomElement & _this ) m_sub3env2.loadSettings( _this, "s3e2" ); m_sub3lfo1.loadSettings( _this, "s3l1" ); m_sub3lfo2.loadSettings( _this, "s3l2" ); - + } @@ -1174,7 +1276,7 @@ QString MonstroInstrument::nodeName() const f_cnt_t MonstroInstrument::desiredReleaseFrames() const { - return qMax( 64, qMax( m_env1_relF, m_env2_relF ) ); + return 64; } @@ -1188,27 +1290,27 @@ void MonstroInstrument::updateVolumes() { m_osc1l_vol = leftCh( m_osc1Vol.value(), m_osc1Pan.value() ); m_osc1r_vol = rightCh( m_osc1Vol.value(), m_osc1Pan.value() ); - + m_osc2l_vol = leftCh( m_osc2Vol.value(), m_osc2Pan.value() ); m_osc2r_vol = rightCh( m_osc2Vol.value(), m_osc2Pan.value() ); - + m_osc3l_vol = leftCh( m_osc3Vol.value(), m_osc3Pan.value() ); - m_osc3r_vol = rightCh( m_osc3Vol.value(), m_osc3Pan.value() ); + m_osc3r_vol = rightCh( m_osc3Vol.value(), m_osc3Pan.value() ); } void MonstroInstrument::updateFreq() { - m_osc1l_freq = powf( 2.0f, m_osc1Crs.value() / 12.0f ) * + m_osc1l_freq = powf( 2.0f, m_osc1Crs.value() / 12.0f ) * powf( 2.0f, m_osc1Ftl.value() / 1200.0f ); - m_osc1r_freq = powf( 2.0f, m_osc1Crs.value() / 12.0f ) * + m_osc1r_freq = powf( 2.0f, m_osc1Crs.value() / 12.0f ) * powf( 2.0f, m_osc1Ftr.value() / 1200.0f ); - - m_osc2l_freq = powf( 2.0f, m_osc2Crs.value() / 12.0f ) * + + m_osc2l_freq = powf( 2.0f, m_osc2Crs.value() / 12.0f ) * powf( 2.0f, m_osc2Ftl.value() / 1200.0f ); - m_osc2r_freq = powf( 2.0f, m_osc2Crs.value() / 12.0f ) * + m_osc2r_freq = powf( 2.0f, m_osc2Crs.value() / 12.0f ) * powf( 2.0f, m_osc2Ftr.value() / 1200.0f ); - + m_osc3_freq = powf( 2.0f, m_osc3Crs.value() / 12.0f ); } @@ -1217,10 +1319,10 @@ void MonstroInstrument::updatePO() { m_osc1l_po = m_osc1Spo.value() / 360.0; m_osc1r_po = ( m_osc1Spo.value() * -1.0 ) / 360.0; - + m_osc2l_po = m_osc2Spo.value() / 360.0; m_osc2r_po = ( m_osc2Spo.value() * -1.0 ) / 360.0; - + m_osc3l_po = m_osc3Spo.value() / 360.0; m_osc3r_po = ( m_osc3Spo.value() * -1.0 ) / 360.0; } @@ -1237,7 +1339,7 @@ void MonstroInstrument::updateEnvelope1() else m_env1_dec = 1.0 / ( m_env1Dec.value() / 1000.0f ) / m_samplerate; if( m_env1Rel.value() == 0.0f ) m_env1_rel = 1.0; else m_env1_rel = 1.0 / ( m_env1Rel.value() / 1000.0f ) / m_samplerate; - + m_env1_len = ( m_env1Pre.value() + m_env1Att.value() + m_env1Hold.value() + m_env1Dec.value() ) * m_samplerate / 1000.0f; m_env1_relF = m_env1Rel.value() * m_samplerate / 1000.0f; } @@ -1253,7 +1355,7 @@ void MonstroInstrument::updateEnvelope2() else m_env2_dec = 1.0 / ( m_env2Dec.value() / 1000.0f ) / m_samplerate; if( m_env2Rel.value() == 0.0f ) m_env2_rel = 1.0; else m_env2_rel = 1.0 / ( m_env2Rel.value() / 1000.0f ) / m_samplerate; - + m_env2_len = ( m_env2Pre.value() + m_env2Att.value() + m_env2Hold.value() + m_env2Dec.value() ) * m_samplerate / 1000.0f; m_env2_relF = m_env2Rel.value() * m_samplerate / 1000.0f; } @@ -1283,30 +1385,30 @@ MonstroView::MonstroView( Instrument * _instrument, setWidgetBackground( m_operatorsView, "artwork_op" ); m_operatorsView->show(); m_operatorsView->move( 0, 0 ); - + m_matrixView = setupMatrixView( this ); setWidgetBackground( m_matrixView, "artwork_mat" ); m_matrixView->hide(); m_matrixView->move( 0, 0 ); - + // "tab buttons" - + pixmapButton * m_opViewButton = new pixmapButton( this, NULL ); m_opViewButton -> move( 0,0 ); m_opViewButton -> setActiveGraphic( PLUGIN_NAME::getIconPixmap( "opview_active" ) ); m_opViewButton -> setInactiveGraphic( PLUGIN_NAME::getIconPixmap( "opview_inactive" ) ); toolTip::add( m_opViewButton, tr( "Operators view" ) ); - + pixmapButton * m_matViewButton = new pixmapButton( this, NULL ); m_matViewButton -> move( 125,0 ); m_matViewButton -> setActiveGraphic( PLUGIN_NAME::getIconPixmap( "matview_active" ) ); m_matViewButton -> setInactiveGraphic( PLUGIN_NAME::getIconPixmap( "matview_inactive" ) ); toolTip::add( m_matViewButton, tr( "Matrix view" ) ); - + m_selectedViewGroup = new automatableButtonGroup( this ); m_selectedViewGroup -> addButton( m_opViewButton ); m_selectedViewGroup -> addButton( m_matViewButton ); - + connect( m_opViewButton, SIGNAL( clicked() ), this, SLOT( updateLayout() ) ); connect( m_matViewButton, SIGNAL( clicked() ), this, SLOT( updateLayout() ) ); } @@ -1336,7 +1438,7 @@ void MonstroView::updateLayout() void MonstroView::modelChanged() { MonstroInstrument * m = castModel(); - + m_osc1VolKnob-> setModel( &m-> m_osc1Vol ); m_osc1PanKnob-> setModel( &m-> m_osc1Pan ); m_osc1CrsKnob-> setModel( &m-> m_osc1Crs ); @@ -1344,6 +1446,8 @@ void MonstroView::modelChanged() m_osc1FtrKnob-> setModel( &m-> m_osc1Ftr ); m_osc1SpoKnob-> setModel( &m-> m_osc1Spo ); m_osc1PwKnob-> setModel( &m-> m_osc1Pw ); + m_osc1SSRButton-> setModel( &m-> m_osc1SSR ); + m_osc1SSFButton-> setModel( &m-> m_osc1SSF ); m_osc2VolKnob-> setModel( &m-> m_osc2Vol ); m_osc2PanKnob-> setModel( &m-> m_osc2Pan ); @@ -1352,25 +1456,27 @@ void MonstroView::modelChanged() m_osc2FtrKnob-> setModel( &m-> m_osc2Ftr ); m_osc2SpoKnob-> setModel( &m-> m_osc2Spo ); m_osc2WaveBox-> setModel( &m-> m_osc2Wave ); + m_osc2SyncButton-> setModel( &m-> m_osc2Sync ); m_osc3VolKnob-> setModel( &m-> m_osc3Vol ); m_osc3PanKnob-> setModel( &m-> m_osc3Pan ); m_osc3CrsKnob-> setModel( &m-> m_osc3Crs ); m_osc3SpoKnob-> setModel( &m-> m_osc3Spo ); - m_osc3SubKnob-> setModel( &m-> m_osc3Sub ); + m_osc3SubKnob-> setModel( &m-> m_osc3Sub ); m_osc3Wave1Box-> setModel( &m-> m_osc3Wave1 ); m_osc3Wave2Box-> setModel( &m-> m_osc3Wave2 ); - + m_osc3SyncButton-> setModel( &m-> m_osc3Sync ); + m_lfo1WaveBox-> setModel( &m-> m_lfo1Wave ); m_lfo1AttKnob-> setModel( &m-> m_lfo1Att ); m_lfo1RateKnob-> setModel( &m-> m_lfo1Rate ); m_lfo1PhsKnob-> setModel( &m-> m_lfo1Phs ); - + m_lfo2WaveBox-> setModel( &m-> m_lfo2Wave ); m_lfo2AttKnob-> setModel( &m-> m_lfo2Att ); m_lfo2RateKnob-> setModel( &m-> m_lfo2Rate ); m_lfo2PhsKnob-> setModel( &m-> m_lfo2Phs ); - + m_env1PreKnob-> setModel( &m-> m_env1Pre ); m_env1AttKnob-> setModel( &m-> m_env1Att ); m_env1HoldKnob-> setModel( &m-> m_env1Hold ); @@ -1378,7 +1484,7 @@ void MonstroView::modelChanged() m_env1SusKnob-> setModel( &m-> m_env1Sus ); m_env1RelKnob-> setModel( &m-> m_env1Rel ); m_env1SlopeKnob-> setModel( &m-> m_env1Slope ); - + m_env2PreKnob-> setModel( &m-> m_env2Pre ); m_env2AttKnob-> setModel( &m-> m_env2Att ); m_env2HoldKnob-> setModel( &m-> m_env2Hold ); @@ -1386,10 +1492,10 @@ void MonstroView::modelChanged() m_env2SusKnob-> setModel( &m-> m_env2Sus ); m_env2RelKnob-> setModel( &m-> m_env2Rel ); m_env2SlopeKnob-> setModel( &m-> m_env2Slope ); - + m_o23ModGroup-> setModel( &m-> m_o23Mod ); m_selectedViewGroup-> setModel( &m-> m_selectedView ); - + m_vol1env1Knob-> setModel( &m-> m_vol1env1 ); m_vol1env2Knob-> setModel( &m-> m_vol1env2 ); m_vol1lfo1Knob-> setModel( &m-> m_vol1lfo1 ); @@ -1444,7 +1550,7 @@ void MonstroView::modelChanged() m_sub3env2Knob-> setModel( &m-> m_sub3env2 ); m_sub3lfo1Knob-> setModel( &m-> m_sub3lfo1 ); m_sub3lfo2Knob-> setModel( &m-> m_sub3lfo2 ); - + } @@ -1461,10 +1567,10 @@ void MonstroView::setWidgetBackground( QWidget * _widget, const QString & _pic ) QWidget * MonstroView::setupOperatorsView( QWidget * _parent ) { // operators view - + QWidget * view = new QWidget( _parent ); view-> setFixedSize( 250, 250 ); - + makeknob( m_osc1VolKnob, KNOBCOL1, O1ROW, "Volume", "%", "osc1Knob" ) makeknob( m_osc1PanKnob, KNOBCOL2, O1ROW, "Panning", "", "osc1Knob" ) makeknob( m_osc1CrsKnob, KNOBCOL3, O1ROW, "Coarse detune", " seminotes", "osc1Knob" ) @@ -1475,19 +1581,24 @@ QWidget * MonstroView::setupOperatorsView( QWidget * _parent ) m_osc1VolKnob -> setVolumeKnob( true ); + maketinyled( m_osc1SSRButton, 230, 34, "Send sync on pulse rise" ) + maketinyled( m_osc1SSFButton, 230, 44, "Send sync on pulse fall" ) + makeknob( m_osc2VolKnob, KNOBCOL1, O2ROW, "Volume", "%", "osc2Knob" ) makeknob( m_osc2PanKnob, KNOBCOL2, O2ROW, "Panning", "", "osc2Knob" ) makeknob( m_osc2CrsKnob, KNOBCOL3, O2ROW, "Coarse detune", " seminotes", "osc2Knob" ) makeknob( m_osc2FtlKnob, KNOBCOL4, O2ROW, "Finetune left", " cents", "osc2Knob" ) makeknob( m_osc2FtrKnob, KNOBCOL5, O2ROW, "Finetune right", " cents", "osc2Knob" ) makeknob( m_osc2SpoKnob, KNOBCOL6, O2ROW, "Stereo phase offset", " deg", "osc2Knob" ) - + m_osc2VolKnob -> setVolumeKnob( true ); - + m_osc2WaveBox = new comboBox( view ); - m_osc2WaveBox -> setGeometry( KNOBCOL7, O2ROW + 4, 42, 22 ); + m_osc2WaveBox -> setGeometry( 204, O2ROW + 7, 42, 22 ); m_osc2WaveBox->setFont( pointSize<8>( m_osc2WaveBox->font() ) ); - + + maketinyled( m_osc2SyncButton, 204, O2ROW - 3, "Sync oscillator 2" ) + makeknob( m_osc3VolKnob, KNOBCOL1, O3ROW, "Volume", "%", "osc3Knob" ) makeknob( m_osc3PanKnob, KNOBCOL2, O3ROW, "Panning", "", "osc3Knob" ) makeknob( m_osc3CrsKnob, KNOBCOL3, O3ROW, "Coarse detune", " seminotes", "osc3Knob" ) @@ -1495,29 +1606,31 @@ QWidget * MonstroView::setupOperatorsView( QWidget * _parent ) makeknob( m_osc3SubKnob, KNOBCOL5, O3ROW, "Sub-osc mix", "", "osc3Knob" ) m_osc3Wave1Box = new comboBox( view ); - m_osc3Wave1Box -> setGeometry( 160, O3ROW + 4, 42, 22 ); + m_osc3Wave1Box -> setGeometry( 160, O3ROW + 7, 42, 22 ); m_osc3Wave1Box->setFont( pointSize<8>( m_osc3Wave1Box->font() ) ); m_osc3Wave2Box = new comboBox( view ); - m_osc3Wave2Box -> setGeometry( 204, O3ROW + 4, 42, 22 ); + m_osc3Wave2Box -> setGeometry( 204, O3ROW + 7, 42, 22 ); m_osc3Wave2Box->setFont( pointSize<8>( m_osc3Wave2Box->font() ) ); - + + maketinyled( m_osc3SyncButton, 204, O3ROW - 3, "Sync oscillator 3" ) + m_lfo1WaveBox = new comboBox( view ); m_lfo1WaveBox -> setGeometry( 2, LFOROW + 7, 42, 22 ); - m_lfo1WaveBox->setFont( pointSize<8>( m_lfo1WaveBox->font() ) ); + m_lfo1WaveBox->setFont( pointSize<8>( m_lfo1WaveBox->font() ) ); maketsknob( m_lfo1AttKnob, LFOCOL1, LFOROW, "Attack", " ms", "lfoKnob" ) maketsknob( m_lfo1RateKnob, LFOCOL2, LFOROW, "Rate", " ms", "lfoKnob" ) makeknob( m_lfo1PhsKnob, LFOCOL3, LFOROW, "Phase", " deg", "lfoKnob" ) - + m_lfo2WaveBox = new comboBox( view ); m_lfo2WaveBox -> setGeometry( 127, LFOROW + 7, 42, 22 ); - m_lfo2WaveBox->setFont( pointSize<8>( m_lfo2WaveBox->font() ) ); + m_lfo2WaveBox->setFont( pointSize<8>( m_lfo2WaveBox->font() ) ); maketsknob( m_lfo2AttKnob, LFOCOL4, LFOROW, "Attack", " ms", "lfoKnob" ) maketsknob( m_lfo2RateKnob, LFOCOL5, LFOROW, "Rate", " ms", "lfoKnob" ) makeknob( m_lfo2PhsKnob, LFOCOL6, LFOROW, "Phase", " deg", "lfoKnob" ) - + maketsknob( m_env1PreKnob, KNOBCOL1, E1ROW, "Pre-delay", " ms", "envKnob" ) maketsknob( m_env1AttKnob, KNOBCOL2, E1ROW, "Attack", " ms", "envKnob" ) maketsknob( m_env1HoldKnob, KNOBCOL3, E1ROW, "Hold", " ms", "envKnob" ) @@ -1546,7 +1659,7 @@ QWidget * MonstroView::setupOperatorsView( QWidget * _parent ) m_amButton -> setActiveGraphic( PLUGIN_NAME::getIconPixmap( "am_active" ) ); m_amButton -> setInactiveGraphic( PLUGIN_NAME::getIconPixmap( "am_inactive" ) ); toolTip::add( m_amButton, tr( "Modulate amplitude of Osc3 with Osc2" ) ); - + pixmapButton * m_fmButton = new pixmapButton( view, NULL ); m_fmButton -> move( 225, 185 + 15*2 ); m_fmButton -> setActiveGraphic( PLUGIN_NAME::getIconPixmap( "fm_active" ) ); @@ -1558,13 +1671,13 @@ QWidget * MonstroView::setupOperatorsView( QWidget * _parent ) m_pmButton -> setActiveGraphic( PLUGIN_NAME::getIconPixmap( "pm_active" ) ); m_pmButton -> setInactiveGraphic( PLUGIN_NAME::getIconPixmap( "pm_inactive" ) ); toolTip::add( m_pmButton, tr( "Modulate phase of Osc3 with Osc2" ) ); - + m_o23ModGroup = new automatableButtonGroup( view ); m_o23ModGroup-> addButton( m_mixButton ); m_o23ModGroup-> addButton( m_amButton ); m_o23ModGroup-> addButton( m_fmButton ); m_o23ModGroup-> addButton( m_pmButton ); - + return( view ); } @@ -1572,10 +1685,10 @@ QWidget * MonstroView::setupOperatorsView( QWidget * _parent ) QWidget * MonstroView::setupMatrixView( QWidget * _parent ) { // matrix view - + QWidget * view = new QWidget( _parent ); view-> setFixedSize( 250, 250 ); - + makeknob( m_vol1env1Knob, MATCOL1, MATROW1, "Modulation amount", "", "matrixKnob" ) makeknob( m_vol1env2Knob, MATCOL2, MATROW1, "Modulation amount", "", "matrixKnob" ) makeknob( m_vol1lfo1Knob, MATCOL3, MATROW1, "Modulation amount", "", "matrixKnob" ) @@ -1630,7 +1743,7 @@ QWidget * MonstroView::setupMatrixView( QWidget * _parent ) makeknob( m_sub3env2Knob, MATCOL6, MATROW6, "Modulation amount", "", "matrixKnob" ) makeknob( m_sub3lfo1Knob, MATCOL7, MATROW6, "Modulation amount", "", "matrixKnob" ) makeknob( m_sub3lfo2Knob, MATCOL8, MATROW6, "Modulation amount", "", "matrixKnob" ) - + return( view ); } diff --git a/plugins/monstro/Monstro.h b/plugins/monstro/Monstro.h index 43dc40b7c..b86525ad0 100644 --- a/plugins/monstro/Monstro.h +++ b/plugins/monstro/Monstro.h @@ -53,6 +53,14 @@ name ->setObjectName( oname ); \ name ->setFixedSize( 20, 20 ); +#define maketinyled( name, x, y, ttip ) \ + name = new pixmapButton( view, NULL ); \ + name -> setCheckable( true ); \ + name -> move( x, y ); \ + name -> setActiveGraphic( PLUGIN_NAME::getIconPixmap( "tinyled_on" ) ); \ + name -> setInactiveGraphic( PLUGIN_NAME::getIconPixmap( "tinyled_off" ) ); \ + toolTip::add( name, tr( ttip ) ); + #define setwavemodel( name ) \ name .addItem( tr( "Sine wave" ), static_cast( new PluginPixmapLoader( "sin" ) ) ); \ name .addItem( tr( "Triangle wave" ), static_cast( new PluginPixmapLoader( "tri" ) ) ); \ @@ -159,7 +167,7 @@ inline double fastPow( double a, double b ) } -class MonstroSynth +class MonstroSynth { public: MonstroSynth( MonstroInstrument * _i, NotePlayHandle * _nph, @@ -172,7 +180,7 @@ public: { return m_samplerate; } - + private: MonstroInstrument * m_parent; @@ -193,14 +201,14 @@ private: return s1 + ( s2 - s1 ) * x; } - + inline sample_t calcSlope( sample_t _s, float _slope ) { if( _slope == 0.0f ) return _s; const double exp = fastPow( 10.0, static_cast( _slope * -1.0 ) ); return fastPow( _s, exp ); } - + inline sample_t oscillate( int _wave, const float _ph ) { switch( _wave ) @@ -245,7 +253,7 @@ private: } return 0.0; } - + float m_osc1l_phase; float m_osc1r_phase; @@ -256,10 +264,15 @@ private: sample_t m_env1_phase; sample_t m_env2_phase; - + + float m_lfo1_phase; + float m_lfo2_phase; + sample_t m_lfo1_last; sample_t m_lfo2_last; + sample_t m_osc1l_last; + sample_t m_osc1r_last; }; class MonstroInstrument : public Instrument @@ -305,7 +318,7 @@ protected: float m_osc2l_freq; float m_osc2r_freq; float m_osc3_freq; - + float m_osc1l_po; float m_osc1r_po; float m_osc2l_po; @@ -318,7 +331,7 @@ protected: float m_env1_hold; float m_env1_dec; float m_env1_rel; - + float m_env2_pre; float m_env2_att; float m_env2_hold; @@ -327,13 +340,13 @@ protected: f_cnt_t m_env1_len; f_cnt_t m_env2_len; - + f_cnt_t m_env1_relF; f_cnt_t m_env2_relF; - + f_cnt_t m_lfo1_att; f_cnt_t m_lfo2_att; - + sample_rate_t m_samplerate; fpp_t m_fpp; @@ -361,6 +374,8 @@ private: FloatModel m_osc1Ftr; FloatModel m_osc1Spo; FloatModel m_osc1Pw; + BoolModel m_osc1SSR; + BoolModel m_osc1SSF; FloatModel m_osc2Vol; FloatModel m_osc2Pan; @@ -369,6 +384,7 @@ private: FloatModel m_osc2Ftr; FloatModel m_osc2Spo; ComboBoxModel m_osc2Wave; + BoolModel m_osc2Sync; FloatModel m_osc3Vol; FloatModel m_osc3Pan; @@ -377,6 +393,7 @@ private: FloatModel m_osc3Sub; ComboBoxModel m_osc3Wave1; ComboBoxModel m_osc3Wave2; + BoolModel m_osc3Sync; ComboBoxModel m_lfo1Wave; TempoSyncKnobModel m_lfo1Att; @@ -505,6 +522,8 @@ private: knob * m_osc1FtrKnob; knob * m_osc1SpoKnob; knob * m_osc1PwKnob; + pixmapButton * m_osc1SSRButton; + pixmapButton * m_osc1SSFButton; knob * m_osc2VolKnob; knob * m_osc2PanKnob; @@ -513,6 +532,7 @@ private: knob * m_osc2FtrKnob; knob * m_osc2SpoKnob; comboBox * m_osc2WaveBox; + pixmapButton * m_osc2SyncButton; knob * m_osc3VolKnob; knob * m_osc3PanKnob; @@ -521,6 +541,7 @@ private: knob * m_osc3SubKnob; comboBox * m_osc3Wave1Box; comboBox * m_osc3Wave2Box; + pixmapButton * m_osc3SyncButton; comboBox * m_lfo1WaveBox; TempoSyncKnob * m_lfo1AttKnob; @@ -560,7 +581,7 @@ private: // matrix view knobs // // // ///////////////////////////////// - + knob * m_vol1env1Knob; knob * m_vol1env2Knob; knob * m_vol1lfo1Knob; @@ -614,7 +635,7 @@ private: knob * m_sub3env1Knob; knob * m_sub3env2Knob; knob * m_sub3lfo1Knob; - knob * m_sub3lfo2Knob; + knob * m_sub3lfo2Knob; }; diff --git a/plugins/monstro/artwork_op.png b/plugins/monstro/artwork_op.png index d53ffae057069941b0e6abb3acae848c92f67f18..2f7b69ca0fda75a6b5ca0ce897b76daa28f26883 100644 GIT binary patch literal 59412 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 Y*v=b6_KwC@wh-{8EUzwCDr*w-Z`fe(`2YX_ literal 58075 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

KTtJkY7M|93 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 literal 0 HcmV?d00001 diff --git a/plugins/monstro/tinyled_on.png b/plugins/monstro/tinyled_on.png new file mode 100644 index 0000000000000000000000000000000000000000..3b1d97db5cf7d383e91dc1d1190f6b76d5ed8c1f GIT binary patch literal 594 zcmV-Y0e zSad^gZEa<4bO1wgWnpw>WFU8GbZ8()Nlj2!fese{00Fv5L_t&-(*?o3YZO5k2jJg3 zvp2W5dmq_+ku!+Fkf5OCP$ZI4EHr|ke?TCJwY{yjfwbC)y@hCFCti^hsq6&BNG_K< zz1v*&_G@-#XV>SU?U&tZtuBP^h??zIoN7(jqQ*s~YH`jPKrls7Dx-{4(j=KwNtS4p z#yYnuf;rnO!#&rrpAh3S%;Hd5qcng~If5Vn$`U9FpfHe`e)rSedXeWvX+2sU?|(ZQ z?(~v2R<5tXatN2MEP{l=?1G0lioi)=&>O*|1pmj!-PQRo?umDQm$^>u@h^WK8+W$g z2j{rixr!j3;P$2mg&3QiCL$T2b88usV2sedhA5mq{Qlw93IhQpfPViJjb;O9g9%zQ z4GjMg7M2?D3xemhFc?ZSn=SbM7+NW)XfkUB)9_QJ*o4O~PcEM1<%c=8u> zi!G#5B2P;Ud*?_l6qdyqbZ)*Hof&%i`p{d?yKfky2aNMZNd)2yj581sa;>3M22O-5 zO(9eHxqEoDr{eI`GNwrW)bBkzIe5RuEVOOcaqN2CvZ{h}MkoqnbeiO8IL%^zB*XC_ gGfMUEK7V`s9~6Vv&`C*P-T(jq07*qoM6N<$f;k-f%K!iX literal 0 HcmV?d00001 From df6fa14bf34d649233df1409db3719a830989e7f Mon Sep 17 00:00:00 2001 From: Oskar Wallgren Date: Mon, 31 Mar 2014 00:50:05 +0200 Subject: [PATCH 131/647] New arpeggio direction - Down, up --- include/InstrumentFunctions.h | 1 + src/core/InstrumentFunctions.cpp | 14 ++++++++++++++ 2 files changed, 15 insertions(+) diff --git a/include/InstrumentFunctions.h b/include/InstrumentFunctions.h index 345221979..5b6c36b9e 100644 --- a/include/InstrumentFunctions.h +++ b/include/InstrumentFunctions.h @@ -165,6 +165,7 @@ public: ArpDirUp, ArpDirDown, ArpDirUpAndDown, + ArpDirDownAndUp, ArpDirRandom, NumArpDirections } ; diff --git a/src/core/InstrumentFunctions.cpp b/src/core/InstrumentFunctions.cpp index 70a94e6f1..79b6509d1 100644 --- a/src/core/InstrumentFunctions.cpp +++ b/src/core/InstrumentFunctions.cpp @@ -314,6 +314,7 @@ InstrumentFunctionArpeggio::InstrumentFunctionArpeggio( Model * _parent ) : m_arpDirectionModel.addItem( tr( "Up" ), new PixmapLoader( "arp_up" ) ); m_arpDirectionModel.addItem( tr( "Down" ), new PixmapLoader( "arp_down" ) ); m_arpDirectionModel.addItem( tr( "Up and down" ), new PixmapLoader( "arp_up_and_down" ) ); + m_arpDirectionModel.addItem( tr( "Down and up" ), new PixmapLoader( "arp_up_and_down" ) ); m_arpDirectionModel.addItem( tr( "Random" ), new PixmapLoader( "arp_random" ) ); m_arpDirectionModel.setInitValue( ArpDirUp ); @@ -429,6 +430,19 @@ void InstrumentFunctionArpeggio::processNote( NotePlayHandle * _n ) cur_arp_idx = range - cur_arp_idx % ( range - 1 ) - 1; } } + else if( dir == ArpDirDownAndUp && range > 1 ) + { + // copied from ArpDirUpAndDown above + cur_arp_idx = ( cur_frame / arp_frames ) % ( range * 2 - 2 ); + // if greater than range, we have to play down... + // looks like the code for arp_dir==DOWN... :) + if( cur_arp_idx >= range ) + { + cur_arp_idx = range - cur_arp_idx % ( range - 1 ) - 1; + } + // inverts direction + cur_arp_idx = range - cur_arp_idx - 1; + } else if( dir == ArpDirRandom ) { // just pick a random chord-index From 243c66e0e8cc6b6898fe00197ea7c8af1d2c89bc Mon Sep 17 00:00:00 2001 From: Hannu Haahti Date: Mon, 31 Mar 2014 06:34:58 +0300 Subject: [PATCH 132/647] kicker: backwards compatibility --- plugins/kicker/kicker.cpp | 15 ++++++++++++++- plugins/kicker/kicker.h | 5 +++++ 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/plugins/kicker/kicker.cpp b/plugins/kicker/kicker.cpp index 5bbd35a10..c7dd50805 100644 --- a/plugins/kicker/kicker.cpp +++ b/plugins/kicker/kicker.cpp @@ -69,7 +69,8 @@ kickerInstrument::kickerInstrument( InstrumentTrack * _instrument_track ) : m_clickModel( 0.4f, 0.0f, 1.0f, 0.05f, this, tr( "Click" ) ), m_slopeModel( 0.06f, 0.001f, 1.0f, 0.001f, this, tr( "Slope" ) ), m_startNoteModel( false, this, tr( "Start from note" ) ), - m_endNoteModel( false, this, tr( "End to note" ) ) + m_endNoteModel( false, this, tr( "End to note" ) ), + m_versionModel( 0, 0, KICKER_PRESET_VERSION, this, "" ) { } @@ -97,6 +98,7 @@ void kickerInstrument::saveSettings( QDomDocument & _doc, m_slopeModel.saveSettings( _doc, _this, "slope" ); m_startNoteModel.saveSettings( _doc, _this, "startnote" ); m_endNoteModel.saveSettings( _doc, _this, "endnote" ); + m_versionModel.saveSettings( _doc, _this, "version" ); } @@ -115,6 +117,17 @@ void kickerInstrument::loadSettings( const QDomElement & _this ) m_slopeModel.loadSettings( _this, "slope" ); m_startNoteModel.loadSettings( _this, "startnote" ); m_endNoteModel.loadSettings( _this, "endnote" ); + m_versionModel.loadSettings( _this, "version" ); + + // Try to maintain backwards compatibility + if( m_versionModel.value() < 1 ) + { + m_decayModel.setValue( m_decayModel.value() * 1.33f ); + m_envModel.setValue( 1.0f ); + m_slopeModel.setValue( 1.0f ); + m_clickModel.setValue( 0.0f ); + m_versionModel.setValue( KICKER_PRESET_VERSION ); + } } diff --git a/plugins/kicker/kicker.h b/plugins/kicker/kicker.h index 8253becf8..8e58a42e0 100644 --- a/plugins/kicker/kicker.h +++ b/plugins/kicker/kicker.h @@ -34,6 +34,9 @@ #include "led_checkbox.h" +#define KICKER_PRESET_VERSION 1 + + class kickerInstrumentView; class NotePlayHandle; @@ -80,6 +83,8 @@ private: BoolModel m_startNoteModel; BoolModel m_endNoteModel; + IntModel m_versionModel; + friend class kickerInstrumentView; } ; From 643de68907f3a2dbc8cc205dba5be4b9b5871221 Mon Sep 17 00:00:00 2001 From: Hannu Haahti Date: Mon, 31 Mar 2014 06:41:56 +0300 Subject: [PATCH 133/647] kicker: add some presets to demonstrate its new features --- data/presets/Kicker/Clap.xpf | 52 +++++++++++++++++++++++++++++ data/presets/Kicker/HihatClosed.xpf | 21 ++++++++++++ data/presets/Kicker/HihatOpen.xpf | 21 ++++++++++++ data/presets/Kicker/Shaker.xpf | 21 ++++++++++++ data/presets/Kicker/SnareLong.xpf | 21 ++++++++++++ 5 files changed, 136 insertions(+) create mode 100644 data/presets/Kicker/Clap.xpf create mode 100644 data/presets/Kicker/HihatClosed.xpf create mode 100644 data/presets/Kicker/HihatOpen.xpf create mode 100644 data/presets/Kicker/Shaker.xpf create mode 100644 data/presets/Kicker/SnareLong.xpf diff --git a/data/presets/Kicker/Clap.xpf b/data/presets/Kicker/Clap.xpf new file mode 100644 index 000000000..4b3394228 --- /dev/null +++ b/data/presets/Kicker/Clap.xpf @@ -0,0 +1,52 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/data/presets/Kicker/HihatClosed.xpf b/data/presets/Kicker/HihatClosed.xpf new file mode 100644 index 000000000..72ee5b9bd --- /dev/null +++ b/data/presets/Kicker/HihatClosed.xpf @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/data/presets/Kicker/HihatOpen.xpf b/data/presets/Kicker/HihatOpen.xpf new file mode 100644 index 000000000..1e0c9b3a9 --- /dev/null +++ b/data/presets/Kicker/HihatOpen.xpf @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/data/presets/Kicker/Shaker.xpf b/data/presets/Kicker/Shaker.xpf new file mode 100644 index 000000000..452047aa3 --- /dev/null +++ b/data/presets/Kicker/Shaker.xpf @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/data/presets/Kicker/SnareLong.xpf b/data/presets/Kicker/SnareLong.xpf new file mode 100644 index 000000000..bcccb4172 --- /dev/null +++ b/data/presets/Kicker/SnareLong.xpf @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + From 12c6ec25c9f37ee1463ee8376d39b87bf530e6b9 Mon Sep 17 00:00:00 2001 From: Vesa Date: Mon, 31 Mar 2014 16:42:27 +0300 Subject: [PATCH 134/647] New FX Mixer: GUI improvements - better icons for send button, fade the arrow a bit, use smaller knob that fits better --- data/themes/default/mixer_send_off.png | Bin 467 -> 916 bytes data/themes/default/mixer_send_on.png | Bin 471 -> 1207 bytes data/themes/default/send_bg_arrow.png | Bin 267 -> 270 bytes src/gui/widgets/FxLine.cpp | 6 +++--- 4 files changed, 3 insertions(+), 3 deletions(-) diff --git a/data/themes/default/mixer_send_off.png b/data/themes/default/mixer_send_off.png index 6f426c36f9599a1fd8dbef8de6a5577d8bd17a86..0adafe29633cc0224c6b91bf07be427a4c262448 100644 GIT binary patch delta 832 zcmV-G1Hb&!1C$4lBo78+OGiWiaRC1SpjE%+1(84=3f==B4Hg1XbgfR2XeWOH{7FPX zR5;6}lu=7uR}ja4bIzQ5mqgoO)ru%vp=(edniz$er$RI@eJ*`%KS4iLprmgBVFd#r z!m6wq!Xo=%mj&0gx;Jqn3$Cks@9D$U)sj5bf#J-|IrE=6|ACR8fBDUSj3TUa02mSC zZj1&2aoi=7$>8IJB!Sq+SYv;QlNe_e4FW_UNn$h%Q4x$)+UIS)?(0VzNB@vqv}qh1 z(rLFb)*wh)$XwY1cy3O7YRBM707FayKJ}hFUE*Hyui@}h&a7Hcfl8q_LA z3`QhXYcM8NF%}~Ru?Ax;VgzdpB7zlRue3>je;*3a?VR)IhewQ#j*@@N<@mp{x3|aP z;UVu!@4=ITTWc8~A7^rMlDo*%)D)^psZ>g7#RJALGc!Y{)8WORFL?dtHO@KK*VoCf z-f~xXr`4!I> zpY!aeXQ(PC%@gM5=2?GQTp|oZq9~$LsbGv@b#)b0B@9AFz8#@nuT!hlP*to5Vn9_L ztyYV2xlH4@!P?pyvyW#1I669_(P+?WwE#G798)`}ae8`6v)QCvE_2*CCY#NoPFY@F z#<>(vRWV5t_c)t>GS7Z(pTc^f7kj(*mSVBU+1VKYx$krA?CgJh#`nUYHaUp^KkNEFILbP*{6&C;O`O(3qLY3F~MD>TCK9NvB9su|A7%> zKs-?tQLR?*3><$&5qM9WBxv02;#@$bQlV0*u(`RJZWa+l1gVlE;Jhc)*nb`%bDmpwe!p9FE z=zB28gMmT9%zdo2|M{+S`b8R4(|1lSK@boI3K%k(kWUz&n*0lVcuYoIpOI1k0000< KMNUMnLSTZ~HIN+u delta 405 zcmV;G0c!q~2h#(PBt!voQb$4nuFf3k00006VoOIv0RI600RN!9r;`8x010qNS#tmY z3ljhU3ljkVnw%H_000McNliru*$EI48YMy@HFA+#Cw~DhNklAhixaYtX=NFe>tVs%M)CRs(5@68p(d{%Dk3Rv(YsxummRz~&vbq4+3(w(Mh?8f)7?cuzZR62ug5BYe1)pKn|AK!5S~y?+qN>z700000NkvXXu0mjftSPhI diff --git a/data/themes/default/mixer_send_on.png b/data/themes/default/mixer_send_on.png index 6861c7acdf717cd4e6b164956346fa7413447423..e4b865587f7bd145e137c1c3b66c2159f412b130 100644 GIT binary patch delta 1125 zcmV-r1e*KT1Gfo~Bo78+OGiWiaRC1SpjE%+1(84=3f==B4HgZ-%dp>(XeWOJA4x<( zR5;6BluL+}WdMes@Am)aKXcAFXy-jM({+My zB&``~ONpdfB27x@#GtiCX@O800mKMCM51>%=WsDBB}$bN zDv@ZDB#hR_>F?`fa=6Zw{5O9AXzyCV|D$7wL>~ywaaU&t49A$E(#>B1Ld>HdE@p=oi}qrJ6gp_%HfGcz>7$dz7_%%IZ*ofwqTC@B$2AP~eDi6Ig~zxi-g>vQj0bkWfW2>gi;6*Aqqn9gy8YT zq7g&ku+|a^PjG>Co42C0Mt3Y*#>DtIm9}=;?ruFNEmzP+Bb8jVp^_wNf{@~0#9~;S rMhZdni~2R%kZJ`;N~M(P=_&pOKmQv%zwc&x00000NkvXXu0mjf^^zQs delta 409 zcmV;K0cQTU3D*OVBt!voQb$4nuFf3k00006VoOIv0RI600RN!9r;`8x010qNS#tmY z3ljhU3ljkVnw%H_000McNliru*$EI47%&~mvm23HCw~DlNklCcD z!^OxD>&wP)`PN@Vm^Wo}FeC-CF?{|0pP_#054d8V?5}VP1HKL{3~TrN#%VbtdYCga zGcxF_Gcj;;vM}sE{s(Wc7-=#y@NqLTeENc!_ex;FqN~P?FdXJG9!>^^7#~&?m!n(6 z$jHdxW6#PkW7RJdgMG5UGH^m8G&hP3qINX<4==+3jS*neVV3z+00000NkvXXu0mjf Dc>}I5 diff --git a/data/themes/default/send_bg_arrow.png b/data/themes/default/send_bg_arrow.png index fde514da62ab29e40dd44632fa9757edc65ea2bf..daeb9fe65d0751485a381a456316dab9fe3c9b71 100644 GIT binary patch delta 180 zcmeBX>SLOq!q1lE?e4-*$nc+GLFoRctP>sNxb88_^J+*j-_=Wzqvv{{BD=8633zc6V{%Lj^Zj6+Nzahy4hO&?9*B2 z50o@u0(;iw7nuXICpI77w|4yj4y!|V7O;O!Q2fC8H7RjJyW576Mb{S1fBBAOioV2> UHMb9(Smgt;=))QYhW{YAVDIwDKoQOYkH}&M25w;xW@MN( zM*=9wUgGKN%6^kmfKNkk=KR9n6Qeb%(>z@qLn02py}6K=K~ccvVyhKL)4yz|39p-l z)Adu>gs%KAJNkLEVA|4cky*1hM)sX%WWoaKmR`LWTQ~pWWx*Emove(0, 22); + m_sendKnob = new knob( knobBright_26, this, tr("Channel send amount") ); + m_sendKnob->move(3, 22); m_sendKnob->setVisible(false); // send button indicator @@ -59,7 +59,7 @@ FxLine::FxLine( QWidget * _parent, FxMixerView * _mv, int _channelIndex) : // channel number m_lcd = new LcdWidget( 2, this ); m_lcd->setValue( m_channelIndex ); - m_lcd->move( 2, 58 ); + m_lcd->move( 4, 58 ); m_lcd->setMarginWidth( 1 ); } From b9e33736de4c3fdb3887cb2471848ba5c6152f4d Mon Sep 17 00:00:00 2001 From: "Raine M. Ekman" Date: Mon, 31 Mar 2014 20:54:48 +0300 Subject: [PATCH 135/647] OpulenZ: changed some __inline functions to "static inline", which is more in line with later C dialects --- plugins/opl2/fmopl.c | 18 +++++++++--------- plugins/opl2/fmopl.h | 4 ++-- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/plugins/opl2/fmopl.c b/plugins/opl2/fmopl.c index f6382b6cb..6ead130d7 100644 --- a/plugins/opl2/fmopl.c +++ b/plugins/opl2/fmopl.c @@ -31,7 +31,7 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#define INLINE __inline +#define INLINE static inline #define HAS_YM3812 1 #include @@ -39,7 +39,7 @@ #include #include #include -//#include "driver.h" /* use M.A.M.E. */ +/* #include "driver.h" */ /* use M.A.M.E. */ #include "fmopl.h" #ifndef PI @@ -236,10 +236,10 @@ INT32 feedback2; /* connect for SLOT 2 */ #define LOG_WAR 2 /* WARNING */ #define LOG_INF 1 /* INFORMATION */ -//#define LOG_LEVEL LOG_INF +/* #define LOG_LEVEL LOG_INF */ #define LOG_LEVEL LOG_ERR -//#define LOG(n,x) if( (n)>=LOG_LEVEL ) logerror x +/* #define LOG(n,x) if( (n)>=LOG_LEVEL ) logerror x */ #define LOG(n,x) /* --------------------- subroutines --------------------- */ @@ -313,7 +313,7 @@ INLINE void OPL_KEYOFF(OPL_SLOT *SLOT) /* set envelope counter from envleope output */ SLOT->evm = ENV_MOD_RR; if( !(SLOT->evc&EG_DST) ) - //SLOT->evc = (ENV_CURVE[SLOT->evc>>ENV_BITS]<evc = (ENV_CURVE[SLOT->evc>>ENV_BITS]<evc = EG_DST; SLOT->eve = EG_DED; SLOT->evs = SLOT->evsr; @@ -545,10 +545,10 @@ INLINE void OPL_CALC_RH( OPL_CH *CH ) outd[0] += OP_OUT(SLOT,env_out, feedback2)*2; } - // SD (17) = mul14[fnum7] + white noise - // TAM (15) = mul15[fnum8] - // TOP (18) = fnum6(mul18[fnum8]+whitenoise) - // HH (14) = fnum7(mul18[fnum8]+whitenoise) + white noise + /* SD (17) = mul14[fnum7] + white noise + TAM (15) = mul15[fnum8] + TOP (18) = fnum6(mul18[fnum8]+whitenoise) + HH (14) = fnum7(mul18[fnum8]+whitenoise) + white noise */ env_sd =OPL_CALC_SLOT(SLOT7_2) + whitenoise; env_tam=OPL_CALC_SLOT(SLOT8_1); env_top=OPL_CALC_SLOT(SLOT8_2); diff --git a/plugins/opl2/fmopl.h b/plugins/opl2/fmopl.h index a01ff902c..9443c6c50 100644 --- a/plugins/opl2/fmopl.h +++ b/plugins/opl2/fmopl.h @@ -3,8 +3,8 @@ /* --- select emulation chips --- */ #define BUILD_YM3812 (HAS_YM3812) -//#define BUILD_YM3526 (HAS_YM3526) -//#define BUILD_Y8950 (HAS_Y8950) +/* #define BUILD_YM3526 (HAS_YM3526) */ +/* #define BUILD_Y8950 (HAS_Y8950) */ /* --- system optimize --- */ /* select bit size of output : 8 or 16 */ From 95ecb51b510a32137bf96c746f7457f401b7975b Mon Sep 17 00:00:00 2001 From: Vesa Date: Tue, 1 Apr 2014 00:02:21 +0300 Subject: [PATCH 136/647] Update aeffectx.h --- include/aeffectx.h | 106 +++++++++++++++++++++++++++------------------ 1 file changed, 64 insertions(+), 42 deletions(-) diff --git a/include/aeffectx.h b/include/aeffectx.h index 4188bf41a..619c2ca39 100644 --- a/include/aeffectx.h +++ b/include/aeffectx.h @@ -113,16 +113,29 @@ const int effGetVstVersion = 58; // currently unused const int kEffectMagic = CCONST( 'V', 's', 't', 'P' ); const int kVstLangEnglish = 1; const int kVstMidiType = 1; -const int kVstParameterUsesFloatStep = 1 << 2; +/*const int kVstParameterUsesFloatStep = 1 << 2; const int kVstPpqPosValid = 1 << 9; const int kVstTempoValid = 1 << 10; const int kVstBarsValid = 1 << 11; const int kVstCyclePosValid = 1 << 12; -const int kVstTimeSigValid = 1 << 13; +const int kVstTimeSigValid = 1 << 13;*/ const int kVstTransportPlaying = 1 << 1; const int kVstTransportCycleActive = 1 << 2; const int kVstTransportChanged = 1; +/* validity flags for a VstTimeInfo structure, this info comes from the web */ + +const int kVstNanosValid (1 << 8); +const int kVstPpqPosValid (1 << 9); +const int kVstTempoValid (1 << 10); +const int kVstBarsValid (1 << 11); +const int kVstCyclePosValid (1 << 12); +const int kVstTimeSigValid (1 << 13); +const int kVstSmpteValid (1 << 14); +const int kVstClockValid (1 << 15); + + + class RemoteVstPlugin; @@ -180,43 +193,50 @@ public: } ; - - -// Not finished, neither really used -class VstParameterProperties +/* constants from http://www.rawmaterialsoftware.com/juceforum/viewtopic.php?t=3740&sid=183f74631fee71a493316735e2b9f28b */ +enum Vestige2StringConstants { -public: -/* float stepFloat; - char label[64]; - int flags; - int minInteger; - int maxInteger; - int stepInteger; - char shortLabel[8]; - int category; - char categoryLabel[24]; - char empty[128];*/ - - float stepFloat; - float smallStepFloat; - float largeStepFloat; - char label[64]; - unsigned int flags; - unsigned int minInteger; - unsigned int maxInteger; - unsigned int stepInteger; - unsigned int largeStepInteger; - char shortLabel[8]; - unsigned short displayIndex; - unsigned short category; - unsigned short numParametersInCategory; - unsigned short reserved; - char categoryLabel[24]; - char future[16]; - -} ; + VestigeMaxNameLen = 64, + VestigeMaxLabelLen = 64, + VestigeMaxShortLabelLen = 8, + VestigeMaxCategLabelLen = 24, + VestigeMaxFileNameLen = 100 +}; +/* this struct taken from http://asseca.com/vst-24-specs/efGetParameterProperties.html */ +struct VstParameterProperties +{ + float stepFloat; /* float step */ + float smallStepFloat; /* small float step */ + float largeStepFloat; /* large float step */ + char label[VestigeMaxLabelLen]; /* parameter label */ + int32_t flags; /* @see VstParameterFlags */ + int32_t minInteger; /* integer minimum */ + int32_t maxInteger; /* integer maximum */ + int32_t stepInteger; /* integer step */ + int32_t largeStepInteger; /* large integer step */ + char shortLabel[VestigeMaxShortLabelLen]; /* short label, recommended: 6 + delimiter */ + int16_t displayIndex; /* index where this parameter should be displayed (starting with 0) */ + int16_t category; /* 0: no category, else group index + 1 */ + int16_t numParametersInCategory; /* number of parameters in category */ + int16_t reserved; /* zero */ + char categoryLabel[VestigeMaxCategLabelLen]; /* category label, e.g. "Osc 1" */ + char future[16]; /* reserved for future use */ +}; + + +/* this enum taken from http://asseca.com/vst-24-specs/efGetParameterProperties.html */ +enum VstParameterFlags +{ + kVstParameterIsSwitch = 1 << 0, /* parameter is a switch (on/off) */ + kVstParameterUsesIntegerMinMax = 1 << 1, /* minInteger, maxInteger valid */ + kVstParameterUsesFloatStep = 1 << 2, /* stepFloat, smallStepFloat, largeStepFloat valid */ + kVstParameterUsesIntStep = 1 << 3, /* stepInteger, largeStepInteger valid */ + kVstParameterSupportsDisplayIndex = 1 << 4, /* displayIndex valid */ + kVstParameterSupportsDisplayCategory = 1 << 5, /* category, etc. valid */ + kVstParameterCanRamp = 1 << 6 /* set if parameter value can ramp up/down */ +}; class AEffect @@ -274,7 +294,7 @@ public: // 08 double sampleRate; // unconfirmed 10 - char empty1[8]; + double nanoSeconds; // 18 double ppqPos; // 20? @@ -286,13 +306,15 @@ public: // 38? double cycleEndPos; // 40? - int timeSigNumerator; + int32_t timeSigNumerator; // 44? - int timeSigDenominator; - // unconfirmed 48 4c 50 - char empty3[4 + 4 + 4]; + int32_t timeSigDenominator; + + int32_t smpteOffset; + int32_t smpteFrameRate; + int32_t samplesToNextClock; // 54 - int flags; + int32_t flags; } ; From 4355a2f0bb3e35f9004ac961a8978f16cfe46a99 Mon Sep 17 00:00:00 2001 From: Vesa Date: Tue, 1 Apr 2014 01:27:24 +0300 Subject: [PATCH 137/647] Remove comment --- include/aeffectx.h | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/include/aeffectx.h b/include/aeffectx.h index 619c2ca39..852ac72fe 100644 --- a/include/aeffectx.h +++ b/include/aeffectx.h @@ -113,12 +113,7 @@ const int effGetVstVersion = 58; // currently unused const int kEffectMagic = CCONST( 'V', 's', 't', 'P' ); const int kVstLangEnglish = 1; const int kVstMidiType = 1; -/*const int kVstParameterUsesFloatStep = 1 << 2; -const int kVstPpqPosValid = 1 << 9; -const int kVstTempoValid = 1 << 10; -const int kVstBarsValid = 1 << 11; -const int kVstCyclePosValid = 1 << 12; -const int kVstTimeSigValid = 1 << 13;*/ + const int kVstTransportPlaying = 1 << 1; const int kVstTransportCycleActive = 1 << 2; const int kVstTransportChanged = 1; From 0140e94f79bf196503e4dc1d45b381636505647f Mon Sep 17 00:00:00 2001 From: Vesa Date: Tue, 1 Apr 2014 19:13:36 +0300 Subject: [PATCH 138/647] Make loop points different --- data/themes/default/loop_point.png | Bin 522 -> 0 bytes data/themes/default/loop_point_b.png | Bin 0 -> 472 bytes data/themes/default/loop_point_e.png | Bin 0 -> 474 bytes include/timeline.h | 3 ++- src/core/timeline.cpp | 15 ++++++++++----- 5 files changed, 12 insertions(+), 6 deletions(-) delete mode 100644 data/themes/default/loop_point.png create mode 100644 data/themes/default/loop_point_b.png create mode 100644 data/themes/default/loop_point_e.png diff --git a/data/themes/default/loop_point.png b/data/themes/default/loop_point.png deleted file mode 100644 index be64992079b2cb8ad78f6e2ce8769af7e1f47d87..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 522 zcmV+l0`>igP)7zd19r+05!j5|jv$3xWg-LG5kw3S#FY z2x4uW(n`5t;VVS2v$3#I?Cui;M6eUG3&F&l8H-#l7JBu-sm}TM;s1Yt-++lR^4$Vv z_OI|b^8hS-11#Xo0}2myU8vp8n{xUQSo;E4Q%*ms-Od|zT?jz3(>B@R#){<0y|Svu zhf!AbBv0r)>ZPz`7c4tIhIhuW6U&26{d@0MPTvfnAy#ET8t8ZmW%THD-_~ zjJ24W#jQ5!4)z+^`eNVa>7Q(UvELo+HQZ_wQ?nRrLDWo1i9)m>TCjOa+G$Aev6Xfj zV)OLhO^N!eL?nhl@Bu%q7#>}hFE_)hFrNN;xfxy!kFHBUtq494LjWQ|fND}vjVC-G z- z2Vq7hjoB4ILCF%=h?3y^w370~qEv?R@^Zb*yzJuS#DY}4{G#;P?`)(P7#Kr6T^vI+ zCbkCc^lAaUlw>+N^VlbESW!U>uUv4Ne{JB0a*)H|gmOboyKKx)9dGp@Az80xejCJ5_4*V{M!-X*hza1;vou&Os zJ65(k-*W(ID>c)YLV!}$0+mj8mQ&RNjWQubCbgNrPuEJ3Kxm){zUyJ2zL-$NTAba= z-<2=d~3w3|5SA5JXBtxgJO=E4H4w&Yf(R6e++_ zV6B6pfoAxw2bS8lk17kk?*snmAejmE2(l-^X7KTP`S>imeT>YCL?A@NA(*)D-n5Rp zckOrS^dX%-SkZ)filBz;=~nkFoKIxQG6$hzGRm6p?|J}0ZRgOdH?O?r8 Date: Tue, 1 Apr 2014 19:24:48 +0300 Subject: [PATCH 139/647] Finish previous --- include/timeline.h | 2 +- src/core/timeline.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/include/timeline.h b/include/timeline.h index 642ee76f2..58322d747 100644 --- a/include/timeline.h +++ b/include/timeline.h @@ -149,7 +149,7 @@ protected: private: static QPixmap * s_timeLinePixmap; static QPixmap * s_posMarkerPixmap; - static QPixmap * s_loopPointStartPixmap; + static QPixmap * s_loopPointBeginPixmap; static QPixmap * s_loopPointEndPixmap; static QPixmap * s_loopPointDisabledPixmap; diff --git a/src/core/timeline.cpp b/src/core/timeline.cpp index 53843034e..1aa932acf 100644 --- a/src/core/timeline.cpp +++ b/src/core/timeline.cpp @@ -47,8 +47,8 @@ QPixmap * timeLine::s_timeLinePixmap = NULL; QPixmap * timeLine::s_posMarkerPixmap = NULL; -QPixmap * timeLine::s_loopPointPixmap = NULL; - +QPixmap * timeLine::s_loopPointBeginPixmap = NULL; +QPixmap * timeLine::s_loopPointEndPixmap = NULL; timeLine::timeLine( const int _xoff, const int _yoff, const float _ppt, song::playPos & _pos, const MidiTime & _begin, From 93689f758fc81ab878e169834c65cd08ce7364ab Mon Sep 17 00:00:00 2001 From: Tres Finocchiaro Date: Tue, 1 Apr 2014 13:03:35 -0400 Subject: [PATCH 140/647] Added Apple specific artwork --- data/dmg_branding.png | Bin 0 -> 249220 bytes data/lmms.icns | Bin 0 -> 280023 bytes 2 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 data/dmg_branding.png create mode 100644 data/lmms.icns diff --git a/data/dmg_branding.png b/data/dmg_branding.png new file mode 100644 index 0000000000000000000000000000000000000000..aa76cdc62dd0ac23df807df89d204d59ebbe6b3c GIT binary patch literal 249220 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%0D4gWJ6K_D_{a} zR~BB>3larQ?L9H^4ZnaKg%b(R<xe< zq>*Wu>XxmP67LaNLb}0!z={Sx>C5c)8E8;gw^3hoItMNRKkw}3?Cb|42eO#S;}v`uAUE-ozaOPsyD2vmLu$t}PcQO$X+>oV%f$hGS~ zo?l#CXfx!+R`Dw5I%Gj7wJR;_z9Uq8CTFQ-{j^{WtiycH`*7uW%W+goy#5$F^6M7~ z>~??BG>ZM~?ftll1qI6&2lrDhvyh(5{Wph#u#+)sK>TlA?T&{RzwBC&0a(#|JnGB5~y*KyQ^e<6fJKWfy=wM}vBP1aBYp2A$@mO6^ z(Ti*1gAOXPHvr9#r!cWZp%oO)0C0PYI=@_SzlTURiVmKtdYym&U^Ycn z7@z**6x_kg%*=wdu*jZ}POf^%Y)s9v1W=~rUB3o4-giBk7-;4#PW%{>{vv*Sbkw`J zs81kL1u9drY1ig1YNXR200pq$lq8plDX| z5NiS2!m70&z1MvUD;^Hi(374XSaXa6`?E`+)F7U@X`j_HfTVLgX>4g^3E#f|==(V> zyVvO!4cAla9@GLteouUketsB)uQMk7`}K__tBuq0V*QkRLtPa9N{sr>txcFqug6`{ zqqr&O6EdWQ%t4K8y{{l#)5CYW7+~hP(BRA#6LjHu0-82Atz@jg!Ec|!awZ$uoG~)+MysJ{KX%j!(;Kk6c2~os<`-K8 zjU0^N4&BbCN&EqsFnmWfb9+(+D`RbQ2y9W>x@ZK|-TcCW9CP?S!Ori`ZOP@vz*(=Mm3H-C`*Jo1EKq%w@KE>~5^78Noe?ru|yAQpchhWsDM zN+~e}61(f=A2|U*%1A3MEe-bP@B<9cB@^R4{Yn9~+p~+eIuXrd-gsb8O298d**J;5 zvbqLXb{RiWq|9U)*viV=^`5VW>sCrI0wm*9S2TvO#!=k)rT7e!)Fr4kcn}EP_=0n@ zvpC0UBRxB>{;zYxrm6?X4O06_H8GNF7=g&Le>|4__M%%HSEyeySeak+n_+)}P!D)t zsm(m}8Qxv=W`j142_EIx&7=wbdBba$tfu*ZMV-{y1%sS%6~V3ieC~ve0Umy=)G@jbw!`6R*7huVb*N9OCe+* zU&yY=U7NEr+U1-e_*Cs~X&_BK0vGTZ3J3j?@WJf73(Mt-r-@BIp0fOiyoXHmuXH1k|honFJ~DkWE)4 z5pC${>6r%&G3aAplotgSMMvAe$(~LvEfE455VKX#{7G-v`ZAZVFCxWY2?QNi225Sf z4X3s!WM@4*=YdMlLON;3&?^*uo7_S!GDSm0Ri9TZ|MjyGq^~6lm^!5Lw<;n{x9q7>dh5_;$2|&AQL3y64Inj5^zd+S>Y|OHX@?bf z?*ot?bu_Xo&~g+3aI_C>QyGk!7-E=S!2Z6~2g1l{<8-Gei6}_8-_n7Yk;%bPWxM-$4#yV1CLirq;3YK!yAUwgBUUa#4=Hv_|U^;HUdR z3LfIMUG?>ee|;07F^bAirYxY@BO-R;{fRf&fa?X)qeSYFlv%l96c`bB+ijg7K!T4y z7-=0&-1q{BcMDK>>^o|`Ya1Dx#$gOL;gXazhagPH6E4Sgb#X~}?P`Pr!A1`j$_OMQ zy$*sItUcIx@YyP!z!jPNZ4Q#wXKH{Wfn?$D6bg#EfB*i?udaeu{sLnQK~#fySAroA zXKiIgW26qd2*_ulrd9;@fZg!k)Hm;>T}(GCjQDUN_`F+wez2ZRv$>z&yUgOp^__W8UNh&aUV}F?hU(3 zrm9&L3#*OfV*oWo#>jhTJ|`BoJotzT2nskpe@UNn?)1SjI&Q{92k_SUf^~M^8-x=U z_P>YuakDQs35Czz-u^9R{4hXV-!rM`pRuI`W{%EY?l>zQE6(-L9~Itk$G7g(DB6zb zd2DRM&5J&7GNLM`im&TuR3xc`jDMl<8{3ZZ_Y-T==0(?|EtjBEUUM@mfsW3E-Kyl{ zmZtTJl78X7S8Xvv~ldiBS|DSlrDsblO z&*3fjPO)~Cym{>eN#$Wf+xa#XS(2{DOfjM>5v!3mHcpLwN54KiC3RisTo?kLuooow zrt^lRKxU~OK*B}%F~jZ*Qs7+Q-dYpxgJx&YjzKzX6AX8y&s>2g3P8o8YRr}Nz;`GR z0X0oc$umNXXyFk}Gn}Gw&L+XZmz}2Ck^a5gXPEJnnWv6%GzXY;?{y310JRh!X-3763-Na$$kytc77qSwv(oePi zm;f_e8eOeTO`!P4EgjO=*Z=F$+0j7^00wqZQBrUjCvFC5vzNz%zGJt$!`>QfhHuM~ z>xaQvf@0yZs4z#qF$|6>NPU8cgrpyw5jX@ZFka!kPifWxBj|fFg!+}F#+O%dtcBY` zW&GPbS-zK7UQl*`$qhd9T0u}T2QLppH(s?)R+&#ADIoDvQ=+P1+sIswboogbbe-us zKqCsQl(?wC@XQb*RbbGUl(P7eilcM=mZmqlG8o;boWRGi!y6^Z8otK@LJJvYSvPQ! z&=OFGM!bP`=AX;?H7_xUgthh$N(t0qU;mN5m?Qu)1pP{{ocbWu;vadM#Y!U*;-}g?dKf~XCC}1cqNzO&X!|qNzx(GpWt(W<< zpZ#Ks#CY!p5$6Bs^m=UH_~0k4VJit^=y=Lte`*Wf31%oZ{9+b35w)$Y_-_SEaud+V zjAo=vv^Yv~Ipr1S3v%lMs|KLS1(ieJ?@%-iiSwuXOSkHenl_hpwp0Oxrs&NzQw>q6 zkd?rGHVY8X^0;PQCT4G?11#h18c;&?gHAdMNYHk({Yloq4($5l9yWD@JQxx#sl_uU zHc(f*iAW4gxQtT`ax@;(i+0!7$$+%v;`uKtlk(qG`U&%kWBSYbE##x1F&uQgar`;f zv^VAFRs%`@WWzk@GNA@QsKxsA@NBP|sTI`{g`s1rWM`30@u>_D-*4fd2mdz}I z{56SV2EO({bL9%zFqqjIy)E9`OaXfxQZyn?(0!?!J-%e?G4|BfBcc6S=^vLPkNRz3 zVAg>a59zjtiyhU_q|C!r~k`RBsppq)H{Xuszv+{g_B(aB%SSvMj~T zx3r7NJkXcka$p68G_{O`TK$WZ-RqgzdjKBaVFT&jQqfjsP4EA8qjDU zpn2=`gaGw)ipgvDOVR-uN^rW4o@h6cb^!D^57*@I0dN2=JPg3_wo(RAaB?e$Gf?$w1xUXdWuc~|o6wp)7N zRlZ+gSYM_dgX+e?#n$qveuGjf^#-R>t2d5-jscNq2r+qoe;M*V?hD~0pZ!CwtDerRh*ue#XAQUn$lT{|AR6(HFc?E~APIux^6Nt#iiCs& zzbz~qP#Icha{DTjlw-@>u^69;Lu~+NWy(I~KHF8+hUrAtsE66uF?WGI$*_FJr5kRL z3?5Qi08Q6%YSg@L`4e$Gl!~B@iwnnKFzDExIHNmMl$1V>7Bu!g2+lESqVT4LsJorl zK`JRS<6LhhydBuk1TlFJjV*@=s;z0#28_f?HUH2K;XZ&Xwp!maR0J;b% zuDT*9@)R_tgLNu+?o!~pcc@^W`^W-(McJ?l(I|=4$4K8 zf)C4)`hDl?^YimU*R4gCUS9mP zyTCR9pc-&xWOyFAMe!=|xN%%q! zOi&PgfS-o41cK=cQNRvR5FvWjXm%4gw@w%kMBd-uzv1k~=K#`sBf$WQsCWU6N9kz> zz!(}40-iun5ur_TZY@w%Sn!_3h$myG>CV3k!FTxdDH1Ha6$O$g*P+JnI1V0wp@0Zz z2KO?YxHv|Cm6`KF<&)$-90?44|jp~0~seW>siEN zCE(|;xT26v;Y*z?WPjd3+AmNL-QRl!ffC@Tnc_`P9v+ae9q%OHj&-XOZ%>Uz4=)H4 zzMSpt=?U;B;{ALo4_#tQBxRw#Gt*VjHS|k5hrB4C=XtUs7jx{`r~wfOE!j@0V@ko= z;jY=QfK{-6b8I?AiqxQS&`jzipceU?0WtQmPx*U>la>Pm z5vxp>aZXMCcGf!|`wk#k`X+F(o}$nJ5z-IZ_nR2d zS6x!vJ8s(u>MNsZs4mXWzro=jU4r|`ZM&-NF(-%dRA3sOS|LiCl5f^7E?gWHfbHzC zM9D_O{0V4`KEJv?hSVT!=ICcN5Ek0N=0>VV(G?nR*VtE;KGYcy=l!A0FNol$g{ba^Wq0Se*f z=CgODdIx=8aNOP6cmw}TyuG|o z-_A-(9Mjfs>9R+XANg)QZ_lIgPy@sVrtoI$LPD8|)6{!#0b92H-C=L?!M)SdF@GL2 zeXl1QL1jh70?B}ry`v+hvNzL?hj22xUVUz|n%uYD5*&YkcazY2rbjKrph{?CeHDcg zAt4Hixe*Z1Xp@RR=;`Z60MNGJ{BI|XX&wVd*+@Y(7q4dg`-M&*Oc*JJfeTB~QQfy6 z8v8Y-wZeJtnoDJbILg7*h9Ro3kz}}^-5`2&4#n{XrP7Yt`GD37G^}-bpicX{OY2-R z?n&%}jR1uCFh+aZlN>~__8TRj0`$nm<7R1=!VI_bPO3zkB7Tao`HzY<$VxG9Y*-E} znDM_Optst^d|!?P%h&k*Z{-pL#BLE$>#U0@gzky?CBKJ8|%;5tNJX;u@R9XmoEo^^WYG0 z^Ms%!3pA_obOCBnNJs|#GbpP-FFCj{dL6rQZBrL2Vgi^oBk_=97&sy1A`d!0Es^9I ztawgXDukQab_g7>J_ecSXco`~!WPPiYu?)5?qU{|BhZ5*#y0QYNRBtzpsOn<5d78= z^iMB6+xx`zQYU4DFmGOkaxwi35zo9iG1-#f~Y!QVF3XG&|}>5 zdqx1ZywGnjdkIiWH)LFN+r-f6Paa35yTgp~7hKWPfawS1<6Bq4Cm`bUq7@m%N+KF9%>WWYC~52zXJJpS(HU$U{Wy$7XyBsev1$FK$d z$Sb6%pi)kpCAAl`%QOK{KYW6M3cKFtxQxh5kg?Fv(9IB+k87_lv|QMrHAN&LQ`nF= z@JpgAa{{p6S2{_1b(!(2Q)+x;SP*_dfrJCv3;vMe2=T$Z=8~(fbg^0_zpT)WZ49+! zU)eP&WEsY88==2LU#FzWXC=QtiSlMrFklB6nz&*rlwwlhmFOh=`?f%IuHvR8#-{s zUCGHD5Z*^DG8=gUATi;9rysEvxoTVcK{_8De7^IYkqnqZJkbh(SQ+crLZ{8M9RIwq zXLDs-ATA2FF&(CCdXKqtijnQk61@b%coU;mE)vS%ItVszkt&I42?fH?mNCa@3cNy4 zZ11NZu1-wKKEMDwa^Y2=o>c4wQIAFd5n{g9D77gfw|I;Vydi6}-^HKzQFB*nsZU}8 z%E~OP$MiBGiM!C!o74|=SSYO&fPrMPn^!A-T3FgC9GMe3b%;{VXWAn(Mx8i_)WZLx z=_`Pu?!Ld5Wob~Pq`SMNySuv^M5J4~TcnZhlIEdHx?4a>B&9=8Kz;B2-uXM@7&AH> z_j~R+pE|Py{cZrW1jK!Jre|JoaFl>-JS+waC=^8DqLP3?Y}ZYEZ8pSKi?tD#*tEqu zZ$1okq*%Q?`!SCgbkN-peiUMk8wdX*=~RPl5hyVgQD=pvuift;`Vxzm;j7>Bx+b$s>O>l;jnBZ2 z1|M-vMee_r2hxm3&vk~qyuHiGB_k1IUsquhp!=I4AA}dZzk@vVZMar*vyqu)I>N4&)%Q(L6qSOtpoOv!b*-ANTh3 z{t8|Ze4vF}_#|i{#gwh@!92RKW!P(2)OQ<1VMdK6vdBFgs_r+t_2TZiv!2wT1dxAA?+tsEw!$BtQWA? z2!e+MA<&Lg9&FRUD#RozacxmH2o}l~`|IduEXBsBXl-RC$Ui{Z7ISE2I&(>f%h= zzXAr4NU9W&4pShD)suWbrStwnFSHRfcVMLX8x;8$NGL{#9!9wBV?UoWlVpP*36l_y zw{PD91Brc6?7SW!lm@&#L(ii^QqUL!F6uyb$7pmQ0I3puA6k<%eYp=>5(cSCERJvD z#f{B`#l_XF)!2glsg*@lKkEh``UD+*aIY#*4wr4H@&$t)QXD7=^M#bm*x0Q_gS6xd z^&eBQFOLu%>|^F2=sI|^?FE|Xt4Ewbb>B1*meVRiyQo)_UObd~z4Z8XbyZ zRd#xlj)F5$-U_r0$$$mG>&P!CsBqOU){(WWRq_%mYPtwF{4Bzm&P;^xh7+N2-eCxQ zK7Va7Z=67ZgN9hPx zqF|SyesySU&z8&iQpkknR z_zw2h%wC!8fMnT2K~AoHG2@mh2g!eMjWh7+iE0ao8I})nI;K{8gzF-5P8R65jnLtr z*~>+*W`kJ~Mzg96{Q}xZ6NevU)~~R91#%&lj;09h^Y#$`{QugeM|p*Wa@@?WTPG*2 zrohRC3pO$>&m@P5r$78s8hV_F)Y3b?iuM{*liShv*lucUv}B_=iZ`bBU7RmFuMew}Y53$7h&}m;mbq58l=y zm@~S+IQIGJLkwonrQ0t&MHA&{GIKloR=r7xQc(6@fIS0=+rK~r1U>ba5*ti=6bw7i zi)qJJH9(-bJ)%>o83(bU=Q4gp7OkJAc5_q0xRHWUT6NwklY4TPyZ8POcvwzHf{=dE zWDYpvs5GMk)Xo2Bc1Z^QXeYC|mgxu3?d99a(3K)pn$JojEWZK`uMu>K>P{y8jC&1n z0rWn)@8c3uTmX#6&_6c@1Oo7W(`e~cx`iqtc3~%J2%-}4_abK5&CZC_ma2|=cAFMj zy@IVrz|GHkr^uL{+ev0}H_9k48p9`9;97xmnpT3DYeTuSpjjaSmy#cUXIIyURQlQv zl!CuA*qE2&OV3SkdW$vZKjS1@sK?Yt(zQDc2z_rsc=FSUOXZ=A$t#N=taOWHGv+w2 zl0maUEj6;nki^(ARlMAcLV)WTVP#F47XRtGtfX14rG07k6 zgE(d_1_ou^qhE&rW~Hb6e8<>;Zm1LOs+u(ctaEW$luYGG@PKj-E# z2|@GI#6jJ6MK0oD3cWW5S9ITFY+WIMpYBE2S074r>6}qQ4cc#muAo55aTA$#pxv7i zfAD!vEv`#RVc``ChwlrabVb>p$7Pk+6K;IFmgTC7E->kb2J2NAfPTfTbf7*9JoBl)GSpO+rRCt(5hwrZ%aO7W)biC;r%e z=Zsp*W`bA;R%vf|*bs=ZLcUmOSm^8ictnreN-R*0aWaK%E&>91p;M(#=YC7roak@> zmc#rLG@^pln1xjufQRrv(srx z7)TcX(H-GCR2gUoZd$j&yzAzPR_qqKU80n~x;Nrn!_PRRX@l7Git!$y{Oh|`6#Vh$ zGF%h#kx6pKDvvoUDg%_|b6>`M%6gxDIR8zk()dCBtI|^`4exsZL^ff8S&AHJ%axw9 zzZUY;a3;Gy2O#)@82E%Jtycj=1|Y#rYw?h7`1v8jud*VM`1Bp&D5J0kc#NmL8%_3y zI6YKZlPzR%J{?7N|)S!&4EjoLnOlvd_l5$w~Ja_~* zXjxuVw={_C)32t^f7_>VB~s1M;6!$?JHsZY!NEO?``f4~^9C_f&iHea;xZX=)|ns` zy}eBVex!=LBq3vE%YXmL11QvndgqadUIs9{?$PmH`0H<;1qfDsKg>brK44sH{r^h$ zckz>!n!9jFRaZw?6demgX_;qEZ4f#A0WBs7j4O}Rfa5tn4hvnN#(Ofc%RzNE?U2X7 zW~!Ko!B@p@*ty@#w)$~q9W-H4zig`{bE0a@Rslihs<$wMa?WNd=rvqiT&SnWD^#UJ zF&*r)_n3_rB`(3x5+<=I%iIqq?0_7usclsovqDrLsDM8wqaXt%{8epX8zxn$fL7Ac z;(9vGr+$usTEYm;!hn9gIl0Cbi^#$z2CeeEd2a-C5Z=j?G(9yn1i-XZ*=r9G^^hEw zfdXT-6RhXYw{sm>?iU@uW%!GqiQ|eHkl|+J^J#bC(B|9;0+4C70l>EQljp5XbRGZw z=cCSmVl$r*qgXzjF!9>DYul>9=fq4w2*A))_Ql_97+igQed}#!!l1tQ&o+(gmKMCo zzE_h??0$Yg`aQv03{7RX1z#xH#jx$HTObx30 zZ?(3zdP2bG*_X+nbXR85A;VnqQ&&yUY1}a7WE&_AMnJp1<+wMl|85mvx+M=+Ake|; z$7uM-xxz|$s!s2^VHp!eV^bS~yaH78yNeMbG^$X-B0FQ+XIJ5+y7{UtbKRw`!$a|$ zKx_BsZ4f+Z2KHppRGC5f&zKY7`rfz)7}h&w#jo~m-!$WTzr%T*wEt}O?_b2MoAZFi zz7Eg3LCx9BhlqtYWNVWS@3z_%UxZ2{Kz*#Oa~_QK_t0 z2-^U!yos5eMXB5jbc;aS{k~Ta^eIG`Fi4jts=ndLW35=Y5>bd`XmyA#8xBqpbx#V+ zPwBzVZ^FW4~rpsT35SF&0!ET*WLi zZ7cqW-z)6@Jq*@={D?U3$%uoxO_^RnD1o{S$Zex%ygY6#(6P<(Xs~NZF=Q{{vh2#V z0V~U3HuI9AA8(S7p!#+Q8zV3@NGKifFo6XCqybgbqYwKahQ7wxgGXW5zxnKoKQB_4 z>Hxjvk&?VkoiH0n+0D@9iL!b3?oU2s%Y#nkr8$L&Z;DEM1Y#+ZYeSd~;$4y-g~9V- z(w$<{IN2-GAwjNb`|oM$PbVD~rVir0%nB=7B|N-#Zyr1H92U zx@sGMini)xK9-Ts4*fza+8{?qk2$>(R9=3sf10_`{8TIT`+UpSX~Z;cxZ2Bc%XPkBj0{ZUrp;5)kR zh8C_b7}U zon|4zwT$l$C=EWn`BKh^G~pkn(W1IGm&sA06gEcL;f@4b$61FpDK&Fz(-@#ruP(B!IG8R0@6JH6pdDTUK-KyxVKf6K^% zxJ+bkH~V32XKl@}ZIKhD8lgIH<)~68Q-9lpk`#cA%~jkY0Cj4>vM71;^GW%A>sGf% zT(!QXv5C`SOaIhMX*UR^(#O>b_&Ww@Es$5)d6k>mq-sFeD-I^0GP!ex2*sgYpuA(o zFiWv5xT7(Vq2#@n*aRXncn^X}h2{tBm&KrG7kfNy-r&5LZQ__|GIHJlWf?%^GGMHL zYjF|3<n`zdH2$;VCK3LC<$0t2&53xChe^B^HFnK70$Qk|EXSp zQ{-206uW^Ul%$XWN*r;yhtW8-Uz}VJ3#!l`Bkz!w}`U%GrX6v zUv=Eo;`-jV#$ns~+)WH?88nJOw_Q#eDu(gf6{u|~0xu;AI@iM`I4@k||NEvLbjgrl1==6Hd+oMdKqia}Ac#i960jxO{9eacBV`umQTF z{9~n_Cq5X^KOE-0Q`vuk>yM_%jF4W&+!x5Ez`~M`&qtSDDv>I|{=)T!V3rgYHz#&p z0ZC6i?`Xhd6w3{^_^d*0KRp##P(2E$ z*7Ff}!vK&^0XlrM9{=>)uEOd=BV-zsl}bLHWOjx&xhiy_vS$w9uIUMj`9Soks9JYx zq@|VV$TWoMds=@~Avn7?Md*`R@3(wzli7;yT??LRAPv0^+ZmLoWx2 z2oIGtg-=XW11}#fmbyXkygf>kJxF5!^n>Aix>yP*|A49)tTy09XWfmspniXtV3HX2NotQe|S@b+^|Ii~{qkpt7lYS!u-O z?wDKm6|uK2%84_81ch1`l-$zY5RJh?nt(C(<0UIntxU&I>-wKnLhFAb#Vs{wEPIW- ze0=HWR}qs2+%Es2tJJ2xKLlT+h;)X!)yIwJi~Zo3f~lwpb(EH+cFm~WV`d(-$WVm8 zPUi@hnre^?m+6^;!D7;#!Ve1>UhFL!p%xNVyf2r8Y^Dx*G8MNjMu*~BLvp-L9A86f zv)Tro{kHd+=~X`5y{kHIVm??@7w`Epg0z5IGKnwC>tt03xSa?CqMO*z>x5&F=?wL3 zfVC-hW#-pBDEHke7Z~j9zfAkUCN>9(W2d;#hJ!37)UArkT^j*fie5^(wv5Q0I8(R} z&<@Ggjp3qYpfdb$x14|_SmLB@K^TI;p<~6X1UH9Re}}6?FUG3$-)1rqu*LP3DCxUX zWw9a^uEU_wiunL64DeoI)XZlefmPjsiee35Lbwrv7VD#c^WQZjJw8M&x|{yyZ{I#g zyMcfn07M_(xO#e~^>|y=gPs)c^f!4m(|Yl>7HSJUxz74J zq!?Q&QiVBm%95=gmmnJspF@bY4*?vaPF0F=wwY$^eVlnaJNf5Lm>42==;r`XXJWz6 zB?1IviQ}cEr89%Qyief=3VcbXJGf9C1TiDke#$%L$seFWmtB`LSH_5OFX`yV%0kq^ z33+E^@azy1JLu*>m7YTARiA!5DWm4^IMG#+9L6ZmRkVU-JbZ~L(Z*7(uVmVvsR&;m ztw9+)ajV@F(PHRJhh!FM8hi>HckkVNeY5JC7jmSgO82F|y=I%^dg1q|VjvOau})KF z_c?u=qivK zsQB(*D^A6?*>_MVOV;FlBV`c?%m-puXSz&ff!2l)%oE)w!+j~msf=!^OXKxmi}xW+ z+eJ%R9f**|;9z%m98fLc6aYM306o5=#)IsRHI!NE-kn=dY%b{fPt5gX+bI|ao!`9K z{{_##0KXZYnNcG^G9dHmb6s|(7Z3- z5xGv_qXz})0rLDmZGF&dRl)94L28ZrLP&}iP|k#R3^f35rw>$cjz?QUge8vk{Gf1G z17+6tU&!L*-T*MmPSza#rFm~)wr5TF^D|s~A>Si`qxs+)Lt2hcAG=j`!g;Z(HMXbg z(+y|^@k&FIRKaBPct2u-WSg#ScvW&*WJ#%>3{R{npjuDbX}vXJ@*<*#Q}q|B#@I-i zlT<*&X$`b(qtE+6_W#(2X&JcY8hBvD1aZ~DoeN#S1&5# ztb+$9OXAb4Ik#ksJsl^)CqU<@38sfAa~lEO%!C@{4H-V=R)Mh9COnh`*@KNWA(VM> z4nh_U+e=tnZ)fP%fQYvU??|Q{ch9|cuw5{%Ds^;7z`eoY{#0whjL{0T3N~}J+-IEW zbx?3~GssuA`mnMMH$a?5+>R$#F9Jqqj^^hz+YFBF@SJ3_o|3a9C!(AYh#>8`-_YiCes&a>8Ybyjql>*Aw6n4z1U!Ca-dcpr?h z+R><_X?TBul!P7`;ZKb+v+_e9xRxvU9GjFjLBf_%7+=X5JttQh@QNINmW`S8nCw|J znxvUEnfe(c19(E3#j_=B@#=SR@}ELO`>vumJr4 z?qA@f%h$)?!3t&EO=xQlZ}^oX0pM6xHYLs}P~z@o7RzE8B>Vsz4Q5@zKL;v^yEZ7d z8T-4Ii;m!lsj`1B95Mme4%mc&(PS-n^*7DwTRw8XCwIyF^{`Vc3GswLTovdAox_<* zxs1%oO8eQ@^DT~K|1S2HU=f5nbcL9(DB)=?oB!Q6{|jU0CP3cLcnwi%75womk=6A@ zReJ3EQP^A55{ne3IL)6$KdlzoTNG_wzVlHvVhlK-kwr;;#u4}keQDH$XK{CXYr`VH z0G)~g*yjRe9DcW^8?zE}go7gxSIo;mX)gcK^g++;tB_Oh%V$-rr41A~>Z2SQoRcuDH0g1X&^ks2~6Q~0fM$VWj+ zXTEdPwy0=$5WSyPA$ttes2dl*tw8RHpV0C-*jIN|Oz)Ay-6v&(nwV6Fi5ExUHruHG zyb@MPvKX1ih;<#}u5zQ#!10d0AJ7d9re%3v#4qZ+A~DHKIyO5uI{)f!GoNX*az1CU zGRnb=#7sH+2&b>W>aFiUwwTQtGFq?q7XZ*5V{0x#+kG~t6OpA>MHjqaI=P69wUycU zij#~#U>3vUObhgFJa_Yl=_BuWJ#g%PcMsveA!?(Wffdlwtb)$YF<<^|_-yAZ1>;oMt*cl`P)X!=YL3|XMH6BAEQnryKm-0N5GK)LYKYlnJP{@7|F?!fD z+)xgWLjrb7%|Dyle>T-A)kic`VjD=-xj-od{qpzY#R|nDC4T@dGda5}sF1Ar8)+4j zM`S*871)6vbp3$|PE6oCO#tefTMV~vFqC)ReJcggZE%!m{CSKP=Vgx{&L!d{S?haJ zdJfW^xh`4bAMz)TRs}8Us1C91&!0cH4h$6GlUFIFWr-!tGBPk|x1W%YmpBFb-tO&t=Rs1c&-m zM__>=C2npZfXcGQlgErF2ctajlRehg)`$RUe;iEx-YtR6R1Zi(;2Cm`>B&ffVq$8P zN|+p|N7*HVbS0qGJ=78oPx<;s_VnB`k-E6YmsE+=m$cSD3kW0=81}h{~=_CrXCg-|!Z}VD& zL5YlV)(Z`^e8%EnXwOerW(2<8DOtukCm}Blp?o?8&)%94*GMn;veR2A z9OF;MZUBhGru`^!f=}=qr|}XD=ODiCkXj+0f~z79n((4uRvg|5>*0x{013F3^2C(( zw<1~E=(KQdbUh;)iBdobhDf3kCwxV~ zdTZh5ro9~ji&$EWo1B# z1O^rxjMaXmkbie)U$gS^rgv*-6*iQ`L}Om?(>e1tY=XMoc=G6m@_$-@|NeUk{%Ram zw+~P%?*`wu0(rw`Kx~Yo4R{MpQ2JW!P02Fw#lh|Cs06vxR8?DaHm3>EVQp6J@~@$L z5?y9LK+INKoDzzxKaOszBi8^5Uwr}A((3ynbCWnjI*4^?xdP0qZ^aXP1x=#(o(QPy zrJ025eK9)}3=rR7P|JQGA4#A02;&qA^!DZljoU&~7wrI|I<{%{${bCeK6-s*yS7P}Tx z{m%X(olPpcy`^qqlY`M5KkA-?sfnM_G;^{sFki#=YpSo-&qSAVV8g6Koa=`z%IyC9 z>Gd?o@g%iy8*vd5;Akfw9@fZO8{m0gv<@@)^PwhpAbzBuF2LV^OB%Q#1Yc=JbN!o>uge8a2 z1%z-p+G4v{(YBOE#T*sCvlOr2UOCqq&MUFVE?bQ^+t2QTiUT+8K48WN)JYX3zdvn& zfWrZNE(Jo^Mwpl)lrz51t;Iw{NCDP2Im@I5c?PavxRzv!D9dP_A2Sw~P<{s`( z5*kU&m?~(nEOh>N6s^Ld`VuJR{$RS5#3q(tAUilDpcPT%0Nb-LXmPB-FT8&!axDWvN!*Ydk)eq+X>T+o%{&8jV5Ic+LBpXBAQ5~TT8g%<<{CZnLVFFIi*8mHwM@YR#z;f=qx) zy$WJI$gs&UGLW;b6Iyw0(_--eyUUZ^3AU7HuGx>G9>-sto^E{Q=D+IkP)HSX& z;Wate*C9>oYR4no{bZR8U{sO#RaSq=NYHB>ioW>w^z_u@{VA*nP;8=`AB7(TJNcxM z&LdZXk10le5*vsJ2#h`L{9(Bqqa;KNcy2)G&6QvE@l8E(+X*00$J=s9Jqbi--J{FJ zYaYS@e2puV2-+JNUv|}Tyd&waERkrgW3P0wTh8eWG!D33Z=NJoD6$iNq< zZgaM`JW|O_FIJHx=BcI&bz{M8K8(Mbzd7X5MOSPEijYk9$|+n&J{Ub)x_d_nTEoJg zT5eHkW2k&Aum;oQwI4tG`KVjU%eAjY$7=1EY@roB_VHPWI$9#JUdWu5v4ZSzfa8A| z@w|=Lz?ce5MMOY)!T;(NuFhg-_BAtu_U1fjaF>QEy<2xDiqM=xyfcJN)P!&Xtd&AA z*@PE^*A-^k2DO#H@UY#pz(s~x?#*l6uZCYEwl(Xk9WjG24)5zJgS76ZCik~amxjJeCvT3~XVLf(g7Vx!l;v->U;gFIb4&{)mBPQM2tWOg zZB^DC60-?8p8YyMpzjDje`vFF+4%l-n^w1x(=s#>PmvbsX z>

5efhmM7k<#Kodox#40O_3rjB?^sW*IS>`I^!LTev|b)0qx z2W%oD!))SwaqKho`yCUNQ|8q~bebI&xh^qD&TBV{l4|8JNao#N(%f8sGJ*sp(+mfF zp6pI5;KH=iMjcUqt^Y7LZaBjx+0l}P1w13N+}U>(U(7MT#3}Tc;4^zpMV^jr4+2ela(2p zts@MCoaGHE!ebFv=7~3dSN-Q6P^Bbl%)GA1Nfey(%XY6Q7s4u+!ayJe+cgOi?S)talF|#*ZQ6u znmoKfp@k3$)aJU02ngXf6D?)kW1_-_>f0iP6jPK=K1{KarJDlobgeL?#{fUjy6#1#Yl@e>j<9Ib)~|OW2q_8h#>`uX>8(n zJb0IrWYo-1Yh`0JS3)$@WsN=zpF%>dE3VnQv{X%neI>dAF4mTrhApaK{rl{gHjpAE z%VTzG7##Mf`~0qde-21&1L1r(wD+6G&Xf_+(Z}2;tADP4ypdb4`p+F^U^|3?beNz> zt+7uFr5rjLlKXB`&DUG~{i-vTVV>MQnPw|#wyFMl0exHVW>@`>0=yem$=ekfLqMAY zvvnM`U?|!(m5g?FY4DkFH)iB z)=*@dQ^WSKg%ZitMPu&caEh9_rbI%ja;c{+1e*vsT&a$7W;xet%!%?i@Oqy(9sp*P zy|D|PpgYyND46bii2D|I&183Q$@0EMyh&Qut&tN1-4ot92ZVgB#KSzGE-(hkXiFUK zTb7M>OaNLw|L)6 z3CG4(#ru3Crvj{r^L^qt9?G7hap64Qu(?o=iu^b*=iun6Hv|VN2s&t5>~c!zP0_|F zsKJxA8?9@+738n(lNtbTcrH`RXxcCJw;eg`JimH>RGi9#N0=xFg-0tU1aSkfsPX>h z?!zUrTH*otDfe&n532vP-N1Kr5>yi#E@`*=uUq{)fUJ!9oHFJb2%w(44^RE& z0#oXN-cO9tw{L*;=fokegz|Jn9Zg2<%_iJ1*Jk{4{nuJVHrK-AcrJh$-tENWc<{b1 zrQ-X4Y;4%oiu`!8?-n?+oZQiGnb%V9OpPMeG{nN=Lri&RIZ^V-m!bDT2jpTL4^vVM zAxA7E9!CY&PyUdUj1V~!ZLKkf`<5YfvCG31E+4^E3+J2Vfau45iOWJth-+Yl1Y+Hy zE@gU1I>%&;PELEb8ndebBn@@%Q1B%)=j2jAY17+3ysWHug?fRnlK2pFa!b^A8*%+Ytx zWSKkZ*2S&c@zZQn23Z}w$Kme4kX3()KSE?9h{RbS{H^{pN!k3R{(~L(91H5fQ5~m$ zYX4CG+usrRGI~CE&OFB6@A+PT{o$-Xmu)VlLmBG|V(|KR)!zj});rF7{ZmAa0XE4g zWIc&m^ZMt!&}T=Aq}@2+vYlM?Q^`BFsyqtoU!TR3aov!j=J#|vQ_p1*~*2Lo1| zBAC)x;S`OyplF-QJF<>d!4^@&?h8)JTUU7FumKAMKN0|tu4c~Y`vFejvR}rWuKY5r zoo+IfUQ&HM7K#JC4nNxKEi6 zb9=pzO2$jOEtP(G(_EL^4Hw;Bu!Y{=^Sjf5FwJ-H1Yb!Aj6CWZBXG`ScI9ueyM*fQfKy|iAhj8 zOk>kFbIODTG6nTDL(b^EgBhcdia9|^5F$a3A&@{^S^x9vg+A!Uns^F@lD`v%!djUNHHVkvL(GHjB-*~B&~@{(L_<WQ zxIrclA0w?>+h_ThC^2q-s3^B>@492MqbsdIi1tk_7c!GuY*4BV$?Lqg`gV-4-I% z-&~M24J!o%HOb~0?8|hHK7XzM=&I}PQ~Y!N=UCT5lOh)*jow0kil`b9#+w)3meF47 zO!`S7Og$%pDEHT1cv zc~duT3o)QP4$4GB20%em-buJ~PZT_C&=zOMxn`y62<&fv>@?R>Q8MkXQvr`5C$w+% zFNm4XMG!b~-0JV*7K*3xceh=Ldz#?&H|^r>?A&#KslO-lL@?aLbh3y!(`w%yD?r$**o~J^{9?zXEZkk-X;rV>RRzSoc$)%r|3h0Qt{)Xq{fv=xG z5z~Qx*#>nM08LH1{%zOaZK7k^&ZGw@L3WW*E*Uvwj71SqQT{x%(0cuSvxs5>oZ=mX zU+bSE%8H0FqqkFZp0pEA(!Ku1d_ePwl2n0f7;_9FZXR*t-Cg&3*Gim<>`pl$dWebh z6OV(IZcTb(VEj|SbtMT>zNNf&e0ZsOGwq{)n{I|7#)Wb`FxplB$ML{82PRm5KgFJ3 zvTmom$ItKg7eOAWB8S3V+UKWHkx3pbUn@JfN38+?@EdOD3n`Y{gSECkea{U}lM#&k+=Ld3380SebjlPff`$a)eDa`P; zya~4{NW6i7)*EuIn0-*&-8(;LEh0I8W<^=yn?GU4_lCIHfo@V7y~Cny-?#sIo~Y99 z+~30x#~gd3@BoaB$Lks)sfU#JGsCo?a#RK`DDKHTJ@?La^B@bO-W}QY^IMCu+T{Hv zm+k^+)~cAY5@oE0D*yl>07*naR53=!Ge1>-0x&Vxm1n1kL<$ih6{;Nry&ube2D*S7 zOU%D%KoB}TrXml&>Yr5q^G(Kq_gQRUE}-Uu=jSKtQPID?kbnO1Z^Zvgk+~%+9!Mn3 zTT`KpLDp7b6i?2Tdf$9p0Km0&vS%u6q$KyX!?uUn9~S6A2r&Ya>6tMn*qB5tNe=1_ zu6^{gxmnpMR|WH#;)h7z3^5Xaw%D37l6R+fBXl{ zPOmr2CUXj=DcX5qbVCQXS0Vvk0)Mps#n{_!Np2%an}$y^GP6q3^z82a-`>o0OI4K- zK>~1Kf0zM`RL^^M`y7q>Xw*_Boy3Q`*<+e@TOa7d;cN{lIGojVbZbC}I2z@>HVo(I ziI_9ClrVzGxl;i*X(S^UOsJM- zlS4_YG4dn@k88AOy28z#kDQyqInA$w?%n+7ms%M4Gy38wHtR4e2*KgFv;Igts)xY* zwk~C&8RMf7OLG-lO1nU02I_FeFJJSm4Z^=zJ{$n-VvdHzC5 z8C%XWI`KNzZA^J|Tv+7V`nqq|%Ht$tkF#paG1dD(N(r@6w85Q{CWfhtcS>K$IiWN| z71k+l8F}N;#2R1R`m!LjG2nZLYggd=X@<1I->)#i05)y9!U8%N_qj2q_IVIyN5wqcSR|4FevB?2&ojc^s|Y?5_H3AxW1aew;!9g}P)0CG+?_+2&O zo3DDt7}yk^NkL1ftSN`*wJc&1k}99O4;VHWeCizh5P6kw1%}JbA^tF~(4|&2i%8^T z=CujFpWp_qpj|8agb~h_e?{gt!&&MwvUGj8J~F;$1dm;fn=-=_Wc}=B=-va;p}WrT z!`gUv3@IR|jDHXuTHzF7+6%eMaD{BzF+Eu1;XJCb*0rKl`mg>yIs>#S{Z-Xp41 zlrhctX8t}i%e^bZth}V%wAN5tK~+PH!Jn+Zk5s#D`)y5rW-W&Pz1;^mjpBHE;7Mg> znrHFnODSa7y(H_{oMg-hr9m_o9K}4P7F6qNjvkaQdmaZK_Xi%IcgAT4hb?ai131MM zNGUHjA%7tiFZH*IB;{J~4Yg3?Z>^%~ddM*;h>O-$mF_v#f0ATxvP8o>^{^a#=S0ed zO9q}&h8Y7ZW0HKnMpaNZHWBF|48cfPeRI-|+e4C+CHcpLVlWnI>DTEpB?s zXVK?}}XWFd7d|bki;eqpc2v<$24rls)5prhk`4~+e zZH{ceo}BCYUgB9))qRnza&NY)kbOLcsYvm$E7WNq_Ko*R|%= z&Uz6$uh}y1f`Q|y-+#mN^G-c-PH5$n{4(>D^qN_&Tf^|Ov%aw4yzZIf1quiN_s4_w zRsEId{gN)fy}zTCinAIu!4N(dQL+MMze;WfBuPT9UmX>U+O=4hjWHL0)T?v z8_H1?2VB<-nO0_#>M!6p4u9~CZBGO7rhpBYnosQW9_0x z4jKOU-|_hTB*#8wlzOg!3a0c-MIBb^%W#}vbr)6yR9G%h_a#;6^M8I94am`8AM`S_ zFF?~uj91RpT=gNUW$O*zNBsEn2hz47=d{vXW|~I`3`aEG#UNk;l{{%tF1r~KN8TxL zfH6*9K6mdte*675{QB!BLQb$+bvGwCpeq}^Do%-^22@a$gQ0*!bI*zFAqB<=M~Kw8 zPnbf8K|g<7F#NTcsDD$+;D!D-V4u6lo+O)nNl)d=H&03(<|>>I$hRHsEVQmBE|%pu zF7W0W9M9F#31aXPdHoXb$Yu_7-{VQe3H~_~ZJlY>?+Dm1NkVA>HYV1lul1i{kRf=q z-VlAnuh;rZ129cPAsE9E)d+Ozj8Acqa}K_;{#`JP;XH;_U4QAEenyYq|M(q0|NMcl zMOY!mYbXR`2t8J(at>hBk_bmJC7E>EnglZ#f&CaC9eQo3odJ%dy13Qt4(c5Z$%Z5G zAsAn{Jd~n-2}%|*=oJS(udt&Tnyv}?P4%xj@r;go9Pn{Ylg3Mq-dH3i|B@nv7suN| zgby}`V@`-^-+z!c3NFklL(@~D&G9T!UUA$I9gn!wfmZ-kM*7O}fD0^m-q()Uba$Co z0k7!e6e5~6aPSvHydGNtS&mhBfSG*mE7oLMRnBYQ{lED zjRAW+smXRj^(S)6$GEWF0S?1E_(2R*d#V471bVH%8R@(sB+-btSp*4MGJoK`9Fh|&)w=j}v;G0y1%xzp;GWjZ)=;f4lIk>XS<|uKW#rqAjfnvdr}3Q_Pp z9kssVpxg}ZnAg>p`uj0qB5g%pIRu@WBidOJkAM4fRPyP2KcX37?ltZ;{?bGhsvQp%pcduF)Dp4uVJAcjQcg zf$5qNeZG!_;*Ue_!x$ryB#Wh0WbwZZ9=_8)8n+F3&wLRhcb5=7ygc3*FURzmwo>^Z zLw{t?q&GIeYzzd!AXjSXi>!C_2Hyu+V39ARsS(#3n?NyT_|ReEjOTsleROh*1jv|l z9q&7O{W}C$E4>6gy_=vL?t(mcCo(N(>QSMTtu@wP+g=FqrT)|nJf3&y@)K$^ijm~) zHr3zzfRrM({f2$A<5~eK>mNe8c0vVbbbm9t`Fvo?NeCFVN&f4R_ZuU+s!1zgnv=Vg z+18EYOfn-fVg$}|pwz-hZv}Ju)=^OqH9}^9Az1(L_xe}bmnW>VGXHL-lW9o6`fC)8 z*GQ|GK?s90P6I+D?wsRSuV^ucls8@t3+3o(-zlQf3DM2^4@isBVHN*|fp+rgyMHk8 z*A+43#Ab^bcUu`NOdK*>aDsmyHim`ePQ&2P+@qcr&Fa}KwV8G@|*%-nJPgS7)@8kXp?;qdcJ4a#8 zN94B~qkhhld@utL9K3xksl9yIuZXMZh4yl0r5Mqya}4HqRJPVQ?s8FVeAsSdOBEu!O6p79S_>d5y6Pgd6OJ=cmG~>pS^M+E+_0*3bsZl(983ujwK9M%W#*$F!EtNv#!i<-L)3+hK{9D8gk}+(gh%C%&}h3;Naz)>);W|JJMJntAFTP!CzMK{vyP% zYRkpt^pa00?vP34^Vd)8+m7va;~29M91ypxtcxq{gcjNX-(NDiX4d)Zp;4CJJ_cUm z+b&m|T#6>@Z3rB3b}JbDa*mmpbyXpmT&z2eC-cnr{YHh_6yC_0Ra+s4PZ+Qe(|RV1 zqGC#mQ;&v;rwUapCx4s4{tB&peBSZ)uKNG>8y=tc#g}&mjB>Ka(AmZJ-mQ&>o^2+Q z5{cHAh9PHZEIg1rPk}2g>ZSe$AdJE5tLE{&ey#tS{Lk^Sa|={*8LRpV+86-x_J+@& zKd|p_*l#z^{^glK&bTPh<3c%u^Lazfy2#KKi83&iS|#oRM)!GV>(1bUyE&_;~+7w~ilw{R?@! z;dZ;Ng{eCOY+83;{q&T~HYKwT<>mz$l)S9QuKOz!UBZ}o&uhvp^OHPk9j*0$tN$1R zU36P=;IwTRHiR5&U%-xS)t?J(ZB>6wy+njn z?nIHm=2#C1<`i1vz-_TpfUw?o86Z?L{ zuKLej)M6Tht4}jLeeza|n&_IUq#&adt>rN#bgPJ5ISF!1x=@$KBa2T_^GcvT4x|)e zmHygVD|6HvmT4iUj6S*|btvk1Esj}5J3DIP9R9c8euwpr8&V4R?e{-m-EfGwLX{fFq8A;Qaa^oF z0~@B8=YOq#j2JG%g{CH8;>jUJ9QOxOO6>UifEW_WS!6NIqRp_0I6Lk`_w1RiXT}X} zQhg`xx~u-dg(cFN^{0OwIRI?{s4$n|g6jX|b*{or=JYcwi80DUF z5k3W!J5w-uS9-ZcD7e{bLq$VM3H$9vDPe6C2k6B(?+@(n?`nV4RM=72=*cWr-1#Ct z?|1CC8*cCKXve|S6*Hi!ljK|=q} z^)D-_wu|qFVQ2-YFr*Z*-);nZltzJ&PH*M@!1n%*ZVg8%Xh%__Hz92s!i}ef=i{n> zJq}KR^id3T{V_W7&aeq974QS)*?<5%pP#D#M!`vANMV07vhp}nA1GEZs=*2Sgnre3 zro{Gcq$#^7A)4wxkNeKU>-0PGMM!Y17@pV8+8eK>J@Di?RDUhjt#A|>w++2CUE%1o zdsTIKIMm)4(CAn4XV>x76pSZ`fFK9Mj9Fp&SZAa`m)fW)VbyuS&Wb(>COW>1!OpW2 zinhxIRZD+`3t&fGvreGnc%I06#`Aus955#!kq%Ny(LIQxKt}VjI3%EUBo(*A5L|){ ze)NVWRPu)I1Fapk1F2(s!BfwI;N5i!gWP5xzx@WQP4&-Ys>uY^V`sy)Q^spr$hWjfqhM&Y zVk}S!4JXbmU|}pW%THsrjyD4 zvca*CQvl!S6!Y`$PO*ZuinCUvz=&Aq@dAHepv?9)qQ$IY*ue8R=vqn}Fo3*msApv~ zRNzZvrsjfTVc`az#}oITpGZk0Oh7PzF8QW$SE*zDyJ-h)3#vHAK(CA}GHHpqgUwaC zE)-SNte0uf4ZT-budvz~{weB7m|16&73RM3z*J+#7bgWoRvlSAbhMU{!wkpqz~_ID zUwHny>)POjY`Ow1;KW25EWHiR;b(JkCUuV2Bfi`_wZa#1! zk8)?d)W6iGT((A~rDj6zOH!}WeOCRSbV;U-HQY8v9_36y%jjse3)8H9Yu5kAFT|WE z#Raf!8{c2WX}4A`aODuhb98wqW*SIQQxj0o5heI?axrxxZppcs^kux~>q<2QtDw*& zURK?gz=u8?8GicC8)6E)k2gbY91(x1e=|IvcYOZ%f%~sdO}f0Iug2?_6*~b$eL|Q~UyB?1Zl4$B&;&5moCcR1n~E7a7JBM-> zw6oCum;yb^&lBZ*YEGL}6E@Vke`e)wwrhpkZraUWzca&>_hRLTd!?cb5LZ1fbF=i{^W)ONeKfvGXhxrU_ho+CJ5yVRks^Z8e-(J((RFletpi@F zK7}R%j!wX?UAR+}(R%+<{~+g}4`Ff9I;eKcF)WL5j0trBQFG-kq!HCiQg$)&lV+T0 zV_x+SsM^s@qqN({JFiI!`Dn+JdG_MVbr&$g#90%f@$0W2`1t-ETi$Uz9yBtE-ZIBo z0YKOi5FGM$!}0maf86_FXr(WUHRPjUmO)}R{CO;u-eozSvRF;7Cii_fT@8VNpl@kN zIE$qh@FAeq6Cp-y+m550!mUyM%ZMBk{=^qnFy~%*9dtho?)i6oaqN z1HE>odq!^a!q?7B=DzZ_wSvkW#VqhHP(B+8h<+%B4AE@_`P!S}hE@de zQMco>c6S}Lzd?`EeW1haHn_OtNw11Z(r(90*_xopWF}#Yk5BI%YVM=KXV%Tg|D{W zsn1{PuU;2bX-4HfK0hy=H^!1Lj)9d3QJyEZ+dF?^j5K3JcIVv~Xv4#yAs}MzZ(|r5 z8XFV^*xq)|1t$5RlIMpQ6yq$cdefEAd+dL= z8;VZC4sId8VYB{(#dzo8AD?&a3WV5?7YS7>6~C+fE<2^G z*uvyaVNW?&Jc?0>KPpp!weL&0WTk&Cz5Q`8MZ_zS!}K!7#JTtJeByW>uu?cLUj#03 zyvD_{=M8}7jhM6g9ARODV@?>|aKGQtTg7o!R7LaD(l|QlbU>M$cXMP$DX2%$7>S84 zUA9a1QP}+J*F8~UAHooWV3Y;N`9w4JE1IH19g`7Yg@8#W=2G$4<-7_mzzu&+SlCEB zQOrqG6DGHA{};ph)TjS)R0hRh==Xa5x0cVsfw!4L*3DRjmv^aAw$Q8 zv}Mg31%B+(SEnSER+BkiK61yHUF$q5&ECOw+m_WY#DvdZKlrihNt1sZYOAp~v#*ZF z1ATP7zkg%+pnU1I6l^&y-8*y3fNkGIHc>Y`#N`;G!)i)kdFL9hTIShRo^nKS_@;8I zHJt!bT(iznIPX86hhUc`qXX%vAw@(7M17o2_C#wHy_!rM{N3lGSDq(#S}$(g)L(lp zI$gW^#7sx!l#RxZvNeD121A6HuE|8epd@z;1|*)x>W(jr@t698fq$SI%*4p|Au4`I z$u8oaFA|J(MKld%%MEO|eJyk$Bz*q-3;WycGVzEUJ3Z!G=0|coKGC}2_U$`edLaVV z{=NQ6sM)rSCk@q&l39Mh!-l}8%0_c5KWHf;mlWD`Y$@$^}%8kZriQ&VK84lnVzadoT#iWm0yhU5NF zawG3`VdE&Po>g5wkMsUm<0lsb&gV&^Oz=|qC~?Im5hcPqTX!xf!`r>w=R=HW$4Tc_ zZD>~U@%=lSEg^p*#Dx3jFXeeBoM%y9x09Z|AZK9PGOUBHCCN0M;*&gprjWhqoa(LV zgO?sga?UXmL!3j%1OUQJ#FVF)ky3G{SOv&&>t5YVb0in!Oq{2+kbw|i-)WSRXT5(#z zx8J_wd4Gy(`&xgG^OVUdFg~=F0-u4r(>G9y{N=5y{@aRna?vA=peaV1aqJ5()u8~8 zmr?6mOd~FYW+>PRI_{8{(B7;jZw6v4YK(k9>c7!>RjMtL(fF2T5Od9FIG0A0IgH zPi*fuocE{XlYR*XhHHfMImcc>tqd|8Mo;Yv%zrL+Nv#wZ2Ki}5@y`9{FT}{4xbuAC z{o@-33_t(%=h6u?7miev^E~ku-`ER#(U)XK0YQJ?ZaP(Hw>4u2+cTVQ^4y(_B)xZL zndxNYIt2_0&JIxfaB{~zk_xeJ+2 zc+v6d!1~iZIqN?Zu<7NOpNMcP)G(yD36f~I|M(?*mH%7)|H8KK!hr!XBs8n4KkJou zC9Z!Q72Z?F-x}c>qYrHFH}pE-Whm+btmK)?rg4>z3C<7NRvXZr@fps^2LK-uQjSPU z9U4{jKb~}pI)-S}W=NSroN2Kx#}nJ_O;|V5c3NxHxI4%CYa$kepPCb_8DO%Qg)xF> zs2MWf3~;s@J5K60@41sq-E)wGYQi775nz8%j|2NVEp~a&f-CfOAE#!LtM>rN>KeT7 z&AEXMV-*LiWiFIC+T7U{=7|3n`Q z{JBGlN;%~s*Tw7GZ*O>heo_G8J&pY<_8;yz$q;b(c||1hR3g8igI!|9tXC!9p~{tjGQ*5EfBofuYT0> zwGCV$DKFjng+X&3ao(rDfKlccjBW|U9C18J;y8~dF;H;mPM+5V^_v-M9S+Pu?`MTi zbW)jEWJBm@H*>Ls7lP1Gy!X%~VDk5FHzEuH?JE-0o-!t!&nH4kIK>=)Yo)DU;oGf1$n9NhIN>9k&m(W_UdAYzSG`+?5&ERVz71Ji-hY5=FY0=5QXS%sRL$RFKU$ zy5yLo(sVN7N51VF>=d?29}RQpO{5*B*G_$SnvuHR;XJWoged-rutA4j0CUW|7M`yA z=XqSC%4$t_bC1)C7GPR`GG{`Ga;xP{2#7i0@pvL-PE}$g25gw(jm7hy`Uz&R^W$!( z!AFM_A`BfiOq7^F9r^5*4=PKp`j4ghb8y(+*b8`mJ`r=m`8*J}yz0LwGyp!nf5YSX zU}IE@K<6XMS(Q-gRiB2(<6uT!H=Zt3|MFUYfP&rDmeylxLrl$oX1t8$&JFohC z!ZI;v?QLh_l~&xh$?Nx?i;1->yws<#1Xt&IUiBZc1@{IY6Fj_T>cqHB*Iz3q{EQub zk;lP{NoK}l?eY2G%ORO*Oc`fkvSdmbMc|4M3H?9Mg4PW&Gu&^8E^D>IgR??*>?<53 zZEX^(h|4xQ1QpdEMusMx0q^;!3?No6QWpRfLdm|8++z1+7(- zv(P{@$s|$HPGY7_ANIh&`8@FW{Dty7=+u%>V|MgC#+sdf&Jozo211Q2n>O;kNIH!IRSBI1aQ*$?f?( z)U-;=<30L+cnS98&TeKBS}B9A)McfO${p|hO4hP-;Wrnx51O~N#UMB+RsxToIKGB*OB-5QrC&)WL z|C~~ii;brZ6RY0&fV|(xS${rPWN*=Kx{_vWAn!XHLXI&zKC&rUjXZnPGYK-*%ucEo z8hhC=Cp|~G=@U}GdzxGM=B-tYVA$bJIV;DzBc+WEpAc|+e-k&aDbRsH2)g9Pf`)Yc z&M9wyG8vh!U1}P&#<0Yl-27S?zQNqHhH8}(-zovdtiPI&U8yO-dz?=;-G*~`90&5e z2Bn1i&!4#6-q0F9s@Z*B^|y}JY+aK|tzYVIqQ6%QmJM6k03#41 z9YR>45flI1<)5GZ80UD>i(6XL8s-LYq|N$=#ko&n^N&{^p`UWxj+nPEcXlSz?rh?E z9}#_!@{A3zrn%=Z85cVByYpd9{keA@$MHnmcGQF1?dS8pY?&eOgPA#QPN2S_2e?pw zJzXP}Il}Oc^G~fzPK%A7Ip)s61+uZ3oXHp9@p!HdW<5_f3-_JZgx*ogNg1mr8+#1e z`|7DglVR9zH}qQJ;E*K{D#r=xayxbB@Lf+VvY_s+!_tT0V&Sq#O@1N+MVy>9@k+wn+6xF2{By-lE zK78%ooqC8_|26fQ`EtNzRlaOp4lYeydqdL;*C*FqtHi$VFwH)hRIv%(PZG(#lk8cm zN&oJp>9!S}6k^iLPU&ilkud##ne?Ibki`(Yz&RIq@kPNm<*n0Cz6zoFZHf`4R{lGN zVEE!;Z?ft_FHkK-bN7g|90+y2ovHiP^$(`F7? z#ryj=lvZ&*?^o20Ohx4^l38`MYACI)osD&UV&n3^J@PkK{q_|w`jURj|CFxq~nw%d*K*V$lcCifU~z`GgzVEUv9Dv@tHhG#P|=cqUxql-wGDgF-qiW^pz zwNrk$bJRCOyS>#02$$44f9_^uA*@#Cd!r9vW!Cp0w0762$6vt1rPR{1F=e<*d;+mZ@h)TEFSM4Himki54Q^8A-TM{GA{9+pc1 zxn)>kb2a#&1;45Oilo*!@@xI&WzZ&MeZV_MfxVaU!UxYWMqr}HEFvkOd^q)_5GF-7 z=-%Gnk)mIbu-3YA$%%h5seAIa$@b|NTa8l8zB<2)4St4uJxjIA~TC0tM>^AM|iQ*&(~Wa{{zkEb5wV6(9C z_}O1*pcsbzwj<=ABW9IcGAx|1caF2)Zp0etueECEmE#)&P>sf);2j%CkuRgoqukOw zxuyT7{PcXdiafUz=n%6QE;U*U{0j-FC#xK1kDbAS$Gxca9Oa{l-4Y zd145EEIO|vaU)lrjbUyuDMoo9*gKlP$5ns-QhxzD9(Q&FUoz~4i&gU_1kQ8!9UW9P zIp=Xa59~LFus8GcrsuQ_C$$vX88sH`42UL$b9uhqYt9A52F@#5XvLs%m3oQbosO(A z3}$YTTf23XU!T0wB`Wda1Q=}W4mUIW{vZE;z+eCTC-Sy&6_$EQZBUXvwv7gmN%_bb z!8tsij8EFOolPCj@y2i-XbwK;9!oI*+T)3kGxA%6RUQ3GL+=e~e?vPDSQ_Y62rBPs z?+t9ES>?FIhqM5mtvvuAvE`jjx?ymALZm&Mzl=0drVG57YG#`2X$?>You78%IfK=I z(LUtBk?OX?(58s{rT(@YbRp9~(Lr^Wss6LS!q7v8FbwOOW-PNEA(ReE!I{NY?A1&3 zl?&`05&NXyTm1C%^A|}#i7vymaVoTJnaQPx;rD<1C;s~9|19}#+;+4&>(4OBS^qwa zNU=;W{quPToI~Dc{dwvg>L~;X`KJJX$nLEFruv&zv_e=#y4_ID1AegnrcG{01m&IB zbdJ}Xp-E0{1gP%YhEfR*ab3zyjcZ*Wi_Z{3poM0xh%2{h;eW&Ow)R@(%@vulH=NG{ z@85o7-j}0yxs;;2dR`I5R;%X0`f!&mQ!kYkkl`IH1UT0bUs6dXVHNU#(=I-LFns(v zf6oeOP`9zxx?T`d^lbEGk^laWf8cSyuf<~8K#4Na{U4e9rJ_6^Oz3b9A!S%C%MR>)gbn^P zn+ay&<4f!?on|9=FiiIaL97mctysN^p(d5aEfK~X5eN8jjeKU10a8G19j+Ve|NZ+q z84NR=XW?_sX?4Y|6@eAF5x^51;b#3cvv=Jou6nTf2rRZ9Z1A*&S^q0XZvY6x!R5r= z?FA=ZRsY(W;-q+2|NS5TiRb;3r!bTBSJL32sfhOu=i|V)KmNc#XL6B$XB<}-fPxX; zQ#)aRSGZ?qU>JYUS${*$J9-{ywV*dcOdDD~Neqg-4wlE0i|M@>SADr=4YuF?~Eyoj9 zY1Oppyzv}&?6)2J`y1YWzI`Zh^kPw)%o+?NypBK(U~^_6hoLSgA%L|Ox~jH~-BU-| zYE|a<{eEZDX3HqY6TklYfw%W}7HuYxc#q)%LQ1ITsl00$1=K00AK!Rywa)u^aDeAk zWNHD%D|5YbEax3H?OjQnDFr#Y#&QqlZKqy5B(yRmR}IoX(Djsv=v z&*QqD&#)I<*x>F>-}{UAS-{R#+mdGnff1u@$6oT=`O#W8{P{m$>%ZUF%|DMP>tYS9 z4PDg>JCY~p2@vC+|5 zLv(4~RrcFXr`I6Px0Qwv2V6+NsQA}^{};ah;~!K=eLnF1@rKZ8KTVm9CKn^BRX79o zw}}1yCPFH(?Ft+kvoGIYcz9e8Q;NJFHmq)VbcAype}%~G{aqi&^H6qq<SM4KwHaI>y<`}@?7qE3xcJM*@TKK7miYq0Q1$8a_a4KOacF%Yr^L~c0zHOC zLLo%?%h_c0fqC$^+Z)PxF!5D8FYnb&_%DJI^PX2zb^NXVBoyIGFv4)S-T~dey{>n) zH)Ko8e;l*jNGKXc^GZ?uLrmzk;-CNZU- z{?^#9*n~VYsSsi9A_7YjkY_^f5T|zl(UZ>lEFIAWWeEW1<5(xr*=zDI@0Ej>QjZgm zCMmgFW-wlddQ-~Hm~2G{KeNV%UWgd{0x{AOf5`^G7#-PrZ2Kl1vB_0M>tNTseYCc^ z%L@z;{o>G>yw7&l#parG_M8&D?4ncE)9n?0=;8ZIkX>iDwQJFsGiB!;q8pm6QXs?J z=_VWNwsOxOKYw9V!^gLGgqYz&Kq=?f1_!)ICPst9z9VGPRCtf&XejUWi66(4zGCf= ze={8=$e-*}pq6|<4K|Nnn?fIWfA-G9NluC}V71{qo)UXRK{T~!1@5lhGZZl82p1eu zNSrV@o`#yB6}56iI2>yYAGl*W<%L^cdQ)UzzVzY{u{3A@n8&+FDCVNB4-e;4)NfTXYV6%4W3hUf9#j7q%oEbPR0E;1=I z9y;fQ`_Er!BGP0{Y|iuK33sKWcx9W@;I!{MQcg?)?uH;7TiSQHKyl8jfBk#?V?t15 z_ErDD`UgL4f3l!6;;h6PLfv&p&q@dkjkqRZ z*Ul{O=q2lv9=kR)d8WIHC=CQ#TVCg>~3qWYrU<;Sl;rw zTSmH3qT>klxGGgE&v+q03(pI8L6q_t$f(A>i+y&2*yMNx8e9=kC zi812#?VX+V#t&{b+|s@isjEbre=!El37sm!a-5`=D)a0tCsQ-QB-JR`rVnDk`$#Xb zn?aZS@aEXYCB8_-DuU8%g1hdRW4xNr>_C{^QaD35ErK#Yh{#}BqW?hW+s*JaKjqfB$wtA`0dgqvrG}o+If4^d&d#7@9 zT6aB1di6Y)a&p!`<+N~BZ*RLspcrcZw^UfA!%x@r8N+_~5GUW}f$0DK4g2FP&6DaXnY&b(8X^YsFt6 z#TUsQ8*x|Uz=YuidDd$wT=hk5S+dx0Nf1p70)6frHFyOHv}O#GZynHr;3P&V=gE=9 zSulb_&ScGXK`Z;PH7(fR_GL4)TG9G-^mO7rr_9cF+A`8cf+;b`e?m2l+2qr;Na2y? zad4+TPfjUHWd~b+X<8`z3Y2uwGsMt2^imao$o@xAI0NORVJXwND`@5nNB{RySn+q7 zVxTQ2BBTJkeY}6E|NQsV*4RkI__zAcbW`>-0yFj&UD$n@noM=&Y8H7osJ;CAEg zJ#kUZ8h7`FuNuOO6T*@Aog?Bzv6NrvY+Fn@Cs4}ye8O78adOsgXIawNDPc7;IsZrw zD(5LO5>G_0{tP%lKb*hr?-N4le3b7zXwFJ0>~TD(RhQ}pe+s8F*(_m0i6PYCM(L-U z++2^(&t-89NxPJvkV7Zlo2Tq@nL>(EUHS4bMBu_(4J`;kdfzDoS@1!zwMR2`+&gY> zH{5iWjyY2i=Nz`27d@u64xebAp*)fj-Js|m05~28dEhdwG-<{84Jp-g8X`P%ui)5s zXuS)a&B=mye-1-4e;Zf}N1p-^%~<=GL3tf62Gp~1n$ZVbh^WtFWs{3zMN2KZa&!5t zJ=_aA_WIC=z>`Cxu?e1tF|q-97BS`_`U_8Bok$_w$-U;gtbaAms~?|qk4;2(n&Kga zcP`Sdh%44P)o6;{n)Uy?kYY6n)og>idJMywd>M_Ie{_RVVuCgmn=r{zgX?b2K*AabVKu8l}@><|;+)hyO&b@o5Jp0f|!poV%@Hm4(_ zFTTL^F!&Tv&gq66aFMRWt`idUzr!T<%*U*8yY9BAe()XzvkSt(@U|3e_JA)F)>S89BZlAx2&8n^5#OETK_AI zppEgR8tdN$C=ud$s8;gJ&-w=+QO+l9 z7@qe#kM&yo@|KaZ>R-7?T4mRLavEF+tiKPd7uMR)RaQ9)A)uTE`^GE5wq*fM!!mFU zE!_5{{?~K&tgS?Y2V>yCI6thL}7;R4-*Y z9}P!g6uGJIwR+4$X+babPdTgpw9h65Svt+>$Ny6Q`SFi2;P(&yz$q}Tf3cnwUBuI_ zBh?fu1m{-*=UkCTSCg){<%{($V86X#FwaIGz-6|8g64SaB8s`HSu@QgDQ|@MOK`%t z6}JEi?A{idNkp&dFN}HKBZ((AcTL4#W*p_c%T-Ve-*~)NSPsy&Rq*#i~+4HVWVC8b?@RrWeq_xhZ=f>XRuZa zNQoDT>)&FJmMl_Dn;|#d=nMr&>P2hG)b3iLXQT&)fdB{z|i*bN^oH%@|F)x#sIRe<_YgK7=SUmUCWn zZ;xIH$K3Z>{}Xu%hRozyrvr`Q~={XOc-eZA|rIZZ(~03Ou@5Cs2$am&~I zG6*fSIiS#E?41Lof7zukJFq)D2)|pai}OqQNeS%x#|L%J!PCg#*+ur61v9yH;5-lbm|!+= z)+drDhUxbHzU-;3-YGh9jw!J5@=8Y^7+w&0B(v5StE0KEf77mQ2PefI1AR1jq_v}u z!RK;&dqdSr8=^-_H;$dOJ1^?&bl)u(9(To%vy@_tFK)e|`9VsF0q8-|KTnj}SbvbA zKI`ATqK`MG%0NE%|9|zDr4>LhPh^yuS$@VNm2=g9cKqAl>+dE5t@HN}0VyQ-l+b4V zQ_%Io0V$%CE5gvtRsV0SfAj<}dQOz6WbDKw+rW7~Icx77^+5<_A04-kcQ#B%N4@_f zmrP{=8-JJjcLXp?uMa~X9;H?35sDTq51;dDpuX0BHRQh3pM9ycCHQ~+>tFhZQ``|0 z+*b7g#K7>kR!%a_t>G*MwduHFGc}YeO!Q2ktfj0R?QS!Q_Uioybwtl{${??CP#7>3mN@F zHIo7Z`k6Iu>Z33CUO5Uz>+Asc#+1%h@jRbmp(!C{6@@lU7u^C7baluHPhh|yW0$;$ zKXm%ppl!In1Sif^F9)a5rpzenJ6My1*ZGAGYqjCmuTPR)#~?u{6E9mUKe7<$T&v|o zIe(rc)YQ5Zl;dyp51t^yS^ruKlT0RgMH_nzaV7Zn>7}1JYcKWh|5kq>?wKF8oLX(P zm#d-t%hTM`3{DvVr4+=-&c62%tuaT>c@lkxo+q53Au`(3O2CA3jy!{N)}Ld;kP^zl ze6%EF)BuxdC-9;v|8CZwfs$$E+Iu%0lYbQJv}U5_HpHYXJgM^97ziopN;6h~$*O<9 z>ff}<__QS)&nI0_8X-Bw8`bkbvAP-{V|2I>>28v?d95N!%xH4)%zIr-nPaxVM#gy@ zTvP&^E#)}ZIAP!S#R|9HU{W}(&a73ufBS|2pd4%roio21TI9sJV{8 zOMnrVBF!MetbiR{gxH)dyO8=|fe zU5c;xQvbJ)cX)w727p7TriGB&=_8*DCSH0&7+>o@2H}_^@Q6H&qbVoghYJBo;E5){ z#QVoL+KZ(NL2x+B2?QrrdsD8_nj6A;M@kVnM}j0IF0!GGVFE+cteo*tDSt&-ofB^F zZ}b|d(LDbX1HJrT>Tg&5o#&O?qcK4whroM++)h>-Q!gqrt|ne+;y$J&vuczvg8(7* za)`<@>m8fodN4pAbL4J1j~87enR1*QNwo?;s1ct)y_xXx>*r5|m?)if9@%SN>pVhm zQhjy!F;J~yiy1j2M9=#p#(xZqpk?!RdtalZYNkF#St_NW(7kT`YDRho9}`mEiPQqH z#RQ+ih00#a)o~?yc!t@}CZu&fzoD7=d@&%6H_byl38k12-AgLS=t>pUeYcZS-_(F> zbryUqX8%y2z>wa4y;$C3iwRauFZQf|BDkYn*jU`ti>T+EHw5Ly+29@At06dj<*n7#Jo9pO zO*P-N*M#bOe<`3{DI@ zf=3^KNap+efvE@9%y3X?HdjohyZ}z=5!D)e=Ln=)MT!}&4iw`Z*@w6q2(6i-m`Jsp z4XaujqW5S<%+vEY5PiV@@y6uIQ=WOa6$AkndGv~7g%glh(0>=W!h1&t*4sPcmhi9t z{%?GI|6M*`pq=Lm{R0Mr1e`(?*YA7DF#|kW7v}TAt;CPwK!GC>e`b=;`aExd6-tz>boUxhH=NwS1Vl%%CQ&AlE)+qh-N~)b4HRgmj z_>`6^trn7jsu^y#9na%H@)6tnJE5beY{E{2R!J#&^uF+99fWC&aRm_ecfhk-S@d`~446 zJW7-1dQ*dPtV9tEgY!E8!{a!V3HW$nTVry7vY zW)p0Pm?M78`nQJT&wp`zrK?mkf)#rw1t_L~^EeSRJ=rtpvg_10CmId`$wz$u;}1G0 z3xCsxHr0PHUT@Xk`yB&@$MaYK#%9cjXZKmMQp zgzE$6S&;Ik<7cOWDaN%bx~aR?-I0wm>Eu1>wjl&$#VS43nf>|eCw%nSZ#(aS);Z$_ zkU|u>qb+8-^UR6&-Xm=^6cE0_eQnO_Q(}O_SqiK%L~oNmdd!_RhQ;t^CU(C<^M9ls zvV%v!AoN|FilNU8-O zr^Ijt(Pvweh-5|w`%A6%H(8q|6@ktxrM1vN#Rf2xE;H1O^WvTL(Q!Ub{Kx6{eZIDe#wP4zG56M6f8%Q~Me&1oZwU#TQpb`Q`!EPzdt zO_Dd`Iau&`IkNx`F8~b58Ny_k@3SRKma@1dxo24SIsLEvS*ogge|N_Hk9V-1^-p_Z z+oG$i`5FDSdn=4(hP|~GGEW-4EijF_@FEh~num!?N9n6t@S_Wu=znbkG^3iI!d_ z_A#d6{kuQl!;GN4Ru5*h-hV+16E|TDtoQ0RlOdQXeNAOA4DYF2t&|eHJmT^33EQ^e zp0ZjXufD11LzQBLu?9<6a0q+h$4yW_X2!c)18U{dY9u#m5?oF?1VFdN^68#ncf?migjVV1+d_ z?zWD`%Cujnm_}?=QO|tI8LwaeiZ8zUa;Wz#08Gx|r(b`;n}7cY-+%WV-v0MD?6(`r zS%5~jPnZKlyhibsE3dh+cWnxnr>VliE3ANE$xOSd5>~|+Jb$bYL!K&@q81-!dU)pv zwf0zLCV*PUbP;PTa*TXf)$>cy4Mj4d(MQ%8JiK_&a7P1cxKy;L2Eufb z93w?Jt-?Etc?u&`plA+U9~%C-{z3_CQ;TcKL(G#iX*$cg^6yrkMbT5PDoMDibB=sH zQiDb1z$HeV$WyRGNM%D!$A~bp#$tW(KvI&(*!@qpboZpQ<_US?h}L-BdKu zRehbi-mh`3fhC1-&xMtCdm8h}~qH9hbDkCYRFpFdc;wA#iCoAE=JqpZ6V#dYCKufJ8vZ5?d? zUVnU4f2Z~5!Bn2rpIZ62-wCg99<3D|2YCU@vW(=PKI!i3urB)~J&1D{s9A`PJ<+pQ zRDUT3x)bA}VVWF_of@oYVDvc>4lRv?sJ1}>7;)J44bJ*eyLcpc-GAp?5avK0U2k2y z&^@O{DF?thDjvI<%?eOU8!kY8Sj|unx@jU@G%UE??rgUlwHE8LV%s;?48Rt5I7^6W z$p@ZZKH=~G{0AOhtQyEyV7~tLo7S_<{C~3YihNQCkV}Grg);(7wE2kkFU-h=*8zZ<@&FyM52U(mo+e0`P*u5ha+d=aCghztV|^Oj(2x?NfPbfH zMofvSDQ!LGu<#T-D~C$Xk9~FjTa1@0Hd+j1no*8~V^7z<+gkX^p`Aogizw()lR!(P z#CG2|02R&=Waz~YM_vqA)gO9Q=gLtaA>j7E-+!@;`a34#IJN=t{T)6y>@nffPd;V5QO+=)Sz`TX z@Pp|Gz!7LL`cgq|fH&7+WIe2@A0)({DGfb;)hzPX=*w_E;Ous7G@w-2FeC2~-ZSOY zd)9x~DCjWHjD?m wr%}}<@#P%vH`dO1Ux!kxo^aW3X&rln?T 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%0D}01br!8J6#xYoYQl&9 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 Hu0mjf|AH Date: Sun, 23 Mar 2014 14:20:24 +0200 Subject: [PATCH 082/647] fix previous --- plugins/wtsynth/WTSynth.cpp | 6 ++++-- plugins/wtsynth/WTSynth.h | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/plugins/wtsynth/WTSynth.cpp b/plugins/wtsynth/WTSynth.cpp index 1c7272200..42df80133 100644 --- a/plugins/wtsynth/WTSynth.cpp +++ b/plugins/wtsynth/WTSynth.cpp @@ -293,8 +293,10 @@ WTSynthInstrument::WTSynthInstrument( InstrumentTrack * _instrument_track ) : m_abmix( 0.0f, -100.0f, 100.0f, 0.1f, this, tr( "A-B Mix" ) ), m_envAmt( 0.0f, -200.0f, 200.0f, 1.0f, this, tr( "A-B Mix envelope amount" ) ), - m_envAtt( 0.0f, 0.0f, 2000.0f, 1.0f, this, tr( "A-B Mix envelope attack" ) ), - m_envDec( 0.0f, 0.0f, 2000.0f, 1.0f, this, tr( "A-B Mix envelope decay" ) ), + + m_envAtt( 0.0f, 0.0f, 2000.0f, 1.0f, 1.0f, this, tr( "A-B Mix envelope attack" ) ), + m_envHold( 0.0f, 0.0f, 2000.0f, 1.0f, 1.0f, this, tr( "A-B Mix envelope hold" ) ), + m_envDec( 0.0f, 0.0f, 2000.0f, 1.0f, 1.0f, this, tr( "A-B Mix envelope decay" ) ), m_amod( 0, 0, 3, this, tr( "A2-A1 modulation" ) ), m_bmod( 0, 0, 3, this, tr( "B2-B1 modulation" ) ), diff --git a/plugins/wtsynth/WTSynth.h b/plugins/wtsynth/WTSynth.h index 599d0d487..3a3fe7d0b 100644 --- a/plugins/wtsynth/WTSynth.h +++ b/plugins/wtsynth/WTSynth.h @@ -31,7 +31,7 @@ #include "graph.h" #include "AutomatableModel.h" #include "automatable_button.h" -#include "knob.h" +#include "TempoSyncKnob.h" #include "NotePlayHandle.h" #include "pixmap_button.h" From 6eca2b422c6e54ce87ab845215c8d113af080929 Mon Sep 17 00:00:00 2001 From: Vesa Date: Sun, 23 Mar 2014 14:26:02 +0200 Subject: [PATCH 083/647] fix env tempo sync --- plugins/wtsynth/WTSynth.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/plugins/wtsynth/WTSynth.cpp b/plugins/wtsynth/WTSynth.cpp index 42df80133..7b236507f 100644 --- a/plugins/wtsynth/WTSynth.cpp +++ b/plugins/wtsynth/WTSynth.cpp @@ -294,9 +294,9 @@ WTSynthInstrument::WTSynthInstrument( InstrumentTrack * _instrument_track ) : m_abmix( 0.0f, -100.0f, 100.0f, 0.1f, this, tr( "A-B Mix" ) ), m_envAmt( 0.0f, -200.0f, 200.0f, 1.0f, this, tr( "A-B Mix envelope amount" ) ), - m_envAtt( 0.0f, 0.0f, 2000.0f, 1.0f, 1.0f, this, tr( "A-B Mix envelope attack" ) ), - m_envHold( 0.0f, 0.0f, 2000.0f, 1.0f, 1.0f, this, tr( "A-B Mix envelope hold" ) ), - m_envDec( 0.0f, 0.0f, 2000.0f, 1.0f, 1.0f, this, tr( "A-B Mix envelope decay" ) ), + m_envAtt( 0.0f, 0.0f, 2000.0f, 1.0f, 2000.0f, this, tr( "A-B Mix envelope attack" ) ), + m_envHold( 0.0f, 0.0f, 2000.0f, 1.0f, 2000.0f, this, tr( "A-B Mix envelope hold" ) ), + m_envDec( 0.0f, 0.0f, 2000.0f, 1.0f, 2000.0f, this, tr( "A-B Mix envelope decay" ) ), m_amod( 0, 0, 3, this, tr( "A2-A1 modulation" ) ), m_bmod( 0, 0, 3, this, tr( "B2-B1 modulation" ) ), From e38ef81e032f154d4d6d7afd7475b0be70f25286 Mon Sep 17 00:00:00 2001 From: Vesa Date: Sun, 23 Mar 2014 18:47:02 +0200 Subject: [PATCH 084/647] Add waveform load button, better button graphics --- plugins/wtsynth/WTSynth.cpp | 50 +++++++++++++++++++++++----- plugins/wtsynth/WTSynth.h | 2 ++ plugins/wtsynth/inv_active.png | Bin 581 -> 655 bytes plugins/wtsynth/inv_inactive.png | Bin 489 -> 596 bytes plugins/wtsynth/load_active.png | Bin 628 -> 676 bytes plugins/wtsynth/load_inactive.png | Bin 537 -> 631 bytes plugins/wtsynth/norm_active.png | Bin 603 -> 702 bytes plugins/wtsynth/norm_inactive.png | Bin 502 -> 641 bytes plugins/wtsynth/phl_active.png | Bin 667 -> 734 bytes plugins/wtsynth/phl_inactive.png | Bin 517 -> 693 bytes plugins/wtsynth/phr_active.png | Bin 667 -> 708 bytes plugins/wtsynth/phr_inactive.png | Bin 536 -> 671 bytes plugins/wtsynth/saw_active.png | Bin 590 -> 706 bytes plugins/wtsynth/saw_inactive.png | Bin 426 -> 646 bytes plugins/wtsynth/sin_active.png | Bin 698 -> 734 bytes plugins/wtsynth/sin_inactive.png | Bin 585 -> 699 bytes plugins/wtsynth/smooth_active.png | Bin 653 -> 709 bytes plugins/wtsynth/smooth_inactive.png | Bin 567 -> 649 bytes plugins/wtsynth/sqr_active.png | Bin 611 -> 687 bytes plugins/wtsynth/sqr_inactive.png | Bin 506 -> 640 bytes plugins/wtsynth/tri_active.png | Bin 655 -> 738 bytes plugins/wtsynth/tri_inactive.png | Bin 532 -> 699 bytes 22 files changed, 43 insertions(+), 9 deletions(-) diff --git a/plugins/wtsynth/WTSynth.cpp b/plugins/wtsynth/WTSynth.cpp index 7b236507f..54e4580f1 100644 --- a/plugins/wtsynth/WTSynth.cpp +++ b/plugins/wtsynth/WTSynth.cpp @@ -838,33 +838,39 @@ WTSynthView::WTSynthView( Instrument * _instrument, // misc pushbuttons // waveform modifications + m_loadButton = new pixmapButton( this, tr( "Load waveform" ) ); + m_loadButton -> move ( 176, 121 ); + m_loadButton -> setActiveGraphic( PLUGIN_NAME::getIconPixmap( "load_active" ) ); + m_loadButton -> setInactiveGraphic( PLUGIN_NAME::getIconPixmap( "load_inactive" ) ); + toolTip::add( m_loadButton, tr( "Click to load a waveform from a sample file" ) ); + m_phaseLeftButton = new pixmapButton( this, tr( "Phase left" ) ); - m_phaseLeftButton -> move ( 200, 121 ); + m_phaseLeftButton -> move ( 196, 121 ); m_phaseLeftButton -> setActiveGraphic( PLUGIN_NAME::getIconPixmap( "phl_active" ) ); m_phaseLeftButton -> setInactiveGraphic( PLUGIN_NAME::getIconPixmap( "phl_inactive" ) ); toolTip::add( m_phaseLeftButton, tr( "Click to shift phase by -15 degrees" ) ); m_phaseRightButton = new pixmapButton( this, tr( "Phase right" ) ); - m_phaseRightButton -> move ( 216, 121 ); + m_phaseRightButton -> move ( 213, 121 ); m_phaseRightButton -> setActiveGraphic( PLUGIN_NAME::getIconPixmap( "phr_active" ) ); m_phaseRightButton -> setInactiveGraphic( PLUGIN_NAME::getIconPixmap( "phr_inactive" ) ); toolTip::add( m_phaseRightButton, tr( "Click to shift phase by +15 degrees" ) ); m_normalizeButton = new pixmapButton( this, tr( "Normalize" ) ); - m_normalizeButton -> move ( 232, 121 ); + m_normalizeButton -> move ( 230, 121 ); m_normalizeButton -> setActiveGraphic( PLUGIN_NAME::getIconPixmap( "norm_active" ) ); m_normalizeButton -> setInactiveGraphic( PLUGIN_NAME::getIconPixmap( "norm_inactive" ) ); toolTip::add( m_normalizeButton, tr( "Click to normalize" ) ); m_invertButton = new pixmapButton( this, tr( "Invert" ) ); - m_invertButton -> move ( 232, 138 ); + m_invertButton -> move ( 230, 138 ); m_invertButton -> setActiveGraphic( PLUGIN_NAME::getIconPixmap( "inv_active" ) ); m_invertButton -> setInactiveGraphic( PLUGIN_NAME::getIconPixmap( "inv_inactive" ) ); toolTip::add( m_invertButton, tr( "Click to invert" ) ); m_smoothButton = new pixmapButton( this, tr( "Smooth" ) ); - m_smoothButton -> move ( 232, 155 ); + m_smoothButton -> move ( 230, 155 ); m_smoothButton -> setActiveGraphic( PLUGIN_NAME::getIconPixmap( "smooth_active" ) ); m_smoothButton -> setInactiveGraphic( PLUGIN_NAME::getIconPixmap( "smooth_inactive" ) ); toolTip::add( m_smoothButton, tr( "Click to smooth" ) ); @@ -872,25 +878,25 @@ WTSynthView::WTSynthView( Instrument * _instrument, // waveforms m_sinWaveButton = new pixmapButton( this, tr( "Sine wave" ) ); - m_sinWaveButton -> move ( 232, 176 ); + m_sinWaveButton -> move ( 230, 176 ); m_sinWaveButton -> setActiveGraphic( PLUGIN_NAME::getIconPixmap( "sin_active" ) ); m_sinWaveButton -> setInactiveGraphic( PLUGIN_NAME::getIconPixmap( "sin_inactive" ) ); toolTip::add( m_sinWaveButton, tr( "Click for sine wave" ) ); m_triWaveButton = new pixmapButton( this, tr( "Triangle wave" ) ); - m_triWaveButton -> move ( 232, 194 ); + m_triWaveButton -> move ( 230, 194 ); m_triWaveButton -> setActiveGraphic( PLUGIN_NAME::getIconPixmap( "tri_active" ) ); m_triWaveButton -> setInactiveGraphic( PLUGIN_NAME::getIconPixmap( "tri_inactive" ) ); toolTip::add( m_triWaveButton, tr( "Click for triangle wave" ) ); m_sawWaveButton = new pixmapButton( this, tr( "Triangle wave" ) ); - m_sawWaveButton -> move ( 232, 212 ); + m_sawWaveButton -> move ( 230, 212 ); m_sawWaveButton -> setActiveGraphic( PLUGIN_NAME::getIconPixmap( "saw_active" ) ); m_sawWaveButton -> setInactiveGraphic( PLUGIN_NAME::getIconPixmap( "saw_inactive" ) ); toolTip::add( m_sawWaveButton, tr( "Click for saw wave" ) ); m_sqrWaveButton = new pixmapButton( this, tr( "Square wave" ) ); - m_sqrWaveButton -> move ( 232, 230 ); + m_sqrWaveButton -> move ( 230, 230 ); m_sqrWaveButton -> setActiveGraphic( PLUGIN_NAME::getIconPixmap( "sqr_active" ) ); m_sqrWaveButton -> setInactiveGraphic( PLUGIN_NAME::getIconPixmap( "sqr_inactive" ) ); toolTip::add( m_sqrWaveButton, tr( "Click for square wave" ) ); @@ -906,6 +912,7 @@ WTSynthView::WTSynthView( Instrument * _instrument, connect( m_smoothButton, SIGNAL( clicked() ), this, SLOT( smoothClicked() ) ); connect( m_phaseLeftButton, SIGNAL( clicked() ), this, SLOT( phaseLeftClicked() ) ); connect( m_phaseRightButton, SIGNAL( clicked() ), this, SLOT( phaseRightClicked() ) ); + connect( m_loadButton, SIGNAL( clicked() ), this, SLOT( loadClicked() ) ); connect( a1_selectButton, SIGNAL( clicked() ), this, SLOT( updateLayout() ) ); connect( a2_selectButton, SIGNAL( clicked() ), this, SLOT( updateLayout() ) ); @@ -1171,6 +1178,31 @@ void WTSynthView::phaseRightClicked() } +void WTSynthView::loadClicked() +{ + QString fileName; + switch( m_selectedGraphGroup->model()->value() ) + { + case A1_OSC: + a1_graph->model()->setWaveToUser(); + engine::getSong()->setModified(); + break; + case A2_OSC: + a2_graph->model()->setWaveToUser(); + engine::getSong()->setModified(); + break; + case B1_OSC: + b1_graph->model()->setWaveToUser(); + engine::getSong()->setModified(); + break; + case B2_OSC: + b2_graph->model()->setWaveToUser(); + engine::getSong()->setModified(); + break; + } +} + + void WTSynthView::modelChanged() { WTSynthInstrument * w = castModel(); diff --git a/plugins/wtsynth/WTSynth.h b/plugins/wtsynth/WTSynth.h index 3a3fe7d0b..df7aa908b 100644 --- a/plugins/wtsynth/WTSynth.h +++ b/plugins/wtsynth/WTSynth.h @@ -244,6 +244,7 @@ protected slots: void invertClicked(); void phaseLeftClicked(); void phaseRightClicked(); + void loadClicked(); private: virtual void modelChanged(); @@ -300,6 +301,7 @@ private: pixmapButton * m_smoothButton; pixmapButton * m_phaseLeftButton; pixmapButton * m_phaseRightButton; + pixmapButton * m_loadButton; }; diff --git a/plugins/wtsynth/inv_active.png b/plugins/wtsynth/inv_active.png index 791133686ff20c40c3eeb78200b852d1a40c5d6b..31aacc62123f6af736cc06c2d9ba4fdcbc7c38ba 100644 GIT binary patch delta 588 zcmV-S0<-{K~5Y&3`L)-YnV|cNI^p+B&2NEpa9!!5NocG zJA~uFI%i;$9f#ly><}PL1Wb3iY-iCutr=p;QdOz^?f<_8;Oy+|+RT0e3x*I8B4RuP zq?E`xALPlj*pL@c6WCd zv)OFpqaXrF1U3Mw8C~1bwk@mGinq77=j`r_>2ylYdF*m{c*ysY6PlE0nudtr?(UA| za*3*9X5^fSh(&gHCX)#wGLHWE_{i()D;F0RxI4GEx3q1GsuB@M5)z4sAiFy$rLlX{ zG^C-knbCC}T~~kbL7R_}BVsICb9Hx0Db!jqGayJ!0}=lTno~+!h-NnOETzNDx9r?3 zMx>v>+;MkAgi;En6mrg#qC`Ngb*pf+7RUgqh5icf@9(H8v)K$)MUr5(!T_)?lwtA= zVAY5SRF$@EN5RaT6utkl0Wfgw0dmeG@2=}ct0t2P?nZxv3_`L+VI66$cyCt^aBy(I z`T03!hM94BdC7D-rPjKY0CIG6^faH(7pv6@RUO0x0vL2b=rvk57D$p%)#qk^fB##p z^@o{JR0((71CPMN`}829cWS+Os)~sGZeCtq{_K6(`>Lu(5%KBcruCL>zYUh(JUl#H a{R4@XP`?m^p{6SU00007p delta 513 zcmV+c0{;Dv1;qrADlz{6{{a7>y{D4^000SaNLh0L01FcU01FcV0GgZ_00007bV*G` z2i^k}6C?mD5B3d_TPT06Nkle)q9Z3L~84-cIlXJ%1NhxuCeNESO zlv3Di)-)ra*2>-89ko_+&ZLw`DPd+)rDTAJ2qf|S{Y?`Q(vC78TY^M zd47JTZCfIOKMxN){(YqHdunw;qiv!Y4U;rg(`Hs}1|TA^lxUmwY&5gKKQ#adz}=~} z;_hcpq@l&hmu7#pT4Bi$0tq1^oKgzzK7p1s=s+5_U^*)pUGDpyh*;!ftnt4|G~>QG zNp?T8&t)%06i7oRY`#8sr|y)w!*>>rJB$~eOkqobw zrY)PC*%$BQ@koT@Cw7zJ?(FybsYxk?op#JN}~As`r_^FjZzAd z`276j{rw%Afe(knpyKuQHM*{&>$)ET^HT=qz8L=j<#5jZZKg^d00000NkvXXu0mjf D;^g!& diff --git a/plugins/wtsynth/inv_inactive.png b/plugins/wtsynth/inv_inactive.png index 06089449b693563e66b097fe232c0703b62001c8..637bf5390aef3e6e3c7355f59815f79036933aaf 100644 GIT binary patch delta 528 zcmV+r0`L9l1JneNDlq^60002_L%V+f000SaNLh0L01FcU01FcV0GgZ_00007bV*G` z2i^l05D_nmpnoutTPT0LNklnp=BtQENF`<|}rzGTihIb%*Z(dAR>ei2q7?=&G6ojJ^ycKw6#Wv0YLzGdwV0r#QAwo zj1dINk-*^S1&Dk|C^^%b5o2T+25POi&QVG^^#8b@%m5&zOwO5M7^b4lX0u7!xSxUp zCgul!_Uy{D4^000SaNLh0L01FcU01FcV0GgZ_00007bV*G` z2i^k}6CoiQ5fT=WTPS}~NklQvr|xArJtO5E&a1U{4NY02?GE z#Hx`%qEXk!uA0RY^`>V)Fn4MBSoXa($K$c^P1affa?Sv#D$Y4_&g7hFnuZVpAp`(M z)>>4R%jLo+$~hw>sTxn#2A^)W=yA3nx-M8gsKA2wk@M)YdYr`kH;8e>fOc|LI{*nDCNIxqgS_< zQmSzw1Y(S}J}~_itg5IgB2riW3BMems@13m^b7{DkGvle5kd%f@880|Hc-_XQ%dPA zJQ$F3CZ&Y;{$pquz&@h+dG{wUfOXDMN+G3$h}2DPw_9zBG1B+_^8q4)h!A5$L;yG( z4lI|;n*C<8VZB~I9bk65U5PQ$w(TIcce>y2^nL&D6ZiW)-uwD6f6*7Y+bE>|WEAlL O0000S=bCokbW8P6!;Z2?0b%<|@8} zIS$0Wg=4OO1OX06NC2^z#a?EnYr5LO%#Qgfsif-GtH1Y301gfgPGXGTfRf%sgp|?{ z132gK-eYC}r|0MA$Fje_e`03eN23wbq9B@)Wf>y!!B?h1Sv-F)Xqx6!_V)H3Ha0fO z@p$|SD2RX)fma3E7-{O7x~{3Jisf=S_hwe+d5-rU5n(!=a(H-1p67@N&N-ZO+}_@D zc6NrU5@W=BPfDruX2#mu8X`iLWlSa$mdhn~cXwQ0Uo#qwI669FeSIBOC8dNo!Qn_L z;mr)^+_2+fvEYC5@)CfyZHZ=t5U`$`_vTYdWLY*85fRLcwrx>WoO1vlFhhYAU}Z5z zRF&P`U3PYM1}Uqm`jCuBH$gPR%n%Vm2!s&G^PCtX7Z(@I=X2`1Ug`f|TEGLS2D&G_ zyu6^Qga7&ahv&rt`p&CF=_mI9v5lmZP}QN+)zvS? zO*2R}ofed3$^HF3u?N3C^MOR`WeOqCG|d1mih|9}O`LP6>YJoD@oYAGD2k%2stQ%@ z$pjM6^McTEw8|53;!xFjw!OXmrES}(ka}Rh=fKlqT;lt&{BSUoZLT&CSj6KiQ}~v3RymCjbBd07*qoM6N<$f-R9AbpQYW delta 561 zcmV-10?z%U1@r`vDlz{6{{a7>y{D4^000SaNLh0L01FcU01FcV0GgZ_00007bV*G` z2i^k}6C?+YBpPzr9H11A}k)xv{M1&Y4 zsyZlyG<2KW$;KSnN+IZQJtj@W98%$G4Ww&(AqK`-K~b3SHl#0Q325 zLjC>zPSnk}ME>$+6sntaU5#i_YF{{-I0USsvAyWFD zghrNjf*`mXDJ8nDWf(?sHgGR~smUe2ad%WU z464d6FE2bkK5nlFKlb+#kttq9XzIKH%nY-F{`U3;z`?-*S65f4>NM&CUUs6Xe);d;Pbdtl2cfFyL<38eK&};Q9HPr>7@QPENSKzDD$G3sb?py*+m4bIh&${6ces z8dTA(DbNcs@TPT0uNklvl57c1VqD@#q2l$2S5m}z#ZT? za0iyGX2$_o4H6ds2??ZRl8k_d-TrA7AweTxz+1Pgy2@1ou)n{5?3_CgkpbU0W`?Ss zoS&Z`$==@HvG@M4)9K(uurD6hT8S|-9*=3;_QV4ROG`^MP4j;xb4rQl=VzXto={cV zwmtBrl!5nt0kFEd%FfOX-EJ4Nw|#DIZa6zTBZNTC8Sg!2Ht?ksnx;WSXqtw8zt40! zWipv?b#+Cj(_wdamtL<&j1e=#Ifru&GsEYc5fMZLGh;X$G8&BlP}RlSb0X*5KeD`; zy}Otj6=Pg5HBEo>p-+DPEoO#@kaH%+$kx^to12@IQZO?fA0Iz7)|(kAB>+T(5CS0t zy4^0S%EiS6_xJa-ZA&TTJwUCM5Ceh$@bK_}MkR(ojFIWzDU<W%#4+l6*hM^Hn_dLT}b>CAjY`RJ|FJ) z`>d_4;hg&~fNXDXkDPOZc|1$42sRV^rucRGwM-aJ9IE=q=bTSf^{|wJri9h{WhcD% zXi|XF=I-w9*ZTVU4^{nXwf4SK=Q<-fxxT(WdI7$tG7l!Y05<>t002ovPDHLkV1jSn B0;T`} delta 469 zcmV;`0V@9Y1epYoDlz{6{{a7>y{D4^000SaNLh0L01FcU01FcV0GgZ_00007bV*G` z2i^k}6Co)S%9n_tg&+t3aLxf>ttE;goO3wm zXti2stM-|s9I3(|iy#ryx}!Z2h!9y1z^ z&{`uRWLfs%;Fa_FOrGb&am;KsBMd`Us})I-u-$GM4u@E40Vs-s@Uz9iV8DDnug@Za zQVJ14M6lMrJ8Rn2dylmitu@A&I@DKj2!a>IY+0{VKSMZl%m`1{_Mb7i!lbRb)9q^$Mkx=#$E)k1*xivvMi~p z3Z>LrGn-KR{oZF;hKNuU1zKyIbKeH`nd|jR7)24@d#b8JL~8M7vthkn)9?40PN&T) zJPTrsK}7f~YPZ{YV+@zerG6y8Ah1%CBXM9b+!8mlAq2wCXYn26 zab)dV_yYO@vty%>5Df{JL=1B-)m81{%uGhDKP*Cf<=21nFS@R~l;h*$hpnxx z@y5o+3Q-V&AOb4|vKd|5(zY#4)9~{0@|fIxyuQ9pN(m9+=;(-(lM^&&zJB=v!1?(( zJ3Bi}r&F%3t}ruFN|aK@!QH8<3K1d3NJ@#667}XL2L}g~QkEV2zNeIegn?U1A-Fps z1VRV^#2BfniYk94_V)H@+m^2D@wqoCC8|`BQUV~AQiw4ULKw7$!K_)+FdB{K(gw}~ ztA?gU=S8?VUDt7ce@_U);o;$6D*tZ-5ke^ib0_Ca&UvnP(ERP&clP)9F*C9a|EfyP z88btG0HE5Vs`PzN(=>E#OIGFP=7tahqt~x-Gi-r*0TzD+EE}rIY&N59TQn=0GfmU* z^T$s@jF|hfK(>Jo5K>B*8C};cSG5??%(%Y3#_~LIMMBPbFwx!V`<}k<>ALQ(bf2`O@pf9?uY;dU`~`_4~r`TK?17!7y{D4^000SaNLh0L01FcU01FcV0GgZ_00007bV*G` z2i^k}6C*0W^{E_@TPJ@3!%0LzR5;6Rl3#A(Kn#aJd&=`De>|y*4_Zhyb9fm>Drfy!XTyan3QFPASWh zx~>@x2RyX_Aq284BZPqW9_Jj+IaKv#&M6?686v{@eCEl_@ZNtjo6Qgry!WW;jYJR{ zm%0vw5UA@KGvo5_k_g7*398ERcx1ELAR_#Jd*jFRGnewh$Da?(jMZwz%gawJf~ZiG z7ZhMH=-;b0<^FztA|hB!I<%ETh?umpNlMV|QyL-n`#n`vQPnje1kCPQr?!$kBxn!K zjG`z~lIyh{PiKEhcU`pK@1yQc0O@8jnXuh%i7}>^W*}|l#DNHEW~ej-sz5@W&*z*@ zC$234pe?p&^B1%`Z_IAXljk`Ahr{89-dZZ2Xtmpa8*FBbMkBH;W4GJgccLXwMK!ge zSkNyy;}+yRaQ zcOWF%jEtBRq6MUpNOnMC>>ju6c5N_p3sy)_(hnTet6xm)3)uo1&%j2H>rQB>dVS0C045y-g{z< zv~7EA`@WxAYe&G|-X62rj1U5smzR`MI5;?9dwZMf>uYXqZpb-ftwmL*rtf>IszOAt z){dG?ChYF+qN;fBan8|o9jb~kW&mJv&WH#if~rzg)d<+37t`!z5|y!YJyxkrp4>kU02kHM)6?&!X@15Se`zT{zH`oHUF7`X;oy{D4^000SaNLh0L01FcU01FcV0GgZ_00007bV*G` z2i^k}6Cn@A#~;~|TPS~CNklTX;Gbt+cTceL6Uz?XsmRG!DtFcUI-O3&i=rq3Kve+{5t1Z9RZ&%Xy&ldvoO1xg zQ4}E}TrL-WBUQzFkC}13UWrvTz=y+u^?D7!a=BzU98weotJQxBGh?w>FdmO_&f&f1 z@purmk>9o5Zo{{kp{i6>MOl_KO@pdZmL<`rsQdjM?>!=dh~T~F`FtWGm>Fh&PWREE zEK9O13vpHTFEAYaC)msw3*aaMMTK+ z{3HBNf);MaGa7Y`*zI*jonx+W`uS(Oj)8H%1GHaTK^Z6Ve$!}B?1yxlM100V>>bm|h b!TG+IvV)Pp00000NkvXXu0mjfbw$5_ diff --git a/plugins/wtsynth/phl_active.png b/plugins/wtsynth/phl_active.png index c2d0bede0c6d89c34de26edfb20b92f502d4f8b8..b4e34246ddd11ca49f401c9edd10371327f602d9 100644 GIT binary patch delta 667 zcmV;M0%ZN01>OaaDlq^60002_L%V+f000SaNLh0L01FcU01FcV0GgZ_00007bV*G` z2i^l05ELM1XqM!WTPS}_V)G=UckI~Jy#G_QB^(zHKC<@Nc&nc^t{$RlBYMU4$my-##_w4NK&}y{^ab6E#thK}#an4beC3Rgh znM`obvAz9?5CSnqE-o&pT}{8=Cxr0woz2b7w6?ZJUDr70h%xe3EDmpRxok@5E`-o^ z&f&dBRS{nS62K!!K<3Bu+lWC#?y_F5_aTHZj4@JsPf|rSp(&wB=c$R5=1x5=p7$OR z`I*gTv$M{-&bs&hV@hfDE$NHa1CJ`@^ycQ~_#a^y{D4^000SaNLh0L01FcU01FcV0GgZ_00007bV*G` z2i^k}6C@Eqzt;beTPS}6Nkl zgb+xQgsrVD>bk}`N55Z?E&<+qc6WF2-jnA!Ns^Ex398yfk|=*5m>D9%d_E^NGx9uV zXJ-cyAJdYDk>NZzI0VY-H?A(qd#;o7$728>&DS&M3!Yd zK0fmL8UY6f2V_~s^v9IhY}P7?w%4X<5K)2;gb)BalBcI9q*Zu$c-Rp~f_8IPS68;T zw@1CGd2imq;((VQYh|#t;k7Nly}glcY;4dk3aYB=2J{zLB=*e8sf)z|5hcyCjGxcX m)OAe=Vf7q|*6#m>s`3W`YuBNY&j;QB0000i+i;`V>`ma;5&EYQ!gj5JN3 zb@txloTDfTM1-;|`!u@AvyS=h)lZ!#Rhlvazv&szJ343hj;J!I6KSF>ubuQAjW@4R3*=I5`fx!MxzmTcXu2f z9+DS1pXcXkwOZ7^W^i(Xt11>27I@ui;p_ULn*=~){6Oyae0+S2bB?*WIlT9H?->jR zf5ZUH;^Lw<8V#zdqN=LD&iOAn=ddxx8xiR^=MWJ>j2M*hr!Y^6-&aLROagFY>$*M= zkec`N N002ovPDHLkV1j;ZBDDYj delta 450 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 N002ovPDHLkV1hM-^Pd0! diff --git a/plugins/wtsynth/saw_inactive.png b/plugins/wtsynth/saw_inactive.png index 40b4abf5e48359aa0fbbf598bcce8df027c14aa3..570dab73fec86eb2c40402bc732c8bad52c1f3f7 100644 GIT binary patch delta 579 zcmV-J0=)gI1BL~VDlq^60002_L%V+f000SaNLh0L01FcU01FcV0GgZ_00007bV*G` z2i^l05D^N&q^oz4TPT0-Nkl714A*=OeS&g z9rSVZ5eCeKNyH~G5p)sO#LQ%N0`>OX{<+;7+!;aKRSQniMOW21bxHvC_V!McQimea z;R{hpA%t*xd3kv(ySuw5#+akU#YL0|<&)1jXT0}JCKH@wU)KDHH`r1fZ1ct1@ArE+uK-c`F(%S_4W1pt)$dqJ^_C~2<=GyexDEmqtS@TWb$7# zy`cc$y=Q-apO=>xhQr~9Zd_Vg;*D-wTU%qLRA+9_CTE1w5}xVu8Zy_SphOWu_+wH^ zXCZ{6rfCQy{D4^000SaNLh0L01FcU01FcV0GgZ_00007bV*G` z2i^k}6Ceym)qf(9TPS}LNkl0+1jX zPi)T?NYS!vc8A};??2z3$?md;^Zjf_ERS^-ouA{DNw%hFh4yBL5W`>9mW29*scDvmhJZex11J5n| zd~+%MmcYzNDIp?7@QZ=F)AxPx*7$Vzb%s zsV4jVKBts8pU)}7Cn?e6@u2HEW&nr7ffyrZ_HlwQ5-|WC;RzcN00000NkvXXu0mjf DV6mQS diff --git a/plugins/wtsynth/sin_active.png b/plugins/wtsynth/sin_active.png index de78b98773a0bb37f5ad5fdf9004452e94a4e093..c3cbffc43fc2c3432af168687b1320ec17e220e8 100644 GIT binary patch delta 667 zcmV;M0%ZNV1>OaaDlq^60002_L%V+f000SaNLh0L01FcU01FcV0GgZ_00007bV*G` z2i^l05EBFxD&+E!TPS}{K~5V%5Jg}0v<-@FDVFhw1&RQB;RUcGD-M!7 zgyV#DZjlS%1Hcvp3oHv^Wh{YZ?3wPa%EHEhq@(}qoboAs`|ZNuhVQaNUCI6hKT&vZxw&4!1K#9Wm#UxU@-XI zYPCAs+uQFR3L@Y{;N5_j66JEqa=B!&STLW@3$Lo3t*tG*_lO7w2M6r$?~`R2_xJZa zJUjqwL?HxHN_g)vvyM|$YPA|7Lciaqo9B$jW9IWYhlhu>+iez$#YSvqh!e6b!_081 zigOO<9KBwjyxV_eG#YVrbwx^vX0u6IR_L0I_nw-s;k^gIn;BV_(eL+}&0ZLf$EYeX zM!fgrc@7vZ%fReEpx!wLK%VD#@0m;{lx0Z>f!S<^nSEI2dody_2T7ITaEORdRTWiL z5kjDjkB{eRF%uiO9b!$Ayf#f$*-@kD_DPPHsXX7BZ#oOyUXi*PEi!3 zlvWV{QcRc`Aq1AoC8~<5a(jEr-rgQDB}9ailM_UQ%i-`Z1MfX4B|-?B>~EPLA0MgL z>ztmRGMyGYJv~tr1u@3I15|aByDZC%HGs)vLbKUqFc{EkwYa;x0Dlz{6{{a7>y{D4^000SaNLh0L01FcU01FcV0GgZ_00007bV*G` z2i^k}6C(zVEye$lTPS}bNkl|PfpuV5XOHqCQcwt6A6$AU570fAh72M^aMy; zf;*HQV$VH@vqPe5*atR%BAPhwy_qiT7^+$t$FFsbxI>JA5CZOo z8;AFi~D!UTC#i z^)uM$cDslO=1xkfX&FGj|DE^u_iDKYd3=22U^GIcvZWyeL=;PgnKgb@m7Sd(dc9uV z%*w`OGGTmt+?;i_TH$V3&90(Nm0PVAhlhvU-rgcAOp1c>c-*`f5p-*7i_K04^UAlZ z{npux$74ITx3{_ab%g>aCntyq%jL3CaeaO5Wm!^|WfR`l-}?U!d}*O7e*rHx`w0Si RjCcS5002ovPDHLkV1j#xAE5vM diff --git a/plugins/wtsynth/sin_inactive.png b/plugins/wtsynth/sin_inactive.png index fc13e59aab8f8dc6a5c6636a6c26ed60715aa985..afa36345d6b89e5e3f881659bc5eae45520d92db 100644 GIT binary patch delta 633 zcmV-<0*3v`1iJ;0Dlq^60002_L%V+f000SaNLh0L01FcU01FcV0GgZ_00007bV*G` z2i^l05D+bWwJ%+fTPJ@4BS}O-R5;6xlfO!1K^VnnrQ)>$KZ#CX)%{@fc$aDJ7(oGXSLb9w7um2sSr2SzcadFc@%g zae;G=#l=Ocs$zdeq?97hbMia~K&6z(vW!lr!*Dp{=H_N@RF-8FMZv5lrGG6}v$YgO zL7wN_-`}IPrmkyVUS0?xkW%_@^Lzs59H*zJ2qCEJn!2tr#!yw&Z07(p8V$PLF5Y{3 zz1{~vjFH;Z2m}D5(FkiSAxyoI0`D9ED=RCE-rgw767PTg9|_($VoVrg&{`8hAjU|) z-)D7o6*n#3-rfeFcXsyK18W`5IkeVTYv-Ep?(WF*oZa1B%Ch9);eoO&anp(B0LGZP z_P-w=A0KHpn{+xIn$0FxS65tKUVbuB?Ck6erIfAN_Y5&2NPL7se71agO(dj{SZjYP z@BN9j_8>ikfOU=(y{D4^000SaNLh0L01FcU01FcV0GgZ_00007bV*G` z2i^k}6CXC%2aK$dTPJ@3u}MThR5;6(k}u9GK@h}$-@FH}Yb!V6}f*(eL*ekH^06oWmG{ z)*7W0#uy%t2SI7MBm>N5GftzS%%j7jp#!!ADhjFe!uU@)>`WII;Yc# zq9}a-Uw8qnHQj%1*RM_~MW@r@d_I4Wr_ukTUI7 zt3|C=dlOhLmkfu)r$88nIOiye0%Hs!;%BZ_s|*GM=JQJVS293gjPWOGjQI#@I2_V! zHi@Fh*RS~5?RHLU&E<0O_J4yUNyxH{D!_ifC(m=Nwfrys0DDeGEMrVXI{*Lx07*qo IM6N<$f=veL`v3p{ diff --git a/plugins/wtsynth/smooth_active.png b/plugins/wtsynth/smooth_active.png index 7da2cef11d691085ef02f8e1e8265879afce2b58..e23abe245ae09245abe1230dc03462a406807fd0 100644 GIT binary patch delta 643 zcmV-}0(||A1;quBDlq^60002_L%V+f000SaNLh0L01FcU01FcV0GgZ_00007bV*G` z2i^l05EKK&59gMVTPJ@4ElET{R5;6JlD$r2Nf3p<>TY9$LAGT!Az(*>fB*uLCFL>p z9d;gPi1#fvBA*RNED;b75+d-RHP*%V-s-N};MyLTDXD*|e@>q|rv>2R;^IpwD9%^Yb&`zCDss1fbvVb9Hsa z(a{mJ*{suG;|!1hR9m_f-rn9&Roo17V|Q;4E2XnB=k9-DK-SC?K*v>8kQA$BoX_|)7Xw0Wizq4E}d3bmr=S;~33G&0n_ad4ZZQIheEltx< z*DLl9_L)p393LOAe_&?$-*W8;9{}X!V z9vy{D4^000SaNLh0L01FcU01FcV0GgZ_00007bV*G` z2i^k}6C*OLnK4R{TPJ@3^+`lQR5;6RlEF?JK@db=^$dftEdmFSoI7yGNyI;J@+a{h z`~o>}>%A=S)h8 z5CSPBoO5h#ZBf@XP1CTk(ZSCfVvGz117eJX5OB`noWso8a?XDMk#j~8udlE8oHHQ= zc6N4R+uK`&5U8q(v$O9lnD?Heqa*hA_S*X<;pce+q?G9Q`;0~-o}QlCysxi+ zaex1Zo0}W<_xESyWheYRzWLTor&G*~-Q8V4n2Ec)JAi){u=JEse6QC-5-De5jP0el zVI`S`>x(Mqemb2Z87UUWR~j`l*0i!v<*dB@+uIvCC(?}l;qL>NKP~|{K0YRdK+`lU zz{|1wZnw)ur$bd$NMiHTW}CwK`FWdybB@o0LEAi;Op1!r)6-nnHFaHourPcuyH=F^ Z2M%4!$B_>LHoO1;002ovPDHLkV1kvM4}Aat diff --git a/plugins/wtsynth/smooth_inactive.png b/plugins/wtsynth/smooth_inactive.png index 791f48fedb15d18814c8fdc963ff82db54388d22..7f9511427d1c18b58edee395565dbd3dbd614da9 100644 GIT binary patch delta 582 zcmV-M0=fOS1c?QZDlq^60002_L%V+f000SaNLh0L01FcU01FcV0GgZ_00007bV*G` z2i^l05D_Nxe8-fLTPT0=Nkl2J5J-%#_%ZklvVJb`G`ET|Jz+f;qGsYZ?i02zsYbC~b zesgnkDu;)MXU@5kwY4>j2=$BMQVJmiUSD5nn $DK|GYwdrR%&N+CI%P7M5M!ii znq!x9_RhH_K(E(he}5n69JT(@^Yrw@<>e)9+mcdR^u5bDW35F*u-4+eXMKI0mzNi= zudgx2u)DjvWUaMgjKLT~treG2LPQV|YOPpnan9kKTgc?<>IzlG7=ws>vgH;-#+Xk* zO{Y^r2uoIL?I(XrOMu0*)LIb{Mxzn$@9%WGU5<{9NGXwX=JD~7ySuwpfLbf63V?_( z91eMScvyzm>2x?aIAD8wo7>yl6&0?OLK|9ynYWLR4`PVqoXDlH@neHDCs0*b0L-&+ z07;cnDj@`#rXlA{DTP@tp()MIDXl61h*42hnx?^f&(43&4sUO7+~41$s!NNi`fq>` z0&UyUwk?y%gw4%Oy!Z6`eP#ra@pw#(aV13A+uIu%WBlTy}UBnnqa?V6m>fHPP$~i~W2ykJapPzqjZEf{pjQv_l_dDx65BPjI9G?CL0D(dm U5krVm000UA07*qoM6N<$g38?r@c;k- delta 499 zcmVy{D4^000SaNLh0L01FcU01FcV0GgZ_00007bV*G` z2i^k}6CoKg6RL=jTPS~@NkloL~u=%=`q{_}T9>L90Eu=^il^KGm&Tw_aIM6d9gi+cp4NYXFo|c%FyW8m%>s z;~<1U2myd=+crum&gV1lKx>VZ5@QUP%LP|!T^T+ekId(DZnu9M#{4zsI1asDkHKJo z5CSPB_xt_R!877G=6byXFr7}R)oQF(D>j=AyWNg7O;Jh#kftf_cZ<(k8;u5@=P??M z==b{+MS)VP!f}7Q)fj`660J2^mQfVN%Yt78j4>EvNRk9&3`J4kx-OPwy>MRy+U+*= zdYvRmn9XM8M#q0~7!HSYyWI-kilWGzPN(wWE8YEmPnKl>tk-M8Fr?GzFquqB?%{B# zI#5cH=Q&zyTCG-jP7nl@a#f1=T#%wD{u$U$u!Rs9V^B(!1^Ei`9k`z7l}Sq}3B!=( zatXkAJjVC^($S9sQc9$hd`~ldLAYsPJbf5qL002ovPDHLkV1h5+;LZR5 diff --git a/plugins/wtsynth/sqr_active.png b/plugins/wtsynth/sqr_active.png index 11ade0c8318fb83ce1f88034809a9eab7d38946c..444bcead25b968266ad512f4659e7611edfc50ab 100644 GIT binary patch delta 621 zcmV-z0+RjX1g`~gnB;%nC_%a}9_WK|Kk11i?4R zJ0y=2&v^^q!%GA&3X+_Xg#?|Qp6;s3p=SpZ3mT@or~drDUkkwL>FF0${RpfWLqu@* z=^G$~K#UPH1Gv1tzWyvHCnsOb?9+TcXW6!>8BNn5A}`i1@{oV|{pU9+rAs+FI{LZ4 zzrWhs+k5t-AOb-Io)svnq`s%`d$!vxPft(3qM5B0iv{QB=R7_>A|iwk5D}KkC3p9C z+~3_#NjYa!l^7%LzKUkXY&Ii=K-YDA|M8=C2F}jTSifC!^X-Pd@5wpi?nn><0e2^w z86gCkrXi()ZP$MhLa17ErrUO;G+-l}|0B9PP17)&&4{tWGc!slY&IK8DS#822Hal& zjk|8U3soiOOwM^s<{vwsCnG{|chrolt1E7AZzovW?Us}h^ZA@o3aUyeg@c0wE-o%m zRRoAt>wr)zcU@OujWUWBv=kUSYbls2s#+z~L&e?6In#glJ!XcPp=y{KMRgio$9>MZ z7KkxUx>HJ%RrRvL-D%r)VzAg-Omcu~<1h>i!$3-D8Vz6=2HLje`1rU2L|E=GtF*Cz z93CG2Y}-GA5DdmHzGK}!d9COFq>N3aOCN?1i za?Xgz*Jd%Z*<8JO{pMZH`Ow{8{r}Rc_y3;NDdqCv;ojB delta 544 zcmV+*0^j|w1>*#eDlz{6{{a7>y{D4^000SaNLh0L01FcU01FcV0GgZ_00007bV*G` z2i^k}6C)sBAV30b1rO`+*n4IfNqw%K;Dwi4Xw^ z@I(|&>HL6^IBf6EPv67rEIwGNrPcgYS5?>O>FLS2_#^>fX1F`06ha7;Qs}ylo0}W@ zz9*%`)zyMoyO48cyQu2S&xbVg1^EuXy$Yw}38kYF@_{%U1Q@2+8{U1OeVeXEpy55=L zUPvj8hBuatS3r?p~)u*omtJR9b;lOUU8|VHd;e0+<7B4R^-uFFy i-~TZ0`}ltPV*CR|2Gt!`ygBUv0000b_J1AqmPDlq^60002_L%V+f000SaNLh0L01FcU01FcV0GgZ_00007bV*G` z2i^l05D^he!D5?{TPT0%NklA2`hl* zKum^M!DMWJyfXr_PG(wyrt4L?KAzz9dqax=ELC9H_u9T?8-Vlk^BZgJg)wHzH%wI# zk=w_|$7^$Tc6Q^vzuMZ`!Wx5q0dB34Qev@K5JI^1z{O-T!8w2TW#ybRUDvT%tq>7H z2p7KAI`!Ujd3niVvDg6Y?(Q<1&6v$*gb;Xte<#LBDFyF6syg+xR-AJfV|aai<@xz} zBse`i<>26er>7@Ys}(6FR26G2)>>2*UrNCkgE58>0&j0`7-IlPDY0BG>AH@gkhONB zORuUp=kVT-It+h8&F6DOgds=uv&4S*mLXV5A*Do&aRh&ieL&#z>5j zloDOnvA4H}h>U>4!$Xdaj<~H$PDIcGu$8*_g<=V-05v$Hc2OePa@&YJ{- zXfehy01#tjdwZMXy{D4^000SaNLh0L01FcU01FcV0GgZ_00007bV*G` z2i^k}6CfB|53661TPS~GNklo;24|%aR?Hw!6CQ;F$W?c zLJ$CwErGGSyQ*t~k$Yen@6P_v?f?4sulhI~4#tzRECV3M2!N`R=Q%M(VvO{9J)Cnm z=K$zuS%#`o6a~Lgj1dvR%qYu}evFZ#C|E9+jK|}bpU>wrv)O-)`FxIO}elNZ2XFd)k^nx;u+GsEn=wyf)| zX2x_nC4@j-*Ld&W%$)!;LscoulB%i*A*AmB$K&zu09C~~M+kw_>GWa-Sg+ULfOg)k zLD4iM1&Y)GPiv^xBdnYk+h;B@^UyF4!K^hY`5D^z{hU4Gw(f@%O%DCjjF1muIsN= f-tYHmZ2zlIIdUg`bEU?N00000NkvXXu0mjfq3*~D diff --git a/plugins/wtsynth/tri_active.png b/plugins/wtsynth/tri_active.png index c28c75e4a51c6bb4c9ceb2581674bafe79ac5b0b..690d1ebde8036da8682705cff3d1940d4b37c55f 100644 GIT binary patch delta 672 zcmV;R0$=@)1>yyeDlq^60002_L%V+f000SaNLh0L01FcU01FcV0GgZ_00007bV*G` z2i^l05EByM{!ycmTPJ@4N=ZaPR5;6JlTA(=K@f$%>S@Esj!lpq7Jv*0S#~5)SY^dQ za))pnSmzcwK{x;+U<)K92MHGZ2+W^ny1P1yu}3&5saoBwSFfsHRSUrO_V#`V;TzCo zVj@C}vD^a~W3bkussIN^M@M_IwY9acs^914=J-&n5mZT%1QCDv&!^^c$K&XcEXxk0 z*X!NZ>-A=urtg4)2pAD~N8m#s8;==}$GpA0@$&L=XH~U1KR=JPw#+gO*xlVljBxnt zuncm}5kkOPON_B;RFz7lf{2hL3D#PywRAci(ln)FD=aTBm%%Yc#1z;VBSuv*#$b#A zC`mr|dR$ywaCU!o#@gB%I?={jOT|{O))vCX7-uqz2pbz4jGmsjzP{$_>WVBI)9rRK z#>`+RoiV((YPH7F(h}$A=iJ=f@bK`!aQKIIyUoJF!b~?1DJlr6c<=Gv(`eLDjhvjE zkmothIR=9P)>@j)CeAs$_k<7-zyLT`0Mj(3)oStk_!xhe=Qx++gC}^;pxko?Cjt}fd??wT0#hgaHA2!;jrv= z2%#+3d(Ut<7Zn&Dk4Axm?$nF#ZsP)7@Tu=NvqXrd+)!75XhY)s-hav7}2POYa~WRwQyq$ z&N)QnM{<9E|8w!<;wR_aW{k1QKUVyU*}I}jIk>#M-1`fh)ofS9?sZ)N0000y{D4^000SaNLh0L01FcU01FcV0GgZ_00007bV*G` z2i^k}6C)4w@qJs7TPJ@3_en%SR5;6JlU-8kKoCYxcdUSN9~878Z)%(UU@-X8WD$`jmdhm~!t?Vp&Xts9iCMq`hziHziwl5$zt$I|z?u+2RoQGdJUu<}`1r_bwZfII1x>5+_XVl|>~=fS zG-W!SvfuApCQ^T8K6BAtuZKo;{i=v4Z*Om8S;lZUWHcI)rYU)zclcB~5JAlhmAXx; zm<4vb9n!>QY&PTb^RtyLTK@&@_S?*OeSPKr{+`?0TU4uTwtA>2$&@uwJdmvW#Ssd~>8W1{0Db;o;$d z&1TcCUtL{s+3%D8&AGW5Rxax(XdY5+ve9Tnp648o$4bRwv9O{jD2jp*!Vkmn?QQ%F bRpmc}5xEh_s^^M>00000NkvXXu0mjf)r}Mk diff --git a/plugins/wtsynth/tri_inactive.png b/plugins/wtsynth/tri_inactive.png index 97814a5f7b63ec452299f9248716b8b52c95c448..1e8f13c5c0f960e06e012eea84f4b7fe8d5235c9 100644 GIT binary patch delta 633 zcmV-<0*3vR1iJ;0Dlq^60002_L%V+f000SaNLh0L01FcU01FcV0GgZ_00007bV*G` z2i^l05D@?&aYAX4TPJ@4BS}O-R5;6xlg}<>K^Vn#MrAX3=gNnVC?@SyZLIbIy0FJ_WG5yL+Uy z-d9T1_`(VyAR@v4B?$Nl|1X_~UJu`#??0zj9~62c(=YPHJz{5+jb zhsVc9o}Zt&xw)ZUuQNS8{Z~#pgn)AnYc1AVrlzLw-g9wrL6&8R2(4BNV+^yivpDC5 z0MJEI(6@c8wTz98F*i5I`OkA~e{d#F@Xpa{Hd$O;q&j~wfp-q?{d)`k&B6NmIxjCT zTsAMUB6#od&f~nN-RY2J8IA32ocHez07M)sD=T!nU9PXM5s?p8OWfYxk|YUhYil0~ zthFpGEHFMkPP5tkFG0KAW^!_pdc8g*P>n|8m)5#ge$TupPy_};p*}|bwhaWd(uhdc zc<)a{t9X6BoSd=EuY`N}vK1Cis0hlj)8V0v2} TdUv@i00000NkvXXu0mjfaXBE4 delta 465 zcmV;?0WSW#1(XDkDlz{6{{a7>y{D4^000SaNLh0L01FcU01FcV0GgZ_00007bV*G` z2i^k}6CeZDYGSjITPJ@3d`Uz>R5;6(lRJ*$Koms}25+E+Wyvf6e-N8sO{{{&7zjHYN5_|Vo(F)n764-mzVBnL#ac_h z-$zP`loEh}=Xn@oxLhv$Ce~WC);Q<5Uat(SwVm){u>fE`pW}a=Lu-vv3MnO8Ywq{^ zr$JY4w_8(HDMeLP)OC$927u@DN$+$zxw0&O!0Yw8>4Dao*=$B#*Er{J?z3%WS<+cv z2*G4BAxRR15GbX-!A;ZK;MHoybUGyrLxLb6j$?|V_yKobAcP=ElIG1>ma*IIT1~z8 zf4`IGIa!tw1Ob0_T>}tB5owyT*=+u9V2nWs!FW7w;J0>~rmYs<*8$1%oH&jN!|)pn zFdB_oEj%eD&bg*~9LKHQ?y~TF-^V$}a=9c;Q=%wpg}W>~tu Date: Mon, 24 Mar 2014 02:01:16 +0200 Subject: [PATCH 085/647] Add crosstalk knob, some code changes --- data/themes/default/style.css | 10 ++ plugins/wtsynth/WTSynth.cpp | 232 ++++++++++++++++------------------ plugins/wtsynth/WTSynth.h | 80 +++++++----- plugins/wtsynth/artwork.png | Bin 95662 -> 97631 bytes 4 files changed, 168 insertions(+), 154 deletions(-) diff --git a/data/themes/default/style.css b/data/themes/default/style.css index c2e91bd05..7d41a8f07 100644 --- a/data/themes/default/style.css +++ b/data/themes/default/style.css @@ -648,6 +648,16 @@ WTSynthView knob#mixenvKnob { qproperty-lineWidth: 2; } +WTSynthView knob#xtalkKnob { + color: #fb50fb; + qproperty-outerColor: #fb50fb; + qproperty-innerRadius: 1; + qproperty-outerRadius: 7; + qproperty-centerPointX: 9.5; + qproperty-centerPointY: 9.5; + qproperty-lineWidth: 2; +} + /* palette information - each colour definition must be on a single line, and the line must begin with "palette:", with no leading whitespace * colour codes MUST be of the form #RRGGBB */ diff --git a/plugins/wtsynth/WTSynth.cpp b/plugins/wtsynth/WTSynth.cpp index 54e4580f1..bbbb2bcf9 100644 --- a/plugins/wtsynth/WTSynth.cpp +++ b/plugins/wtsynth/WTSynth.cpp @@ -54,6 +54,17 @@ Plugin::Descriptor PLUGIN_EXPORT wtsynth_plugin_descriptor = } +// these need to be here + +float WTSynthObject::s_lvol [NUM_OSCS]; +float WTSynthObject::s_rvol [NUM_OSCS]; +float WTSynthObject::s_mult [NUM_OSCS]; +float WTSynthObject::s_ltune [NUM_OSCS]; +float WTSynthObject::s_rtune [NUM_OSCS]; +float WTSynthObject::s_xtalk; + + + WTSynthObject::WTSynthObject( float * _A1wave, float * _A2wave, float * _B1wave, float * _B2wave, int _amod, int _bmod, const sample_rate_t _samplerate, NotePlayHandle * _nph, fpp_t _frames ) : @@ -94,6 +105,13 @@ WTSynthObject::~WTSynthObject() void WTSynthObject::renderOutput( fpp_t _frames ) { + // calculate frequencies + for( int i = 0; i < NUM_OSCS; i++ ) + { + m_lfreq[i] = ( s_mult[i] / 8 ) * powf( 2, s_ltune[i] / 1200 ); + m_rfreq[i] = ( s_mult[i] / 8 ) * powf( 2, s_rtune[i] / 1200 ); + } + if( m_abuf == NULL ) m_abuf = new sampleFrame[m_fpp]; if( m_bbuf == NULL ) @@ -101,38 +119,21 @@ void WTSynthObject::renderOutput( fpp_t _frames ) for( fpp_t frame = 0; frame < _frames; frame++ ) { - float frac; - - // A2 - frac = fraction( m_lphase[A2_OSC] ); - sample_t A2_L = - ( m_A2wave[ static_cast( m_lphase[A2_OSC] ) % WAVELEN ] * ( 1.0f - frac ) ) + - ( m_A2wave[ static_cast( m_lphase[A2_OSC] + 1 ) % WAVELEN ] * frac ); - A2_L *= m_lvol[A2_OSC]; - frac = fraction( m_rphase[A2_OSC] ); - sample_t A2_R = - ( m_A2wave[ static_cast( m_rphase[A2_OSC] ) % WAVELEN ] * ( 1.0f - frac ) ) + - ( m_A2wave[ static_cast( m_rphase[A2_OSC] + 1 ) % WAVELEN ] * frac ); - A2_R *= m_rvol[A2_OSC]; - - // B2 - frac = fraction( m_lphase[B2_OSC] ); - sample_t B2_L = - ( m_B2wave[ static_cast( m_lphase[B2_OSC] ) % WAVELEN ] * ( 1.0f - frac ) ) + - ( m_B2wave[ static_cast( m_lphase[B2_OSC] + 1 ) % WAVELEN ] * frac ); - B2_L *= m_lvol[B2_OSC]; - frac = fraction( m_rphase[B2_OSC] ); - sample_t B2_R = - ( m_B2wave[ static_cast( m_rphase[B2_OSC] ) % WAVELEN ] * ( 1.0f - frac ) ) + - ( m_B2wave[ static_cast( m_rphase[B2_OSC] + 1 ) % WAVELEN ] * frac ); - B2_R *= m_rvol[B2_OSC]; - // put phases of 1-series oscs into variables because phase modulation might happen float A1_lphase = m_lphase[A1_OSC]; float A1_rphase = m_rphase[A1_OSC]; float B1_lphase = m_lphase[B1_OSC]; float B1_rphase = m_rphase[B1_OSC]; + ///////////// A-series ///////////////// + + // A2 + sample_t A2_L = interpolate( m_A2wave[ static_cast( m_lphase[A2_OSC] ) % WAVELEN ], + m_A2wave[ static_cast( m_lphase[A2_OSC] + 1 ) % WAVELEN ], + fraction( m_lphase[A2_OSC] ) ) * s_lvol[A2_OSC]; + sample_t A2_R = interpolate( m_A2wave[ static_cast( m_rphase[A2_OSC] ) % WAVELEN ], + m_A2wave[ static_cast( m_rphase[A2_OSC] + 1 ) % WAVELEN ], + fraction( m_rphase[A2_OSC] ) ) * s_rvol[A2_OSC]; // if phase mod, add to phases if( m_amod == MOD_PM ) { @@ -141,6 +142,32 @@ void WTSynthObject::renderOutput( fpp_t _frames ) A1_rphase = fmodf( A1_rphase + A2_R * PMOD_AMT, WAVELEN ); while( A1_rphase < 0 ) A1_rphase += WAVELEN; } + // A1 + sample_t A1_L = interpolate( m_A1wave[ static_cast( A1_lphase ) % WAVELEN ], + m_A1wave[ static_cast( A1_lphase + 1 ) % WAVELEN ], + fraction( A1_lphase ) ) * s_lvol[A1_OSC]; + sample_t A1_R = interpolate( m_A1wave[ static_cast( A1_rphase ) % WAVELEN ], + m_A1wave[ static_cast( A1_rphase + 1 ) % WAVELEN ], + fraction( A1_rphase ) ) * s_rvol[A1_OSC]; + + ///////////// B-series ///////////////// + + // B2 + sample_t B2_L = interpolate( m_B2wave[ static_cast( m_lphase[B2_OSC] ) % WAVELEN ], + m_B2wave[ static_cast( m_lphase[B2_OSC] + 1 ) % WAVELEN ], + fraction( m_lphase[B2_OSC] ) ) * s_lvol[B2_OSC]; + sample_t B2_R = interpolate( m_B2wave[ static_cast( m_rphase[B2_OSC] ) % WAVELEN ], + m_B2wave[ static_cast( m_rphase[B2_OSC] + 1 ) % WAVELEN ], + fraction( m_rphase[B2_OSC] ) ) * s_rvol[B2_OSC]; + + // if crosstalk active, add a1 + if( s_xtalk > 0.0 ) + { + B2_L += ( A1_L * s_xtalk ) / 100.0f; + B2_R += ( A1_R * s_xtalk ) / 100.0f; + } + + // if phase mod, add to phases if( m_bmod == MOD_PM ) { B1_lphase = fmodf( B1_lphase + B2_L * PMOD_AMT, WAVELEN ); @@ -148,30 +175,14 @@ void WTSynthObject::renderOutput( fpp_t _frames ) B1_rphase = fmodf( B1_rphase + B2_R * PMOD_AMT, WAVELEN ); while( B1_rphase < 0 ) B1_rphase += WAVELEN; } - - // A1 - frac = fraction( A1_lphase ); - sample_t A1_L = - ( m_A1wave[ static_cast( A1_lphase ) % WAVELEN ] * ( 1.0f - frac ) ) + - ( m_A1wave[ static_cast( A1_lphase + 1 ) % WAVELEN ] * frac ); - A1_L *= m_lvol[A1_OSC]; - frac = fraction( A1_rphase ); - sample_t A1_R = - ( m_A1wave[ static_cast( A1_rphase ) % WAVELEN ] * ( 1.0f - frac ) ) + - ( m_A1wave[ static_cast( A1_rphase + 1 ) % WAVELEN ] * frac ); - A1_R *= m_rvol[A1_OSC]; - // B1 - frac = fraction( B1_lphase ); - sample_t B1_L = - ( m_B1wave[ static_cast( B1_lphase ) % WAVELEN ] * ( 1.0f - frac ) ) + - ( m_B1wave[ static_cast( B1_lphase + 1 ) % WAVELEN ] * frac ); - B1_L *= m_lvol[B1_OSC]; - frac = fraction( B1_rphase ); - sample_t B1_R = - ( m_B1wave[ static_cast( B1_rphase ) % WAVELEN ] * ( 1.0f - frac ) ) + - ( m_B1wave[ static_cast( B1_rphase + 1 ) % WAVELEN ] * frac ); - B1_R *= m_rvol[B1_OSC]; + sample_t B1_L = interpolate( m_B1wave[ static_cast( B1_lphase ) % WAVELEN ], + m_B1wave[ static_cast( B1_lphase + 1 ) % WAVELEN ], + fraction( B1_lphase ) ) * s_lvol[B1_OSC]; + sample_t B1_R = interpolate( m_B1wave[ static_cast( B1_rphase ) % WAVELEN ], + m_B1wave[ static_cast( B1_rphase + 1 ) % WAVELEN ], + fraction( B1_rphase ) ) * s_rvol[B1_OSC]; + // A-series modulation) switch( m_amod ) @@ -224,40 +235,27 @@ void WTSynthObject::renderOutput( fpp_t _frames ) } -void WTSynthObject::updateFrequencies() -{ - // calculate frequencies - for( int i = 0; i < NUM_OSCS; i++ ) - { - m_lfreq[i] = ( m_mult[i] / 8 ) * powf( 2, m_ltune[i] / 1200 ); - m_rfreq[i] = ( m_mult[i] / 8 ) * powf( 2, m_rtune[i] / 1200 ); - } -} - - - void WTSynthObject::changeVolume( int _osc, float _lvol, float _rvol ) { - m_lvol[_osc] = _lvol / 100.0; - m_rvol[_osc] = _rvol / 100.0; + WTSynthObject::s_lvol[_osc] = _lvol / 100.0; + WTSynthObject::s_rvol[_osc] = _rvol / 100.0; // qDebug( "osc %d vol %f %f", _osc, m_lvol[_osc], m_rvol[_osc] ); } void WTSynthObject::changeMult( int _osc, float _mul ) { - m_mult[_osc] = _mul; + s_mult[_osc] = _mul; } void WTSynthObject::changeTune( int _osc, float _ltune, float _rtune ) { - m_ltune[_osc] = _ltune; - m_rtune[_osc] = _rtune; + s_ltune[_osc] = _ltune; + s_rtune[_osc] = _rtune; } - WTSynthInstrument::WTSynthInstrument( InstrumentTrack * _instrument_track ) : Instrument( _instrument_track, &wtsynth_plugin_descriptor ), @@ -293,11 +291,13 @@ WTSynthInstrument::WTSynthInstrument( InstrumentTrack * _instrument_track ) : m_abmix( 0.0f, -100.0f, 100.0f, 0.1f, this, tr( "A-B Mix" ) ), m_envAmt( 0.0f, -200.0f, 200.0f, 1.0f, this, tr( "A-B Mix envelope amount" ) ), - + m_envAtt( 0.0f, 0.0f, 2000.0f, 1.0f, 2000.0f, this, tr( "A-B Mix envelope attack" ) ), m_envHold( 0.0f, 0.0f, 2000.0f, 1.0f, 2000.0f, this, tr( "A-B Mix envelope hold" ) ), m_envDec( 0.0f, 0.0f, 2000.0f, 1.0f, 2000.0f, this, tr( "A-B Mix envelope decay" ) ), + m_xtalk( 0.0f, 0.0f, 100.0f, 0.1f, this, tr( "A1-B2 Crosstalk" ) ), + m_amod( 0, 0, 3, this, tr( "A2-A1 modulation" ) ), m_bmod( 0, 0, 3, this, tr( "B2-B1 modulation" ) ), @@ -328,10 +328,17 @@ WTSynthInstrument::WTSynthInstrument( InstrumentTrack * _instrument_track ) : connect( &b1_rtune, SIGNAL( dataChanged() ), this, SLOT( updateTunes() ) ); connect( &b2_rtune, SIGNAL( dataChanged() ), this, SLOT( updateTunes() ) ); + connect( &m_xtalk, SIGNAL( dataChanged() ), this, SLOT( updateXtalk() ) ); + a1_graph.setWaveToSine(); a2_graph.setWaveToSine(); b1_graph.setWaveToSine(); b2_graph.setWaveToSine(); + + updateMult(); + updateTunes(); + updateVolumes(); + updateXtalk(); } @@ -353,23 +360,6 @@ void WTSynthInstrument::playNote( NotePlayHandle * _n, engine::mixer()->processingSampleRate(), _n, engine::mixer()->framesPerPeriod() ); - w -> changeMult( A1_OSC, a1_mult.value() ); - w -> changeMult( A2_OSC, a2_mult.value() ); - w -> changeMult( B1_OSC, b1_mult.value() ); - w -> changeMult( B2_OSC, b2_mult.value() ); - - w -> changeTune( A1_OSC, a1_ltune.value(), a1_rtune.value() ); - w -> changeTune( A2_OSC, a2_ltune.value(), a2_rtune.value() ); - w -> changeTune( B1_OSC, b1_ltune.value(), b1_rtune.value() ); - w -> changeTune( B2_OSC, b2_ltune.value(), b2_rtune.value() ); - - w -> changeVolume( A1_OSC, leftCh( a1_vol.value(), a1_pan.value() ), rightCh( a1_vol.value(), a1_pan.value() ) ); - w -> changeVolume( A2_OSC, leftCh( a2_vol.value(), a2_pan.value() ), rightCh( a2_vol.value(), a2_pan.value() ) ); - w -> changeVolume( B1_OSC, leftCh( b1_vol.value(), b1_pan.value() ), rightCh( b1_vol.value(), b1_pan.value() ) ); - w -> changeVolume( B2_OSC, leftCh( b2_vol.value(), b2_pan.value() ), rightCh( b2_vol.value(), b2_pan.value() ) ); - - w -> updateFrequencies(); - _n->m_pluginData = w; } @@ -377,35 +367,6 @@ void WTSynthInstrument::playNote( NotePlayHandle * _n, WTSynthObject * w = static_cast( _n->m_pluginData ); - // update oscs if needed - - if( m_volChanged ) - { - w-> changeVolume( A1_OSC, leftCh( a1_vol.value(), a1_pan.value() ), rightCh( a1_vol.value(), a1_pan.value() ) ); - w-> changeVolume( A2_OSC, leftCh( a2_vol.value(), a2_pan.value() ), rightCh( a2_vol.value(), a2_pan.value() ) ); - w-> changeVolume( B1_OSC, leftCh( b1_vol.value(), b1_pan.value() ), rightCh( b1_vol.value(), b1_pan.value() ) ); - w-> changeVolume( B2_OSC, leftCh( b2_vol.value(), b2_pan.value() ), rightCh( b2_vol.value(), b2_pan.value() ) ); - m_volChanged = false; - } - if( m_tuneChanged ) - { - w-> changeTune( A1_OSC, a1_ltune.value(), a1_rtune.value() ); - w-> changeTune( A2_OSC, a2_ltune.value(), a2_rtune.value() ); - w-> changeTune( B1_OSC, b1_ltune.value(), b1_rtune.value() ); - w-> changeTune( B2_OSC, b2_ltune.value(), b2_rtune.value() ); - w-> updateFrequencies(); - m_tuneChanged = false; - } - if( m_multChanged ) - { - w-> changeMult( A1_OSC, a1_mult.value() ); - w-> changeMult( A2_OSC, a2_mult.value() ); - w-> changeMult( B1_OSC, b1_mult.value() ); - w-> changeMult( B2_OSC, b2_mult.value() ); - w-> updateFrequencies(); - m_multChanged = false; - } - sampleFrame * abuf = w->abuf(); sampleFrame * bbuf = w->bbuf(); @@ -453,7 +414,7 @@ void WTSynthInstrument::playNote( NotePlayHandle * _n, ( bbuf[f][1] * bmix ); } } - + // if sample-exact is not enabled, use simpler calculations: // if mix envelope is active, and we haven't gone past the envelope end, use envelope-aware calculation... else if( envAmt != 0.0f && tfp_ < envLen ) @@ -487,7 +448,7 @@ void WTSynthInstrument::playNote( NotePlayHandle * _n, _working_buffer[f][1] = ( abuf[f][1] * amix ) + ( bbuf[f][1] * bmix ); } - } + } // ... mix envelope is inactive or we've past the end of envelope, so use a faster calculation to save cpu else @@ -563,6 +524,8 @@ void WTSynthInstrument::saveSettings( QDomDocument & _doc, m_envHold.saveSettings( _doc, _this, "envHold" ); m_envDec.saveSettings( _doc, _this, "envDec" ); + m_xtalk.saveSettings( _doc, _this, "xtalk" ); + m_amod.saveSettings( _doc, _this, "amod" ); m_bmod.saveSettings( _doc, _this, "bmod" ); m_selectedGraph.saveSettings( _doc, _this, "selgraph" ); @@ -618,6 +581,8 @@ void WTSynthInstrument::loadSettings( const QDomElement & _this ) m_envHold.loadSettings( _this, "envHold" ); m_envDec.loadSettings( _this, "envDec" ); + m_xtalk.loadSettings( _this, "xtalk" ); + m_amod.loadSettings( _this, "amod" ); m_bmod.loadSettings( _this, "bmod" ); m_selectedGraph.loadSettings( _this, "selgraph" ); @@ -638,16 +603,30 @@ PluginView * WTSynthInstrument::instantiateView( QWidget * _parent ) void WTSynthInstrument::updateVolumes() { - m_volChanged = true; + WTSynthObject::changeVolume( A1_OSC, leftCh( a1_vol.value(), a1_pan.value() ), rightCh( a1_vol.value(), a1_pan.value() ) ); + WTSynthObject::changeVolume( A2_OSC, leftCh( a2_vol.value(), a2_pan.value() ), rightCh( a2_vol.value(), a2_pan.value() ) ); + WTSynthObject::changeVolume( B1_OSC, leftCh( b1_vol.value(), b1_pan.value() ), rightCh( b1_vol.value(), b1_pan.value() ) ); + WTSynthObject::changeVolume( B2_OSC, leftCh( b2_vol.value(), b2_pan.value() ), rightCh( b2_vol.value(), b2_pan.value() ) ); } void WTSynthInstrument::updateMult() { - m_multChanged = true; + WTSynthObject::changeMult( A1_OSC, a1_mult.value() ); + WTSynthObject::changeMult( A2_OSC, a2_mult.value() ); + WTSynthObject::changeMult( B1_OSC, b1_mult.value() ); + WTSynthObject::changeMult( B2_OSC, b2_mult.value() ); } void WTSynthInstrument::updateTunes() { - m_tuneChanged = true; + WTSynthObject::changeTune( A1_OSC, a1_ltune.value(), a1_rtune.value() ); + WTSynthObject::changeTune( A2_OSC, a2_ltune.value(), a2_rtune.value() ); + WTSynthObject::changeTune( B1_OSC, b1_ltune.value(), b1_rtune.value() ); + WTSynthObject::changeTune( B2_OSC, b2_ltune.value(), b2_rtune.value() ); } +void WTSynthInstrument::updateXtalk() +{ + WTSynthObject::changeXtalk( m_xtalk.value() ); +} + WTSynthView::WTSynthView( Instrument * _instrument, @@ -690,11 +669,13 @@ WTSynthView::WTSynthView( Instrument * _instrument, makeknob( m_abmixKnob, 4, 3, "A-B Mix", "", "mixKnob" ) makeknob( m_envAmtKnob, 88, 3, "Mix envelope amount", "", "mixenvKnob" ) - + maketsknob( m_envAttKnob, 88, A1ROW, "Mix envelope attack", " ms", "mixenvKnob" ) maketsknob( m_envHoldKnob, 88, A2ROW, "Mix envelope hold", " ms", "mixenvKnob" ) maketsknob( m_envDecKnob, 88, B1ROW, "Mix envelope decay", " ms", "mixenvKnob" ) + makeknob( m_xtalkKnob, 88, B2ROW, "Crosstalk", "", "xtalkKnob" ) + // let's set volume knobs a1_volKnob -> setVolumeKnob( true ); a2_volKnob -> setVolumeKnob( true ); @@ -839,19 +820,19 @@ WTSynthView::WTSynthView( Instrument * _instrument, // waveform modifications m_loadButton = new pixmapButton( this, tr( "Load waveform" ) ); - m_loadButton -> move ( 176, 121 ); + m_loadButton -> move ( 173, 121 ); m_loadButton -> setActiveGraphic( PLUGIN_NAME::getIconPixmap( "load_active" ) ); m_loadButton -> setInactiveGraphic( PLUGIN_NAME::getIconPixmap( "load_inactive" ) ); toolTip::add( m_loadButton, tr( "Click to load a waveform from a sample file" ) ); m_phaseLeftButton = new pixmapButton( this, tr( "Phase left" ) ); - m_phaseLeftButton -> move ( 196, 121 ); + m_phaseLeftButton -> move ( 193, 121 ); m_phaseLeftButton -> setActiveGraphic( PLUGIN_NAME::getIconPixmap( "phl_active" ) ); m_phaseLeftButton -> setInactiveGraphic( PLUGIN_NAME::getIconPixmap( "phl_inactive" ) ); toolTip::add( m_phaseLeftButton, tr( "Click to shift phase by -15 degrees" ) ); m_phaseRightButton = new pixmapButton( this, tr( "Phase right" ) ); - m_phaseRightButton -> move ( 213, 121 ); + m_phaseRightButton -> move ( 210, 121 ); m_phaseRightButton -> setActiveGraphic( PLUGIN_NAME::getIconPixmap( "phr_active" ) ); m_phaseRightButton -> setInactiveGraphic( PLUGIN_NAME::getIconPixmap( "phr_inactive" ) ); toolTip::add( m_phaseRightButton, tr( "Click to shift phase by +15 degrees" ) ); @@ -912,7 +893,7 @@ WTSynthView::WTSynthView( Instrument * _instrument, connect( m_smoothButton, SIGNAL( clicked() ), this, SLOT( smoothClicked() ) ); connect( m_phaseLeftButton, SIGNAL( clicked() ), this, SLOT( phaseLeftClicked() ) ); connect( m_phaseRightButton, SIGNAL( clicked() ), this, SLOT( phaseRightClicked() ) ); - connect( m_loadButton, SIGNAL( clicked() ), this, SLOT( loadClicked() ) ); + connect( m_loadButton, SIGNAL( clicked() ), this, SLOT( loadClicked() ) ); connect( a1_selectButton, SIGNAL( clicked() ), this, SLOT( updateLayout() ) ); connect( a2_selectButton, SIGNAL( clicked() ), this, SLOT( updateLayout() ) ); @@ -1180,7 +1161,7 @@ void WTSynthView::phaseRightClicked() void WTSynthView::loadClicked() { - QString fileName; + QString fileName; switch( m_selectedGraphGroup->model()->value() ) { case A1_OSC: @@ -1249,6 +1230,7 @@ void WTSynthView::modelChanged() m_envHoldKnob -> setModel( &w -> m_envHold ); m_envDecKnob -> setModel( &w -> m_envDec ); + m_xtalkKnob -> setModel( &w -> m_xtalk ); } diff --git a/plugins/wtsynth/WTSynth.h b/plugins/wtsynth/WTSynth.h index df7aa908b..c412199f4 100644 --- a/plugins/wtsynth/WTSynth.h +++ b/plugins/wtsynth/WTSynth.h @@ -56,20 +56,20 @@ #define B2ROW 95 -const int WAVELEN = 220; -const int PMOD_AMT = 110; +extern const int WAVELEN = 220; +extern const int PMOD_AMT = 110; -const int MOD_MIX = 0; -const int MOD_AM = 1; -const int MOD_RM = 2; -const int MOD_PM = 3; -const int NUM_MODS = 4; +extern const int MOD_MIX = 0; +extern const int MOD_AM = 1; +extern const int MOD_RM = 2; +extern const int MOD_PM = 3; +extern const int NUM_MODS = 4; -const int A1_OSC = 0; -const int A2_OSC = 1; -const int B1_OSC = 2; -const int B2_OSC = 3; -const int NUM_OSCS = 4; +extern const int A1_OSC = 0; +extern const int A2_OSC = 1; +extern const int B1_OSC = 2; +extern const int B2_OSC = 3; +extern const int NUM_OSCS = 4; class WTSynthObject @@ -80,14 +80,17 @@ public: int _amod, int _bmod, const sample_rate_t _samplerate, NotePlayHandle * _nph, fpp_t _frames ); virtual ~WTSynthObject(); + static void changeVolume( int _osc, float _lvol, float _rvol ); + static void changeMult( int _osc, float _mul ); + static void changeTune( int _osc, float _ltune, float _rtune ); + + static inline void changeXtalk( float _xtalk ) + { + s_xtalk = _xtalk; + }; + void renderOutput( fpp_t _frames ); - void updateFrequencies(); - - void changeVolume( int _osc, float _lvol, float _rvol ); - void changeMult( int _osc, float _mul ); - void changeTune( int _osc, float _ltune, float _rtune ); - inline sampleFrame * abuf() const { return m_abuf; @@ -102,11 +105,29 @@ public: } private: - float m_lvol [NUM_OSCS]; - float m_rvol [NUM_OSCS]; - float m_mult [NUM_OSCS]; - float m_ltune [NUM_OSCS]; - float m_rtune [NUM_OSCS]; + static float s_lvol [NUM_OSCS]; + static float s_rvol [NUM_OSCS]; + static float s_mult [NUM_OSCS]; + static float s_ltune [NUM_OSCS]; + static float s_rtune [NUM_OSCS]; + static float s_xtalk; + + // linear interpolation +/* inline sample_t interpolate( sample_t s1, sample_t s2, float x ) + { + return s1 + ( s2 - s1 ) * x; + }*/ + // quick and dirty approximation of cubic interpolation + inline sample_t interpolate( sample_t s1, sample_t s2, float x ) + { + const float x2 = powf( x, 2 ); + const float x3 = powf( x, 3 ); + const float m = s2 - s1; + + return ( ( x3 * 2.0 - x2 * 3.0 + 1.0 ) * s1 ) + + ( ( x3 * -2.0 + x2 * 3.0 ) * s2 ) + + ( ( x + x3 * 2.0 - x2 * 3.0 ) * m ); + } int m_amod; int m_bmod; @@ -160,6 +181,7 @@ public slots: void updateVolumes(); void updateMult(); void updateTunes(); + void updateXtalk(); private: inline float leftCh( float _vol, float _pan ) @@ -205,20 +227,18 @@ private: FloatModel m_abmix; FloatModel m_envAmt; - + TempoSyncKnobModel m_envAtt; TempoSyncKnobModel m_envHold; TempoSyncKnobModel m_envDec; + FloatModel m_xtalk; + IntModel m_amod; IntModel m_bmod; IntModel m_selectedGraph; - bool m_volChanged; - bool m_multChanged; - bool m_tuneChanged; - friend class WTSynthView; }; @@ -278,11 +298,13 @@ private: knob * m_abmixKnob; knob * m_envAmtKnob; - + TempoSyncKnob * m_envAttKnob; TempoSyncKnob * m_envHoldKnob; TempoSyncKnob * m_envDecKnob; + knob * m_xtalkKnob; + automatableButtonGroup * m_selectedGraphGroup; automatableButtonGroup * m_aModGroup; automatableButtonGroup * m_bModGroup; diff --git a/plugins/wtsynth/artwork.png b/plugins/wtsynth/artwork.png index 56413dcea32e35f177f97d88db55b7d9c46b25e1..bd321cdbd1a2bf1832deff70f018efd73592a3bc 100644 GIT binary patch delta 96334 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 Hu0mjfrxrTo delta 94371 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 Date: Mon, 24 Mar 2014 03:55:43 +0200 Subject: [PATCH 086/647] Changes again - moved frequency calculations to a static method... for some reason this saves a lot of cpu. --- plugins/wtsynth/WTSynth.cpp | 27 +++++++++++++++++---------- plugins/wtsynth/WTSynth.h | 6 +++--- 2 files changed, 20 insertions(+), 13 deletions(-) diff --git a/plugins/wtsynth/WTSynth.cpp b/plugins/wtsynth/WTSynth.cpp index bbbb2bcf9..d9c7f7351 100644 --- a/plugins/wtsynth/WTSynth.cpp +++ b/plugins/wtsynth/WTSynth.cpp @@ -62,7 +62,8 @@ float WTSynthObject::s_mult [NUM_OSCS]; float WTSynthObject::s_ltune [NUM_OSCS]; float WTSynthObject::s_rtune [NUM_OSCS]; float WTSynthObject::s_xtalk; - +float WTSynthObject::s_lfreq [NUM_OSCS]; +float WTSynthObject::s_rfreq [NUM_OSCS]; WTSynthObject::WTSynthObject( float * _A1wave, float * _A2wave, @@ -105,13 +106,6 @@ WTSynthObject::~WTSynthObject() void WTSynthObject::renderOutput( fpp_t _frames ) { - // calculate frequencies - for( int i = 0; i < NUM_OSCS; i++ ) - { - m_lfreq[i] = ( s_mult[i] / 8 ) * powf( 2, s_ltune[i] / 1200 ); - m_rfreq[i] = ( s_mult[i] / 8 ) * powf( 2, s_rtune[i] / 1200 ); - } - if( m_abuf == NULL ) m_abuf = new sampleFrame[m_fpp]; if( m_bbuf == NULL ) @@ -225,9 +219,9 @@ void WTSynthObject::renderOutput( fpp_t _frames ) // update phases for( int i = 0; i < NUM_OSCS; i++ ) { - m_lphase[i] += ( static_cast( WAVELEN ) / ( m_samplerate / ( m_nph->frequency() * m_lfreq[i] ) ) ); + m_lphase[i] += ( static_cast( WAVELEN ) / ( m_samplerate / ( m_nph->frequency() * s_lfreq[i] ) ) ); m_lphase[i] = fmodf( m_lphase[i], WAVELEN ); - m_rphase[i] += ( static_cast( WAVELEN ) / ( m_samplerate / ( m_nph->frequency() * m_rfreq[i] ) ) ); + m_rphase[i] += ( static_cast( WAVELEN ) / ( m_samplerate / ( m_nph->frequency() * s_rfreq[i] ) ) ); m_rphase[i] = fmodf( m_rphase[i], WAVELEN ); } } @@ -256,6 +250,17 @@ void WTSynthObject::changeTune( int _osc, float _ltune, float _rtune ) } +void WTSynthObject::updateFrequency() +{ + // calculate frequencies + for( int i = 0; i < NUM_OSCS; i++ ) + { + s_lfreq[i] = ( s_mult[i] / 8 ) * powf( 2, s_ltune[i] / 1200 ); + s_rfreq[i] = ( s_mult[i] / 8 ) * powf( 2, s_rtune[i] / 1200 ); + } +} + + WTSynthInstrument::WTSynthInstrument( InstrumentTrack * _instrument_track ) : Instrument( _instrument_track, &wtsynth_plugin_descriptor ), @@ -614,6 +619,7 @@ void WTSynthInstrument::updateMult() WTSynthObject::changeMult( A2_OSC, a2_mult.value() ); WTSynthObject::changeMult( B1_OSC, b1_mult.value() ); WTSynthObject::changeMult( B2_OSC, b2_mult.value() ); + WTSynthObject::updateFrequency(); } void WTSynthInstrument::updateTunes() { @@ -621,6 +627,7 @@ void WTSynthInstrument::updateTunes() WTSynthObject::changeTune( A2_OSC, a2_ltune.value(), a2_rtune.value() ); WTSynthObject::changeTune( B1_OSC, b1_ltune.value(), b1_rtune.value() ); WTSynthObject::changeTune( B2_OSC, b2_ltune.value(), b2_rtune.value() ); + WTSynthObject::updateFrequency(); } void WTSynthInstrument::updateXtalk() { diff --git a/plugins/wtsynth/WTSynth.h b/plugins/wtsynth/WTSynth.h index c412199f4..145bed795 100644 --- a/plugins/wtsynth/WTSynth.h +++ b/plugins/wtsynth/WTSynth.h @@ -83,6 +83,7 @@ public: static void changeVolume( int _osc, float _lvol, float _rvol ); static void changeMult( int _osc, float _mul ); static void changeTune( int _osc, float _ltune, float _rtune ); + static void updateFrequency(); static inline void changeXtalk( float _xtalk ) { @@ -111,6 +112,8 @@ private: static float s_ltune [NUM_OSCS]; static float s_rtune [NUM_OSCS]; static float s_xtalk; + static float s_lfreq [NUM_OSCS]; + static float s_rfreq [NUM_OSCS]; // linear interpolation /* inline sample_t interpolate( sample_t s1, sample_t s2, float x ) @@ -143,9 +146,6 @@ private: float m_lphase [NUM_OSCS]; float m_rphase [NUM_OSCS]; - float m_lfreq [NUM_OSCS]; - float m_rfreq [NUM_OSCS]; - float m_A1wave [WAVELEN]; float m_A2wave [WAVELEN]; float m_B1wave [WAVELEN]; From 8109d38f2efc5d4cec44757eaf98dcd33fe3ff56 Mon Sep 17 00:00:00 2001 From: Vesa Date: Mon, 24 Mar 2014 05:26:54 +0200 Subject: [PATCH 087/647] I forgot how to think... fix all stupidity of the last commit --- plugins/wtsynth/WTSynth.cpp | 156 ++++++++++++++---------------------- plugins/wtsynth/WTSynth.h | 43 ++++------ 2 files changed, 75 insertions(+), 124 deletions(-) diff --git a/plugins/wtsynth/WTSynth.cpp b/plugins/wtsynth/WTSynth.cpp index d9c7f7351..8ba27e38b 100644 --- a/plugins/wtsynth/WTSynth.cpp +++ b/plugins/wtsynth/WTSynth.cpp @@ -54,26 +54,18 @@ Plugin::Descriptor PLUGIN_EXPORT wtsynth_plugin_descriptor = } -// these need to be here - -float WTSynthObject::s_lvol [NUM_OSCS]; -float WTSynthObject::s_rvol [NUM_OSCS]; -float WTSynthObject::s_mult [NUM_OSCS]; -float WTSynthObject::s_ltune [NUM_OSCS]; -float WTSynthObject::s_rtune [NUM_OSCS]; -float WTSynthObject::s_xtalk; -float WTSynthObject::s_lfreq [NUM_OSCS]; -float WTSynthObject::s_rfreq [NUM_OSCS]; WTSynthObject::WTSynthObject( float * _A1wave, float * _A2wave, float * _B1wave, float * _B2wave, - int _amod, int _bmod, const sample_rate_t _samplerate, NotePlayHandle * _nph, fpp_t _frames ) : + int _amod, int _bmod, const sample_rate_t _samplerate, NotePlayHandle * _nph, fpp_t _frames, + WTSynthInstrument * _w ) : m_amod( _amod ), m_bmod( _bmod ), m_samplerate( _samplerate ), m_nph( _nph ), - m_fpp( _frames ) + m_fpp( _frames ), + m_parent( _w ) { m_abuf = new sampleFrame[_frames]; m_bbuf = new sampleFrame[_frames]; @@ -124,10 +116,10 @@ void WTSynthObject::renderOutput( fpp_t _frames ) // A2 sample_t A2_L = interpolate( m_A2wave[ static_cast( m_lphase[A2_OSC] ) % WAVELEN ], m_A2wave[ static_cast( m_lphase[A2_OSC] + 1 ) % WAVELEN ], - fraction( m_lphase[A2_OSC] ) ) * s_lvol[A2_OSC]; + fraction( m_lphase[A2_OSC] ) ) * m_parent->m_lvol[A2_OSC]; sample_t A2_R = interpolate( m_A2wave[ static_cast( m_rphase[A2_OSC] ) % WAVELEN ], m_A2wave[ static_cast( m_rphase[A2_OSC] + 1 ) % WAVELEN ], - fraction( m_rphase[A2_OSC] ) ) * s_rvol[A2_OSC]; + fraction( m_rphase[A2_OSC] ) ) * m_parent->m_rvol[A2_OSC]; // if phase mod, add to phases if( m_amod == MOD_PM ) { @@ -139,26 +131,27 @@ void WTSynthObject::renderOutput( fpp_t _frames ) // A1 sample_t A1_L = interpolate( m_A1wave[ static_cast( A1_lphase ) % WAVELEN ], m_A1wave[ static_cast( A1_lphase + 1 ) % WAVELEN ], - fraction( A1_lphase ) ) * s_lvol[A1_OSC]; + fraction( A1_lphase ) ) * m_parent->m_lvol[A1_OSC]; sample_t A1_R = interpolate( m_A1wave[ static_cast( A1_rphase ) % WAVELEN ], m_A1wave[ static_cast( A1_rphase + 1 ) % WAVELEN ], - fraction( A1_rphase ) ) * s_rvol[A1_OSC]; + fraction( A1_rphase ) ) * m_parent->m_rvol[A1_OSC]; ///////////// B-series ///////////////// // B2 sample_t B2_L = interpolate( m_B2wave[ static_cast( m_lphase[B2_OSC] ) % WAVELEN ], m_B2wave[ static_cast( m_lphase[B2_OSC] + 1 ) % WAVELEN ], - fraction( m_lphase[B2_OSC] ) ) * s_lvol[B2_OSC]; + fraction( m_lphase[B2_OSC] ) ) * m_parent->m_lvol[B2_OSC]; sample_t B2_R = interpolate( m_B2wave[ static_cast( m_rphase[B2_OSC] ) % WAVELEN ], m_B2wave[ static_cast( m_rphase[B2_OSC] + 1 ) % WAVELEN ], - fraction( m_rphase[B2_OSC] ) ) * s_rvol[B2_OSC]; + fraction( m_rphase[B2_OSC] ) ) * m_parent->m_rvol[B2_OSC]; // if crosstalk active, add a1 - if( s_xtalk > 0.0 ) + const float xt = m_parent->m_xtalk.value(); + if( xt > 0.0 ) { - B2_L += ( A1_L * s_xtalk ) / 100.0f; - B2_R += ( A1_R * s_xtalk ) / 100.0f; + B2_L += ( A1_L * xt ) / 100.0f; + B2_R += ( A1_R * xt ) / 100.0f; } // if phase mod, add to phases @@ -172,10 +165,10 @@ void WTSynthObject::renderOutput( fpp_t _frames ) // B1 sample_t B1_L = interpolate( m_B1wave[ static_cast( B1_lphase ) % WAVELEN ], m_B1wave[ static_cast( B1_lphase + 1 ) % WAVELEN ], - fraction( B1_lphase ) ) * s_lvol[B1_OSC]; + fraction( B1_lphase ) ) * m_parent->m_lvol[B1_OSC]; sample_t B1_R = interpolate( m_B1wave[ static_cast( B1_rphase ) % WAVELEN ], m_B1wave[ static_cast( B1_rphase + 1 ) % WAVELEN ], - fraction( B1_rphase ) ) * s_rvol[B1_OSC]; + fraction( B1_rphase ) ) * m_parent->m_rvol[B1_OSC]; // A-series modulation) @@ -219,9 +212,9 @@ void WTSynthObject::renderOutput( fpp_t _frames ) // update phases for( int i = 0; i < NUM_OSCS; i++ ) { - m_lphase[i] += ( static_cast( WAVELEN ) / ( m_samplerate / ( m_nph->frequency() * s_lfreq[i] ) ) ); + m_lphase[i] += ( static_cast( WAVELEN ) / ( m_samplerate / ( m_nph->frequency() * m_parent->m_lfreq[i] ) ) ); m_lphase[i] = fmodf( m_lphase[i], WAVELEN ); - m_rphase[i] += ( static_cast( WAVELEN ) / ( m_samplerate / ( m_nph->frequency() * s_rfreq[i] ) ) ); + m_rphase[i] += ( static_cast( WAVELEN ) / ( m_samplerate / ( m_nph->frequency() * m_parent->m_rfreq[i] ) ) ); m_rphase[i] = fmodf( m_rphase[i], WAVELEN ); } } @@ -229,37 +222,6 @@ void WTSynthObject::renderOutput( fpp_t _frames ) } -void WTSynthObject::changeVolume( int _osc, float _lvol, float _rvol ) -{ - WTSynthObject::s_lvol[_osc] = _lvol / 100.0; - WTSynthObject::s_rvol[_osc] = _rvol / 100.0; -// qDebug( "osc %d vol %f %f", _osc, m_lvol[_osc], m_rvol[_osc] ); -} - - -void WTSynthObject::changeMult( int _osc, float _mul ) -{ - s_mult[_osc] = _mul; -} - - -void WTSynthObject::changeTune( int _osc, float _ltune, float _rtune ) -{ - s_ltune[_osc] = _ltune; - s_rtune[_osc] = _rtune; -} - - -void WTSynthObject::updateFrequency() -{ - // calculate frequencies - for( int i = 0; i < NUM_OSCS; i++ ) - { - s_lfreq[i] = ( s_mult[i] / 8 ) * powf( 2, s_ltune[i] / 1200 ); - s_rfreq[i] = ( s_mult[i] / 8 ) * powf( 2, s_rtune[i] / 1200 ); - } -} - WTSynthInstrument::WTSynthInstrument( InstrumentTrack * _instrument_track ) : Instrument( _instrument_track, &wtsynth_plugin_descriptor ), @@ -318,32 +280,28 @@ WTSynthInstrument::WTSynthInstrument( InstrumentTrack * _instrument_track ) : connect( &b1_pan, SIGNAL( dataChanged() ), this, SLOT( updateVolumes() ) ); connect( &b2_pan, SIGNAL( dataChanged() ), this, SLOT( updateVolumes() ) ); - connect( &a1_mult, SIGNAL( dataChanged() ), this, SLOT( updateMult() ) ); - connect( &a2_mult, SIGNAL( dataChanged() ), this, SLOT( updateMult() ) ); - connect( &b1_mult, SIGNAL( dataChanged() ), this, SLOT( updateMult() ) ); - connect( &b2_mult, SIGNAL( dataChanged() ), this, SLOT( updateMult() ) ); + connect( &a1_mult, SIGNAL( dataChanged() ), this, SLOT( updateFreq() ) ); + connect( &a2_mult, SIGNAL( dataChanged() ), this, SLOT( updateFreq() ) ); + connect( &b1_mult, SIGNAL( dataChanged() ), this, SLOT( updateFreq() ) ); + connect( &b2_mult, SIGNAL( dataChanged() ), this, SLOT( updateFreq() ) ); - connect( &a1_ltune, SIGNAL( dataChanged() ), this, SLOT( updateTunes() ) ); - connect( &a2_ltune, SIGNAL( dataChanged() ), this, SLOT( updateTunes() ) ); - connect( &b1_ltune, SIGNAL( dataChanged() ), this, SLOT( updateTunes() ) ); - connect( &b2_ltune, SIGNAL( dataChanged() ), this, SLOT( updateTunes() ) ); + connect( &a1_ltune, SIGNAL( dataChanged() ), this, SLOT( updateFreq() ) ); + connect( &a2_ltune, SIGNAL( dataChanged() ), this, SLOT( updateFreq() ) ); + connect( &b1_ltune, SIGNAL( dataChanged() ), this, SLOT( updateFreq() ) ); + connect( &b2_ltune, SIGNAL( dataChanged() ), this, SLOT( updateFreq() ) ); - connect( &a1_rtune, SIGNAL( dataChanged() ), this, SLOT( updateTunes() ) ); - connect( &a2_rtune, SIGNAL( dataChanged() ), this, SLOT( updateTunes() ) ); - connect( &b1_rtune, SIGNAL( dataChanged() ), this, SLOT( updateTunes() ) ); - connect( &b2_rtune, SIGNAL( dataChanged() ), this, SLOT( updateTunes() ) ); - - connect( &m_xtalk, SIGNAL( dataChanged() ), this, SLOT( updateXtalk() ) ); + connect( &a1_rtune, SIGNAL( dataChanged() ), this, SLOT( updateFreq() ) ); + connect( &a2_rtune, SIGNAL( dataChanged() ), this, SLOT( updateFreq() ) ); + connect( &b1_rtune, SIGNAL( dataChanged() ), this, SLOT( updateFreq() ) ); + connect( &b2_rtune, SIGNAL( dataChanged() ), this, SLOT( updateFreq() ) ); a1_graph.setWaveToSine(); a2_graph.setWaveToSine(); b1_graph.setWaveToSine(); b2_graph.setWaveToSine(); - updateMult(); - updateTunes(); updateVolumes(); - updateXtalk(); + updateFreq(); } @@ -363,7 +321,7 @@ void WTSynthInstrument::playNote( NotePlayHandle * _n, const_cast( b2_graph.samples() ), m_amod.value(), m_bmod.value(), engine::mixer()->processingSampleRate(), _n, - engine::mixer()->framesPerPeriod() ); + engine::mixer()->framesPerPeriod(), this ); _n->m_pluginData = w; } @@ -608,32 +566,34 @@ PluginView * WTSynthInstrument::instantiateView( QWidget * _parent ) void WTSynthInstrument::updateVolumes() { - WTSynthObject::changeVolume( A1_OSC, leftCh( a1_vol.value(), a1_pan.value() ), rightCh( a1_vol.value(), a1_pan.value() ) ); - WTSynthObject::changeVolume( A2_OSC, leftCh( a2_vol.value(), a2_pan.value() ), rightCh( a2_vol.value(), a2_pan.value() ) ); - WTSynthObject::changeVolume( B1_OSC, leftCh( b1_vol.value(), b1_pan.value() ), rightCh( b1_vol.value(), b1_pan.value() ) ); - WTSynthObject::changeVolume( B2_OSC, leftCh( b2_vol.value(), b2_pan.value() ), rightCh( b2_vol.value(), b2_pan.value() ) ); -} -void WTSynthInstrument::updateMult() -{ - WTSynthObject::changeMult( A1_OSC, a1_mult.value() ); - WTSynthObject::changeMult( A2_OSC, a2_mult.value() ); - WTSynthObject::changeMult( B1_OSC, b1_mult.value() ); - WTSynthObject::changeMult( B2_OSC, b2_mult.value() ); - WTSynthObject::updateFrequency(); -} -void WTSynthInstrument::updateTunes() -{ - WTSynthObject::changeTune( A1_OSC, a1_ltune.value(), a1_rtune.value() ); - WTSynthObject::changeTune( A2_OSC, a2_ltune.value(), a2_rtune.value() ); - WTSynthObject::changeTune( B1_OSC, b1_ltune.value(), b1_rtune.value() ); - WTSynthObject::changeTune( B2_OSC, b2_ltune.value(), b2_rtune.value() ); - WTSynthObject::updateFrequency(); -} -void WTSynthInstrument::updateXtalk() -{ - WTSynthObject::changeXtalk( m_xtalk.value() ); + m_lvol[A1_OSC] = leftCh( a1_vol.value(), a1_pan.value() ); + m_rvol[A1_OSC] = rightCh( a1_vol.value(), a1_pan.value() ); + + m_lvol[A2_OSC] = leftCh( a2_vol.value(), a2_pan.value() ); + m_rvol[A2_OSC] = rightCh( a2_vol.value(), a2_pan.value() ); + + m_lvol[B1_OSC] = leftCh( b1_vol.value(), b1_pan.value() ); + m_rvol[B1_OSC] = rightCh( b1_vol.value(), b1_pan.value() ); + + m_lvol[B2_OSC] = leftCh( b2_vol.value(), b2_pan.value() ); + m_rvol[B2_OSC] = rightCh( b2_vol.value(), b2_pan.value() ); } +void WTSynthInstrument::updateFreq() +{ + // calculate frequencies + m_lfreq[A1_OSC] = ( a1_mult.value() / 8 ) * powf( 2, a1_ltune.value() / 1200 ); + m_rfreq[A1_OSC] = ( a1_mult.value() / 8 ) * powf( 2, a1_rtune.value() / 1200 ); + + m_lfreq[A2_OSC] = ( a2_mult.value() / 8 ) * powf( 2, a2_ltune.value() / 1200 ); + m_rfreq[A2_OSC] = ( a2_mult.value() / 8 ) * powf( 2, a2_rtune.value() / 1200 ); + + m_lfreq[B1_OSC] = ( b1_mult.value() / 8 ) * powf( 2, b1_ltune.value() / 1200 ); + m_rfreq[B1_OSC] = ( b1_mult.value() / 8 ) * powf( 2, b1_rtune.value() / 1200 ); + + m_lfreq[B2_OSC] = ( b2_mult.value() / 8 ) * powf( 2, b2_ltune.value() / 1200 ); + m_rfreq[B2_OSC] = ( b2_mult.value() / 8 ) * powf( 2, b2_rtune.value() / 1200 ); +} WTSynthView::WTSynthView( Instrument * _instrument, diff --git a/plugins/wtsynth/WTSynth.h b/plugins/wtsynth/WTSynth.h index 145bed795..6513e9141 100644 --- a/plugins/wtsynth/WTSynth.h +++ b/plugins/wtsynth/WTSynth.h @@ -71,25 +71,17 @@ extern const int B1_OSC = 2; extern const int B2_OSC = 3; extern const int NUM_OSCS = 4; +class WTSynthInstrument; class WTSynthObject { public: WTSynthObject( float * _A1wave, float * _A2wave, float * _B1wave, float * _B2wave, - int _amod, int _bmod, const sample_rate_t _samplerate, NotePlayHandle * _nph, fpp_t _frames ); + int _amod, int _bmod, const sample_rate_t _samplerate, NotePlayHandle * _nph, fpp_t _frames, + WTSynthInstrument * _w ); virtual ~WTSynthObject(); - static void changeVolume( int _osc, float _lvol, float _rvol ); - static void changeMult( int _osc, float _mul ); - static void changeTune( int _osc, float _ltune, float _rtune ); - static void updateFrequency(); - - static inline void changeXtalk( float _xtalk ) - { - s_xtalk = _xtalk; - }; - void renderOutput( fpp_t _frames ); inline sampleFrame * abuf() const @@ -106,15 +98,6 @@ public: } private: - static float s_lvol [NUM_OSCS]; - static float s_rvol [NUM_OSCS]; - static float s_mult [NUM_OSCS]; - static float s_ltune [NUM_OSCS]; - static float s_rtune [NUM_OSCS]; - static float s_xtalk; - static float s_lfreq [NUM_OSCS]; - static float s_rfreq [NUM_OSCS]; - // linear interpolation /* inline sample_t interpolate( sample_t s1, sample_t s2, float x ) { @@ -140,6 +123,8 @@ private: fpp_t m_fpp; + WTSynthInstrument * m_parent; + sampleFrame * m_abuf; sampleFrame * m_bbuf; @@ -176,22 +161,27 @@ public: } virtual PluginView * instantiateView( QWidget * _parent ); - + public slots: void updateVolumes(); - void updateMult(); - void updateTunes(); - void updateXtalk(); + void updateFreq(); + +protected: + float m_lvol [NUM_OSCS]; + float m_rvol [NUM_OSCS]; + + float m_lfreq [NUM_OSCS]; + float m_rfreq [NUM_OSCS]; private: inline float leftCh( float _vol, float _pan ) { - return ( _pan <= 0 ? 1.0 : 1.0 - ( _pan / 100.0 ) ) * _vol; + return ( _pan <= 0 ? 1.0 : 1.0 - ( _pan / 100.0 ) ) * _vol / 100.0; } inline float rightCh( float _vol, float _pan ) { - return ( _pan >= 0 ? 1.0 : 1.0 + ( _pan / 100.0 ) ) * _vol; + return ( _pan >= 0 ? 1.0 : 1.0 + ( _pan / 100.0 ) ) * _vol / 100.0; } FloatModel a1_vol; @@ -239,6 +229,7 @@ private: IntModel m_selectedGraph; + friend class WTSynthObject; friend class WTSynthView; }; From b118c23123b4734f2e9032a53fad3f44eee1c8cf Mon Sep 17 00:00:00 2001 From: Vesa Date: Tue, 25 Mar 2014 02:15:03 +0200 Subject: [PATCH 088/647] Rename & refactor to Watsyn, add logo, tweak some algorithms --- data/themes/default/style.css | 46 ++++------ plugins/CMakeLists.txt | 2 +- plugins/watsyn/CMakeLists.txt | 3 + .../WTSynth.cpp => watsyn/Watsyn.cpp} | 82 +++++++++--------- .../{wtsynth/WTSynth.h => watsyn/Watsyn.h} | 58 ++++++++----- plugins/{wtsynth => watsyn}/a1_active.png | Bin plugins/{wtsynth => watsyn}/a1_inactive.png | Bin plugins/{wtsynth => watsyn}/a2_active.png | Bin plugins/{wtsynth => watsyn}/a2_inactive.png | Bin plugins/{wtsynth => watsyn}/aam_active.png | Bin plugins/{wtsynth => watsyn}/aam_inactive.png | Bin plugins/{wtsynth => watsyn}/amix_active.png | Bin plugins/{wtsynth => watsyn}/amix_inactive.png | Bin plugins/{wtsynth => watsyn}/apm_active.png | Bin plugins/{wtsynth => watsyn}/apm_inactive.png | Bin plugins/{wtsynth => watsyn}/arm_active.png | Bin plugins/{wtsynth => watsyn}/arm_inactive.png | Bin plugins/{wtsynth => watsyn}/artwork.png | Bin plugins/{wtsynth => watsyn}/b1_active.png | Bin plugins/{wtsynth => watsyn}/b1_inactive.png | Bin plugins/{wtsynth => watsyn}/b2_active.png | Bin plugins/{wtsynth => watsyn}/b2_inactive.png | Bin plugins/{wtsynth => watsyn}/bam_active.png | Bin plugins/{wtsynth => watsyn}/bam_inactive.png | Bin plugins/{wtsynth => watsyn}/bmix_active.png | Bin plugins/{wtsynth => watsyn}/bmix_inactive.png | Bin plugins/{wtsynth => watsyn}/bpm_active.png | Bin plugins/{wtsynth => watsyn}/bpm_inactive.png | Bin plugins/{wtsynth => watsyn}/brm_active.png | Bin plugins/{wtsynth => watsyn}/brm_inactive.png | Bin plugins/{wtsynth => watsyn}/inv_active.png | Bin plugins/{wtsynth => watsyn}/inv_inactive.png | Bin plugins/{wtsynth => watsyn}/load_active.png | Bin plugins/{wtsynth => watsyn}/load_inactive.png | Bin plugins/watsyn/logo.png | Bin 0 -> 4425 bytes plugins/{wtsynth => watsyn}/norm_active.png | Bin plugins/{wtsynth => watsyn}/norm_inactive.png | Bin plugins/{wtsynth => watsyn}/phl_active.png | Bin plugins/{wtsynth => watsyn}/phl_inactive.png | Bin plugins/{wtsynth => watsyn}/phr_active.png | Bin plugins/{wtsynth => watsyn}/phr_inactive.png | Bin plugins/{wtsynth => watsyn}/saw_active.png | Bin plugins/{wtsynth => watsyn}/saw_inactive.png | Bin plugins/{wtsynth => watsyn}/sin_active.png | Bin plugins/{wtsynth => watsyn}/sin_inactive.png | Bin plugins/{wtsynth => watsyn}/smooth_active.png | Bin .../{wtsynth => watsyn}/smooth_inactive.png | Bin plugins/{wtsynth => watsyn}/sqr_active.png | Bin plugins/{wtsynth => watsyn}/sqr_inactive.png | Bin plugins/{wtsynth => watsyn}/tri_active.png | Bin plugins/{wtsynth => watsyn}/tri_inactive.png | Bin plugins/{wtsynth => watsyn}/wavegraph.png | Bin plugins/wtsynth/CMakeLists.txt | 3 - plugins/wtsynth/logo.png | Bin 174 -> 0 bytes 54 files changed, 98 insertions(+), 96 deletions(-) create mode 100644 plugins/watsyn/CMakeLists.txt rename plugins/{wtsynth/WTSynth.cpp => watsyn/Watsyn.cpp} (95%) rename plugins/{wtsynth/WTSynth.h => watsyn/Watsyn.h} (84%) rename plugins/{wtsynth => watsyn}/a1_active.png (100%) rename plugins/{wtsynth => watsyn}/a1_inactive.png (100%) rename plugins/{wtsynth => watsyn}/a2_active.png (100%) rename plugins/{wtsynth => watsyn}/a2_inactive.png (100%) rename plugins/{wtsynth => watsyn}/aam_active.png (100%) rename plugins/{wtsynth => watsyn}/aam_inactive.png (100%) rename plugins/{wtsynth => watsyn}/amix_active.png (100%) rename plugins/{wtsynth => watsyn}/amix_inactive.png (100%) rename plugins/{wtsynth => watsyn}/apm_active.png (100%) rename plugins/{wtsynth => watsyn}/apm_inactive.png (100%) rename plugins/{wtsynth => watsyn}/arm_active.png (100%) rename plugins/{wtsynth => watsyn}/arm_inactive.png (100%) rename plugins/{wtsynth => watsyn}/artwork.png (100%) rename plugins/{wtsynth => watsyn}/b1_active.png (100%) rename plugins/{wtsynth => watsyn}/b1_inactive.png (100%) rename plugins/{wtsynth => watsyn}/b2_active.png (100%) rename plugins/{wtsynth => watsyn}/b2_inactive.png (100%) rename plugins/{wtsynth => watsyn}/bam_active.png (100%) rename plugins/{wtsynth => watsyn}/bam_inactive.png (100%) rename plugins/{wtsynth => watsyn}/bmix_active.png (100%) rename plugins/{wtsynth => watsyn}/bmix_inactive.png (100%) rename plugins/{wtsynth => watsyn}/bpm_active.png (100%) rename plugins/{wtsynth => watsyn}/bpm_inactive.png (100%) rename plugins/{wtsynth => watsyn}/brm_active.png (100%) rename plugins/{wtsynth => watsyn}/brm_inactive.png (100%) rename plugins/{wtsynth => watsyn}/inv_active.png (100%) rename plugins/{wtsynth => watsyn}/inv_inactive.png (100%) rename plugins/{wtsynth => watsyn}/load_active.png (100%) rename plugins/{wtsynth => watsyn}/load_inactive.png (100%) create mode 100644 plugins/watsyn/logo.png rename plugins/{wtsynth => watsyn}/norm_active.png (100%) rename plugins/{wtsynth => watsyn}/norm_inactive.png (100%) rename plugins/{wtsynth => watsyn}/phl_active.png (100%) rename plugins/{wtsynth => watsyn}/phl_inactive.png (100%) rename plugins/{wtsynth => watsyn}/phr_active.png (100%) rename plugins/{wtsynth => watsyn}/phr_inactive.png (100%) rename plugins/{wtsynth => watsyn}/saw_active.png (100%) rename plugins/{wtsynth => watsyn}/saw_inactive.png (100%) rename plugins/{wtsynth => watsyn}/sin_active.png (100%) rename plugins/{wtsynth => watsyn}/sin_inactive.png (100%) rename plugins/{wtsynth => watsyn}/smooth_active.png (100%) rename plugins/{wtsynth => watsyn}/smooth_inactive.png (100%) rename plugins/{wtsynth => watsyn}/sqr_active.png (100%) rename plugins/{wtsynth => watsyn}/sqr_inactive.png (100%) rename plugins/{wtsynth => watsyn}/tri_active.png (100%) rename plugins/{wtsynth => watsyn}/tri_inactive.png (100%) rename plugins/{wtsynth => watsyn}/wavegraph.png (100%) delete mode 100644 plugins/wtsynth/CMakeLists.txt delete mode 100644 plugins/wtsynth/logo.png diff --git a/data/themes/default/style.css b/data/themes/default/style.css index 7d41a8f07..b68ef0658 100644 --- a/data/themes/default/style.css +++ b/data/themes/default/style.css @@ -238,7 +238,7 @@ TrackContainerView QFrame{ /* autoscroll, loop, stop behaviour toggle buttons */ -nStateButton { +nStateButton { max-height: 26px; max-width: 26px; min-height: 26px; @@ -366,7 +366,7 @@ toolButton#playButton { toolButton#stopButton { border-top-right-radius: 5px 15px; - border-bottom-right-radius: 5px 15px; + border-bottom-right-radius: 5px 15px; } /* record and record-accompany can be styled with #recordButton and #recordAccompanyButton respectively */ @@ -608,54 +608,40 @@ sidInstrumentView knob { qproperty-lineWidth: 2; } -WTSynthView knob#aKnob { +WatsynView knob { + qproperty-innerRadius: 1; + qproperty-outerRadius: 7; + qproperty-centerPointX: 9.5; + qproperty-centerPointY: 9.5; + qproperty-lineWidth: 2; +} + +WatsynView knob#aKnob { color: #43b2ff; qproperty-outerColor: #43b2ff; - qproperty-innerRadius: 1; - qproperty-outerRadius: 7; - qproperty-centerPointX: 9.5; - qproperty-centerPointY: 9.5; - qproperty-lineWidth: 2; } -WTSynthView knob#bKnob { +WatsynView knob#bKnob { color: #fc5431; qproperty-outerColor: #fc5431; - qproperty-innerRadius: 1; - qproperty-outerRadius: 7; - qproperty-centerPointX: 9.5; - qproperty-centerPointY: 9.5; - qproperty-lineWidth: 2; } -WTSynthView knob#mixKnob { +WatsynView knob#mixKnob { color: #43ff82; qproperty-outerColor: #43ff82; - qproperty-innerRadius: 1; qproperty-outerRadius: 13; qproperty-centerPointX: 15.5; - qproperty-centerPointY: 15.5; - qproperty-lineWidth: 2; + qproperty-centerPointY: 15.5; } -WTSynthView knob#mixenvKnob { +WatsynView knob#mixenvKnob { color: #43ff82; qproperty-outerColor: #43ff82; - qproperty-innerRadius: 1; - qproperty-outerRadius: 7; - qproperty-centerPointX: 9.5; - qproperty-centerPointY: 9.5; - qproperty-lineWidth: 2; } -WTSynthView knob#xtalkKnob { +WatsynView knob#xtalkKnob { color: #fb50fb; qproperty-outerColor: #fb50fb; - qproperty-innerRadius: 1; - qproperty-outerRadius: 7; - qproperty-centerPointX: 9.5; - qproperty-centerPointY: 9.5; - qproperty-lineWidth: 2; } /* palette information - each colour definition must be on a single line, and the line must begin with "palette:", with no leading whitespace diff --git a/plugins/CMakeLists.txt b/plugins/CMakeLists.txt index aba116025..b1247ce18 100644 --- a/plugins/CMakeLists.txt +++ b/plugins/CMakeLists.txt @@ -28,7 +28,7 @@ ADD_SUBDIRECTORY(triple_oscillator) ADD_SUBDIRECTORY(vestige) ADD_SUBDIRECTORY(vst_base) ADD_SUBDIRECTORY(VstEffect) +ADD_SUBDIRECTORY(watsyn) ADD_SUBDIRECTORY(waveshaper) -ADD_SUBDIRECTORY(wtsynth) ADD_SUBDIRECTORY(vibed) ADD_SUBDIRECTORY(zynaddsubfx) diff --git a/plugins/watsyn/CMakeLists.txt b/plugins/watsyn/CMakeLists.txt new file mode 100644 index 000000000..c5344f7e7 --- /dev/null +++ b/plugins/watsyn/CMakeLists.txt @@ -0,0 +1,3 @@ +INCLUDE(BuildPlugin) + +BUILD_PLUGIN(watsyn Watsyn.cpp Watsyn.h MOCFILES Watsyn.h EMBEDDED_RESOURCES ${CMAKE_CURRENT_SOURCE_DIR}/*.png) diff --git a/plugins/wtsynth/WTSynth.cpp b/plugins/watsyn/Watsyn.cpp similarity index 95% rename from plugins/wtsynth/WTSynth.cpp rename to plugins/watsyn/Watsyn.cpp index 8ba27e38b..b3b720d4d 100644 --- a/plugins/wtsynth/WTSynth.cpp +++ b/plugins/watsyn/Watsyn.cpp @@ -1,5 +1,5 @@ /* - * WTSynth.cpp - work in process, name pending + * Watsyn.cpp - a 4-oscillator modulating wavetable synth * * Copyright (c) 2014 Vesa Kivimäki * @@ -24,7 +24,7 @@ #include -#include "WTSynth.h" +#include "Watsyn.h" #include "engine.h" #include "InstrumentTrack.h" #include "templates.h" @@ -37,10 +37,10 @@ extern "C" { -Plugin::Descriptor PLUGIN_EXPORT wtsynth_plugin_descriptor = +Plugin::Descriptor PLUGIN_EXPORT watsyn_plugin_descriptor = { STRINGIFY( PLUGIN_NAME ), - "WTSynth", + "Watsyn", QT_TRANSLATE_NOOP( "pluginBrowser", "4-oscillator modulatable wavetable synth" ), "Vesa Kivimäki ", @@ -56,10 +56,10 @@ Plugin::Descriptor PLUGIN_EXPORT wtsynth_plugin_descriptor = -WTSynthObject::WTSynthObject( float * _A1wave, float * _A2wave, +WatsynObject::WatsynObject( float * _A1wave, float * _A2wave, float * _B1wave, float * _B2wave, int _amod, int _bmod, const sample_rate_t _samplerate, NotePlayHandle * _nph, fpp_t _frames, - WTSynthInstrument * _w ) : + WatsynInstrument * _w ) : m_amod( _amod ), m_bmod( _bmod ), m_samplerate( _samplerate ), @@ -89,14 +89,14 @@ WTSynthObject::WTSynthObject( float * _A1wave, float * _A2wave, -WTSynthObject::~WTSynthObject() +WatsynObject::~WatsynObject() { delete[] m_abuf; delete[] m_bbuf; } -void WTSynthObject::renderOutput( fpp_t _frames ) +void WatsynObject::renderOutput( fpp_t _frames ) { if( m_abuf == NULL ) m_abuf = new sampleFrame[m_fpp]; @@ -223,8 +223,8 @@ void WTSynthObject::renderOutput( fpp_t _frames ) -WTSynthInstrument::WTSynthInstrument( InstrumentTrack * _instrument_track ) : - Instrument( _instrument_track, &wtsynth_plugin_descriptor ), +WatsynInstrument::WatsynInstrument( InstrumentTrack * _instrument_track ) : + Instrument( _instrument_track, &watsyn_plugin_descriptor ), a1_vol( 100.0f, 0.0f, 200.0f, 0.1f, this, tr( "Volume A1" ) ), a2_vol( 100.0f, 0.0f, 200.0f, 0.1f, this, tr( "Volume A2" ) ), @@ -305,17 +305,17 @@ WTSynthInstrument::WTSynthInstrument( InstrumentTrack * _instrument_track ) : } -WTSynthInstrument::~WTSynthInstrument() +WatsynInstrument::~WatsynInstrument() { } -void WTSynthInstrument::playNote( NotePlayHandle * _n, +void WatsynInstrument::playNote( NotePlayHandle * _n, sampleFrame * _working_buffer ) { if ( _n->totalFramesPlayed() == 0 || _n->m_pluginData == NULL ) { - WTSynthObject * w = new WTSynthObject( const_cast( a1_graph.samples() ), + WatsynObject * w = new WatsynObject( const_cast( a1_graph.samples() ), const_cast( a2_graph.samples() ), const_cast( b1_graph.samples() ), const_cast( b2_graph.samples() ), @@ -328,7 +328,7 @@ void WTSynthInstrument::playNote( NotePlayHandle * _n, const fpp_t frames = _n->framesLeftForCurrentPeriod(); - WTSynthObject * w = static_cast( _n->m_pluginData ); + WatsynObject * w = static_cast( _n->m_pluginData ); sampleFrame * abuf = w->abuf(); sampleFrame * bbuf = w->bbuf(); @@ -435,13 +435,13 @@ void WTSynthInstrument::playNote( NotePlayHandle * _n, } -void WTSynthInstrument::deleteNotePluginData( NotePlayHandle * _n ) +void WatsynInstrument::deleteNotePluginData( NotePlayHandle * _n ) { - delete static_cast( _n->m_pluginData ); + delete static_cast( _n->m_pluginData ); } -void WTSynthInstrument::saveSettings( QDomDocument & _doc, +void WatsynInstrument::saveSettings( QDomDocument & _doc, QDomElement & _this ) { a1_vol.saveSettings( _doc, _this, "a1_vol" ); @@ -495,7 +495,7 @@ void WTSynthInstrument::saveSettings( QDomDocument & _doc, } -void WTSynthInstrument::loadSettings( const QDomElement & _this ) +void WatsynInstrument::loadSettings( const QDomElement & _this ) { a1_vol.loadSettings( _this, "a1_vol" ); a2_vol.loadSettings( _this, "a2_vol" ); @@ -552,19 +552,19 @@ void WTSynthInstrument::loadSettings( const QDomElement & _this ) } -QString WTSynthInstrument::nodeName() const +QString WatsynInstrument::nodeName() const { - return( wtsynth_plugin_descriptor.name ); + return( watsyn_plugin_descriptor.name ); } -PluginView * WTSynthInstrument::instantiateView( QWidget * _parent ) +PluginView * WatsynInstrument::instantiateView( QWidget * _parent ) { - return( new WTSynthView( this, _parent ) ); + return( new WatsynView( this, _parent ) ); } -void WTSynthInstrument::updateVolumes() +void WatsynInstrument::updateVolumes() { m_lvol[A1_OSC] = leftCh( a1_vol.value(), a1_pan.value() ); m_rvol[A1_OSC] = rightCh( a1_vol.value(), a1_pan.value() ); @@ -579,7 +579,7 @@ void WTSynthInstrument::updateVolumes() m_rvol[B2_OSC] = rightCh( b2_vol.value(), b2_pan.value() ); } -void WTSynthInstrument::updateFreq() +void WatsynInstrument::updateFreq() { // calculate frequencies m_lfreq[A1_OSC] = ( a1_mult.value() / 8 ) * powf( 2, a1_ltune.value() / 1200 ); @@ -596,7 +596,7 @@ void WTSynthInstrument::updateFreq() } -WTSynthView::WTSynthView( Instrument * _instrument, +WatsynView::WatsynView( Instrument * _instrument, QWidget * _parent ) : InstrumentView( _instrument, _parent ) { @@ -871,13 +871,13 @@ WTSynthView::WTSynthView( Instrument * _instrument, } -WTSynthView::~WTSynthView() +WatsynView::~WatsynView() { } -void WTSynthView::updateLayout() +void WatsynView::updateLayout() { switch( m_selectedGraphGroup->model()->value() ) { @@ -910,7 +910,7 @@ void WTSynthView::updateLayout() -void WTSynthView::sinWaveClicked() +void WatsynView::sinWaveClicked() { switch( m_selectedGraphGroup->model()->value() ) { @@ -934,7 +934,7 @@ void WTSynthView::sinWaveClicked() } -void WTSynthView::triWaveClicked() +void WatsynView::triWaveClicked() { switch( m_selectedGraphGroup->model()->value() ) { @@ -958,7 +958,7 @@ void WTSynthView::triWaveClicked() } -void WTSynthView::sawWaveClicked() +void WatsynView::sawWaveClicked() { switch( m_selectedGraphGroup->model()->value() ) { @@ -982,7 +982,7 @@ void WTSynthView::sawWaveClicked() } -void WTSynthView::sqrWaveClicked() +void WatsynView::sqrWaveClicked() { switch( m_selectedGraphGroup->model()->value() ) { @@ -1006,7 +1006,7 @@ void WTSynthView::sqrWaveClicked() } -void WTSynthView::normalizeClicked() +void WatsynView::normalizeClicked() { switch( m_selectedGraphGroup->model()->value() ) { @@ -1030,7 +1030,7 @@ void WTSynthView::normalizeClicked() } -void WTSynthView::invertClicked() +void WatsynView::invertClicked() { switch( m_selectedGraphGroup->model()->value() ) { @@ -1054,7 +1054,7 @@ void WTSynthView::invertClicked() } -void WTSynthView::smoothClicked() +void WatsynView::smoothClicked() { switch( m_selectedGraphGroup->model()->value() ) { @@ -1078,7 +1078,7 @@ void WTSynthView::smoothClicked() } -void WTSynthView::phaseLeftClicked() +void WatsynView::phaseLeftClicked() { switch( m_selectedGraphGroup->model()->value() ) { @@ -1102,7 +1102,7 @@ void WTSynthView::phaseLeftClicked() } -void WTSynthView::phaseRightClicked() +void WatsynView::phaseRightClicked() { switch( m_selectedGraphGroup->model()->value() ) { @@ -1126,7 +1126,7 @@ void WTSynthView::phaseRightClicked() } -void WTSynthView::loadClicked() +void WatsynView::loadClicked() { QString fileName; switch( m_selectedGraphGroup->model()->value() ) @@ -1151,9 +1151,9 @@ void WTSynthView::loadClicked() } -void WTSynthView::modelChanged() +void WatsynView::modelChanged() { - WTSynthInstrument * w = castModel(); + WatsynInstrument * w = castModel(); a1_volKnob -> setModel( &w -> a1_vol ); a2_volKnob -> setModel( &w -> a2_vol ); @@ -1210,11 +1210,11 @@ extern "C" // necessary for getting instance out of shared lib Plugin * PLUGIN_EXPORT lmms_plugin_main( Model *, void * _data ) { - return( new WTSynthInstrument( static_cast( _data ) ) ); + return( new WatsynInstrument( static_cast( _data ) ) ); } } -#include "moc_WTSynth.cxx" +#include "moc_Watsyn.cxx" diff --git a/plugins/wtsynth/WTSynth.h b/plugins/watsyn/Watsyn.h similarity index 84% rename from plugins/wtsynth/WTSynth.h rename to plugins/watsyn/Watsyn.h index 6513e9141..a6860cbed 100644 --- a/plugins/wtsynth/WTSynth.h +++ b/plugins/watsyn/Watsyn.h @@ -1,5 +1,5 @@ /* - * WTSynth.h - work in process, name pending + * Watsyn.h - a 4-oscillator modulating wavetable synth * * Copyright (c) 2014 Vesa Kivimäki * @@ -23,8 +23,8 @@ */ -#ifndef WTSYNTH_H -#define WTSYNTH_H +#ifndef WATSYN_H +#define WATSYN_H #include "Instrument.h" #include "InstrumentView.h" @@ -71,16 +71,16 @@ extern const int B1_OSC = 2; extern const int B2_OSC = 3; extern const int NUM_OSCS = 4; -class WTSynthInstrument; +class WatsynInstrument; -class WTSynthObject +class WatsynObject { public: - WTSynthObject( float * _A1wave, float * _A2wave, + WatsynObject( float * _A1wave, float * _A2wave, float * _B1wave, float * _B2wave, int _amod, int _bmod, const sample_rate_t _samplerate, NotePlayHandle * _nph, fpp_t _frames, - WTSynthInstrument * _w ); - virtual ~WTSynthObject(); + WatsynInstrument * _w ); + virtual ~WatsynObject(); void renderOutput( fpp_t _frames ); @@ -103,17 +103,33 @@ private: { return s1 + ( s2 - s1 ) * x; }*/ + // quick and dirty approximation of cubic interpolation inline sample_t interpolate( sample_t s1, sample_t s2, float x ) { const float x2 = powf( x, 2 ); const float x3 = powf( x, 3 ); - const float m = s2 - s1; + //const float m = s2 - s1; + + return ( ( x3 * 2.0 - x2 * 3.0 + 1.0 ) * s1 ) + + ( ( x3 * -2.0 + x2 * 3.0 ) * s2 );// + + //( ( x + x3 * 2.0 - x2 * 3.0 ) * m ); + } + + // more accurate cubic interpolation... + // consumes more cpu than ^ but doesn't bring a marked increase in sound quality IMO +/* inline sample_t interpolate( sample_t s0, sample_t s1, sample_t s2, sample_t s3, float x ) + { + const float x2 = powf( x, 2 ); + const float x3 = powf( x, 3 ); + const float m1 = ( s2 - s0 ) / 2; + const float m2 = ( s3 - s1 ) / 2; return ( ( x3 * 2.0 - x2 * 3.0 + 1.0 ) * s1 ) + ( ( x3 * -2.0 + x2 * 3.0 ) * s2 ) + - ( ( x + x3 * 2.0 - x2 * 3.0 ) * m ); - } + ( ( x3 - x2 * 2 + x ) * m1 ) + + ( ( x3 - x2 ) * m2 ); + }*/ int m_amod; int m_bmod; @@ -123,7 +139,7 @@ private: fpp_t m_fpp; - WTSynthInstrument * m_parent; + WatsynInstrument * m_parent; sampleFrame * m_abuf; sampleFrame * m_bbuf; @@ -137,12 +153,12 @@ private: float m_B2wave [WAVELEN]; }; -class WTSynthInstrument : public Instrument +class WatsynInstrument : public Instrument { Q_OBJECT public: - WTSynthInstrument( InstrumentTrack * _instrument_track ); - virtual ~WTSynthInstrument(); + WatsynInstrument( InstrumentTrack * _instrument_track ); + virtual ~WatsynInstrument(); virtual void playNote( NotePlayHandle * _n, sampleFrame * _working_buffer ); @@ -161,7 +177,7 @@ public: } virtual PluginView * instantiateView( QWidget * _parent ); - + public slots: void updateVolumes(); void updateFreq(); @@ -229,18 +245,18 @@ private: IntModel m_selectedGraph; - friend class WTSynthObject; - friend class WTSynthView; + friend class WatsynObject; + friend class WatsynView; }; -class WTSynthView : public InstrumentView +class WatsynView : public InstrumentView { Q_OBJECT public: - WTSynthView( Instrument * _instrument, + WatsynView( Instrument * _instrument, QWidget * _parent ); - virtual ~WTSynthView(); + virtual ~WatsynView(); protected slots: void updateLayout(); diff --git a/plugins/wtsynth/a1_active.png b/plugins/watsyn/a1_active.png similarity index 100% rename from plugins/wtsynth/a1_active.png rename to plugins/watsyn/a1_active.png diff --git a/plugins/wtsynth/a1_inactive.png b/plugins/watsyn/a1_inactive.png similarity index 100% rename from plugins/wtsynth/a1_inactive.png rename to plugins/watsyn/a1_inactive.png diff --git a/plugins/wtsynth/a2_active.png b/plugins/watsyn/a2_active.png similarity index 100% rename from plugins/wtsynth/a2_active.png rename to plugins/watsyn/a2_active.png diff --git a/plugins/wtsynth/a2_inactive.png b/plugins/watsyn/a2_inactive.png similarity index 100% rename from plugins/wtsynth/a2_inactive.png rename to plugins/watsyn/a2_inactive.png diff --git a/plugins/wtsynth/aam_active.png b/plugins/watsyn/aam_active.png similarity index 100% rename from plugins/wtsynth/aam_active.png rename to plugins/watsyn/aam_active.png diff --git a/plugins/wtsynth/aam_inactive.png b/plugins/watsyn/aam_inactive.png similarity index 100% rename from plugins/wtsynth/aam_inactive.png rename to plugins/watsyn/aam_inactive.png diff --git a/plugins/wtsynth/amix_active.png b/plugins/watsyn/amix_active.png similarity index 100% rename from plugins/wtsynth/amix_active.png rename to plugins/watsyn/amix_active.png diff --git a/plugins/wtsynth/amix_inactive.png b/plugins/watsyn/amix_inactive.png similarity index 100% rename from plugins/wtsynth/amix_inactive.png rename to plugins/watsyn/amix_inactive.png diff --git a/plugins/wtsynth/apm_active.png b/plugins/watsyn/apm_active.png similarity index 100% rename from plugins/wtsynth/apm_active.png rename to plugins/watsyn/apm_active.png diff --git a/plugins/wtsynth/apm_inactive.png b/plugins/watsyn/apm_inactive.png similarity index 100% rename from plugins/wtsynth/apm_inactive.png rename to plugins/watsyn/apm_inactive.png diff --git a/plugins/wtsynth/arm_active.png b/plugins/watsyn/arm_active.png similarity index 100% rename from plugins/wtsynth/arm_active.png rename to plugins/watsyn/arm_active.png diff --git a/plugins/wtsynth/arm_inactive.png b/plugins/watsyn/arm_inactive.png similarity index 100% rename from plugins/wtsynth/arm_inactive.png rename to plugins/watsyn/arm_inactive.png diff --git a/plugins/wtsynth/artwork.png b/plugins/watsyn/artwork.png similarity index 100% rename from plugins/wtsynth/artwork.png rename to plugins/watsyn/artwork.png diff --git a/plugins/wtsynth/b1_active.png b/plugins/watsyn/b1_active.png similarity index 100% rename from plugins/wtsynth/b1_active.png rename to plugins/watsyn/b1_active.png diff --git a/plugins/wtsynth/b1_inactive.png b/plugins/watsyn/b1_inactive.png similarity index 100% rename from plugins/wtsynth/b1_inactive.png rename to plugins/watsyn/b1_inactive.png diff --git a/plugins/wtsynth/b2_active.png b/plugins/watsyn/b2_active.png similarity index 100% rename from plugins/wtsynth/b2_active.png rename to plugins/watsyn/b2_active.png diff --git a/plugins/wtsynth/b2_inactive.png b/plugins/watsyn/b2_inactive.png similarity index 100% rename from plugins/wtsynth/b2_inactive.png rename to plugins/watsyn/b2_inactive.png diff --git a/plugins/wtsynth/bam_active.png b/plugins/watsyn/bam_active.png similarity index 100% rename from plugins/wtsynth/bam_active.png rename to plugins/watsyn/bam_active.png diff --git a/plugins/wtsynth/bam_inactive.png b/plugins/watsyn/bam_inactive.png similarity index 100% rename from plugins/wtsynth/bam_inactive.png rename to plugins/watsyn/bam_inactive.png diff --git a/plugins/wtsynth/bmix_active.png b/plugins/watsyn/bmix_active.png similarity index 100% rename from plugins/wtsynth/bmix_active.png rename to plugins/watsyn/bmix_active.png diff --git a/plugins/wtsynth/bmix_inactive.png b/plugins/watsyn/bmix_inactive.png similarity index 100% rename from plugins/wtsynth/bmix_inactive.png rename to plugins/watsyn/bmix_inactive.png diff --git a/plugins/wtsynth/bpm_active.png b/plugins/watsyn/bpm_active.png similarity index 100% rename from plugins/wtsynth/bpm_active.png rename to plugins/watsyn/bpm_active.png diff --git a/plugins/wtsynth/bpm_inactive.png b/plugins/watsyn/bpm_inactive.png similarity index 100% rename from plugins/wtsynth/bpm_inactive.png rename to plugins/watsyn/bpm_inactive.png diff --git a/plugins/wtsynth/brm_active.png b/plugins/watsyn/brm_active.png similarity index 100% rename from plugins/wtsynth/brm_active.png rename to plugins/watsyn/brm_active.png diff --git a/plugins/wtsynth/brm_inactive.png b/plugins/watsyn/brm_inactive.png similarity index 100% rename from plugins/wtsynth/brm_inactive.png rename to plugins/watsyn/brm_inactive.png diff --git a/plugins/wtsynth/inv_active.png b/plugins/watsyn/inv_active.png similarity index 100% rename from plugins/wtsynth/inv_active.png rename to plugins/watsyn/inv_active.png diff --git a/plugins/wtsynth/inv_inactive.png b/plugins/watsyn/inv_inactive.png similarity index 100% rename from plugins/wtsynth/inv_inactive.png rename to plugins/watsyn/inv_inactive.png diff --git a/plugins/wtsynth/load_active.png b/plugins/watsyn/load_active.png similarity index 100% rename from plugins/wtsynth/load_active.png rename to plugins/watsyn/load_active.png diff --git a/plugins/wtsynth/load_inactive.png b/plugins/watsyn/load_inactive.png similarity index 100% rename from plugins/wtsynth/load_inactive.png rename to plugins/watsyn/load_inactive.png diff --git a/plugins/watsyn/logo.png b/plugins/watsyn/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..3e77966ff7431d50d581506636e01d9f0af828ea GIT binary patch literal 4425 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 P00000NkvXXu0mjf6lriw literal 0 HcmV?d00001 diff --git a/plugins/wtsynth/norm_active.png b/plugins/watsyn/norm_active.png similarity index 100% rename from plugins/wtsynth/norm_active.png rename to plugins/watsyn/norm_active.png diff --git a/plugins/wtsynth/norm_inactive.png b/plugins/watsyn/norm_inactive.png similarity index 100% rename from plugins/wtsynth/norm_inactive.png rename to plugins/watsyn/norm_inactive.png diff --git a/plugins/wtsynth/phl_active.png b/plugins/watsyn/phl_active.png similarity index 100% rename from plugins/wtsynth/phl_active.png rename to plugins/watsyn/phl_active.png diff --git a/plugins/wtsynth/phl_inactive.png b/plugins/watsyn/phl_inactive.png similarity index 100% rename from plugins/wtsynth/phl_inactive.png rename to plugins/watsyn/phl_inactive.png diff --git a/plugins/wtsynth/phr_active.png b/plugins/watsyn/phr_active.png similarity index 100% rename from plugins/wtsynth/phr_active.png rename to plugins/watsyn/phr_active.png diff --git a/plugins/wtsynth/phr_inactive.png b/plugins/watsyn/phr_inactive.png similarity index 100% rename from plugins/wtsynth/phr_inactive.png rename to plugins/watsyn/phr_inactive.png diff --git a/plugins/wtsynth/saw_active.png b/plugins/watsyn/saw_active.png similarity index 100% rename from plugins/wtsynth/saw_active.png rename to plugins/watsyn/saw_active.png diff --git a/plugins/wtsynth/saw_inactive.png b/plugins/watsyn/saw_inactive.png similarity index 100% rename from plugins/wtsynth/saw_inactive.png rename to plugins/watsyn/saw_inactive.png diff --git a/plugins/wtsynth/sin_active.png b/plugins/watsyn/sin_active.png similarity index 100% rename from plugins/wtsynth/sin_active.png rename to plugins/watsyn/sin_active.png diff --git a/plugins/wtsynth/sin_inactive.png b/plugins/watsyn/sin_inactive.png similarity index 100% rename from plugins/wtsynth/sin_inactive.png rename to plugins/watsyn/sin_inactive.png diff --git a/plugins/wtsynth/smooth_active.png b/plugins/watsyn/smooth_active.png similarity index 100% rename from plugins/wtsynth/smooth_active.png rename to plugins/watsyn/smooth_active.png diff --git a/plugins/wtsynth/smooth_inactive.png b/plugins/watsyn/smooth_inactive.png similarity index 100% rename from plugins/wtsynth/smooth_inactive.png rename to plugins/watsyn/smooth_inactive.png diff --git a/plugins/wtsynth/sqr_active.png b/plugins/watsyn/sqr_active.png similarity index 100% rename from plugins/wtsynth/sqr_active.png rename to plugins/watsyn/sqr_active.png diff --git a/plugins/wtsynth/sqr_inactive.png b/plugins/watsyn/sqr_inactive.png similarity index 100% rename from plugins/wtsynth/sqr_inactive.png rename to plugins/watsyn/sqr_inactive.png diff --git a/plugins/wtsynth/tri_active.png b/plugins/watsyn/tri_active.png similarity index 100% rename from plugins/wtsynth/tri_active.png rename to plugins/watsyn/tri_active.png diff --git a/plugins/wtsynth/tri_inactive.png b/plugins/watsyn/tri_inactive.png similarity index 100% rename from plugins/wtsynth/tri_inactive.png rename to plugins/watsyn/tri_inactive.png diff --git a/plugins/wtsynth/wavegraph.png b/plugins/watsyn/wavegraph.png similarity index 100% rename from plugins/wtsynth/wavegraph.png rename to plugins/watsyn/wavegraph.png diff --git a/plugins/wtsynth/CMakeLists.txt b/plugins/wtsynth/CMakeLists.txt deleted file mode 100644 index eb50e0544..000000000 --- a/plugins/wtsynth/CMakeLists.txt +++ /dev/null @@ -1,3 +0,0 @@ -INCLUDE(BuildPlugin) - -BUILD_PLUGIN( wtsynth WTSynth.cpp WTSynth.h MOCFILES WTSynth.h EMBEDDED_RESOURCES ${CMAKE_CURRENT_SOURCE_DIR}/*.png) diff --git a/plugins/wtsynth/logo.png b/plugins/wtsynth/logo.png deleted file mode 100644 index 4378e3ab4d2db625a31a9ebd03f040c28b72e924..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 174 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1SJ1Ryj={WI14-?iy0WWg+Z8+Vb&Z8pdfpR zr>`sfJ!TP66_agUlKDU($r9Iy66gHf+|;}h2Ir#G#FEq$h4Rdj3 Date: Tue, 25 Mar 2014 10:45:50 +0200 Subject: [PATCH 089/647] Switch back to linear interpolation... --- plugins/watsyn/Watsyn.h | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/plugins/watsyn/Watsyn.h b/plugins/watsyn/Watsyn.h index a6860cbed..a351351a4 100644 --- a/plugins/watsyn/Watsyn.h +++ b/plugins/watsyn/Watsyn.h @@ -99,23 +99,23 @@ public: private: // linear interpolation -/* inline sample_t interpolate( sample_t s1, sample_t s2, float x ) + inline sample_t interpolate( sample_t s1, sample_t s2, float x ) { return s1 + ( s2 - s1 ) * x; - }*/ - + } +/* // quick and dirty approximation of cubic interpolation inline sample_t interpolate( sample_t s1, sample_t s2, float x ) { const float x2 = powf( x, 2 ); const float x3 = powf( x, 3 ); - //const float m = s2 - s1; + const float m = s2 - s1; return ( ( x3 * 2.0 - x2 * 3.0 + 1.0 ) * s1 ) + - ( ( x3 * -2.0 + x2 * 3.0 ) * s2 );// + - //( ( x + x3 * 2.0 - x2 * 3.0 ) * m ); + ( ( x3 * -2.0 + x2 * 3.0 ) * s2 ); + + ( ( x + x3 * 2.0 - x2 * 3.0 ) * m ); } - +*/ // more accurate cubic interpolation... // consumes more cpu than ^ but doesn't bring a marked increase in sound quality IMO /* inline sample_t interpolate( sample_t s0, sample_t s1, sample_t s2, sample_t s3, float x ) From 4c2bf8982f819325e34454f4d9bfd3307f957cc8 Mon Sep 17 00:00:00 2001 From: Tobias Doerffel Date: Tue, 25 Mar 2014 20:09:41 +0100 Subject: [PATCH 090/647] CALF: fixed compilation with clang --- plugins/LadspaEffect/calf/src/calf/buffer.h | 2 +- plugins/LadspaEffect/calf/src/calf/fixed_point.h | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/plugins/LadspaEffect/calf/src/calf/buffer.h b/plugins/LadspaEffect/calf/src/calf/buffer.h index 373fbd1cd..1e7018f3a 100644 --- a/plugins/LadspaEffect/calf/src/calf/buffer.h +++ b/plugins/LadspaEffect/calf/src/calf/buffer.h @@ -153,7 +153,7 @@ void copy_buf(T &dest_buf, const U &src_buf, T scale = 1, T add = 0) { typedef typename T::data_type data_type; data_type *dest = dest_buf.data(); const data_type *src = src_buf.data(); - int size = src.size(); + int size = src_buf.size(); for (int i=0; i - inline U lerp_table_lookup_int(U data[(1<(data[pos], data[pos+1]); } @@ -224,19 +224,19 @@ public: /// Untested... I've started it to get a sin/cos readout for rotaryorgan, but decided to use table-less solution instead /// Do not assume it works, because it most probably doesn't template - inline U lerp_table_lookup_int_shift(U data[(1<(data[pos], data[pos+1]); } template - inline U lerp_table_lookup_float(U data[(1< - inline U lerp_table_lookup_float_mask(U data[(1< Date: Wed, 26 Mar 2014 00:22:14 +0200 Subject: [PATCH 091/647] Add smart oversampling interpolation --- plugins/watsyn/Watsyn.cpp | 38 ++++++++++++++++------ plugins/watsyn/Watsyn.h | 66 ++++++++++++++++++++++++++++++++------- 2 files changed, 82 insertions(+), 22 deletions(-) diff --git a/plugins/watsyn/Watsyn.cpp b/plugins/watsyn/Watsyn.cpp index b3b720d4d..747141304 100644 --- a/plugins/watsyn/Watsyn.cpp +++ b/plugins/watsyn/Watsyn.cpp @@ -81,6 +81,7 @@ WatsynObject::WatsynObject( float * _A1wave, float * _A2wave, m_rphase[B2_OSC] = 0.0f; // copy wavegraphs to the synth object to prevent race conditions + memcpy( &m_A1wave, _A1wave, sizeof( m_A1wave ) ); memcpy( &m_A2wave, _A2wave, sizeof( m_A2wave ) ); memcpy( &m_B1wave, _B1wave, sizeof( m_B1wave ) ); @@ -251,10 +252,10 @@ WatsynInstrument::WatsynInstrument( InstrumentTrack * _instrument_track ) : b1_rtune( 0.0f, -600.0f, 600.0f, 1.0f, this, tr( "Right detune B1" ) ), b2_rtune( 0.0f, -600.0f, 600.0f, 1.0f, this, tr( "Right detune B2" ) ), - a1_graph( -1.0f, 1.0f, WAVELEN, this ), - a2_graph( -1.0f, 1.0f, WAVELEN, this ), - b1_graph( -1.0f, 1.0f, WAVELEN, this ), - b2_graph( -1.0f, 1.0f, WAVELEN, this ), + a1_graph( -1.0f, 1.0f, GRAPHLEN, this ), + a2_graph( -1.0f, 1.0f, GRAPHLEN, this ), + b1_graph( -1.0f, 1.0f, GRAPHLEN, this ), + b2_graph( -1.0f, 1.0f, GRAPHLEN, this ), m_abmix( 0.0f, -100.0f, 100.0f, 0.1f, this, tr( "A-B Mix" ) ), m_envAmt( 0.0f, -200.0f, 200.0f, 1.0f, this, tr( "A-B Mix envelope amount" ) ), @@ -294,6 +295,11 @@ WatsynInstrument::WatsynInstrument( InstrumentTrack * _instrument_track ) : connect( &a2_rtune, SIGNAL( dataChanged() ), this, SLOT( updateFreq() ) ); connect( &b1_rtune, SIGNAL( dataChanged() ), this, SLOT( updateFreq() ) ); connect( &b2_rtune, SIGNAL( dataChanged() ), this, SLOT( updateFreq() ) ); + + connect( &a1_graph, SIGNAL( samplesChanged( int, int ) ), this, SLOT( updateWaves() ) ); + connect( &a2_graph, SIGNAL( samplesChanged( int, int ) ), this, SLOT( updateWaves() ) ); + connect( &b1_graph, SIGNAL( samplesChanged( int, int ) ), this, SLOT( updateWaves() ) ); + connect( &b2_graph, SIGNAL( samplesChanged( int, int ) ), this, SLOT( updateWaves() ) ); a1_graph.setWaveToSine(); a2_graph.setWaveToSine(); @@ -302,6 +308,7 @@ WatsynInstrument::WatsynInstrument( InstrumentTrack * _instrument_track ) : updateVolumes(); updateFreq(); + updateWaves(); } @@ -315,10 +322,11 @@ void WatsynInstrument::playNote( NotePlayHandle * _n, { if ( _n->totalFramesPlayed() == 0 || _n->m_pluginData == NULL ) { - WatsynObject * w = new WatsynObject( const_cast( a1_graph.samples() ), - const_cast( a2_graph.samples() ), - const_cast( b1_graph.samples() ), - const_cast( b2_graph.samples() ), + WatsynObject * w = new WatsynObject( + &A1_wave[0], + &A2_wave[0], + &B1_wave[0], + &B2_wave[0], m_amod.value(), m_bmod.value(), engine::mixer()->processingSampleRate(), _n, engine::mixer()->framesPerPeriod(), this ); @@ -491,7 +499,7 @@ void WatsynInstrument::saveSettings( QDomDocument & _doc, m_amod.saveSettings( _doc, _this, "amod" ); m_bmod.saveSettings( _doc, _this, "bmod" ); - m_selectedGraph.saveSettings( _doc, _this, "selgraph" ); +/* m_selectedGraph.saveSettings( _doc, _this, "selgraph" );*/ } @@ -548,7 +556,7 @@ void WatsynInstrument::loadSettings( const QDomElement & _this ) m_amod.loadSettings( _this, "amod" ); m_bmod.loadSettings( _this, "bmod" ); - m_selectedGraph.loadSettings( _this, "selgraph" ); +/* m_selectedGraph.loadSettings( _this, "selgraph" );*/ } @@ -596,6 +604,16 @@ void WatsynInstrument::updateFreq() } +void WatsynInstrument::updateWaves() +{ + // do cip+oversampling on the wavetables to improve quality + cipcpy( &A1_wave[0], const_cast( a1_graph.samples() ) ); + cipcpy( &A2_wave[0], const_cast( a2_graph.samples() ) ); + cipcpy( &B1_wave[0], const_cast( b1_graph.samples() ) ); + cipcpy( &B2_wave[0], const_cast( b2_graph.samples() ) ); +} + + WatsynView::WatsynView( Instrument * _instrument, QWidget * _parent ) : InstrumentView( _instrument, _parent ) diff --git a/plugins/watsyn/Watsyn.h b/plugins/watsyn/Watsyn.h index a351351a4..6ff570b3b 100644 --- a/plugins/watsyn/Watsyn.h +++ b/plugins/watsyn/Watsyn.h @@ -56,20 +56,24 @@ #define B2ROW 95 -extern const int WAVELEN = 220; -extern const int PMOD_AMT = 110; +const int GRAPHLEN = 220; +const int WAVELEN = 4400; -extern const int MOD_MIX = 0; -extern const int MOD_AM = 1; -extern const int MOD_RM = 2; -extern const int MOD_PM = 3; -extern const int NUM_MODS = 4; +const int WAVERATIO = WAVELEN / GRAPHLEN; -extern const int A1_OSC = 0; -extern const int A2_OSC = 1; -extern const int B1_OSC = 2; -extern const int B2_OSC = 3; -extern const int NUM_OSCS = 4; +const int PMOD_AMT = 110; + +const int MOD_MIX = 0; +const int MOD_AM = 1; +const int MOD_RM = 2; +const int MOD_PM = 3; +const int NUM_MODS = 4; + +const int A1_OSC = 0; +const int A2_OSC = 1; +const int B1_OSC = 2; +const int B2_OSC = 3; +const int NUM_OSCS = 4; class WatsynInstrument; @@ -131,6 +135,7 @@ private: ( ( x3 - x2 ) * m2 ); }*/ + int m_amod; int m_bmod; @@ -181,6 +186,7 @@ public: public slots: void updateVolumes(); void updateFreq(); + void updateWaves(); protected: float m_lvol [NUM_OSCS]; @@ -200,6 +206,37 @@ private: return ( _pan >= 0 ? 1.0 : 1.0 + ( _pan / 100.0 ) ) * _vol / 100.0; } + // memcpy with cubic interpolation (cip for short) and 10x oversampling to increase wavetable quality + inline void cipcpy( float * _dst, float * _src ) + { + // calculate cyclic tangents + float tang[GRAPHLEN]; + tang[0] = ( _src[1] - _src[ GRAPHLEN - 1] ) / 2; + tang[ GRAPHLEN - 1 ] = ( _src[0] - _src[ GRAPHLEN - 2 ] ) / 2; + for( int i = 1; i < GRAPHLEN-1; i++ ) + { + tang[i] = ( _src[i+1] - _src[i-1] ) / 2; + } + + // calculate cspline + for( int i=0; i < WAVELEN; i++ ) + { + const float s1 = _src[ i / WAVERATIO ]; + const float s2 = _src[ ( i / WAVERATIO + 1 ) % GRAPHLEN ]; + const float m1 = tang[ i / WAVERATIO ]; + const float m2 = tang[ ( i / WAVERATIO + 1 ) % GRAPHLEN ]; + + const float x = static_cast( i % WAVERATIO ) / WAVERATIO; + const float x2 = x * x; + const float x3 = x * x * x; + + _dst[i] = ( ( x3 * 2.0 - x2 * 3.0 + 1.0 ) * s1 ) + + ( ( x3 * -2.0 + x2 * 3.0 ) * s2 ) + + ( ( x3 - x2 * 2 + x ) * m1 ) + + ( ( x3 - x2 ) * m2 ); + } + } + FloatModel a1_vol; FloatModel a2_vol; FloatModel b1_vol; @@ -244,6 +281,11 @@ private: IntModel m_bmod; IntModel m_selectedGraph; + + float A1_wave [WAVELEN]; + float A2_wave [WAVELEN]; + float B1_wave [WAVELEN]; + float B2_wave [WAVELEN]; friend class WatsynObject; friend class WatsynView; From 07d37e0fbc66b14cadf387dbf8d0c04c87fab9ff Mon Sep 17 00:00:00 2001 From: Vesa Date: Wed, 26 Mar 2014 00:39:27 +0200 Subject: [PATCH 092/647] Forgot to change phasemod constant --- plugins/watsyn/Watsyn.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/watsyn/Watsyn.h b/plugins/watsyn/Watsyn.h index 6ff570b3b..5b4072202 100644 --- a/plugins/watsyn/Watsyn.h +++ b/plugins/watsyn/Watsyn.h @@ -61,7 +61,7 @@ const int WAVELEN = 4400; const int WAVERATIO = WAVELEN / GRAPHLEN; -const int PMOD_AMT = 110; +const int PMOD_AMT = WAVELEN / 2; const int MOD_MIX = 0; const int MOD_AM = 1; From 1b08cc064999c905bd6d1b8feb22a1dee4da2126 Mon Sep 17 00:00:00 2001 From: Tobias Doerffel Date: Wed, 26 Mar 2014 10:57:04 +0100 Subject: [PATCH 093/647] CALF: do not compile with -finline-limit=80 when building for OS X --- plugins/LadspaEffect/calf/CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/LadspaEffect/calf/CMakeLists.txt b/plugins/LadspaEffect/calf/CMakeLists.txt index 9d766736d..db6dea7a5 100644 --- a/plugins/LadspaEffect/calf/CMakeLists.txt +++ b/plugins/LadspaEffect/calf/CMakeLists.txt @@ -8,9 +8,9 @@ INSTALL(TARGETS calf LIBRARY DESTINATION "${PLUGIN_DIR}/ladspa") SET_TARGET_PROPERTIES(calf PROPERTIES PREFIX "") SET(INLINE_FLAGS "") IF(NOT LMMS_BUILD_APPLE) -SET(INLINE_FLAGS "-finline-functions-called-once") +SET(INLINE_FLAGS "-finline-functions-called-once -finline-limit=80") ENDIF(NOT LMMS_BUILD_APPLE) -SET_TARGET_PROPERTIES(calf PROPERTIES COMPILE_FLAGS "-O2 -finline-limit=80 -finline-functions ${INLINE_FLAGS}") +SET_TARGET_PROPERTIES(calf PROPERTIES COMPILE_FLAGS "-O2 -finline-functions ${INLINE_FLAGS}") IF(LMMS_BUILD_WIN32) ADD_CUSTOM_COMMAND(TARGET calf POST_BUILD COMMAND "${STRIP}" "\"${CMAKE_CURRENT_BINARY_DIR}/calf.dll\"") From f0b6d34b3aa3fde67b3e53d511056439120849f0 Mon Sep 17 00:00:00 2001 From: Tobias Doerffel Date: Wed, 26 Mar 2014 11:06:24 +0100 Subject: [PATCH 094/647] Removed old ChangeLog --- ChangeLog.old | 17877 ------------------------------------------------ 1 file changed, 17877 deletions(-) delete mode 100644 ChangeLog.old diff --git a/ChangeLog.old b/ChangeLog.old deleted file mode 100644 index f9ed32886..000000000 --- a/ChangeLog.old +++ /dev/null @@ -1,17877 +0,0 @@ -2009-02-23 Tobias Doerffel - - * README: - * CMakeLists.txt: - made 0.4.3 release - - * include/atomic_int.h: - - fixed typo - - added copy constructor implementation for AtomicInt class - fixes - build failure with Qt < 4.4.0 - - * CMakeLists.txt: - fixed typos - - * cmake/modules/FindSTK.cmake: - * CMakeLists.txt: - reflect changes in MinGW crosscompiling environment - -2009-02-19 Tobias Doerffel - - * include/fade_button.h: - * src/gui/widgets/fade_button.cpp: - rewrote timing of fading animation for not postponing updates of - hidden fadeButton until it becomes visible - - * src/gui/widgets/automatable_button.cpp: - * src/core/track.cpp: - make sure all buttons in trackOperationsWidget have focus-policy - set to Qt::NoFocus in order to make space play song even if you clicked - e.g. a mute-button (closes #2486211) - - * include/note.h: - * src/core/note.cpp: - - coding style fixes - - improved handling of shared detuningHelper object - - * include/instrument_track.h: - * include/piano_roll.h: - * src/gui/piano_roll.cpp: - * src/gui/song_editor.cpp: - * src/tracks/instrument_track.cpp: - fixed various bugs regarding recording: - - once recording has been started, stop it as soon as playMode of song - changes or similiar things happen (closes #2486341) - - fixed broken record-accompany in most use-cases other than using - record-while-playing-song by also tracking NoteOn events and remember - current play position to use the correct note postitions on NoteOff - events (play position might have wrapped around in the meantime due - to looppoints or end of BB track) (closes #2486299, #2486203) - - move timeLine marker in Piano Roll and autoscroll when recording while - playing song (closes #2486334) - -2009-02-14 Tobias Doerffel - - * src/3rdparty/samplerate/samplerate.h: - reverted rev 2037 as we have custom changes in this file - -2009-02-13 Tobias Doerffel - - * include/pattern.h: - * src/tracks/pattern.cpp: - - added missing slot declaration for abortFreeze(), fixes lockup when - freezing pattern (closes #2530320) - - update patternView after freezing - - fixed drawing of frozen pattern - - * include/sample_buffer.h: - * src/core/sample_buffer.cpp: - - when resampling whole sampleBuffer, set end_of_input = 1 in - libsamplerate data struct - fixes lots of zero samples at the end - of output buffer (closes #2531452) - - coding style fixes - - removed obsolete save/restore of EOF-property in libsample rate - data struct when resampling successively (always use 0) - - * src/3rdparty/samplerate/src_linear.c: - * src/3rdparty/samplerate/samplerate.h: - * src/3rdparty/samplerate/src_sinc.c: - * src/3rdparty/samplerate/src_zoh.c: - * src/3rdparty/samplerate/samplerate.c: - * CMakeLists.txt: - integrated latest libsamplerate which is both faster and more reliable - - * src/gui/widgets/visualization_widget.cpp: - disable output monitor per default and show click-hint - -2009-02-12 Tobias Doerffel - - * include/group_box.h: - * src/gui/widgets/effect_rack_view.cpp: - backport: manage effectRackView with a QVBoxLayout - - * src/gui/widgets/controller_rack_view.cpp: - * src/gui/widgets/effect_rack_view.cpp: - backport: prevent Horizontal bars from appearing in some cases - - * cmake/modules/Win32Toolchain.cmake: - reflect recent changes to MinGW cross compiling environment - - * plugins/sf2_player/sf2_player.cpp: - update patch after loading settings (closes #2486372) - - * src/gui/piano_roll.cpp: - ensure, cursor is never NULL when painting it in paintEvent() - - * src/core/sample_buffer.cpp: - do not load samples bigger than 100 MB (closes #2458375) - -2009-02-05 Tobias Doerffel - - * plugins/ladspa_effect/caps/dsp/Eq.h: - better workaround for optimizer bug in GCC >= 4.3 - - * plugins/sid/sid_instrument.cpp: - * plugins/flp_import/unrtf.cpp: - * src/core/track.cpp: - added missing header for compilation with GCC 4.4 - - * include/pattern.h: - * src/tracks/pattern.cpp: - cleanups - - * src/core/envelope_and_lfo_parameters.cpp: - - simplified formulas for calculating envelope array resulting in about - 3x performance with traditional FPU code - - loops now can be vectorized by GCC 4.4 - - * include/atomic_int.h: - * include/audio_port.h: - * include/mixer.h: - * src/core/mixer.cpp: - reworked mixer-threads (synchronization, realization of jobqueue etc.) - which results in a much better performance and stability - -2009-02-04 Andrew Kelley - - * src/gui/piano_roll.cpp: - fixed bug: you can use shift+left to move notes past the beginning - -2009-02-01 Andrew Kelley - - * src/core/track.cpp: - integrated pitanga's patch to fix unquantized BB dragging in - song editor. Changed ctrl modifier to alt to be consistent. - -2009-01-25 Paul Giblock - - * src/tracks/bb_track.cpp: - Integrate broken BB-clone bug from pitanga - -2009-01-25 Paul Giblock - - * src/gui/widgets/knob.cpp: - Fix infinite recursion on Mac OSX - - * plugins/flp_import/unrtf/html.c: - * plugins/flp_import/unrtf/output.h: - * plugins/flp_import/unrtf/convert.c: - Avoid compile warnings - -2009-01-03 Paul Giblock - - * src/gui/widgets/automatable_button.cpp: - fix drag support for button groups - -2008-12-22 Tobias Doerffel - - * CMakeLists.txt: - fixed plugins/ directory when updating localization file - - * plugins/flp_import/flp_import.cpp: - in FL_EffectChannel initialize isMuted member - fixes muted FX channels - when importing older FLP files - -2008-12-19 Tobias Doerffel - - * CMakeLists.txt: - * README: - made 0.4.2 release - - * plugins/vst_base/vst_plugin.h: - * plugins/vst_base/vst_plugin.cpp: - * plugins/vst_effect/vst_effect_control_dialog.cpp: - * plugins/vst_effect/vst_effect.cpp: - * plugins/vestige/vestige.cpp: - fixed crash when adding VST effects - - * include/project_version.h: - * src/core/project_version.cpp: - fixed broken version comparing which indicated 0.x.y to be less than - 0.x.y-patch - fixes messed up projects when loading files created - with LMMS 0.4.0 - -2008-12-17 Tobias Doerffel - - * CMakeLists.txt: - * README: - made 0.4.1 release - - * cmake/modules/FindSTK.cmake: - * include/combobox_model.h: - * include/combobox.h: - * src/core/config_mgr.cpp: - * data/CMakeLists.txt: - * CMakeLists.txt: - added STK support to win32 version of LMMS - - * data/locale/ja.ts: - * data/locale/ja.qm: - added Japanese localization files by - Keishi Suenaga - - * include/instrument_track.h: - * src/tracks/instrument_track.cpp: - backport: do not create a instrument track window just for calling - dragEnterEvent() - use a static method instead - -2008-12-17 Paul Giblock - - * include/track.h: - * src/core/track.cpp: - backport: cache background per-object instead of per-class - -2008-12-17 Andrew Kelley - - * AUTHORS: - backport: added Andrew Kelley as author - - * src/core/timeline.cpp: - * src/gui/automatable_model_view.cpp: - * src/gui/automation_editor.cpp: - * src/gui/piano_roll.cpp: - * src/gui/widgets/automatable_button.cpp: - * src/gui/widgets/automatable_slider.cpp: - * src/gui/widgets/combobox.cpp: - * src/gui/widgets/fader.cpp: - * src/gui/widgets/knob.cpp: - * src/gui/widgets/lcd_spinbox.cpp: - * src/tracks/sample_track.cpp: - backport: changed modifier detection from mainWindow::isCtrlPressed - etc to Qt framework detection. Fixes a bunch of little glitches and - enables horizontal scroll wheels. - - * include/midi.h: - * include/note.h: - * include/panning.h: - * include/panning_constants.h: - * include/pattern.h: - * include/piano_roll.h: - * src/core/note.cpp: - * src/core/piano.cpp: - * src/tracks/pattern.cpp: - backport: added support for panning editing of notes - -2008-12-15 Paul Giblock - - * src/core/track.cpp: - * include/track.h: - Cache background per-object instead of per-class. - -2008-12-14 Tobias Doerffel - - * CMakeLists.txt: - require at least Qt 4.3.0 - -2008-12-11 Tobias Doerffel - - * include/automation_pattern.h: - * src/core/automation_pattern.cpp: - do not disable automation when just editing first point of an - automation pattern (closes #2146230) - - * include/automation_pattern_view.h: - * src/gui/automation_pattern_view.cpp: - splitted view component out of automation_pattern.* - -2008-12-10 Tobias Doerffel - - * plugins/vst_base/communication.h: - * plugins/vst_base/vst_plugin.cpp: - * plugins/vst_base/remote_vst_plugin.cpp: - rewrote wide parts of LVSL backend: - - now supports two threading models which makes LMMS support plugins - like Sytrus, z3ta+ etc. - - on win32 create native widget as parent for plugin's GUI, fixes - warning message when loading KarmaSynth (closes #2276787) - - try more symbol names for entry procedure - - * include/aeffectx.h: - - made "int"s to "const int"s - - added CCONST macro - - * include/remote_plugin.h: - * src/core/remote_plugin.cpp: - added support for debug messages from remote plugin - -2008-12-08 Tobias Doerffel - - * plugins/vst_base/vst_plugin.cpp: - win32-version: fixed crash when using VST plugins without GUI - - * include/effect_chain.h: - export effectChain for properly building FLP import DLL - - * include/song_editor.h: - * src/gui/song_editor.cpp: - fixed recent commit (m_timeLine was not declared as member yet) - -2008-12-07 Andrew Kelley - - * src/gui/song_editor.cpp: - fixed glitch where it would auto-scroll even if it was off in - song-editor - -2008-12-04 Tobias Doerffel - - * plugins/vst_base/remote_vst_plugin.cpp: - explicitely declare updateSampleRate() and updateBufferSize() as virtual - - * src/tracks/instrument_track.cpp: - decreased step-property of volumeModel and panningModel from 1.0 to 0.1 - for allowing smoother transitions when automating etc. - -2008-12-02 Tobias Doerffel - - * data/locale/ja.ts: - * data/locale/ja.qm: - added Japanese localization files by - Keishi Suenaga - -2008-12-01 Tobias Doerffel - - * plugins/triple_oscillator/triple_oscillator.cpp: - per default play sub-octaves of first oscillator in osc 2 and 3 - -2008-11-22 Tobias Doerffel - - * src/core/automatable_model.cpp: - fixed wrong logic in automatableModel::setValue() which led to bugs when - changing linked controls to 0 - - * src/gui/file_browser.cpp: - do not allow to import unhandled file types, e.g. ZynAddSubFX presets if - plugin is not available (closes #2326384) - -2008-11-21 Tobias Doerffel - - * plugins/flp_import/flp_import.h: - * plugins/flp_import/flp_import.cpp: - completely rewrote FLP import filter since it didn't work at all - anymore - it now doesn't create or change any things in LMMS while - importing and instead builds up a complete data structure first - which represents the FL Studio project and then creates an LMMS - project based upon this data structure - - now supports projects from FL Studio 3 to 8 - - more verbose debug output - - import volume, panning, pitch and FX channel for instrument tracks - - import amplification, loop-mode and reverse-mode settings for - AudioFileProcessor - - import FX mixer settings and effects - - import automation data - - import channel- and pattern names - - import volume and panning settings of individual notes - - add notes of instrument layer master to each layer children for at - least having a complete sound - need to replace with real layering - support later - - map more instruments to various LMMS instruments - - fixed calculations of length and position of notes - - fixed importing steps/dots - - fixed scaling factor of various controls (arpeggio time, - envelope sustain and amount, filter cut/res, TripleOsc volumes etc.) - - if three user defined samples were found for TripleOscillator set - first oscillator to oscillator::SawWave - - * plugins/flp_import/unrtf.cpp: - * plugins/flp_import/CMakeLists.txt: - * plugins/flp_import/unrtf/error.h: - * plugins/flp_import/unrtf/output.c: - * plugins/flp_import/unrtf/html.c: - * plugins/flp_import/unrtf/output.h: - * plugins/flp_import/unrtf/malloc.c: - * plugins/flp_import/unrtf/html.h: - * plugins/flp_import/unrtf/attr.c: - * plugins/flp_import/unrtf/parse.c: - * plugins/flp_import/unrtf/word.c: - * plugins/flp_import/unrtf/malloc.h: - * plugins/flp_import/unrtf/util.c: - * plugins/flp_import/unrtf/attr.h: - * plugins/flp_import/unrtf/parse.h: - * plugins/flp_import/unrtf/convert.c: - * plugins/flp_import/unrtf/word.h: - * plugins/flp_import/unrtf/util.h: - * plugins/flp_import/unrtf/hash.c: - * plugins/flp_import/unrtf/convert.h: - * plugins/flp_import/unrtf/defs.h: - * plugins/flp_import/unrtf/hash.h: - * plugins/flp_import/unrtf/main.h: - * plugins/flp_import/unrtf/error.c: - updated to latest version of unrtf and improved string operations - - * src/core/main.cpp: - added support for importing file from commandline - - * include/effect_chain.h: - added method for enabling/disabling FX chain - - * include/file_browser.h: - * src/gui/file_browser.cpp: - enhanced support for importing various file types directly from browser - - * include/pattern.h: - * src/tracks/pattern.cpp: - added method for toggling steps - - * include/fx_mixer.h: - added method for accessing FX channels - - * plugins/midi_import/midi_import.cpp: - check for tempoAutomationPattern being NULL for not crashing when - importing to BB-Editor - - * include/instrument_track.h: - return pointers instead of references to various internal models - - * include/basic_filters.h: - * include/bb_track_container.h: - * include/instrument_track.h: - * include/pattern.h: - * include/track_container.h: - * src/core/instrument_functions.cpp: - * src/tracks/pattern.cpp: - * src/gui/track_container_view.cpp: - coding style fixes - -2008-11-11 Tobias Doerffel - - * src/core/track.cpp: - * src/core/timeline.cpp: - * src/core/piano.cpp: - * src/core/automation_pattern.cpp: - * src/gui/piano_roll.cpp: - * src/gui/fx_mixer_view.cpp: - * src/gui/widgets/track_label_button.cpp: - * src/gui/widgets/visualization_widget.cpp: - * src/gui/widgets/combobox.cpp: - * src/gui/widgets/tab_widget.cpp: - * src/gui/widgets/kmultitabbar.cpp: - * src/gui/widgets/envelope_and_lfo_view.cpp: - * src/gui/widgets/cpuload_widget.cpp: - * src/gui/widgets/fade_button.cpp: - * src/gui/widgets/lcd_spinbox.cpp: - * src/gui/widgets/group_box.cpp: - * src/gui/widgets/fader.cpp: - * src/gui/widgets/effect_rack_view.cpp: - * src/gui/widgets/effect_view.cpp: - * src/gui/automation_editor.cpp: - set OpaquePaintEvent attribute for all widgets where suitable - makes - whole GUI less sluggish :) - -2008-11-04 Tobias Doerffel - - * plugins/sf2_player/sf2_player.cpp: - fixed broken reference sharing - - * include/automatable_model.h: - * src/core/automatable_model.cpp: - fixed loops when adding a controller to a model which is linked to - another model - - * src/core/effect.cpp: - call saveSettings()/loadSettings() on model rather than loading/saving - value directly - fixes lost automation on basic effect controls - -2008-10-30 Tobias Doerffel - - * CMakeLists.txt: - made 0.4.0 release - - * CMakeLists.txt: - - include all necessary DLLs in win64 build - - fix versioning for CPack if no VERSION_SUFFIX is set - - * plugins/sid/sid_instrument.cpp: - * plugins/papu/papu_instrument.cpp: - * include/clipboard.h: - include QtXml/QDomElement rather than Qt/QtXml - fixes compilation on - OS X - -2008-10-29 Tobias Doerffel - - * plugins/ladspa_effect/ladspa_effect.cpp: - limit processing of TAP Reflector to 192 KHz as it otherwise crashes - - * include/timeline.h: - * src/gui/piano_roll.cpp: - fixed autoscroll feature in piano-roll (closes #2204508) - -2008-10-28 Tobias Doerffel - - * CMakeLists.txt: - disabled PortAudio support until a fix for the crash when accepting - setup-dialog is available - -2008-10-27 Tobias Doerffel - - * data/presets/TripleOscillator/SEGuitar.xpf: - * data/presets/TripleOscillator/SBass2.xpf: - * data/presets/TripleOscillator/STrash.xpf: - * data/presets/TripleOscillator/SString.xpf: - * data/presets/TripleOscillator/SBass.xpf: - added some cool presets by Skiessi - - * plugins/ladspa_effect/ladspa_effect.cpp: - added Freeverb to blacklist as it does not work samplerate independent - - * cmake/modules/Win64Toolchain.cmake: - * cmake/modules/DetectMachine.cmake: - * cmake/modules/BuildPlugin.cmake: - * plugins/ladspa_effect/swh/CMakeLists.txt: - * plugins/ladspa_effect/cmt/CMakeLists.txt: - * plugins/ladspa_effect/tap/CMakeLists.txt: - * plugins/ladspa_effect/caps/CMakeLists.txt: - * plugins/ladspa_effect/caps/dsp/windows.h: - * plugins/vst_base/remote_vst_plugin.cpp: - * plugins/vst_base/basename.c: - * plugins/vst_base/CMakeLists.txt: - * plugins/midi_import/portsmf/allegro.h: - * src/core/midi/midi_winmm.cpp: - * src/core/mixer.cpp: - * lmmsconfig.h.in: - * CMakeLists.txt: - various fixes for successfully building LMMS for win64 - -2008-10-25 Tobias Doerffel - - * include/mixer.h: - * src/core/mixer.cpp: - * src/core/project_renderer.cpp: - - initial (not yet enabled) support for binding mixer threads to CPUs to - reduce scheduling overhead and cache misses (gives avg. 10% performance - boost) - - merged mixer-thread with first worker-thread - no more duplicate - code for single- and multicore processing and better scheduling - on multicore systems - - * include/automatable_model.h: - * src/core/automatable_model.cpp: - * src/core/audio/audio_alsa.cpp: - * src/core/audio/audio_oss.cpp: - * src/core/audio/audio_jack.cpp: - * src/core/envelope_and_lfo_parameters.cpp: - * src/core/piano.cpp: - * src/core/controller.cpp: - * src/gui/fx_mixer_view.cpp: - * src/gui/widgets/combobox.cpp: - * src/gui/widgets/envelope_and_lfo_view.cpp: - * src/gui/widgets/knob.cpp: - * src/gui/widgets/instrument_midi_io_view.cpp: - * src/gui/widgets/automatable_slider.cpp: - * src/gui/widgets/lcd_spinbox.cpp: - * src/gui/widgets/fader.cpp: - * src/gui/widgets/automatable_button.cpp: - * src/tracks/automation_track.cpp: - do not inline code for fetching value from controller and thus reduce - header dependencies - - * plugins/vst_effect/CMakeLists.txt: - * plugins/vestige/CMakeLists.txt: - * plugins/vst_base/CMakeLists.txt: - * CMakeLists.txt: - made building the WINE-part of VST Support Layer optional to allow - packaging it in separate package (e.g. on 64 bit platforms) - -2008-10-25 dieEasy - - * data/locale/it.qm: - * data/locale/it.ts: - updated Italian localization - -2008-10-25 Tobias Doerffel - - * data/locale/cs.qm: - * data/locale/pt_br.qm: - * data/locale/es.qm: - * data/locale/fr.qm: - * data/locale/nl.qm: - * data/locale/ir.qm: - * data/locale/en.ts: - * data/locale/cs.ts: - * data/locale/pt_br.ts: - * data/locale/es.ts: - * data/locale/fr.ts: - * data/locale/nl.ts: - * data/locale/ca.qm: - * data/locale/ir.ts: - * data/locale/ru.qm: - * data/locale/sv.qm: - * data/locale/ca.ts: - * data/locale/ru.ts: - * data/locale/sv.ts: - * data/locale/en.qm: - refreshed localization files - - * data/locale/de.ts: - * data/locale/de.qm: - updated German localization file - - * src/gui/lfo_controller_dialog.cpp: - fixed strings - - * include/file_browser.h: - * src/gui/file_browser.cpp: - renamed class "listView" to "fileBrowserTreeWidget" - - * cmake/modules/DetectMachine.cmake: - allow specifying destination directory for libs via CMAKE_INSTALL_LIBDIR - - * src/core/sample_buffer.cpp: - - fixed out-of-boundary array access when reversing samples - - optimized loops for loading samples - -2008-10-21 Tobias Doerffel - - * include/plugin.h: - reverted to rev. 1766 - fixes broken label on LADSPA effects - - * include/knob.h: - * src/gui/widgets/knob.cpp: - track focusOutEvents in order to unhide cursor in certain situations - -2008-10-20 Tobias Doerffel - - * CMakeLists.txt: - made 0.4.0-rc3 release - - * README: - various fixes - - * src/gui/dialogs/about_dialog.ui: - use QTextEdit rather than QPlainTextEdit for Qt 4.3 compatibility - -2008-10-19 Tobias Doerffel - - * plugins/sid/sid_instrument.cpp: - * plugins/ladspa_effect/ladspa_effect.cpp: - * plugins/patman/patman.cpp: - * plugins/lb302/lb302.cpp: - * plugins/organic/organic.cpp: - * plugins/lb303/lb303.cpp: - * plugins/stereo_matrix/stereo_matrix.cpp: - * plugins/bass_booster/bass_booster.cpp: - * plugins/bit_invader/bit_invader.cpp: - * plugins/vst_effect/vst_effect.cpp: - * plugins/vibed/vibed.cpp: - * plugins/triple_oscillator/triple_oscillator.cpp: - * plugins/peak_controller_effect/peak_controller_effect.cpp: - * plugins/audio_file_processor/audio_file_processor.cpp: - * plugins/stk/mallets/mallets.cpp: - * plugins/stereo_enhancer/stereo_enhancer.cpp: - * plugins/papu/papu_instrument.cpp: - * plugins/sf2_player/sf2_player.cpp: - * plugins/vestige/vestige.cpp: - * plugins/vst_base/vst_base.cpp: - * plugins/ladspa_browser/ladspa_browser.cpp: - * plugins/spectrum_analyzer/spectrum_analyzer.cpp: - * plugins/kicker/kicker.cpp: - * plugins/flp_import/flp_import.cpp: - * plugins/midi_import/midi_import.cpp: - * include/embed.h: - * include/lmms_basics.h: - * include/plugin.h: - * src/gui/embed.cpp: - made STRINGIFY_PLUGIN_NAME from embed.h a generic macro STRINGIFY in - lmms_basics.h - - * include/about_dialog.h: - * src/gui/about_dialog.cpp: - * src/gui/dialogs/about_dialog.ui: - designed-based about dialog - - * src/gui/widgets/rename_dialog.cpp: - initially select whole string so it can be overwritten easily - - * AUTHORS: - moved an item to lmms-extras/AUTHORS - - * plugins/vst_base/vst_plugin.h: - * plugins/vst_base/vst_plugin.cpp: - * plugins/vst_effect/vst_effect_control_dialog.cpp: - improved VST GUI embedding (closes #2167745) - - * src/gui/track_container_view.cpp: - do not call method on deleted trackView but fetch pointer to track - before deleting trackView (fixes crash when removing a track) - -2008-10-18 Tobias Doerffel - - * src/gui/widgets/track_label_button.cpp: - more checks before accessing icon - fixes crash when using ZynAddSubFX - plugin - - * plugins/vst_base/remote_vst_plugin.cpp: - various tweakings - - * src/core/piano.cpp: - check for focusWidget() being NULL before checking inheritance - fixes - crash for example when loading VST plugins - - * src/gui/main_window.cpp: - use "Root directory" rather than "My computer" in non-win32-version - - * cmake/modules/FindAlsa.cmake: - * CMakeLists.txt: - do not create alsaconfig.h - - * plugins/sf2_player/sf2_player.cpp: - do not mess around with global static pointers for a single instance - of patchesDialog - create a local object instead (closes #2139701) - - * include/file_browser.h: - * src/gui/file_browser.cpp: - added filter feature allowing quick file access - - * include/file_browser.h: - * src/gui/main_window.cpp: - * src/gui/file_browser.cpp: - * data/themes/default/computer.png: - * data/themes/default/home.png: - - renamed tab "root" to "My computer" - - on win32 allow browsing drives in "My computer" tab - - improved icons for home and "My computer" browser - - * include/embed.h: - * include/instrument_track.h: - * include/plugin.h: - * include/track_label_button.h: - * src/gui/widgets/track_label_button.cpp: - in instrument tracks draw icon of instrument rather than displaying the - full name of the instrument on track label button - - * src/tracks/instrument_track.cpp: - do not call trackView::dragEnterEvent() if instrument track window - already accepted drag event - fixes dragging of presets and - instruments onto track label button - - * src/core/piano.cpp: - do not reclaim keyboard focus if new focus widget is a QLineEdit - -2008-10-17 Tobias Doerffel - - * include/remote_plugin.h: - * src/core/remote_plugin.cpp: - added helper thread processWatcher which monitors the remote plugin - process - if it terminates unexpectedly, invalidate remotePlugin so - LMMS doesn't lock up - fixes crashes and lockups when using VST - plugins or ZynAddSubFX plugin - -2008-10-16 Tobias Doerffel - - * src/core/piano.cpp: - reclaim keyboard focus if the current focus-widget lives in the same - instrument-track-window as the previously active test piano - this way - running notes are not stopped when modifying a control in the same - instrument-track-window (closes #2139806) - - * include/file_browser.h: - * src/gui/file_browser.cpp: - heavily improved performance when adding items to file browser - tree-widget (closes #2146218) - -2008-10-15 dieEasy - - * data/locale/it.qm: - * data/locale/it.ts: - updated Italian localization - -2008-10-15 Tobias Doerffel - - * data/locale/cs.qm: - * data/locale/cs.ts: - added Czech localization by Ludek Cerny - - * src/core/timeline.cpp: - move position marker lines even if autoscrolling is disabled - - * include/envelope_and_lfo_parameters.h: - * src/core/envelope_and_lfo_parameters.cpp: - reverted to rev. 1479 as the optimizations lately completely screwed - up things... - - * plugins/flp_import/flp_import.cpp: - * include/basic_filters.h: - cleanups - -2008-10-14 Tobias Doerffel - - * tests/README: - * tests/emptyproject.mmp: - first initial "test" - - * src/core/mixer.cpp: - - use ordered memory semantics for atomic int - - more debug output when encountering bad jobqueue items - - * CMakeLists.txt: - improved dependency handling for building manpage - -2008-10-06 Tobias Doerffel - - * include/mmp.h: - * include/cpuload_widget.h: - * include/endian_handling.h: - * include/track.h: - * include/controller_rack_view.h: - * include/mixer.h: - * include/ladspa_manager.h: - * include/instrument_functions.h: - * include/sample_buffer.h: - * include/effect_lib.h: - * include/midi.h: - * include/effect_rack_view.h: - * include/graph.h: - * include/micro_timer.h: - * include/envelope_and_lfo_parameters.h: - * include/piano_roll.h: - * include/volume.h: - * include/midi_time.h: - * include/basic_filters.h: - * include/journalling_object.h: - * include/automation_editor.h: - * include/panning.h: - * include/project_journal.h: - * include/play_handle.h: - * plugins/bit_invader/bit_invader.h: - * plugins/vibed/vibrating_string.h: - * plugins/vibed/nine_button_selector.h: - * plugins/vibed/string_container.h: - * plugins/vst_base/remote_vst_plugin.cpp: - * src/core/base64.cpp: - * src/gui/widgets/side_bar_widget.cpp: - renamed types.h to lmms_basics.h - -2008-10-06 Attila Herman - - * plugins/papu/papu_intrument.cpp: - - renamed from PAPU to FreeBoy - - help added to the knobs - -2008-10-04 Tobias Doerffel - - * plugins/kicker/kicker.cpp: - moved constants out of loop - - * include/types.h: - set global alignment via a #define - - * src/gui/piano_roll.cpp: - - fixed typo - - do not crash when pressing right mouse button while moving a note - with left mouse button - - * src/core/song.cpp: - lock mixer while adjusting lengths of notePlayHandles after tempo change - - * src/gui/file_browser.cpp: - * src/core/note_play_handle.cpp: - * src/core/audio/audio_port.cpp: - coding style fixes - - * include/mixer.h: - * src/core/mixer.cpp: - removed fine-granular locking of various playHandle-vectors, just use - one global big lock for everything now - prevents various - deadlocks (e.g. when previewing samples in file browser) - - * src/gui/automation_editor.cpp: - in erase-mode do not remove values without clicking - - * src/core/envelope_and_lfo_parameters.cpp: - fixed what I broke a few hours ago.. (closes #2146864) - - * src/core/mmp.cpp: - fixed extension for presets - - * plugins/ladspa_effect/ladspa_effect.cpp: - * include/automatable_model.h: - * include/automation_pattern.h: - * src/core/automatable_model.cpp: - * src/core/ladspa_control.cpp: - * src/core/automation_pattern.cpp: - fixed lost automation relations when switching samplerate - - * plugins/lb302/lb302.cpp: - * plugins/lb302/lb302.h: - * plugins/bass_booster/bass_booster.cpp: - * plugins/bass_booster/bass_booster.h: - * plugins/bit_invader/bit_invader.cpp: - * plugins/vst_effect/vst_effect.cpp: - * plugins/peak_controller_effect/peak_controller_effect.cpp: - * plugins/stereo_enhancer/stereo_enhancer.cpp: - * plugins/stereo_enhancer/stereo_enhancer.h: - * plugins/spectrum_analyzer/spectrumanalyzer_control_dialog.cpp: - * plugins/kicker/kicker.cpp: - * include/sweep_oscillator.h: - * include/envelope_and_lfo_parameters.h: - * include/remote_plugin.h: - * include/types.h: - * src/core/midi/midi_client.cpp: - * src/core/journalling_object.cpp: - * src/core/audio/audio_pulseaudio.cpp: - * src/core/envelope_and_lfo_parameters.cpp: - * src/core/instrument_sound_shaping.cpp: - * src/core/effect.cpp: - * src/core/ladspa_control.cpp: - * src/core/peak_controller.cpp: - * src/gui/widgets/visualization_widget.cpp: - * src/gui/widgets/tempo_sync_knob.cpp: - - added missing includes to compile with GCC 4.4 - - optimized various loops for getting tree-vectorized, especially with - upcoming GCC 4.4 - - * CMakeLists.txt: - use -ftree-vectorize per default - everyone compiling LMMS (which - needs Qt >= 4.3.0) will at least have GCC 4.1, anyways only makes - sense when setting C(XX)FLAGS=-march=... - - * include/effect_lib.h: - improved effectLib for not being based on virtual-functions rather than - direct function-inlining via template parameter - -2008-10-02 Tobias Doerffel - - * plugins/lb302/lb302.h: - * plugins/lb303/lb303.h: - removed obsolete supportsParallelizing() method - - * src/tracks/instrument_track.cpp: - fixed volume-scaling for IPH-based but not MIDI-based instruments - - * src/core/envelope_and_lfo_parameters.cpp: - use memset() rather than initializing the buffer in a loop with 0 - - * plugins/ladspa_effect/ladspa_effect.cpp: - fetch pointer to LADSPA port descriptor once outside the inner loops - - improves performance of ladspaEffect::processAudioBuffer() by 400% - - * include/types.h: - faster floating point comparison - - * data/locale/ru.ts: - added updated Russian localization by Alexey Kouznetsov - - * buildtools/bin2res.cpp: - * include/mmp.h: - * include/knob.h: - * include/effect.h: - * include/templates.h: - * include/track.h: - * include/note.h: - * include/automatable_model.h: - * include/import_filter.h: - * include/mixer.h: - * include/combobox_model.h: - * include/ladspa_manager.h: - * include/instrument.h: - * include/sample_buffer.h: - * include/midi.h: - * include/effect_lib.h: - * include/sample_record_handle.h: - * include/shared_object.h: - * include/plugin.h: - * include/note_play_handle.h: - * include/instrument_sound_shaping.h: - * include/oscillator.h: - * include/tempo_sync_knob.h: - * include/midi_time.h: - * include/remote_plugin.h: - * include/basic_filters.h: - * include/journalling_object.h: - * include/types.h: - * include/dummy_effect.h: - * include/automatable_model_view.h: - * include/inline_automation.h: - * include/audio_device.h: - * include/panning.h: - * include/combobox.h: - * include/ladspa_2_lmms.h: - * src/core/preset_preview_play_handle.cpp: - * src/core/note_play_handle.cpp: - * src/core/song.cpp: - * src/core/serializing_object.cpp: - * src/core/bb_track_container.cpp: - * src/core/remote_plugin.cpp: - * src/core/journalling_object.cpp: - * src/core/automatable_model.cpp: - * src/core/audio/audio_alsa.cpp: - * src/core/audio/audio_sdl.cpp: - * src/core/audio/audio_portaudio.cpp: - * src/core/audio/audio_jack.cpp: - * src/core/main.cpp: - * src/core/instrument_sound_shaping.cpp: - * src/core/effect.cpp: - * src/core/instrument_functions.cpp: - * src/core/controller_connection.cpp: - * src/core/track.cpp: - * src/core/engine.cpp: - * src/core/piano.cpp: - * src/core/timeline.cpp: - * src/core/instrument.cpp: - * src/core/surround_area.cpp: - * src/core/sample_buffer.cpp: - * src/core/oscillator.cpp: - * src/core/automation_pattern.cpp: - * src/core/lfo_controller.cpp: - * src/core/sample_record_handle.cpp: - * src/gui/piano_roll.cpp: - * src/gui/plugin_browser.cpp: - * src/gui/main_window.cpp: - * src/gui/song_editor.cpp: - * src/gui/widgets/kmultitabbar.cpp: - * src/gui/widgets/knob.cpp: - * src/gui/widgets/lcd_spinbox.cpp: - * src/gui/automation_editor.cpp: - * src/tracks/sample_track.cpp: - * src/tracks/bb_track.cpp: - * src/tracks/instrument_track.cpp: - * src/tracks/pattern.cpp: - * plugins/ladspa_effect/tap/CMakeLists.txt: - * plugins/audio_file_processor/audio_file_processor.cpp: - fixed a bunch warnings and remarks issued by Intel Compiler - - * include/fx_mixer.h: - * src/core/fx_mixer.cpp: - * src/core/mixer.cpp: - - use one static jobqueue for not getting problems with cached pointers - - check for job being NULL - - improved performance of master mix - - * CMakeLists.txt: - allow overriding compiler flags - -2008-09-30 Tobias Doerffel - - * plugins/sid/sid_instrument.h: - * plugins/sid/sid_instrument.cpp: - * plugins/ladspa_effect/tap/CMakeLists.txt: - * plugins/ladspa_effect/caps/CMakeLists.txt: - * plugins/patman/patman.cpp: - * plugins/patman/patman.h: - * plugins/lb302/lb302.cpp: - * plugins/lb302/lb302.h: - * plugins/organic/organic.cpp: - * plugins/organic/organic.h: - * plugins/lb303/lb303.cpp: - * plugins/lb303/lb303.h: - * plugins/bit_invader/bit_invader.cpp: - * plugins/bit_invader/bit_invader.h: - * plugins/vst_effect/vst_effect.cpp: - * plugins/vibed/vibed.h: - * plugins/vibed/vibed.cpp: - * plugins/triple_oscillator/triple_oscillator.h: - * plugins/triple_oscillator/triple_oscillator.cpp: - * plugins/audio_file_processor/audio_file_processor.cpp: - * plugins/audio_file_processor/audio_file_processor.h: - * plugins/stk/mallets/mallets.cpp: - * plugins/stk/mallets/mallets.h: - * plugins/papu/papu_instrument.h: - * plugins/papu/papu_instrument.cpp: - * plugins/sf2_player/sf2_player.cpp: - * plugins/sf2_player/sf2_player.h: - * plugins/vestige/vestige.cpp: - * plugins/vestige/vestige.h: - * plugins/kicker/kicker.cpp: - * plugins/kicker/kicker.h: - * include/instrument_play_handle.h: - * include/instrument_track.h: - * include/instrument.h: - * include/sample_record_handle.h: - * include/plugin.h: - * include/note_play_handle.h: - * include/sample_play_handle.h: - * include/remote_plugin.h: - * include/preset_preview_play_handle.h: - * include/play_handle.h: - * src/core/plugin.cpp: - * src/core/preset_preview_play_handle.cpp: - * src/core/note_play_handle.cpp: - * src/core/remote_plugin.cpp: - * src/core/sample_play_handle.cpp: - * src/core/mixer.cpp: - * src/core/instrument.cpp: - * src/core/sample_record_handle.cpp: - * src/tracks/instrument_track.cpp: - removed obsolete instrument-parallelization support as this is handled - much better by worker threads and adds unnecessary complexity - - * cmake/modules/FindPCHSupport.cmake: - * INSTALL: - * CMakeLists.txt: - - removed (buggy) PCH support - - added support for CFLAGS and CXXFLAGS environment variables - -2008-09-29 Tobias Doerffel - - * plugins/sf2_player/sf2_player.cpp: - use notePlayHandle::getMidiVelocty() rather than - notePlayHandle::getVolume() for allowing less bright sounds by - decreasing instrument-track's volume (if soundfont supports it) - - * plugins/sf2_player/sf2_player.h: - * plugins/vestige/vestige.h: - * plugins/vibed/vibed.h: - * include/instrument.h: - * include/note_play_handle.h: - * src/core/note_play_handle.cpp: - * src/tracks/instrument_track.cpp: - - replaced instrument::notePlayHandleBased() with - instrument::isMidiBased() - - renamed bendable() to isBendable() - - if the instrument is MIDI based and instrument-track's volume - is below 100, adjust velocity of MIDI events and scaling factor when - mixing sound - -2008-09-25 Tobias Doerffel - - * plugins/CMakeLists.txt: - moved LiveTool to LMMS-extras - - * plugins/live_tool/live_tool.h: - * plugins/live_tool/live_tool.cpp: - replaced X11-specific parts by platform independent code but still - does not work properly - - * src/gui/piano_roll.cpp: - play preview notes also while playing (closes #2089399) - - * src/gui/widgets/project_notes.cpp: - minor code improvements - -2008-09-24 Tobias Doerffel - - * plugins/ladspa_effect/cmt/src/syndrum.cpp: - * plugins/ladspa_effect/cmt/src/vcf303.cpp: - * plugins/ladspa_effect/cmt/src/canyondelay.cpp: - * plugins/ladspa_effect/cmt/src/lofi.cpp: - * plugins/ladspa_effect/cmt/src/phasemod.cpp: - * plugins/ladspa_effect/cmt/src/analogue.cpp: - * plugins/ladspa_effect/swh/CMakeLists.txt: - * CMakeLists.txt: - properly build on OS X - - * src/core/main.cpp: - do not show splash if environment variable NOSPLASH is set - - * include/audio_portaudio.h: - * src/core/audio/audio_portaudio.cpp: - * src/core/audio/audio_pulseaudio.cpp: - * src/core/sample_buffer.cpp: - * src/core/sample_record_handle.cpp: - * src/tracks/sample_track.cpp: - * plugins/bit_invader/bit_invader.cpp: - * plugins/sid/wave.cc: - * plugins/sid/sid.cc: - * plugins/sid/sid.h: - * plugins/sid/filter.cc: - fixed compiler warnings - - * src/gui/controller_connection_dialog.cpp: - do not crash when opening controller connection dialog and using a - non-sequenced (raw) MIDI-client - - * data/presets/TripleOscillator/SawLead.xpf: - fixed preset name - -2008-09-23 Tobias Doerffel - - * CMakeLists.txt: - made 0.4.0-rc2 release - - * src/gui/song_editor.cpp: - * data/themes/default/playpos_marker.png: - improved appearence of position line - - * src/gui/file_browser.cpp: - if adding play handle failed for some reason, set internal pointer to - it to NULL - - * include/play_handle.h: - made QThread pointer const - - * include/mixer.h: - * src/core/mixer.cpp: - - lock playHandle mutex in mixer::clear() - - moved implementation of mixer::removePlayHandle() from header to - source-file - - only delete play-handle in mixer::removePlayHandle() if it was - found in playHandle vector (fixes crash when previewing a preset - under high load) - -2008-09-22 Tobias Doerffel - - * CMakeLists.txt: - package ZynAddSubFX into win32 build - - * plugins/vst_base/remote_vst_plugin.cpp: - * include/remote_plugin.h: - made remotePluginClient::process() have no return value - - * src/core/main.cpp: - * data/locale/CMakeLists.txt: - install and load Qt translation files on win32 - - * src/core/song.cpp: - fixed file-dialog for choosing export filename - - * src/core/project_renderer.cpp: - start render-thread with normal priority on win32 as otherwise the - whole GUI is almost frozen - - * CMakeLists.txt: - removed -Wstrict-aliasing=2 warning - - * src/core/midi/midi_winmm.cpp: - cleanups - - * include/audio_sdl.h: - * src/core/audio/audio_sdl.cpp: - fixed deadlocks after projectRenderer ran - - * src/core/main.cpp: - set PaintOnScreen property for splash for not taking part of - compositing management - - * include/song_editor.h: - * include/timeline.h: - * src/core/timeline.cpp: - * src/gui/song_editor.cpp: - added a vertical position line - - * src/core/midi/midi_winmm.cpp: - added support for MIDI out in WinMM MIDI client - -2008-09-22 Paul Giblock - - * plugins/midi_import/portsmf/allegro.cpp: - fixed broken SVN on 64bit systems. Who needs these printfs anyways? - - * plugins/lb302/lb302.cpp: - max wave-shape model's max match the new total of wave-shapes. - - * include/peak_controller.h: - * src/core/peak_controller.cpp: - delete controller when effect is destroyed, but not the other way around - -2008-09-21 Tobias Doerffel - - * src/core/plugin.cpp: - always return a dummy model in plugin::getChildModel() for not - crashing if something goes wrong - - * include/controller_connection_dialog.h: - * src/gui/controller_connection_dialog.cpp: - automatically enable auto-detect LED when selecting a MIDI device - - * include/remote_plugin.h: - * src/core/audio/audio_device.cpp: - * src/core/audio/audio_oss.cpp: - * src/core/drumsynth.cpp: - * src/core/main.cpp: - * src/core/mixer.cpp: - * src/core/sample_record_handle.cpp: - * src/core/track_container.cpp: - * src/gui/widgets/lcd_spinbox.cpp: - * plugins/bit_invader/bit_invader.cpp: - * plugins/lb302/lb302.cpp: - * plugins/midi_import/portsmf/allegrosmfwr.cpp: - * plugins/midi_import/portsmf/allegro.cpp: - * plugins/midi_import/midi_import.cpp: - * plugins/papu/gb_apu/Blip_Buffer.cpp: - * plugins/papu/gb_apu/Blip_Synth.h: - * plugins/papu/gb_apu/blargg_source.h: - * plugins/papu/gb_apu/Blip_Buffer.h: - * plugins/sf2_player/sf2_player.cpp: - fixed compiler warnings - - * src/core/midi/midi_alsa_seq.cpp: - fixed subscription of output ports - - * include/group_box.h: - * include/midi.h: - * include/midi_port.h: - * include/instrument_midi_io_view.h: - * src/core/midi/midi_port.cpp: - * src/gui/widgets/instrument_midi_io_view.cpp: - * data/themes/default/midi_in.png: - * data/themes/default/midi_out.png: - refactored MIDI tab in instrumentTrackWindow which now also allows - setting arbitrary fixed velocity and defining a program for MIDI output - - * include/midi_mapper.h: - * src/core/midi/midi_mapper.cpp: - * data/midi-maps/gm.map: - * data/midi-maps/YamahaPSS790.map: - * data/midi-maps/YamahaPSR400.map: - * data/midi-maps/YamahaPSR500.map: - * data/midi-maps/YamahaQY10.map: - * data/midi-maps/README: - removed obsolete/unused support for MIDI maps - - * CMakeLists.txt: - enable all compiler warnings per default - - * include/audio_file_ogg.h: - * include/audio_file_device.h: - * src/gui/export_project_dialog.cpp: - * src/core/audio/audio_file_device.cpp: - * src/core/audio/audio_file_ogg.cpp: - fixed crashes when exporting as OGG and output file can't be created - or OGG encoding settings are wrong - - * src/core/automation_pattern.cpp: - fixed automationPattern::length() for cases where the key of the - last value was the first tick in a new tact - - * plugins/ladspa_effect/cmt/src/delay.cpp: - initialize CMT_PluginDescriptor with correct number of ports - - * plugins/ladspa_effect/cmt/src/freeverb/Components/allpass.h: - * plugins/ladspa_effect/cmt/src/freeverb/Components/comb.h: - * plugins/ladspa_effect/cmt/src/freeverb/Components/denormals.h: - fixed strict aliasing violation - - * plugins/ladspa_effect/cmt/src/analogue.cpp: - initialize members - - * plugins/ladspa_effect/swh/CMakeLists.txt: - * plugins/ladspa_effect/cmt/CMakeLists.txt: - * plugins/ladspa_effect/tap/CMakeLists.txt: - * plugins/ladspa_effect/caps/basics.h: - * plugins/ladspa_effect/CMakeLists.txt: - - build LADSPA-effect plugin after subdirs have been processed, - otherwise LADSPA plugins are linked against Qt4 and so on - - compile with -fno-strict-aliasing, fixes win32 builds of plugins - -2008-09-21 Paul Giblock - - * include/config_mgr.h: - * include/setup_dialog.h: - * src/gui/main_window.cpp: - * src/gui/setup_dialog.cpp: - * src/core/config_mgr.cpp: - Add support for user-configurable backgound artwork - - * src/core/mmp.cpp: - * data/samples/drumsynth/r_b: - * data/samples/drumsynth/r_n_b: - - Fix incorrect replacement for drumsynth/misc - - Replace r&b,r_b with r_n_b - - * src/core/main.cpp: - - Make "could not set realtime priority" sound less like an error - - Actually commit the file - - * plugins/lb302/lb302.cpp: - * plugins/lb302/lb302.h: - * src/core/mmp.cpp: - * data/themes/default/round_square_wave_inactive.png: - * data/themes/default/round_square_wave_active.png: - - Remove useless inverted-saw waveform - - Add Sine, Noise, and Exponential waveforms - - Use buttons instead of a knob - - * plugins/bit_invader/bit_invader.cpp: - * plugins/bit_invader/bit_invader.h: - - Add support for pitch bend - - Move smoothing button to a more noticable location - - Some coding style changes - - * plugins/stk/mallets/mallets.cpp: - * plugins/stk/mallets/mallets.h: - Add support for pitch bend - - * src/tracks/instrument_track.cpp: - * include/instrument_track.h: - - Correctly update instrumentTrackView when changing the instrument plugin - - Add bendable property to hide pitchBend knob for Vibed - - * plugins/vibed/vibed.h: - * include/instrument.h: - * src/tracks/instrument_track.cpp: - Hide pitch bend one vibed instrument - - * src/gui/setup_dialog.cpp: - - Minor layout fix - - Fix incorrect starting directory for STK - - * data/CMakeLists.txt: - * data/backgrounds: - * data/backgrounds/CMakeLists.txt: - * data/backgrounds/lmms_tile.png: - * data/backgrounds/vinnie.png: - - Move llama theme background to backgrounds/ - - Resurrect the old background - - more to come.. - - * data/themes/llama: - * data/themes/llama/background_artwork.png: - - Remove llama theme - -2008-09-20 Paul Giblock - - * plugins/sf2_player/sf2_player.cpp: - Fix bug introduced in the last edit. Reference sharing was not working - at all because the check was performed with a different filename than - the insert - - * plugins/vibed/logo.png: - Add fabi's improved vibed logo - - * CMakeLists.txt: - Fix copy-and-paste error in a message - - * plugins/papu/papu_instrument.cpp: - - Unselect the noise-channel (ch4) by default - - Coding style changes - - * src/core/song.cpp: - Add hard-coded file-extension filters to the import file screen - -2008-09-20 Tobias Doerffel - - * src/core/config_mgr.cpp: - set default path if a path only contains of a dir-separator - - * data/presets/CMakeLists.txt: - fixed extension of presets - - * plugins/ladspa_effect/cmt/doc/bugs.html: - * plugins/ladspa_effect/cmt/doc/plugins.html: - * plugins/ladspa_effect/cmt/doc/installation.html: - * plugins/ladspa_effect/cmt/doc/license.html: - * plugins/ladspa_effect/cmt/doc/tasks.html: - * plugins/ladspa_effect/cmt/doc/COPYING: - * plugins/ladspa_effect/cmt/doc/overview.html: - * plugins/ladspa_effect/cmt/doc/index.html: - * plugins/ladspa_effect/cmt/doc/adding_plugins.html: - * plugins/ladspa_effect/cmt/doc/changes.html: - * plugins/ladspa_effect/cmt/src/sine.cpp: - * plugins/ladspa_effect/cmt/src/delay.cpp: - * plugins/ladspa_effect/cmt/src/syndrum.cpp: - * plugins/ladspa_effect/cmt/src/vcf303.cpp: - * plugins/ladspa_effect/cmt/src/utils.h: - * plugins/ladspa_effect/cmt/src/wshape_sine.cpp: - * plugins/ladspa_effect/cmt/src/canyondelay.cpp: - * plugins/ladspa_effect/cmt/src/noise.cpp: - * plugins/ladspa_effect/cmt/src/amp.cpp: - * plugins/ladspa_effect/cmt/src/disintegrator.cpp: - * plugins/ladspa_effect/cmt/src/run_adding.h: - * plugins/ladspa_effect/cmt/src/hardgate.cpp: - * plugins/ladspa_effect/cmt/src/cmt.cpp: - * plugins/ladspa_effect/cmt/src/mixer.cpp: - * plugins/ladspa_effect/cmt/src/filter.cpp: - * plugins/ladspa_effect/cmt/src/lofi.cpp: - * plugins/ladspa_effect/cmt/src/am.cpp: - * plugins/ladspa_effect/cmt/src/phasemod.cpp: - * plugins/ladspa_effect/cmt/src/grain.cpp: - * plugins/ladspa_effect/cmt/src/pink.cpp: - * plugins/ladspa_effect/cmt/src/init.cpp: - * plugins/ladspa_effect/cmt/src/ambisonic.cpp: - * plugins/ladspa_effect/cmt/src/pinknoise.h: - * plugins/ladspa_effect/cmt/src/organ.cpp: - * plugins/ladspa_effect/cmt/src/null.cpp: - * plugins/ladspa_effect/cmt/src/logistic.cpp: - * plugins/ladspa_effect/cmt/src/descriptor.cpp: - * plugins/ladspa_effect/cmt/src/freeverb/freeverb.cpp: - * plugins/ladspa_effect/cmt/src/freeverb/Components/allpass.cpp: - * plugins/ladspa_effect/cmt/src/freeverb/Components/comb.cpp: - * plugins/ladspa_effect/cmt/src/freeverb/Components/revmodel.h: - * plugins/ladspa_effect/cmt/src/freeverb/Components/allpass.h: - * plugins/ladspa_effect/cmt/src/freeverb/Components/comb.h: - * plugins/ladspa_effect/cmt/src/freeverb/Components/tuning.h: - * plugins/ladspa_effect/cmt/src/freeverb/Components/denormals.h: - * plugins/ladspa_effect/cmt/src/freeverb/Components/revmodel.cpp: - * plugins/ladspa_effect/cmt/src/freeverb/readme.txt: - * plugins/ladspa_effect/cmt/src/peak.cpp: - * plugins/ladspa_effect/cmt/src/pink_full.cpp: - * plugins/ladspa_effect/cmt/src/dynamic.cpp: - * plugins/ladspa_effect/cmt/src/cmt.h: - * plugins/ladspa_effect/cmt/src/pink_sh.cpp: - * plugins/ladspa_effect/cmt/src/analogue.cpp: - * plugins/ladspa_effect/cmt/src/sledgehammer.cpp: - * plugins/ladspa_effect/cmt/src/ladspa_types.h: - * plugins/ladspa_effect/cmt/CMakeLists.txt: - * plugins/ladspa_effect/CMakeLists.txt: - * CMakeLists.txt: - added CMT LADSPA plugins - should be enough then :) - - * plugins/ladspa_effect/swh/ladspa-util.h: - * plugins/ladspa_effect/swh/phasers_1217.c: - * plugins/ladspa_effect/swh/vynil_1905.c: - * plugins/ladspa_effect/swh/mbeq_1197.c: - * plugins/ladspa_effect/swh/fast_lookahead_limiter_1913.c: - * plugins/ladspa_effect/swh/flanger_1191.c: - * plugins/ladspa_effect/swh/comb_1190.c: - * plugins/ladspa_effect/swh/dc_remove_1207.c: - * plugins/ladspa_effect/swh/dj_eq_1901.c: - * plugins/ladspa_effect/swh/util/biquad.h: - * plugins/ladspa_effect/swh/CMakeLists.txt: - * plugins/ladspa_effect/swh/AUTHORS: - * plugins/ladspa_effect/swh/COPYING: - * plugins/ladspa_effect/swh/README: - * plugins/ladspa_effect/CMakeLists.txt: - * CMakeLists.txt: - added a selection of nice SWH LADSPA plugins - - * include/piano_roll.h: - * src/gui/piano_roll.cpp: - fixed quantization when moving selected notes (closes #2118371) - - * plugins/sid/envelope.h: - * plugins/sid/extfilt.h: - * plugins/sid/wave.h: - * plugins/sid/voice.h: - * plugins/sid/sid.cc: - * plugins/sid/sid.h: - * plugins/sid/filter.h: - * plugins/sid/sid_instrument.cpp: - renamed class SID to cSID for not conflicting with data structure SID - in win32 headers - - * include/ladspa_base.h: - * src/core/ladspa_control.cpp: - * src/gui/widgets/ladspa_control_view.cpp: - * plugins/ladspa_effect/ladspa_effect.cpp: - renamed FLOAT constant to FLOATING for not conflicting with FLOAT type - in win32 headers - - * include/midi_time.h: - export MIDI class - DLL version of midiImport plugin needs it - -2008-09-19 Tobias Doerffel - - * data/locale/pt_br.qm: - * data/locale/fr.qm: - * data/locale/es.qm: - * data/locale/nl.qm: - * data/locale/ir.qm: - * data/locale/en.ts: - * data/locale/it.qm: - * data/locale/pt_br.ts: - * data/locale/fr.ts: - * data/locale/es.ts: - * data/locale/nl.ts: - * data/locale/ir.ts: - * data/locale/ca.qm: - * data/locale/it.ts: - * data/locale/ru.qm: - * data/locale/de.qm: - * data/locale/sv.qm: - * data/locale/ca.ts: - * data/locale/ru.ts: - * data/locale/de.ts: - * data/locale/sv.ts: - * data/locale/en.qm: - refreshed localizations - - * CMakeLists.txt: - added "finalize-locales" target - - * include/config_mgr.h: - * src/core/config_mgr.cpp: - * src/core/main.cpp: - fixed paths when starting with no configuration file - - * src/core/timeline.cpp: - * src/core/track.cpp: - * data/themes/default/playpos_marker.png: - * data/themes/default/loop_points_on.png: - * data/themes/default/style.css: - * data/themes/default/loop_point_disabled.png: - * data/themes/default/autoscroll_off.png: - * data/themes/default/loop_point.png: - * data/themes/default/autoscroll_on.png: - * data/themes/default/loop_points_off.png: - improved visual appearence of timeline - - * CMakeLists.txt: - improved detection of Qt4 translation directory - -2008-09-18 Tobias Doerffel - - * src/gui/fx_mixer_view.cpp: - fixed tooltip of mute button - - * data/presets/AudioFileProcessor/Fat-Reversed-Kick.xpf: - * data/presets/AudioFileProcessor/orion.xpf: - * data/presets/AudioFileProcessor/Kick-4-your-Subwoofer.xpf: - * data/presets/AudioFileProcessor/Erazor.cs.xml: - * data/presets/AudioFileProcessor/Bass-Mania.xpf: - * data/presets/AudioFileProcessor/Fat-Reversed-Kick.cs.xml: - * data/presets/AudioFileProcessor/Kick-4-your-Subwoofer.cs.xml: - * data/presets/AudioFileProcessor/Bass-Mania.cs.xml: - * data/presets/AudioFileProcessor/Erazor.xpf: - * data/presets/LB302/Oh: - * data/presets/LB302/GoodOldTimes.xpf: - * data/presets/LB302/Oh: - * data/presets/Organic/organ_swish.xpf: - * data/presets/Organic/pad_ethereal.cs.xml: - * data/presets/Organic/organ_swish.cs.xml: - * data/presets/Organic/puresine.xpf: - * data/presets/Organic/default.cs.xml: - * data/presets/Organic/organ_blues.xpf: - * data/presets/Organic/puresine.cs.xml: - * data/presets/Organic/sequencer_64.xpf: - * data/presets/Organic/organ_blues.cs.xml: - * data/presets/Organic/organ_risingsun.xpf: - * data/presets/Organic/pad_sweep.xpf: - * data/presets/Organic/pad_rich.xpf: - * data/presets/Organic/sequencer_64.cs.xml: - * data/presets/Organic/pad_ethereal.xpf: - * data/presets/Organic/pad_sweep.cs.xml: - * data/presets/Organic/organ_risingsun.cs.xml: - * data/presets/Organic/pad_rich.cs.xml: - * data/presets/BitInvader/drama.xpf: - * data/presets/BitInvader/pluck.cs.xml: - * data/presets/BitInvader/bell.cs.xml: - * data/presets/BitInvader/spacefx.xpf: - * data/presets/BitInvader/drama.cs.xml: - * data/presets/BitInvader/default.cs.xml: - * data/presets/BitInvader/cello.xpf: - * data/presets/BitInvader/soft_pad.xpf: - * data/presets/BitInvader/spacefx.cs.xml: - * data/presets/BitInvader/alien_strings.xpf: - * data/presets/BitInvader/toy_piano.xpf: - * data/presets/BitInvader/subbass.xpf: - * data/presets/BitInvader/wah_synth.xpf: - * data/presets/BitInvader/cello.cs.xml: - * data/presets/BitInvader/soft_pad.cs.xml: - * data/presets/BitInvader/sweep_pad.xpf: - * data/presets/BitInvader/beehive.xpf: - * data/presets/BitInvader/toy_piano.cs.xml: - * data/presets/BitInvader/alien_strings.cs.xml: - * data/presets/BitInvader/subbass.cs.xml: - * data/presets/BitInvader/wah_synth.cs.xml: - * data/presets/BitInvader/epiano.xpf: - * data/presets/BitInvader/sweep_pad.cs.xml: - * data/presets/BitInvader/beehive.cs.xml: - * data/presets/BitInvader/bell.xpf: - * data/presets/BitInvader/pluck.xpf: - * data/presets/BitInvader/epiano.cs.xml: - * data/presets/Vibed/SadPad.cs.xml: - * data/presets/Vibed/Harpsichord.xpf: - * data/presets/Vibed/SadPad.xpf: - * data/presets/Vibed/Harpsichord.cs.xml: - * data/presets/TripleOscillator/Short4.xpf: - * data/presets/TripleOscillator/Arpeggio_1.cs.xml: - * data/presets/TripleOscillator/Fat-FMish-Bells.cs.xml: - * data/presets/TripleOscillator/AmazingBubbles.xpf: - * data/presets/TripleOscillator/HiPad.xpf: - * data/presets/TripleOscillator/Whistle.cs.xml: - * data/presets/TripleOscillator/Plucked.xpf: - * data/presets/TripleOscillator/SawLead.cs.xml: - * data/presets/TripleOscillator/Harp-of-a-Fairy.cs.xml: - * data/presets/TripleOscillator/Short4.cs.xml: - * data/presets/TripleOscillator/ArpKing.xpf: - * data/presets/TripleOscillator/Dull-Bell-Arp.xpf: - * data/presets/TripleOscillator/Rough!.cs.xml: - * data/presets/TripleOscillator/Plucked.cs.xml: - * data/presets/TripleOscillator/Harmonium.xpf: - * data/presets/TripleOscillator/E-Organ.cs.xml: - * data/presets/TripleOscillator/Gong.cs.xml: - * data/presets/TripleOscillator/ArpKing.cs.xml: - * data/presets/TripleOscillator/AnalogDreamz.xpf: - * data/presets/TripleOscillator/Harmonium.cs.xml: - * data/presets/TripleOscillator/PowerStrings.xpf: - * data/presets/TripleOscillator/SpaceBass.cs.xml: - * data/presets/TripleOscillator/RaveBass.cs.xml: - * data/presets/TripleOscillator/ResonantPad.xpf: - * data/presets/TripleOscillator/SawLead.xpf: - * data/presets/TripleOscillator/Fat.cs.xml: - * data/presets/TripleOscillator/ResoBass.xpf: - * data/presets/TripleOscillator/LovelyDream.xpf: - * data/presets/TripleOscillator/AnalogTimes2.xpf: - * data/presets/TripleOscillator/RockOrgan.xpf: - * data/presets/TripleOscillator/TB303-Arpeggio.xpf: - * data/presets/TripleOscillator/Xylophon.cs.xml: - * data/presets/TripleOscillator/E-Organ.xpf: - * data/presets/TripleOscillator/Short3.cs.xml: - * data/presets/TripleOscillator/LovelyDream.cs.xml: - * data/presets/TripleOscillator/SoftStrings.cs.xml: - * data/presets/TripleOscillator/DeathBass.xpf: - * data/presets/TripleOscillator/Play-some-rock.xpf: - * data/presets/TripleOscillator/TranceLead.xpf: - * data/presets/TripleOscillator/MoveYourBody.xpf: - * data/presets/TripleOscillator/SpaceBass.xpf: - * data/presets/TripleOscillator/Harpsichord.xpf: - * data/presets/TripleOscillator/Freaky-Bass.xpf: - * data/presets/TripleOscillator/MoveYourBody.cs.xml: - * data/presets/TripleOscillator/PowerStrings.cs.xml: - * data/presets/TripleOscillator/Fat-FMish-Bells.xpf: - * data/presets/TripleOscillator/Arpeggio_1.xpf: - * data/presets/TripleOscillator/Freaky-Bass.cs.xml: - * data/presets/TripleOscillator/Bell.xpf: - * data/presets/TripleOscillator/Arpeggio_2.xpf: - * data/presets/TripleOscillator/Xylophon.xpf: - * data/presets/TripleOscillator/Jupiter.xpf: - * data/presets/TripleOscillator/SawReso.xpf: - * data/presets/TripleOscillator/LFO-party.cs.xml: - * data/presets/TripleOscillator/ResonantPad.cs.xml: - * data/presets/TripleOscillator/Rough!.xpf: - * data/presets/TripleOscillator/Distorted-FM-Bass.xpf: - * data/presets/TripleOscillator/Kick.cs.xml: - * data/presets/TripleOscillator/Short2.cs.xml: - * data/presets/TripleOscillator/SawReso.cs.xml: - * data/presets/TripleOscillator/TheFirstOne.xpf: - * data/presets/TripleOscillator/SoftBass.cs.xml: - * data/presets/TripleOscillator/AmazingBubbles.cs.xml: - * data/presets/TripleOscillator/HiPad.cs.xml: - * data/presets/TripleOscillator/TB303-Arpeggio.cs.xml: - * data/presets/TripleOscillator/Distorted-FM-Bass.cs.xml: - * data/presets/TripleOscillator/Analogous.cs.xml: - * data/presets/TripleOscillator/TheMaster.cs.xml: - * data/presets/TripleOscillator/WarmStack.cs.xml: - * data/presets/TripleOscillator/Ravemania.xpf: - * data/presets/TripleOscillator/PluckArpeggio.cs.xml: - * data/presets/TripleOscillator/Square.cs.xml: - * data/presets/TripleOscillator/Play-some-rock.cs.xml: - * data/presets/TripleOscillator/TranceLead.cs.xml: - * data/presets/TripleOscillator/Ravemania.cs.xml: - * data/presets/TripleOscillator/OldComputerGames.xpf: - * data/presets/TripleOscillator/Harpsichord.cs.xml: - * data/presets/TripleOscillator/MoogArpeggio.xpf: - * data/presets/TripleOscillator/Snare.cs.xml: - * data/presets/TripleOscillator/Harp-of-a-Fairy.xpf: - * data/presets/TripleOscillator/FutureBass.xpf: - * data/presets/TripleOscillator/Fat-TB303-Arp.xpf: - * data/presets/TripleOscillator/SoftBass.xpf: - * data/presets/TripleOscillator/Bell.cs.xml: - * data/presets/TripleOscillator/Arpeggio_2.cs.xml: - * data/presets/TripleOscillator/SoftStrings.xpf: - * data/presets/TripleOscillator/MoogArpeggio.cs.xml: - * data/presets/TripleOscillator/Short1.cs.xml: - * data/presets/TripleOscillator/FatCheese.xpf: - * data/presets/TripleOscillator/Analogous.xpf: - * data/presets/TripleOscillator/ResoBass.cs.xml: - * data/presets/TripleOscillator/Jupiter.cs.xml: - * data/presets/TripleOscillator/Fat-TB303-Arp.cs.xml: - * data/presets/TripleOscillator/FutureBass.cs.xml: - * data/presets/TripleOscillator/Gong.xpf: - * data/presets/TripleOscillator/TB303.xpf: - * data/presets/TripleOscillator/RockOrgan.cs.xml: - * data/presets/TripleOscillator/AnalogTimes2.cs.xml: - * data/presets/TripleOscillator/PluckArpeggio.xpf: - * data/presets/TripleOscillator/TheMaster.xpf: - * data/presets/TripleOscillator/WarmStack.xpf: - * data/presets/TripleOscillator/FatCheese.cs.xml: - * data/presets/TripleOscillator/Bell_2.xpf: - * data/presets/TripleOscillator/Square.xpf: - * data/presets/TripleOscillator/TheFirstOne.cs.xml: - * data/presets/TripleOscillator/TB303.cs.xml: - * data/presets/TripleOscillator/AnalogTimes.xpf: - * data/presets/TripleOscillator/Dull-Bell-Arp.cs.xml: - * data/presets/TripleOscillator/ChurchOrgan.xpf: - * data/presets/TripleOscillator/Kick2.xpf: - * data/presets/TripleOscillator/Bell_2.cs.xml: - * data/presets/TripleOscillator/RaveBass.xpf: - * data/presets/TripleOscillator/Snare.xpf: - * data/presets/TripleOscillator/ChurchOrgan.cs.xml: - * data/presets/TripleOscillator/Kick2.cs.xml: - * data/presets/TripleOscillator/AnalogTimes.cs.xml: - * data/presets/TripleOscillator/E-Organ2.xpf: - * data/presets/TripleOscillator/Fat.xpf: - * data/presets/TripleOscillator/AnalogDreamz.cs.xml: - * data/presets/TripleOscillator/LFO-party.xpf: - * data/presets/TripleOscillator/Whistle.xpf: - * data/presets/TripleOscillator/Short1.xpf: - * data/presets/TripleOscillator/OldComputerGames.cs.xml: - * data/presets/TripleOscillator/Kick.xpf: - * data/presets/TripleOscillator/Short2.xpf: - * data/presets/TripleOscillator/Short3.xpf: - * src/gui/main_window.cpp: - * src/gui/file_browser.cpp: - * src/tracks/instrument_track.cpp: - changed preset's extension from "*.cs.xml" to "*.xpf" - - * include/instrument_track.h: - * include/track.h: - * include/track_label_button.h: - * src/core/bb_track_container.cpp: - * src/core/track.cpp: - * src/gui/widgets/track_label_button.cpp: - * src/tracks/automation_track.cpp: - * src/tracks/bb_track.cpp: - * src/tracks/instrument_track.cpp: - * src/tracks/sample_track.cpp: - - when used on instrumentTrack, also show instrument name on - trackLabelButton - - removed obsolete support for choosing custom track icons - - * src/core/mixer.cpp: - when just rendering at console, use DEFAULT_BUFFER_SIZE - - * data/track_icons/harp02.png: - * data/track_icons/harp03.png: - * data/track_icons/cello01.png: - * data/track_icons/guitar_electric01.png: - * data/track_icons/piano01.png: - * data/track_icons/guitar_electric02.png: - * data/track_icons/maracas01.png: - * data/track_icons/guitar_electric03.png: - * data/track_icons/guitar_electric04.png: - * data/track_icons/connectors01.png: - * data/track_icons/drumset01_.png: - * data/track_icons/trombone01.png: - * data/track_icons/CMakeLists.txt: - * data/track_icons/african_drum01.png: - * data/track_icons/french_horn01.png: - * data/track_icons/african_drum02.png: - * data/track_icons/mouth01.png: - * data/track_icons/african_drum03.png: - * data/track_icons/african_drum04.png: - * data/track_icons/african_drum05.png: - * data/track_icons/gramophone01.png: - * data/track_icons/trumpet01.png: - * data/track_icons/violin01.png: - * data/track_icons/trumpet02.png: - * data/track_icons/violin02.png: - * data/track_icons/trumpet03.png: - * data/track_icons/microphone01.png: - * data/track_icons/guitar_bass01.png: - * data/track_icons/trumpet04.png: - * data/track_icons/microphone02.png: - * data/track_icons/microphone03.png: - * data/track_icons/microphone04.png: - * data/track_icons/flute01.png: - * data/track_icons/oboe01.png: - * data/track_icons/xylophone01.png: - * data/track_icons/guitar_accoustic01.png: - * data/track_icons/guitar_accoustic02.png: - * data/track_icons/speaker01.png: - * data/track_icons/harp01.png: - * data/track_icons/guitar_accoustic03.png: - * data/CMakeLists.txt: - finally removed obsolete track icons - -2008-09-17 Tobias Doerffel - - * plugins/sf2_player/sf2_player.cpp: - try to use relative paths for s_fonts map too as otherwise - s_fonts.remove( m_filename ) won't do anything if a full path was - inserted and m_filename was made relative - fixes crash when - re-opening a soundfont which was shared before - - * plugins/midi_import/portsmf/strparse.cpp: - fixed compilation issue - -2008-09-16 Paul Giblock - - * plugins/sf2_player/sf2_player.cpp: - * plugins/sf2_player/sf2_player.h: - * plugins/midi_import/portsmf: - * plugins/midi_import/portsmf/allegrowr.cpp: - * plugins/midi_import/portsmf/trace.cpp: - * plugins/midi_import/portsmf/algsmfrd_internal.h: - * plugins/midi_import/portsmf/trace.h: - * plugins/midi_import/portsmf/strparse.cpp: - * plugins/midi_import/portsmf/allegrosmfwr.cpp: - * plugins/midi_import/portsmf/mfmidi.cpp: - * plugins/midi_import/portsmf/strparse.h: - * plugins/midi_import/portsmf/mfmidi.h: - * plugins/midi_import/portsmf/allegrord.cpp: - * plugins/midi_import/portsmf/license.txt: - * plugins/midi_import/portsmf/allegrosmfrd.cpp: - * plugins/midi_import/portsmf/allegro.cpp: - * plugins/midi_import/portsmf/allegroserial.cpp: - * plugins/midi_import/portsmf/algrd_internal.h: - * plugins/midi_import/portsmf/allegro.h: - * plugins/midi_import/portsmf/README.txt: - * plugins/midi_import/CMakeLists.txt: - * plugins/midi_import/midi_import.cpp: - * include/meter_model.h: - * include/instrument_track.h: - * include/config_mgr.h: - * include/plugin.h: - * include/setup_dialog.h: - * src/gui/setup_dialog.cpp: - * src/core/plugin.cpp: - * src/core/config_mgr.cpp: - - Add Portsmf-based MIDI import to trunk - - Add default-sf2 to settings dialog, but currently only loads when - importing a MIDI - - * src/gui/piano_roll.cpp: - - Add new shortcuts for change Q and note length - - Add "Note lock" mode to keep Q equal to note length - -2008-09-16 Tobias Doerffel - - * src/gui/track_container_view.cpp: - * src/core/track.cpp: - disabled undo/redo of track/TCO addition/removal as not mature yet and - causes unnecessary crashes (closes #2014439, #2100407) - - * data/projects/cool_songs/Skiessi-TurningPoint.mmpz: - * data/projects/cool_songs/Skiessi-RandomProjectNumber14253.mmpz: - added two cool projects from Skiessi - more to come - - * src/core/track.cpp: - * src/core/automation_pattern.cpp: - - fixed cloning of automation-patterns (closes #2102218) - - allow dropping automation patterns onto existing automation patterns - - * src/core/project_journal.cpp: - improved usage of random number generator (closes #2109211) - - * plugins/ladspa_effect/tap/tap_pinknoise.c: - * plugins/ladspa_effect/caps/interface.cc: - * src/core/drumsynth.cpp: - * src/core/main.cpp: - don't mis-initialize random number generator with default value - - * src/core/journalling_object.cpp: - print name of object which uses ID if another object requests it - - * src/core/automation_pattern.cpp: - make sure we don't return NULL in automationPattern::firstObject() - - * plugins/ladspa_effect/ladspa_effect.cpp: - * include/engine.h: - * include/effect_rack_view.h: - * include/effect_chain.h: - * src/core/effect_chain.cpp: - * src/core/preset_preview_play_handle.cpp: - * src/core/engine.cpp: - * src/gui/widgets/effect_rack_view.cpp: - - do not show messages about missing plugins when previewing - presets (closes #2110203) - - clear effect view before loading settings in effectChain - - * CMakeLists.txt: - improved out-of-tree builds - -2008-09-14 Csaba Hruska - - * src/core/audio/audio_portaudio.cpp: - Bugfix: Fixed segfault when other app uses and blocks the audio device - -2008-09-08 Paul Giblock - - * src/core/timeline.cpp: - Keep loop markers from being in same position - -2008-09-11 Tobias Doerffel - - * include/audio_port.h: - * include/midi.h: - * include/mixer.h: - * include/play_handle.h: - * include/sample_play_handle.h: - * include/track.h: - * src/core/audio/audio_port.cpp: - * src/core/effect_chain.cpp: - * src/core/mixer.cpp: - * src/core/sample_play_handle.cpp: - * src/core/track.cpp: - - ensure correct thread affinity when deleting play handles - fixes - crash when previewing samples and LMMS was linked against Qt 4.3.x - - renamed destroyed()-signals for not conflicting with - QObject::destroyed() in Qt 4.3 - - made effectChain creation in audioPort optional - - fixed various compiler warnings - -2008-09-08 Paul Giblock - - * plugins/papu/gb_abu/Blip_Buffer.cpp: - Fix PAPU for 64bit machines - -2008-09-08 Tobias Doerffel - - * CMakeLists.txt: - made 0.4.0-rc1 release - - * plugins/vst_base/CMakeLists.txt: - * CMakeLists.txt: - - fixed win32-specific build issues - - on Linux install manpage - - * include/gui_templates.h: - * src/core/instrument_sound_shaping.cpp: - * src/gui/widgets/instrument_sound_shaping_view.cpp: - * src/gui/widgets/lcd_spinbox.cpp: - * data/locale/de.qm: - * data/locale/de.ts: - further UI finetuning - - * include/midi_winmm.h: - * src/core/midi/midi_winmm.cpp: - finally made WinMM MIDI driver work properly by fixing internal data - structures - - * buildtools/bin2res.cpp: - * plugins/bit_invader/logo.png: - * plugins/bit_invader/bit_invader.cpp: - * plugins/bit_invader/wavegraph.png: - * plugins/bit_invader/wavegraph3.png: - * plugins/bit_invader/artwork.png: - * plugins/lb302/artwork.png: - * plugins/papu/artwork.png: - * plugins/sf2_player/chorus_off.png: - * plugins/sf2_player/chorus_on.png: - * plugins/sf2_player/logo.png: - * plugins/sf2_player/sf2_player.cpp: - * plugins/sf2_player/fileselect_off.png: - * plugins/sf2_player/fileselect_on.png: - * plugins/sf2_player/reverb_off.png: - * plugins/sf2_player/patches_off.png: - * plugins/sf2_player/patches_on.png: - * plugins/sf2_player/artwork.png: - * plugins/sid/3off.png: - * plugins/sid/8580red.png: - * plugins/sid/trianglered.png: - * plugins/sid/logo.png: - * plugins/sid/bp.png: - * plugins/sid/6581.png: - * plugins/sid/8580.png: - * plugins/sid/syncred.png: - * plugins/sid/hp.png: - * plugins/sid/lp.png: - * plugins/sid/sync.png: - * plugins/sid/noise.png: - * plugins/sid/test.png: - * plugins/sid/pulsered.png: - * plugins/sid/filter.png: - * plugins/sid/sawred.png: - * plugins/sid/3offred.png: - * plugins/sid/pulse.png: - * plugins/sid/artwork.png: - * plugins/sid/saw.png: - * plugins/sid/bpred.png: - * plugins/sid/6581red.png: - * plugins/sid/ring.png: - * plugins/sid/hpred.png: - * plugins/sid/triangle.png: - * plugins/sid/lpred.png: - * plugins/sid/noisered.png: - * plugins/sid/testred.png: - * plugins/sid/filterred.png: - * plugins/sid/ringred.png: - * plugins/spectrum_analyzer/log_x_axis.png: - * plugins/spectrum_analyzer/log_y_axis.png: - * plugins/spectrum_analyzer/background.png: - * plugins/spectrum_analyzer/spectrum_background.png: - * plugins/spectrum_analyzer/spectrum_background_plain.png: - * plugins/vestige/vestige.cpp: - * plugins/vst_base/remote_vst_plugin.cpp: - * data/themes/default/groupbox_led_bg.png: - * include/aeffectx.h: - * include/effect_rack_view.h: - * include/group_box.h: - * include/gui_templates.h: - * src/core/piano.cpp: - * src/gui/fx_mixer_view.cpp: - * src/gui/plugin_browser.cpp: - * src/gui/widgets/effect_rack_view.cpp: - * src/gui/widgets/group_box.cpp: - * src/gui/widgets/instrument_function_views.cpp: - * src/gui/widgets/instrument_midi_io_view.cpp: - * src/gui/widgets/instrument_sound_shaping_view.cpp: - * src/gui/widgets/knob.cpp: - * src/gui/widgets/tab_widget.cpp: - UI finetuning / recompression of some PNG-files - - * src/core/remote_plugin.cpp: - improved destruction - - * src/core/mixer.cpp: - re-enabled WinMM MIDI - - * include/midi_winmm.h: - * src/core/midi/midi_winmm.cpp: - create separate thread for WinMM MIDI - -2008-09-08 Paul Giblock - - * plugins/sid/logo.png: - Un-box the sid logo - - * plugins/papu: - * plugins/papu/Basic_Gb_Apu.cpp: - * plugins/papu/btn_off.png: - * plugins/papu/btn_on.png: - * plugins/papu/papu_instrument.h: - * plugins/papu/logo.png: - * plugins/papu/Basic_Gb_Apu.h: - * plugins/papu/btn_up.png: - * plugins/papu/btn_15.png: - * plugins/papu/btn_7.png: - * plugins/papu/artwork.png: - * plugins/papu/gb_apu: - * plugins/papu/gb_apu/Blip_Buffer.cpp: - * plugins/papu/gb_apu/Gb_Oscs.cpp: - * plugins/papu/gb_apu/Blip_Synth.h: - * plugins/papu/gb_apu/Gb_Apu.h: - * plugins/papu/gb_apu/blargg_source.h: - * plugins/papu/gb_apu/Multi_Buffer.cpp: - * plugins/papu/gb_apu/Blip_Buffer.h: - * plugins/papu/gb_apu/Gb_Oscs.h: - * plugins/papu/gb_apu/boost: - * plugins/papu/gb_apu/boost/config.hpp: - * plugins/papu/gb_apu/boost/cstdint.hpp: - * plugins/papu/gb_apu/boost/static_assert.hpp: - * plugins/papu/gb_apu/Multi_Buffer.h: - * plugins/papu/gb_apu/LGPL.txt: - * plugins/papu/gb_apu/blargg_common.h: - * plugins/papu/gb_apu/Gb_Apu.cpp: - * plugins/papu/btn_down.png: - * plugins/papu/CMakeLists.txt: - * plugins/papu/papu_instrument.cpp: - * plugins/CMakeLists.txt: - - Add Csaba and Attila's GameBoy emulator so it can be tested in RC1 - - Update artwork to something not trademarked. "Freeboy" is just for now - -2008-09-07 Tobias Doerffel - - * plugins/patman/patman.cpp: - * plugins/patman/patman.h: - - apply release of 128 frames - - enable loop mode per default - - * plugins/patman/patman.cpp: - * plugins/patman/patman.h: - * plugins/triple_oscillator/triple_oscillator.h: - * plugins/triple_oscillator/triple_oscillator.cpp: - * plugins/audio_file_processor/audio_file_processor.cpp: - * plugins/audio_file_processor/audio_file_processor.h: - * plugins/sf2_player/sf2_player.cpp: - * plugins/sf2_player/sf2_player.h: - * plugins/vestige/vestige.cpp: - * plugins/vestige/vestige.h: - * plugins/flp_import/flp_import.cpp: - * plugins/midi_import/midi_import.cpp: - * include/engine.h: - * include/file_browser.h: - * include/preset_preview_play_handle.h: - * include/plugin.h: - * include/remote_plugin.h: - * include/sample_play_handle.h: - * src/core/engine.cpp: - * src/core/plugin.cpp: - * src/core/preset_preview_play_handle.cpp: - * src/gui/file_browser.cpp: - * src/gui/main_window.cpp: - * src/gui/track_container_view.cpp: - - rewrote the way plugins can handle certain filetypes - - rewrote various parts of file-browser to be less redundant and - more stable (closes #2071891) - - * data/themes/default/sample_file.png: - renamed from sound_file.png - - * include/midi.h: - * src/core/midi/midi_client.cpp: - * src/core/midi/midi_port.cpp: - * src/core/midi/midi_alsa_seq.cpp: - fixed MIDI output channel issues (closes #2098722) - - * include/graph.h: - * src/gui/widgets/graph.cpp: - integrated patch by Attila Herman which adds support for colorized - graph and quantized values - - * src/core/config_mgr.cpp: - made default VST path to be inside LMMS working directory - - * src/gui/track_container_view.cpp: - changed size constraint for scrollArea-widget layout - fixes messed up - Song Editor after loading various projects - - * src/gui/main_window.cpp: - set QMdiArea::DontMaximizeSubWindowOnActivation option for not - crashing when loading project while a subwindow is maximized (this - looks like a bug in Qt) (closes #2077774) - - * src/gui/controller_connection_dialog.cpp: - fixed crash when closing controller select dialog and no controller - has been selected (closes #2078357) - - * include/track_container.h: - * src/core/song.cpp: - * src/core/track_container.cpp: - display message if project is empty and user tries to export - it (closes #2091056) - - * src/core/song.cpp: - - fixed freeze after adding BB-tracks (closes #2089337) - - replaced bad cast for calling projectNotes::save/restoreState by - proper C++ construct - - * include/controller_rack_view.h: - * include/fx_mixer_view.h: - * include/main_window.h: - * include/piano_roll.h: - * include/project_notes.h: - * include/track_container.h: - * include/track_container_view.h: - * src/core/song.cpp: - * src/core/track_container.cpp: - * src/gui/fx_mixer_view.cpp: - * src/gui/main_window.cpp: - * src/gui/track_container_view.cpp: - * src/gui/widgets/controller_rack_view.cpp: - * src/tracks/instrument_track.cpp: - properly save and restore position, size, visibility and state of - MDI-subwindows (closes #2072383) - - * src/core/serializing_object.cpp: - fixed hook-mechanism - - * include/song_editor.h: - * src/gui/song_editor.cpp: - * src/gui/fx_mixer_view.cpp: - * src/gui/widgets/visualization_widget.cpp: - * plugins/spectrum_analyzer/spectrumanalyzer_control_dialog.cpp: - moved peridic update-timer from songEditor to mainWindow - - * data/projects/cool_songs/Chris-HorizonRemix.mmp: - added song - -2008-09-06 Tobias Doerffel - - * data/themes/default/background_artwork.png: - added more decent background artwork - - * plugins/ladspa_effect/ladspa_subplugin_features.cpp: - * include/ladspa_base.h: - save LADSPA effect filenames without extension and add correct - one (depending on platform built for) when loading settings - fixes - missing effects when loading songs in Windows which were made in Linux - and vice versa - - * include/audio_pulseaudio.h: - added information about bad latency when using PulseAudio output - - * plugins/vestige/vestige.cpp: - * plugins/vestige/vestige.h: - only use MIDI anymore for controlling VST instruments - - * plugins/lb302/lb302.cpp: - * include/note.h: - * include/instrument_track.h: - * include/midi.h: - * include/note_play_handle.h: - * src/tracks/instrument_track.cpp: - * src/core/preset_preview_play_handle.cpp: - * src/core/note_play_handle.cpp: - * src/core/instrument_functions.cpp: - * src/core/piano.cpp: - - improved the way, MIDI-events are internally sent and handled - - fixed names of various member methods of notePlayHandle class - - full MIDI velocity when pressing key on test piano - - send volume changes of a notePlayHandle as MidiKeyPressure events - - send pitch changes of instrument track as MidiPitchBend events - - added detection for running MIDI notes - - correct calculation of MIDI key - makes remotePlugins respect - base note settings - - * src/core/midi/midi_port.cpp: - * src/core/midi/midi_alsa_seq.cpp: - fixed broken MIDI-output (when masking output events it didn't match - against correct output MIDI channel) - -2008-09-06 Csaba Hruska - - * plugins/sid/sid_instrument.cpp: - Fixed overlapping notes distorsion SID bug. - Some warnings are also had removed. - -2008-09-05 Tobias Doerffel - - * include/lmms_style.h: - * src/gui/lmms_style.cpp: - * src/core/main.cpp: - - moved palette initialization into lmmsStyle class - - added a hack for making titlebar text colors in QMdiSubWindows - common on all platforms - -2008-09-04 Tobias Doerffel - - * plugins/vst_base/vst_plugin.cpp: - hold lock while dumping parameters - - * include/remote_plugin.h: - * lmmsconfig.h.in: - * CMakeLists.txt: - - set common numeric locale to make atof() work properly in Germany - - increased SHM_FIFO_SIZE from 4000 to 64000 for not getting stuck - when exchanging bigger messages (e.g. parameter dumps) - - * plugins/vst_base/vst_plugin.h: - * plugins/vst_base/remote_vst_plugin.cpp: - * plugins/vst_base/communication.h: - * plugins/vst_base/vst_plugin.cpp: - * plugins/vst_base/CMakeLists.txt: - * include/text_float.h: - * include/remote_plugin.h: - * CMakeLists.txt: - made VST support layer work on native win32 - -2008-09-03 Tobias Doerffel - - * plugins/vst_base/communication.h: - * plugins/vst_base/vst_plugin.h: - * plugins/vst_base/vst_plugin.cpp: - * plugins/vst_base/remote_vst_plugin.cpp: - * plugins/vst_base/CMakeLists.txt: - * plugins/vst_effect/vst_effect.h: - * plugins/vst_effect/vst_effect.cpp: - * plugins/vestige/vestige.h: - * plugins/vestige/vestige.cpp: - * include/aeffectx.h: - rewrote VST support layer to use the new remotePlugin-framework - - * include/remote_plugin.h: - * src/core/remote_plugin.cpp: - - added channel splitting mode - - made initial wait optional - - messages now can be constructed and set inline - - * CMakeLists.txt: - added hint about removing CMakeCache.txt when libsndfile is missing - -2008-09-02 Tobias Doerffel - - * cmake/modules/Win32Toolchain.cmake: - added include and library-directory of cross compiling environment - - * include/remote_plugin.h: - use QSystemSemaphore in win32-version as libpthread-w32 does not - support process shared mutexes and semaphores - - * src/core/mixer.cpp: - disabled WinMM MIDI for the time being - -2008-09-02 Paul Giblock - - * src/gui/widgets/graph.cpp: - Display crosshair cursor as a hint to the user - - * src/gui/piano_roll.cpp: - Change Piano-Roll paste behavior. Instead of pasting at 0, paste at the - quantized location of the time-line's position-indicator - - * src/gui/main_window.cpp: - Display waiting cursor when loading project. Really only helps when - loading a large song while another is loaded. Provides feedback before - the loading dialog appears (I guess this is during project close) - - * src/core/automation_pattern.cpp: - Don't connect to the same model more than once - -2008-09-01 Paul Giblock - - * include/track_container.h: - * src/core/song.cpp: - * src/core/track_container.cpp: - * src/core/track.cpp: - Add locking to trackContainer::m_tracks and clean up some const-ness - This should fix most crashes causes by moving/adding TCOs. This also - seems to fix the no-sound bug that I hate so much - - * plugins/bit_invader/logo.png: - * plugins/bit_invader/artwork.png: - Improve BitInvader logo - - * data/lmms.desktop: - * lmms.1: - A more consise description for English - -2008-09-02 Csaba Hruska - - * include/song.h: - * src/core/song.cpp: - * src/gui/song_editor.cpp: - * src/tracks/sample_track.cpp: - added implementation for recordAndPlay button - record button is disabled because it is not handled yet - -2008-08-31 Tobias Doerffel - - * include/remote_plugin.h: - * src/core/remote_plugin.cpp: - * lmmsconfig.h.in: - * CMakeLists.txt: - added shmFifo class which replaces communication via pipes and is - portable as well - -2008-08-29 Tobias Doerffel - - * plugins/sid/sid_instrument.cpp: - * plugins/ladspa_effect/ladspa_effect.cpp: - * plugins/patman/patman.cpp: - * plugins/lb302/lb302.cpp: - * plugins/organic/organic.cpp: - * plugins/stereo_matrix/stereo_matrix.cpp: - * plugins/bass_booster/bass_booster.cpp: - * plugins/bit_invader/bit_invader.cpp: - * plugins/vst_effect/vst_effect.cpp: - * plugins/vibed/vibed.cpp: - * plugins/triple_oscillator/triple_oscillator.cpp: - * plugins/live_tool/live_tool.cpp: - * plugins/peak_controller_effect/peak_controller_effect.cpp: - * plugins/audio_file_processor/audio_file_processor.cpp: - * plugins/audio_file_processor/audio_file_processor.h: - * plugins/stk/mallets/mallets.cpp: - * plugins/stereo_enhancer/stereo_enhancer.cpp: - * plugins/sf2_player/sf2_player.cpp: - * plugins/sf2_player/sf2_player.h: - * plugins/vestige/vestige.cpp: - * plugins/ladspa_browser/ladspa_browser.cpp: - * plugins/spectrum_analyzer/spectrum_analyzer.cpp: - * plugins/kicker/kicker.cpp: - * plugins/flp_import/flp_import.cpp: - * plugins/midi_import/midi_import.cpp: - * include/plugin.h: - * include/instrument_track.h: - * include/instrument.h: - * include/file_browser.h: - * include/preset_preview_play_handle.h: - * src/core/engine.cpp: - * src/core/preset_preview_play_handle.cpp: - * src/gui/file_browser.cpp: - - improved concept for file types supported by certain plugins - - various small improvements for an even better ZynAddSubFX integration - - * src/tracks/instrument_track.cpp: - pass all MIDI events to instrument - - * include/remote_plugin.h: - * src/core/remote_plugin.cpp: - added remotePlugin-framework allowing to easily write plugins which - actually run as external process - -2008-08-28 Tobias Doerffel - - * plugins/vst_base/lvsl_client.cpp: - * plugins/vst_base/lvsl_server.cpp: - * plugins/vst_base/CMakeLists.txt: - fixed broken VST-support - - * CMakeLists.txt: - completed information about packages needed for building VST support - on 64 bit machines (thanks to Stephane Thomas!) - -2008-08-28 Csaba Hruska - - * include/audio_portaudio.h: - * src/core/audio/audio_portaudio.cpp: - fixed segfault in PortAudio's setup widget - fixed hangon on PortAudio exit - -2008-08-27 Csaba Hruska - - * include/audio_portaudio.h: - * src/core/audio/audio_portaudio.cpp: - PortAudio V18 and V19 are supported now - - * cmake/modules/FindPortaudio.cmake: - * include/audio_portaudio.h: - * src/core/audio/audio_portaudio.cpp: - * src/gui/setup_dialog.cpp: - * lmmsconfig.h.in: - * CMakeLists.txt: - added support for PortAudio - - * include/mixer.h: - * include/sample_record_handle.h: - * include/song_editor.h: - * include/sample_track.h: - * include/audio_device.h: - * src/gui/song_editor.cpp: - * src/tracks/sample_track.cpp: - * src/core/audio/audio_device.cpp: - * src/core/mixer.cpp: - * src/core/engine.cpp: - * src/core/sample_record_handle.cpp: - added basic support for recording sound into sample tracks - -2008-08-27 Paul Giblock - - * include/controller_view.h: - * src/gui/widgets/controller_view.cpp: - Add stub for controller help - - * src/gui/piano_roll.cpp: - * data/themes/default/note_triplethalf.png: - * data/themes/default/note_tripleteighth.png: - * data/themes/default/note_tripletthirtysecond.png: - * data/themes/default/note_tripletquarter.png: - * data/themes/default/note_tripletsixteenth.png: - - Add support for directly entering triplet notes - - Add support for triplet Quantization - - Switch grid layout for triplets - - Add additional 32nd note grid resolution when zooming - -2008-08-26 Tobias Doerffel - - * cmake/modules/DetectMachine.cmake: - * plugins/vst_base/CMakeLists.txt: - * lmmsconfig.h.in: - * CMakeLists.txt: - improved detection of machine type - -2008-08-26 Paul Giblock - - * include/controller_connection.h: - * include/controller.h: - * include/controller_rack_view.h: - * include/automatable_model.h: - * include/controller_view.h: - * src/gui/widgets/controller_rack_view.cpp: - * src/gui/widgets/controller_view.cpp: - * src/core/automatable_model.cpp: - * src/core/controller_connection.cpp: - * src/core/controller.cpp: - Add basic support for delete. The controller dialogs probably leak, and - peakController isn't handled yet - -2008-08-24 Tobias Doerffel - - * CMakeLists.txt: - made 0.4.0-beta2 release - -2008-08-24 Paul Giblock - - * plugins/sid/sid_instrument.cpp: - Fix what's this text with extra arg value. - -2008-08-23 Tobias Doerffel - - * cmake/modules/BuildPlugin.cmake: - added missing dependency to bin2res-target in order to build properly - when using "make -jX" - - * CMakeLists.txt: - improved summary page (specific information on what to do if a certain - feature isn't enabled because something was missing) - -2008-08-23 Paul Giblock - - * plugins/bit_invader/bit_invader.cpp: - * plugins/vibed/vibed.cpp: - * plugins/triple_oscillator/triple_oscillator.cpp: - * plugins/audio_file_processor/audio_file_processor.cpp: - * src/gui/piano_roll.cpp: - * src/gui/lfo_controller_dialog.cpp: - * src/gui/main_window.cpp: - * src/gui/song_editor.cpp: - * src/gui/widgets/instrument_sound_shaping_view.cpp: - * src/gui/widgets/envelope_and_lfo_view.cpp: - * src/gui/widgets/instrument_function_views.cpp: - * src/gui/widgets/effect_view.cpp: - * src/gui/automation_editor.cpp: - * src/gui/bb_editor.cpp: - * src/core/envelope_and_lfo_parameters.cpp: - * src/core/mmp.cpp: - Fix English grammer, punctuation, and hard to read strings - -2008-08-23 Tobias Doerffel - - * src/gui/automatable_model_view.cpp: - coding style fixes - - * src/gui/string_pair_drag.cpp: - if no pixmap was given and parent-widget is valid, use a snapshot of - the widget as drag-icon - - * src/tracks/instrument_track.cpp: - added display-name for baseNoteModel - - * src/core/piano.cpp: - made base-note automatable via drag'n'drop - -2008-08-22 Paul Giblock - - * include/automatable_model.h: - * src/gui/automation_editor.cpp: - * src/gui/lmms_style.cpp: - * src/core/lfo_controller.cpp: - Fix various casting warnings - - * src/core/audio/audio_alsa.cpp: - Fix warning about obsolete snd_pcm_sw_params_set_xfer_align(). - ALSA >= 1.0.16 defaults to 1 now. - -2008-08-22 Tobias Doerffel - - * src/core/main.cpp: - fixed splash-screen for win32 - - * src/core/sample_buffer.cpp: - fixed sampleBuffer::tryToMakeRelative() for win32 - paths to samples - are now saved relative in win32-version too (if possible) - - * src/core/piano.cpp: - fixed keycodes for win32 version - - * include/midi_winmm.h: - fixed missing virtual method - - * include/bb_track_container.h: - * include/track.h: - * src/core/track.cpp: - * src/tracks/bb_track.cpp: - implemented correct behaviour when cloning BB-tracks (closes #2042409) - - * src/core/midi/midi_alsa_seq.cpp: - fixed strange ALSA-sequencer behaviour when using MIDI-controllers and - controlling intrument-tracks via MIDI (closes #2062907) - - * src/gui/piano_roll.cpp: - fixed notes appearing multiple times in pattern when recording from - MIDI-device (closes #2058971) - - * src/gui/automation_editor.cpp: - fixed selection of all bars via Ctrl+A (closes #2048163) - - * plugins/audio_file_processor/audio_file_processor.cpp: - * plugins/audio_file_processor/audio_file_processor.h: - * include/sample_buffer.h: - * src/core/sample_buffer.cpp: - fixed crashes when automating start- and end-point in - AudioFileProcessor (closes #2048125) - - * include/oscillator.h: - made oscillator::userWaveSample() const - - * include/instrument_track.h: - * src/gui/file_browser.cpp: - * src/tracks/instrument_track.cpp: - fixed loading presets when dragging them onto existing - instrument-track-window (finally closes #2025902) - - * src/gui/piano_roll.cpp: - fixed moving selected notes (closes #2039248, #2039254, #2043463) - -2008-08-20 dieEasy - - * data/locale/it.qm: - * data/locale/it.ts: - updated Italian localization-file - -2008-08-20 Tobias Doerffel - - * include/automatable_model.h: - restored old controller-behaviour for all models whose step-size is - not 1, i.e. only round for integer models - - * plugins/sid/sid_instrument.h: - * plugins/sid/test.png: - * plugins/sid/sid_instrument.cpp: - * plugins/sid/testred.png: - integrated patch by Csaba Hruska - - * src/core/plugin.cpp: - fixed messages - - * src/core/config_mgr.cpp: - add trailing slashes to paths where necessary (closes #2056353) - - * data/locale/de.qm: - * data/locale/de.ts: - updated German localization file and fixed various messages - - * include/track.h: - * include/track_label_button.h: - * src/tracks/bb_track.cpp: - update combobox in BB-editor when renaming BB-track (closes #2056354) - - * include/controller.h: - * src/gui/widgets/knob.cpp: - only skip GUI-updates when connected to frequently changing controllers - - * include/automatable_model.h: - when connected to controller and returning current value, respect - step-property of automatableModel - - * src/gui/widgets/instrument_midi_io_view.cpp: - minor UI improvements - - * include/midi_winmm.h: - * include/mixer.h: - * src/core/midi/midi_controller.cpp: - * src/core/midi/midi_port.cpp: - * src/core/midi/midi_winmm.cpp: - * src/core/mixer.cpp: - * src/gui/controller_connection_dialog.cpp: - * src/tracks/instrument_track.cpp: - cleanups and coding-style fixes - - * src/core/midi/midi_alsa_seq.cpp: - * src/core/midi/midi_port.cpp: - - fixed crash when changing mode of midiPort - - various small improvements - - * include/instrument_track.h: - * src/core/note_play_handle.cpp: - made midiPort of instrumentTrack accessible via getMidiPort() - -2008-08-19 Tobias Doerffel - - * plugins/sf2_player/sf2_player.cpp: - fixed reverb/chorus after change of samplerate - - * src/core/main.cpp: - * lmms.1: - improved documentation of commandline options - - * src/core/main.cpp: - * src/core/project_renderer.cpp: - improved progress information when rendering at console - -2008-08-18 Paul Giblock - - * include/controller.h: - * src/core/controller.cpp: - * src/gui/automatable_model_view.cpp: - * src/gui/controller_connection_dialog.cpp: - Detect loops before allowing controller-connection - - * src/core/peak_controller.cpp: - Changes displayName from LFO to Peak - -2008-08-07 Tobias Doerffel - - * CMakeLists.txt: - made 0.4.0-beta1 release - - * plugins/sid/sid_instrument.h: - removed unused slot-definitions - - * CMakeLists.txt: - added missing lmmsconfig.h.in for dist target - -2008-08-05 Tobias Doerffel - - * plugins/sid/wave8580__ST.cc: - * plugins/sid/spline.h: - * plugins/sid/3off.png: - * plugins/sid/8580red.png: - * plugins/sid/trianglered.png: - * plugins/sid/logo.png: - * plugins/sid/bp.png: - * plugins/sid/6581.png: - * plugins/sid/wave.cc: - * plugins/sid/8580.png: - * plugins/sid/pot.h: - * plugins/sid/syncred.png: - * plugins/sid/hp.png: - * plugins/sid/sid_instrument.h: - * plugins/sid/lp.png: - * plugins/sid/sync.png: - * plugins/sid/noise.png: - * plugins/sid/wave8580_PST.cc: - * plugins/sid/envelope.cc: - * plugins/sid/extfilt.cc: - * plugins/sid/envelope.h: - * plugins/sid/extfilt.h: - * plugins/sid/pulsered.png: - * plugins/sid/siddefs.h: - * plugins/sid/filter.png: - * plugins/sid/sawred.png: - * plugins/sid/wave6581_PS_.cc: - * plugins/sid/3offred.png: - * plugins/sid/pulse.png: - * plugins/sid/artwork.png: - * plugins/sid/saw.png: - * plugins/sid/CMakeLists.txt: - * plugins/sid/wave8580_P_T.cc: - * plugins/sid/wave6581__ST.cc: - * plugins/sid/bpred.png: - * plugins/sid/6581red.png: - * plugins/sid/ring.png: - * plugins/sid/hpred.png: - * plugins/sid/pot.cc: - * plugins/sid/sid_instrument.cpp: - * plugins/sid/triangle.png: - * plugins/sid/wave.h: - * plugins/sid/voice.cc: - * plugins/sid/lpred.png: - * plugins/sid/noisered.png: - * plugins/sid/voice.h: - * plugins/sid/wave6581_PST.cc: - * plugins/sid/sid.cc: - * plugins/sid/filterred.png: - * plugins/sid/sid.h: - * plugins/sid/version.cc: - * plugins/sid/filter.cc: - * plugins/sid/filter.h: - * plugins/sid/wave6581_P_T.cc: - * plugins/sid/wave8580_PS_.cc: - * plugins/sid/ringred.png: - * plugins/CMakeLists.txt: - added SID instrument plugin by Attila Herman and Csaba Hruska - - * src/gui/widgets/automatable_button.cpp: - show context-menu of button-group if a button is part of it - - * plugins/sf2_player/sf2_player.cpp: - - query data from correct model when activating reverb (closes #2035134) - - convert from note-play-handle's volume to MIDI-velocity when calling - fluid_synth_noteon() - - set fluidsynth's internal interpolation-method to high-quality when - running LMMS in HQ-mode - -2008-08-04 Tobias Doerffel - - * plugins/ladspa_effect/ladspa_effect.cpp: - * plugins/ladspa_effect/ladspa_subplugin_features.cpp: - * plugins/vst_effect/vst_subplugin_features.cpp: - * plugins/vst_effect/vst_effect.cpp: - * plugins/vst_effect/vst_effect_controls.cpp: - * include/plugin.h: - * include/base64.h: - * include/ladspa_base.h: - * src/core/plugin.cpp: - * src/core/effect_chain.cpp: - * src/core/mmp.cpp: - * src/core/ladspa_manager.cpp: - * CMakeLists.txt: - use XML rather than binary blobs for saving plugin-/effect-key - - * src/core/project_journal.cpp: - use random-number-generator correctly - fixes predictable random - numbers and avoids used Journalling-Object-IDs upon loading - project (closes #2036745) - anyways this still might happen under rare - circumstances and needs a further fix - -2008-08-03 Tobias Doerffel - - * include/lmms_math.h: - * src/core/oscillator.cpp: - made oscillator-phase always being positive which allows further - optimizations of fraction()-method - -2008-08-01 Tobias Doerffel - - * include/visualization_widget.h: - * src/gui/widgets/visualization_widget.cpp: - improved anti-aliased visualization - - * src/core/sample_buffer.cpp: - heavily improved performance by using QPainter::drawPolylines and - disabling anti-aliasing if more than 60000 samples have to be - drawn (closes #1938413) - - * src/core/midi/midi_winmm.cpp: - added debug-code - - * src/core/song.cpp: - do not reset window title twice when creating new project - - * src/core/main.cpp: - when creating a new project, show main-window afterwards - fixes - behaviour when debugging win32-version via WINE - - * cmake/modules/BuildPlugin.cmake: - * plugins/ladspa_effect/tap/CMakeLists.txt: - * plugins/ladspa_effect/caps/CMakeLists.txt: - * data/CMakeLists.txt: - * data/nsis_branding.bmp: - * CMakeLists.txt: - * lmms.rc.in: - - made cmake-files ready for NSIS-packaging - - added win-resource-object to LMMS-binary - - * plugins/sf2_player/patches_dialog.cpp: - * plugins/sf2_player/sf2_player.cpp: - * plugins/sf2_player/patches_dialog.h: - * plugins/sf2_player/sf2_player.h: - * data/themes/default/style.css: - - integrated patch by Csaba Hruska - - fixed spinbox-ranges - - * plugins/vst_base/CMakeLists.txt: - fixed include-directories for lvsl_server-target for allowing - out-of-tree builds - -2008-07-31 Tobias Doerffel - - * CMakeLists.txt: - added win32-pkg target - - * include/fft_helpers.h: - added missing EXPORT-declarations - - * src/core/midi/midi_winmm.cpp: - removed some debugging code - -2008-07-30 Tobias Doerffel - - * include/track.h: - * src/core/track.cpp: - * src/gui/file_browser.cpp: - * src/tracks/instrument_track.cpp: - added simple-serializing mode which makes tracks not save their TCOs - - used for improved save and restore of presets (closes #2025902) - - * src/gui/widgets/effect_view.cpp: - do not cast model to effect for only calling displayName() - - * src/gui/widgets/effect_rack_view.cpp: - - initialize bool-map with correct size - fixes crashes under various - circumstances - - do not cast model of effectView as the effect might not exist - anymore - - * data/presets/TripleOscillator/Steel.cs.xml: - * data/presets/TripleOscillator/SawLead.cs.xml: - * data/presets/TripleOscillator/Bass.cs.xml: - * data/presets/TripleOscillator/E-Organ.cs.xml: - * data/presets/TripleOscillator/FM-Wood-Arp.cs.xml: - * data/presets/TripleOscillator/Harmonium.cs.xml: - * data/presets/TripleOscillator/NostalgicFeelings.cs.xml: - * data/presets/TripleOscillator/Moog.cs.xml: - * data/presets/TripleOscillator/SawLead2.cs.xml: - * data/presets/TripleOscillator/HardClipping.cs.xml: - * data/presets/TripleOscillator/RaveBass.cs.xml: - * data/presets/TripleOscillator/EvilHardcore.cs.xml: - * data/presets/TripleOscillator/Distorted-FM-Bass_2.cs.xml: - * data/presets/TripleOscillator/ShortBass.cs.xml: - * data/presets/TripleOscillator/Crystallo.cs.xml: - * data/presets/TripleOscillator/Fear.cs.xml: - * data/presets/TripleOscillator/HorrorBass.cs.xml: - * data/presets/TripleOscillator/Default.cs.xml: - * data/presets/TripleOscillator/SoftStrings.cs.xml: - * data/presets/TripleOscillator/RaveBass_2.cs.xml: - * data/presets/TripleOscillator/Warmth.cs.xml: - * data/presets/TripleOscillator/Beam.cs.xml: - * data/presets/TripleOscillator/SquareLead2.cs.xml: - * data/presets/TripleOscillator/Weird.cs.xml: - * data/presets/TripleOscillator/LFO-party.cs.xml: - * data/presets/TripleOscillator/Nice.cs.xml: - * data/presets/TripleOscillator/ChurchOrgan_2.cs.xml: - * data/presets/TripleOscillator/SoftBass.cs.xml: - * data/presets/TripleOscillator/Stranger.cs.xml: - * data/presets/TripleOscillator/TB303-Arpeggio.cs.xml: - * data/presets/TripleOscillator/E-Piano.cs.xml: - * data/presets/TripleOscillator/PluckArpeggio.cs.xml: - * data/presets/TripleOscillator/WarmStack.cs.xml: - * data/presets/TripleOscillator/Square.cs.xml: - * data/presets/TripleOscillator/MyComputer.cs.xml: - * data/presets/TripleOscillator/Simple-Acid-Bass.cs.xml: - * data/presets/TripleOscillator/MoogArpeggio.cs.xml: - * data/presets/TripleOscillator/Jupiter.cs.xml: - * data/presets/TripleOscillator/AnalogTimes2.cs.xml: - * data/presets/TripleOscillator/SquareLead.cs.xml: - * data/presets/TripleOscillator/TB303.cs.xml: - * data/presets/TripleOscillator/Detuned-Synced-FM-Bass.cs.xml: - * data/presets/TripleOscillator/ChurchOrgan.cs.xml: - * data/presets/TripleOscillator/SquareArp.cs.xml: - * data/presets/TripleOscillator/OldComputerGames.cs.xml: - removed old raw presets, tuned others and added a few new ones - - * plugins/stk/mallets/mallets.cpp: - detect incomplete Stk-installation in model rather than view for not - crashing when playing without opening the GUI before - - * src/core/main.cpp: - - added --dump parameter for easily uncompressing mmpz-files - - try to set realtime priority after command-line parsing as the - resulting warning might be annoying at this place - - moved initialization of RNG to top of main() - - * src/core/mmp.cpp: - quirks for loading drumsynth-samples whose directory-names have - changed from space to underscore - -2008-07-29 Tobias Doerffel - - * plugins/ladspa_effect/tap/CMakeLists.txt: - * plugins/ladspa_effect/caps/CMakeLists.txt: - fixed linker-flags - - * plugins/spectrum_analyzer/spectrum_analyzer.cpp: - * plugins/spectrum_analyzer/spectrum_analyzer.h: - * include/fft_helpers.h: - * src/core/fft_helpers.cpp: - * lmmsconfig.h.in: - moved FFT-helper functions from Spectrum Analyzer plugin to core to - make it also usable by other plugins - -2008-07-28 Tobias Doerffel - - * plugins/ladspa_effect/ladspa_controls.cpp: - * plugins/lb302/lb302.cpp: - * plugins/lb303/lb303.cpp: - * plugins/stereo_matrix/stereomatrix_controls.cpp: - * plugins/bass_booster/bassbooster_controls.cpp: - * plugins/vst_effect/vst_effect_controls.cpp: - * plugins/vibed/vibed.cpp: - * plugins/triple_oscillator/triple_oscillator.cpp: - * plugins/peak_controller_effect/peak_controller_effect_controls.cpp: - * plugins/audio_file_processor/audio_file_processor.cpp: - * plugins/stereo_enhancer/stereoenhancer_controls.cpp: - * plugins/sf2_player/sf2_player.cpp: - * plugins/vst_base/lvsl_client.cpp: - * plugins/vst_base/lvsl_client.h: - * plugins/kicker/kicker.cpp: - * plugins/flp_import/flp_import.cpp: - * plugins/midi_import/midi_import.cpp: - * include/mmp.h: - * include/effect.h: - * include/meter_model.h: - * include/automatable_slider.h: - * include/song.h: - * include/pch.h: - * src/gui/main_window.cpp: - * src/gui/song_editor.cpp: - * src/gui/widgets/tempo_sync_knob.cpp: - * src/gui/widgets/meter_dialog.cpp: - * src/tracks/sample_track.cpp: - * src/tracks/bb_track.cpp: - * src/tracks/instrument_track.cpp: - * src/tracks/pattern.cpp: - * src/core/effect_chain.cpp: - * src/core/midi/midi_controller.cpp: - * src/core/midi/midi_port.cpp: - * src/core/track_container.cpp: - * src/core/serializing_object.cpp: - * src/core/journalling_object.cpp: - * src/core/config_mgr.cpp: - * src/core/automatable_model.cpp: - * src/core/instrument_sound_shaping.cpp: - * src/core/mmp.cpp: - * src/core/effect.cpp: - * src/core/instrument_functions.cpp: - * src/core/controller_connection.cpp: - * src/core/note.cpp: - * src/core/timeline.cpp: - * src/core/surround_area.cpp: - * src/core/automation_pattern.cpp: - * src/core/inline_automation.cpp: - * src/core/fx_mixer.cpp: - * src/core/controller.cpp: - * src/core/lfo_controller.cpp: - * src/core/peak_controller.cpp: - reduced header-dependencies - - * src/core/plugin.cpp: - - don't show messagebox if no GUI is running - - if plugin failed to load also tell about the reason - - * plugins/ladspa_effect/tap/CMakeLists.txt: - * plugins/ladspa_effect/caps/CMakeLists.txt: - * src/core/main.cpp: - * cmake/modules/BuildPlugin.cmake: - * lmmsconfig.h.in: - * CMakeLists.txt: - added support for building LMMS on OS X and generating a DMG-package - - * src/core/main.cpp: - win32-compatibility - - * data/projects/cool_songs/StrictProduction-DearJonDoe.mmp: - * data/projects/cool_songs/OrtalDj-FirstProyect.mmp: - * data/projects/cool_songs/TobyDox-Psycho.mmp: - * data/projects/cool_songs/TobyDox-Confused.mmp: - * data/projects/cool_songs/Djeezus-BeatRolls.mmp: - * data/projects/cool_songs/Lokori-Systematic_Chaos.mmp: - * data/projects/cool_songs/StrictProduction-Underline.mmp: - * data/projects/cool_songs/Djeezus-Oscilisous.mmp: - * data/projects/cool_songs/Chris-RaveRiff.mmpz: - * data/projects/cool_songs/TobyDox-TheFourthDimension.mmp: - * data/projects/cool_songs/Mart-Concave_flow.mmp: - * data/projects/cool_songs/MysthR-Living.mmpz: - * data/projects/cool_songs/Marfil-MarfilDrum01.mmp: - * data/projects/cool_songs/j1m-DingDong.mmp: - * data/projects/cool_songs/Malex-Horizon4.mmp: - * data/projects/cool_songs/Siegel-DreamWave.mmp: - * data/projects/cool_songs/BlueWolf-DreamTravel.mmp: - * data/projects/cool_songs/StrictProduction-Lamentelnes.mmp: - * data/projects/cool_songs/OrtalDj-FirstProyect.mmpz: - * data/projects/cool_songs/Silva-ElvesCall.mmp: - upgraded projects to match current file format - diffstat: 17 files changed, 12811 insertions(+), 37791 deletions(-) - - * include/song_editor.h: - * src/core/song.cpp: - make sure all TCOs are shown after loading project (closes #2016741) - - * src/core/automatable_model.cpp: - when loading legacy automation with only one value in, eliminate - global automation pattern right after loading data - - * src/core/main.cpp: - - initialize random-number generation - fixes problems with duplicate - JO-IDs - - show main-window before loading project given on command-line or - creating a new project (closes #2016741) - - * src/core/automation_pattern.cpp: - fixed some segfaults in case of invalid objects in object-vector - - * src/core/mmp.cpp: - - use QTextStream to save uncompressed XML-files - - when encountering problems while parsing XML-file, print line and - column of problem - -2008-07-27 Tobias Doerffel - - * src/gui/automation_editor.cpp: - also allow drawing new dots when clicking inside already existing - value (closes #2026120) - - * include/instrument_track.h: - * src/tracks/instrument_track.cpp: - reverted previous change of some models from floatModel to intModel as - it caused crashes in knob-class - - * include/automation_pattern.h: - * src/core/automation_pattern.cpp: - when connecting object to automation-pattern which has no object - connected yet, set default-value (closes #2026102) - - * plugins/vst_base/CMakeLists.txt: - added missing support for out-of-tree builds - - * README: - * INSTALL: - updated documentation on how to build LMMS with cmake - -2008-07-26 Tobias Doerffel - - * data/locale/en.ts: - * data/locale/pt_br.ts: - * data/locale/es.ts: - * data/locale/fr.ts: - * data/locale/nl.ts: - * data/locale/ir.ts: - * data/locale/it.ts: - * data/locale/ca.ts: - * data/locale/de.ts: - * data/locale/sv.ts: - refreshed localizations - diffstat: 10 files changed, 34785 insertions(+), 6862 deletions(-) - - * data/locale/ru.ts: - added updated Russian localization by Alexey Kouznetsov - - * CMakeLists.txt: - - added locale targets - - added "update-locales" target - - added "distclean" target - - added "tarball" target - - * plugins/organic/organic.cpp: - * plugins/triple_oscillator/triple_oscillator.cpp: - * include/mixer.h: - * include/sample_buffer.h: - * include/oscillator.h: - * include/types.h: - * src/core/sample_play_handle.cpp: - * src/core/sample_buffer.cpp: - * src/core/oscillator.cpp: - * lmmsconfig.h.in: - * CMakeLists.txt: - less header-dependencies and moved some type-definitions - -2008-07-23 Tobias Doerffel - - * data/locale/fr.qm: - * data/locale/fr.ts: - updated French localization-files by Stephane Thomas - - * cmake/modules/FindPkgConfig.cmake: - * include/midi_winmm.h: - * include/midi_alsa_seq.h: - * CMakeLists.txt: - * cmake/modules/BuildPlugin.cmake: - support for cmake < 2.4.8 - - * plugins/ladspa_effect/caps/CMakeLists.txt: - do not compile with -O3 when using GCC 4.1.x as this version segfaults - while optimizing - - * plugins/spectrum_analyzer/spectrum_analyzer.cpp: - * include/effect_lib.h: - fixed compiler-warnings - - * src/core/midi/midi_winmm.cpp: - * src/core/midi/midi_alsa_seq.cpp: - fixed subscribe/unsubscribe-warnings - - * CMakeLists.txt: - fixes for cmake 2.4 - -2008-07-22 Tobias Doerffel - - * cmake/modules/BuildPlugin.cmake: - * plugins/patman/CMakeLists.txt: - * plugins/ladspa_effect/CMakeLists.txt: - * plugins/organic/CMakeLists.txt: - * plugins/lb302/CMakeLists.txt: - * plugins/lb303/CMakeLists.txt: - * plugins/bass_booster/CMakeLists.txt: - * plugins/stereo_matrix/CMakeLists.txt: - * plugins/bit_invader/CMakeLists.txt: - * plugins/vst_effect/CMakeLists.txt: - * plugins/vibed/CMakeLists.txt: - * plugins/triple_oscillator/CMakeLists.txt: - * plugins/live_tool/CMakeLists.txt: - * plugins/peak_controller_effect/CMakeLists.txt: - * plugins/audio_file_processor/CMakeLists.txt: - * plugins/stk/mallets/CMakeLists.txt: - * plugins/stereo_enhancer/CMakeLists.txt: - * plugins/sf2_player/CMakeLists.txt: - * plugins/vestige/CMakeLists.txt: - * plugins/ladspa_browser/CMakeLists.txt: - * plugins/spectrum_analyzer/CMakeLists.txt: - * plugins/kicker/CMakeLists.txt: - * plugins/flp_import/CMakeLists.txt: - * CMakeLists.txt: - various fixes for allowing out-of-tree builds - - * CMakeLists.txt: - - initial support for CPack - - remove old include/lmmsconfig.h from the autotools-era - - * cmake/modules/InstallHelpers.cmake: - fixed INSTALL_DATA_SUBDIRS-macro (use normal string-replace - instead of regex-replace) - - * include/project_renderer.h: - * src/core/project_renderer.cpp: - also compile without OGG/Vorbis-support - - * cmake/modules/Win32Toolchain.cmake: - * cmake/modules/BuildPlugin.cmake: - * src/3rdparty/samplerate/config.h: - * CMakeLists.txt: - fixes for successfully cross-compiling - - * cmake/modules/Win32Toolchain.cmake: - * cmake/modules/BuildPlugin.cmake: - * plugins/ladspa_effect/tap/CMakeLists.txt: - * plugins/ladspa_effect/caps/CMakeLists.txt: - * plugins/vst_effect/CMakeLists.txt: - * include/audio_sdl.h: - * src/core/midi/midi_winmm.cpp: - * build_mingw32: - * CMakeLists.txt: - initial support for mingw-cross-compiling - - * include/midi_alsa_seq.h: - * include/midi_client.h: - * include/midi_port.h: - * include/midi_winmm.h: - * src/core/mixer.cpp: - * src/core/midi/midi_alsa_raw.cpp: - * src/core/midi/midi_alsa_seq.cpp: - * src/core/midi/midi_client.cpp: - * src/core/midi/midi_oss.cpp: - * src/core/midi/midi_winmm.cpp: - * src/gui/setup_dialog.cpp: - added rudimentary WinMM MIDI support - - * src/core/mmp.cpp: - * plugins/lb302/lb302.h - * plugins/CMakeLists.txt: - switched back to LB302 as Paul wants LB303 for 0.4.1 - - * cmake/modules/FindAlsa.cmake: - * cmake/modules/FindOggVorbis.cmake: - * cmake/modules/FindSTK.cmake: - * cmake/modules/FindPCHSupport.cmake: - * cmake/modules/config-alsa.h.cmake: - * cmake/modules/InstallHelpers.cmake: - * cmake/modules/FindPulseAudio.cmake: - * cmake/modules/ChecksForLibSamplerate.cmake: - * cmake/modules/BuildPlugin.cmake: - * plugins/patman/patman.cpp: - * plugins/patman/CMakeLists.txt: - * plugins/ladspa_effect/ladspa_effect.cpp: - * plugins/ladspa_effect/tap/tap_deesser.c: - * plugins/ladspa_effect/tap/tap_sigmoid.c: - * plugins/ladspa_effect/tap/tap_doubler.c: - * plugins/ladspa_effect/tap/ladspa-local.h: - * plugins/ladspa_effect/tap/tap_eqbw.c: - * plugins/ladspa_effect/tap/tap_pinknoise.c: - * plugins/ladspa_effect/tap/tap_chorusflanger.c: - * plugins/ladspa_effect/tap/tap_limiter.c: - * plugins/ladspa_effect/tap/tap_eq.c: - * plugins/ladspa_effect/tap/tap_vibrato.c: - * plugins/ladspa_effect/tap/tap_autopan.c: - * plugins/ladspa_effect/tap/tap_pitch.c: - * plugins/ladspa_effect/tap/tap_dynamics_st.c: - * plugins/ladspa_effect/tap/tap_echo.c: - * plugins/ladspa_effect/tap/tap_tremolo.c: - * plugins/ladspa_effect/tap/tap_tubewarmth.c: - * plugins/ladspa_effect/tap/tap_dynamics_m.c: - * plugins/ladspa_effect/tap/tap_reflector.c: - * plugins/ladspa_effect/tap/tap_reverb.c: - * plugins/ladspa_effect/tap/tap_rotspeak.c: - * plugins/ladspa_effect/tap/CMakeLists.txt: - * plugins/ladspa_effect/ladspa_control_dialog.cpp: - * plugins/ladspa_effect/caps/basics.h: - * plugins/ladspa_effect/caps/CMakeLists.txt: - * plugins/ladspa_effect/ladspa_controls.cpp: - * plugins/ladspa_effect/CMakeLists.txt: - * plugins/organic/organic.cpp: - * plugins/organic/CMakeLists.txt: - * plugins/lb302/lb302.cpp: - * plugins/lb302/CMakeLists.txt: - * plugins/lb303/lb303.cpp: - * plugins/lb303/CMakeLists.txt: - * plugins/bass_booster/bassbooster_controls.cpp: - * plugins/bass_booster/CMakeLists.txt: - * plugins/stereo_matrix/stereomatrix_controls.cpp: - * plugins/stereo_matrix/CMakeLists.txt: - * plugins/bit_invader/bit_invader.cpp: - * plugins/bit_invader/CMakeLists.txt: - * plugins/vst_effect/vst_effect_controls.cpp: - * plugins/vst_effect/CMakeLists.txt: - * plugins/vibed/CMakeLists.txt: - * plugins/vibed/nine_button_selector.cpp: - * plugins/vibed/vibed.cpp: - * plugins/triple_oscillator/CMakeLists.txt: - * plugins/triple_oscillator/triple_oscillator.cpp: - * plugins/live_tool/live_tool.cpp: - * plugins/live_tool/CMakeLists.txt: - * plugins/peak_controller_effect/peak_controller_effect.cpp: - * plugins/peak_controller_effect/peak_controller_effect_controls.cpp: - * plugins/peak_controller_effect/CMakeLists.txt: - * plugins/audio_file_processor/audio_file_processor.cpp: - * plugins/audio_file_processor/CMakeLists.txt: - * plugins/stk/mallets/mallets.cpp: - * plugins/stk/mallets/CMakeLists.txt: - * plugins/stk/CMakeLists.txt: - * plugins/stereo_enhancer/stereoenhancer_controls.cpp: - * plugins/stereo_enhancer/CMakeLists.txt: - * plugins/sf2_player/patches_dialog.cpp: - * plugins/sf2_player/sf2_player.cpp: - * plugins/sf2_player/CMakeLists.txt: - * plugins/vestige/vestige.cpp: - * plugins/vestige/CMakeLists.txt: - * plugins/vst_base/lvsl_client.cpp: - * plugins/vst_base/CMakeLists.txt: - * plugins/ladspa_browser/ladspa_browser.cpp: - * plugins/ladspa_browser/ladspa_description.cpp: - * plugins/ladspa_browser/ladspa_port_dialog.cpp: - * plugins/ladspa_browser/CMakeLists.txt: - * plugins/spectrum_analyzer/spectrumanalyzer_controls.cpp: - * plugins/spectrum_analyzer/CMakeLists.txt: - * plugins/kicker/kicker.cpp: - * plugins/kicker/CMakeLists.txt: - * plugins/flp_import/CMakeLists.txt: - * plugins/flp_import/unrtf/output.c: - * plugins/flp_import/unrtf/html.c: - * plugins/flp_import/unrtf/malloc.c: - * plugins/flp_import/unrtf/parse.c: - * plugins/flp_import/unrtf/attr.c: - * plugins/flp_import/unrtf/word.c: - * plugins/flp_import/unrtf/util.c: - * plugins/flp_import/unrtf/convert.c: - * plugins/flp_import/unrtf/hash.c: - * plugins/flp_import/unrtf/error.c: - * plugins/midi_import/CMakeLists.txt: - * plugins/CMakeLists.txt: - * Makefile.svn: - * include/midi_dummy.h: - * include/midi_alsa_raw.h: - * include/config_mgr.h: - * include/audio_file_wave.h: - * include/audio_file_ogg.h: - * include/ladspa_manager.h: - * include/ladspa_control.h: - * include/ladspa.h: - * include/midi_oss.h: - * include/pch.h: - * include/sample_buffer.h: - * include/audio_dummy.h: - * include/midi_mapper.h: - * include/audio_pulseaudio.h: - * include/audio_sdl.h: - * include/micro_timer.h: - * include/audio_jack.h: - * include/project_renderer.h: - * include/midi_alsa_seq.h: - * include/ladspa-1.1.h: - * include/setup_dialog.h: - * include/export_project_dialog.h: - * include/midi_client.h: - * include/audio_device.h: - * include/audio_oss.h: - * include/audio_alsa.h: - * src/gui/piano_roll.cpp: - * src/gui/track_container_view.cpp: - * src/gui/plugin_browser.cpp: - * src/gui/controller_dialog.cpp: - * src/gui/automatable_model_view.cpp: - * src/gui/effect_select_dialog.cpp: - * src/gui/effect_control_dialog.cpp: - * src/gui/fx_mixer_view.cpp: - * src/gui/main_window.cpp: - * src/gui/song_editor.cpp: - * src/gui/setup_dialog.cpp: - * src/gui/controller_connection_dialog.cpp: - * src/gui/file_browser.cpp: - * src/gui/widgets/ladspa_control_view.cpp: - * src/gui/widgets/track_label_button.cpp: - * src/gui/widgets/graph.cpp: - * src/gui/widgets/visualization_widget.cpp: - * src/gui/widgets/combobox.cpp: - * src/gui/widgets/tab_widget.cpp: - * src/gui/widgets/midi_port_menu.cpp: - * src/gui/widgets/led_checkbox.cpp: - * src/gui/widgets/side_bar_widget.cpp: - * src/gui/widgets/controller_rack_view.cpp: - * src/gui/widgets/kmultitabbar.cpp: - * src/gui/widgets/caption_menu.cpp: - * src/gui/widgets/instrument_sound_shaping_view.cpp: - * src/gui/widgets/rename_dialog.cpp: - * src/gui/widgets/envelope_and_lfo_view.cpp: - * src/gui/widgets/pixmap_button.cpp: - * src/gui/widgets/knob.cpp: - * src/gui/widgets/instrument_function_views.cpp: - * src/gui/widgets/fade_button.cpp: - * src/gui/widgets/cpuload_widget.cpp: - * src/gui/widgets/tab_bar.cpp: - * src/gui/widgets/automatable_slider.cpp: - * src/gui/widgets/group_box.cpp: - * src/gui/widgets/lcd_spinbox.cpp: - * src/gui/widgets/rubberband.cpp: - * src/gui/widgets/tool_button.cpp: - * src/gui/widgets/controller_view.cpp: - * src/gui/widgets/project_notes.cpp: - * src/gui/widgets/fader.cpp: - * src/gui/widgets/effect_rack_view.cpp: - * src/gui/widgets/effect_view.cpp: - * src/gui/widgets/nstate_button.cpp: - * src/gui/widgets/automatable_button.cpp: - * src/gui/widgets/tempo_sync_knob.cpp: - * src/gui/export_project_dialog.cpp: - * src/gui/automation_editor.cpp: - * src/gui/bb_editor.cpp: - * src/gui/about_dialog.cpp: - * src/tracks/sample_track.cpp: - * src/tracks/bb_track.cpp: - * src/tracks/instrument_track.cpp: - * src/tracks/pattern.cpp: - * src/3rdparty/samplerate/src_sinc.c: - * src/3rdparty/samplerate/config.h: - * src/core/midi/midi_controller.cpp: - * src/core/midi/midi_mapper.cpp: - * src/core/midi/midi_oss.cpp: - * src/core/midi/midi_port.cpp: - * src/core/midi/midi_alsa_seq.cpp: - * src/core/midi/midi_alsa_raw.cpp: - * src/core/song.cpp: - * src/core/track_container.cpp: - * src/core/bb_track_container.cpp: - * src/core/config_mgr.cpp: - * src/core/automatable_model.cpp: - * src/core/audio/audio_alsa.cpp: - * src/core/audio/audio_file_wave.cpp: - * src/core/audio/audio_sdl.cpp: - * src/core/audio/audio_oss.cpp: - * src/core/audio/audio_jack.cpp: - * src/core/audio/audio_pulseaudio.cpp: - * src/core/audio/audio_file_ogg.cpp: - * src/core/envelope_and_lfo_parameters.cpp: - * src/core/main.cpp: - * src/core/mixer.cpp: - * src/core/combobox_model.cpp: - * src/core/instrument_sound_shaping.cpp: - * src/core/project_renderer.cpp: - * src/core/meter_model.cpp: - * src/core/ladspa_manager.cpp: - * src/core/instrument_functions.cpp: - * src/core/controller_connection.cpp: - * src/core/ladspa_control.cpp: - * src/core/track.cpp: - * src/core/piano.cpp: - * src/core/timeline.cpp: - * src/core/surround_area.cpp: - * src/core/sample_buffer.cpp: - * src/core/mv_base.cpp: - * src/core/automation_pattern.cpp: - * src/core/lfo_controller.cpp: - * src/core/controller.cpp: - * src/core/peak_controller.cpp: - * data/locale/CMakeLists.txt: - * data/track_icons/CMakeLists.txt: - * data/samples/CMakeLists.txt: - * data/presets/PluckedStringSynth/Default.cs.xml: - * data/presets/VeSTige/Default.cs.xml: - * data/presets/CMakeLists.txt: - * data/themes/CMakeLists.txt: - * data/projects/CMakeLists.txt: - * data/CMakeLists.txt: - * lmmsconfig.h.in: - * CMakeLists.txt: - migrated build-system to CMAKE - - * plugins/patman/Makefile.am: - * plugins/ladspa_effect/tap/Makefile.am: - * plugins/ladspa_effect/caps/Makefile.am: - * plugins/ladspa_effect/Makefile.am: - * plugins/organic/Makefile.am: - * plugins/lb302/Makefile.am: - * plugins/lb303/Makefile.am: - * plugins/bass_booster/Makefile.am: - * plugins/stereo_matrix/Makefile.am: - * plugins/bit_invader/Makefile.am: - * plugins/vst_effect/Makefile.am: - * plugins/vibed/Makefile.am: - * plugins/triple_oscillator/Makefile.am: - * plugins/live_tool/Makefile.am: - * plugins/peak_controller_effect/Makefile.am: - * plugins/audio_file_processor/Makefile.am: - * plugins/stk/mallets/Makefile.am: - * plugins/stk/Makefile.am: - * plugins/stereo_enhancer/Makefile.am: - * plugins/sf2_player/Makefile.am: - * plugins/vestige/Makefile.am: - * plugins/vst_base/Makefile.am: - * plugins/ladspa_browser/Makefile.am: - * plugins/spectrum_analyzer/Makefile.am: - * plugins/kicker/Makefile.am: - * plugins/Makefile.am: - * plugins/flp_import/Makefile.am: - * plugins/midi_import/Makefile.am: - * data/locale/Makefile.am: - * data/track_icons/Makefile.am: - * data/midi-maps/Makefile.am: - * data/samples/effects/Makefile.am: - * data/samples/stringsnpads/Makefile.am: - * data/samples/basses/Makefile.am: - * data/samples/shapes/Makefile.am: - * data/samples/latin/Makefile.am: - * data/samples/Makefile.am: - * data/samples/bassloopes/Makefile.am: - * data/samples/drums/Makefile.am: - * data/samples/instruments/Makefile.am: - * data/samples/misc/Makefile.am: - * data/samples/drumsynth/effects/Makefile.am: - * data/samples/drumsynth/misc_synth/Makefile.am: - * data/samples/drumsynth/tr606/Makefile.am: - * data/samples/drumsynth/cr78/Makefile.am: - * data/samples/drumsynth/tr808/Makefile.am: - * data/samples/drumsynth/magnetboy/Makefile.am: - * data/samples/drumsynth/tr909/Makefile.am: - * data/samples/drumsynth/misc_fx/Makefile.am: - * data/samples/drumsynth/misc/Makefile.am: - * data/samples/drumsynth/electro/Makefile.am: - * data/samples/drumsynth/ferraro/Makefile.am: - * data/samples/drumsynth/linn/Makefile.am: - * data/samples/drumsynth/r_b/Makefile.am: - * data/samples/drumsynth/tr77/Makefile.am: - * data/samples/drumsynth/misc_bass/Makefile.am: - * data/samples/drumsynth/misc_perc/Makefile.am: - * data/samples/drumsynth/latin/Makefile.am: - * data/samples/drumsynth/instrument/Makefile.am: - * data/samples/drumsynth/misc_electro/Makefile.am: - * data/samples/drumsynth/Makefile.am: - * data/samples/drumsynth/acoustic/Makefile.am: - * data/samples/drumsynth/misc_hats/Makefile.am: - * data/samples/drumsynth/farfisa/Makefile.am: - * data/samples/drumsynth/jorgensohn/Makefile.am: - * data/samples/drumsynth/cr8000/Makefile.am: - * data/samples/drumsynth/misc_claps/Makefile.am: - * data/samples/beats/Makefile.am: - * data/presets/AudioFileProcessor/Makefile.am: - * data/presets/Organic/Makefile.am: - * data/presets/PluckedStringSynth/Makefile.am: - * data/presets/VeSTige/Makefile.am: - * data/presets/BitInvader/Makefile.am: - * data/presets/Makefile.am: - * data/presets/TripleOscillator/Makefile.am: - * data/themes/Makefile.am: - * data/projects/covers/Makefile.am: - * data/projects/recorded_loops/Makefile.am: - * data/projects/cool_songs/Makefile.am: - * data/projects/tutorials/Makefile.am: - * data/projects/demos/Makefile.am: - * data/projects/Makefile.am: - * data/projects/misc/Makefile.am: - * data/projects/templates/Makefile.am: - * data/Makefile.am: - * Makefile.am: - * acinclude.m4: - * configure.in: - removed old autotools-files - -2008-07-18 Tobias Doerffel - - * plugins/ladspa_effect/tap/tap_deesser.c: - * plugins/ladspa_effect/tap/tap_sigmoid.c: - * plugins/ladspa_effect/tap/tap_doubler.c: - * plugins/ladspa_effect/tap/tap_eqbw.c: - * plugins/ladspa_effect/tap/tap_pinknoise.c: - * plugins/ladspa_effect/tap/tap_chorusflanger.c: - * plugins/ladspa_effect/tap/tap_eq.c: - * plugins/ladspa_effect/tap/tap_limiter.c: - * plugins/ladspa_effect/tap/tap_vibrato.c: - * plugins/ladspa_effect/tap/tap_pitch.c: - * plugins/ladspa_effect/tap/tap_autopan.c: - * plugins/ladspa_effect/tap/tap_dynamics_st.c: - * plugins/ladspa_effect/tap/tap_echo.c: - * plugins/ladspa_effect/tap/tap_tremolo.c: - * plugins/ladspa_effect/tap/tap_tubewarmth.c: - * plugins/ladspa_effect/tap/tap_dynamics_m.c: - * plugins/ladspa_effect/tap/tap_reflector.c: - * plugins/ladspa_effect/tap/tap_reverb.c: - * plugins/ladspa_effect/tap/tap_rotspeak.c: - * plugins/ladspa_effect/tap/Makefile.am: - added constructor/destructor-attribute to _init() and _finit()-methods - in order to make those LADSPA-plugins work properly in win32-version - - * src/core/config_mgr.cpp: - * src/core/ladspa_manager.cpp: - * src/gui/setup_dialog.cpp: - separate LADSPA-paths with ',' instead of ':' as win32-paths usually - contain ':'-characters... - - * src/core/ladspa_2_lmms.cpp: - also allow LADSPA-plugins which are not realtime capable - not all of - them work properly but most do and it's better to provide more of them - - * src/gui/widgets/effect_view.cpp: - handled rename of up/down arrow graphics - - * include/ladspa_2_lmms.h: - cleanups - - * src/core/ladspa_manager.cpp: - fixed paths to LADSPA-plugins for win32 - - * src/gui/string_pair_drag.cpp: - at destruction check whether mainWindow is still alive - - * src/core/midi/midi_port.cpp: - range-checking for keys of input-events - - * src/core/song.cpp: - lock mixer while adding BB-track (finally closes #2014486) - - * src/core/bb_track_container.cpp: - * src/core/mv_base.cpp: - * src/gui/automation_editor.cpp: - * src/gui/bb_editor.cpp: - * src/gui/widgets/knob.cpp: - * src/tracks/instrument_track.cpp: - do not create queued signal-slot-connections - - * src/core/audio/audio_sdl.cpp: - changed number of frames per callback which seems to fix distorted sound - - * plugins/lb303/lb303.h: - removed declaration of unimplemented slot - fixes win32-build - - * plugins/ladspa_effect/ladspa_effect.cpp: - * plugins/vibed/vibed.cpp: - * include/controller.h: - * include/lfo_controller.h: - * include/midi_controller.h: - * include/peak_controller.h: - * include/plugin.h: - * src/core/controller.cpp: - * src/core/lfo_controller.cpp: - * src/core/peak_controller.cpp: - * src/core/tool.cpp: - * src/core/midi/midi_controller.cpp: - * src/gui/effect_control_dialog.cpp: - * src/gui/effect_select_dialog.cpp: - * src/gui/main_window.cpp: - * src/gui/plugin_browser.cpp: - * src/gui/widgets/controller_view.cpp: - * src/gui/widgets/effect_view.cpp: - * src/tracks/instrument_track.cpp: - removed publicName-properties in various classes and plugin-descriptor - and use model::displayName instead - - * src/gui/controller_connection_dialog.cpp: - improved GUI-layout - - * include/automation_pattern.h: - * src/core/automation_pattern.cpp: - - removed obsolete variable - - fixed wrong behaviour of automationPattern::valueAt() - - in case there's only one initial value in time-map, set it for all - objects when loading settings - - * src/tracks/instrument_track.cpp: - save actual instrument-settings in separate sub-node for not mixing up - unknown nodes with instruments - - * src/gui/widgets/group_box.cpp: - only toggle LED on left click - - * include/detuning_helper.h: - * include/inline_automation.h: - fixed behaviour for inline-automations with only one value in time-map - - * src/core/mmp.cpp: - - fixed and improved various tag-renaming-loops - - added upgrade path from LB302 to LB303 - - * plugins/bit_invader/bit_invader.cpp: - * plugins/sf2_player/sf2_player.cpp: - * plugins/spectrum_analyzer/spectrum_analyzer.cpp: - fixed compiler warnings - - * plugins/Makefile.am: - removed lb302 from list of plugins to build - - * plugins/midi_import/midi_import.cpp: - improved tempo-automation import - - * include/automatable_model.h: - * include/mv_base.h: - * src/core/automatable_model.cpp: - moved displayName-property from automatableModel to model base-class - - * src/tracks/pattern.cpp: - fixed types - - * src/core/automation_pattern.cpp: - improved behaviour in automationPattern::clear() and - automationPattern::putValue() - - * include/instrument_sound_shaping.h: - * src/core/effect_chain.cpp: - * src/core/instrument_functions.cpp: - * src/core/instrument_sound_shaping.cpp: - * src/core/meter_model.cpp: - * src/core/song.cpp: - * src/core/track.cpp: - * src/core/surround_area.cpp: - * src/gui/widgets/graph.cpp: - * src/tracks/instrument_track.cpp: - added more values for displayName-property - - * include/track_label_button.h: - * src/gui/widgets/track_label_button.cpp: - * src/tracks/automation_track.cpp: - * src/tracks/bb_track.cpp: - * src/tracks/instrument_track.cpp: - * src/tracks/sample_track.cpp: - * Makefile.am: - - moved name_label.* to track_label_button.* - - bigger icons for trackLabelButtons - -2008-07-17 Tobias Doerffel - - * src/tracks/automation_track.cpp: - make sure, hidden automation-tracks are not muted when loading - - * src/core/automatable_model.cpp: - cleanups - - * data/projects/covers/J.S.Bach-Preludium_and_Fugue_A-Minor.mmpz: - fixed tempo-automation - -2008-07-16 Tobias Doerffel - - * src/gui/main_window.cpp: - added minimal width and height when restoring subwindow-states - - * include/bb_track_container.h: - * src/core/bb_track_container.cpp: - * src/core/song.cpp: - added quirk for fixing projects with broken positions of TCOs inside - BB-tracks - - * src/core/automation_pattern.cpp: - update views after resolving IDs for drawing bars with proper range - - * src/tracks/automation_track.cpp: - fixed behaviour of automation-tracks in BB-editor (closes #2014486) - - * include/track.h: - * src/core/track.cpp: - fixed "Cut"-action on TCOs (closes #2016731) - -2008-07-12 Tobias Doerffel - - * src/core/config_mgr.cpp: - * src/core/main.cpp: - do not terminate silently if parsing of configuration file failed - - * src/gui/automation_editor.cpp: - fixed drawing of bars which do not fit within current viewport - - * data/themes/default/factory_files.png: - better icon - - * data/projects/covers/J.S.Bach-Preludium_and_Fugue_A-Minor.mmpz: - upgraded + reverb in master-FX channel - - * Makefile.am: - * include/effect_label.h: - * src/gui/widgets/effect_label.cpp: - removed obsolete files - - * include/automation_track.h: - * include/bb_track.h: - * include/effect_rack_view.h: - * include/instrument_track.h: - * include/name_label.h: - * include/sample_track.h: - * include/track.h: - * src/core/track.cpp: - * src/gui/widgets/group_box.cpp: - * src/gui/widgets/name_label.cpp: - * src/tracks/automation_track.cpp: - * src/tracks/bb_track.cpp: - * src/tracks/instrument_track.cpp: - * src/tracks/sample_track.cpp: - * data/themes/default/style.css: - * data/themes/default/add_automation.png: - * data/themes/default/add_sample_track.png: - * data/themes/default/automation.png: - * data/themes/default/automation_track.png: - * data/themes/default/colorize.png: - * data/themes/default/instrument_track.png: - * data/themes/default/sample_track.png: - * data/themes/default/surround_area.png: - unified track-view appearence and behaviour - -2008-07-11 Tobias Doerffel - - * plugins/sf2_player/Makefile.am: - added missing SOURCES-entry for UI-file - - * src/gui/widgets/combobox.cpp: - better position for text-drawing - - * include/instrument_functions.h: - * include/instrument_function_views.h: - * src/core/instrument_functions.cpp: - * src/gui/widgets/instrument_function_views.cpp: - * data/themes/default/arp_down.png: - * data/themes/default/arp_down_off.png: - * data/themes/default/arp_down_on.png: - * data/themes/default/arp_random.png: - * data/themes/default/arp_random_off.png: - * data/themes/default/arp_random_on.png: - * data/themes/default/arp_up.png: - * data/themes/default/arp_up_off.png: - * data/themes/default/arp_up_on.png: - * data/themes/default/arp_up_and_down.png: - * data/themes/default/arp_up_and_down_off.png: - * data/themes/default/arp_up_and_down_on.png: - use combobox instead of button-group for selecting arpeggio-direction - -2008-07-08 Paul Giblock - - * plugins/lb303: - * plugins/lb303/lb303.cpp: - * plugins/lb303/lb303.h: - * plugins/lb303/artwork.png: - * plugins/lb303/logo.png: - * plugins/lb303/Makefile.am: - * plugins/Makefile.am: - * configure.in: - First version of lb303, NO backward compatability YET - - * src/gui/controller_connection_dialog.cpp: - Fix MIDI AutoDetect - - * src/gui/widgets/knob.cpp: - Fix occationally missing line after instantiation - -2008-07-07 Paul Giblock - - * src/gui/controller_connection_dialog.cpp: - Show name instead of type in connection dialog - - * src/gui/widgets/controller_view.cpp: - Remove bypass - - * plugins/lb302/lb302.cpp: - * plugins/lb302/lb302.h: - - Initial support for pitch-bend, doesn't work during slide. - - Next version will probably be the first lb303 - - Cleanup, fixed dropped-notes - - Fix pitch-bend while sliding - -2008-07-07 Tobias Doerffel - - * configure.in: - made 0.4.0-alpha2 release - - * src/core/mmp.cpp: - added compat-code for loading old presets where content-node is named - "channelsettings" - - * plugins/sf2_player/sf2_player.cpp: - * plugins/sf2_player/sf2_player.h: - added support for pitch-bending - - * include/instrument_track.h: - * include/note_play_handle.h: - * src/core/note_play_handle.cpp: - * src/tracks/instrument_track.cpp: - - additionally provide frequency without pitch-wheel - - added instrumentTrack::midiPitch() - - * include/instrument.h: - * include/instrument_track.h: - * include/midi_controller.h: - * include/midi_event_processor.h: - * include/midi_port.h: - * src/core/note_play_handle.cpp: - * src/core/midi/midi_controller.cpp: - * src/tracks/instrument_track.cpp: - removed buggy and obsolete support for monophonic instruments - -2008-07-06 Paul Giblock - - * plugins/lb302/lb302.cpp: - * plugins/lb302/lb302.h: - New version (and probably last) of new IPH-based lb302 - -2008-07-06 Tobias Doerffel - - * src/gui/widgets/combobox.cpp: - draw text at correct position in win32-version - - * src/core/drumsynth.cpp: - when building for win32 define powf() as pow() due to symbol-conflicts - in win32-libm - - * data/themes/default/style.css: - fixed font-color for what's-this-popups so that they're readable - -2008-07-05 Tobias Doerffel - - * plugins/stk/mallets/mallets.cpp: - protect critical section when creating STK-synths as STK is not - thread-safe (closes #2005888) - - * include/instrument_track.h: - * src/tracks/instrument_track.cpp: - - set hand-cursor for instrument-track-window button - - in instrumentTrack::processInEvent() lock mixer in outer branch - - * include/instrument.h: - added note for scheduled removal of monophonic-property - - * include/note_play_handle.h: - made m_released volatile - - * src/core/note_play_handle.cpp: - - instantly exit noteOff() if already released - - manually unlink references to itself in instrumentTrack (fixes - segfaults in various situations) - - * src/core/envelope_and_lfo_parameters.cpp: - * src/core/instrument_functions.cpp: - * src/core/ladspa_control.cpp: - fixed tempo-sync-models (closes #2010776) - - * src/core/mixer.cpp: - cleanups - - * src/tracks/automation_track.cpp: - made muting automation-tracks work (closes #2010770) - - * src/tracks/bb_track.cpp: - made muting BB-tracks work (closes #2010764) - - * src/gui/widgets/effect_rack_view.cpp: - made removing effect-plugins thread-safe (closes #2010984) - - * src/core/automation_pattern.cpp: - save and restore automationPattern's name (closes #2011011) - - * include/inline_automation.h: - delete automation-pattern is in correct thread (closes #2008232) - -2008-07-04 Tobias Doerffel - - * include/track.h: - made trackContentObject and track implement displayName() in order to - return their name - - * include/effect_label.h: - * src/gui/widgets/effect_label.cpp: - * src/tracks/sample_track.cpp: - do not take _initial_name as it can be retrieved from track - - * src/tracks/sample_track.cpp: - added name to volumeModel - - * data/themes/default/hand.png: - * src/gui/automatable_model_view.cpp: - * src/gui/fx_mixer_view.cpp: - * src/gui/widgets/fade_button.cpp: - * src/gui/widgets/effect_label.cpp: - * src/gui/widgets/name_label.cpp: - * src/core/track.cpp: - added hand-cursor for all controls - - * data/themes/default/style.css: - common font-size for track-labels - -2008-07-02 Tobias Doerffel - - * src/core/main.cpp: - * src/core/song.cpp: - added new commandline option "--upgrade" for upgrading project-files - easily - - * src/core/config_mgr.cpp: - fixed wrong macro-name - fixes unusable Mallets-plugin - -2008-07-01 Tobias Doerffel - - * plugins/sf2_player/Makefile.am: - removed ui_patches_dialog.h from SOURCES-list - - * src/core/mmp.cpp: - don't mess up projects when loading files being created using - 0.4.0-alpha in a later version because "0.4.0-alpha" < "0.4.0-svn..." - - * include/mv_base.h: - Qt 4.3 compatibility - -2008-06-30 Tobias Doerffel - - * configure.in: - made 0.4.0-alpha release - - * src/core/song.cpp: - * src/core/mmp.cpp: - * src/core/track.cpp: - * src/core/automation_pattern.cpp: - fixed broken load/save of song-global automation - - * Makefile.am: - win32-pkg-fixes - - * data/locale/de.qm: - * data/locale/de.ts: - updated German localization file - - * include/song_editor.h: - * src/gui/song_editor.cpp: - made icon on play-button change according to current mode - - * include/main_window.h: - * src/gui/bb_editor.cpp: - * src/gui/fx_mixer_view.cpp: - * src/gui/main_window.cpp: - * src/gui/song_editor.cpp: - * src/gui/widgets/controller_rack_view.cpp: - added toggle-button for controller-rack-view and improved default - positions of sub-windows in workspace - - * src/core/song.cpp: - - send posted events after creating a new project - makes project not - being marked as modified right after it's been created - - create empty sample-track and automation-track in new projects - - * src/core/engine.cpp: - clear whole project before deleting everything - fixes segfault when - quitting with controllers added - - * src/core/effect_chain.cpp: - fixed crash when an effect failed to load because its sub-plugin is - missing (closes #2005910) - - * src/core/automation_pattern.cpp: - - initialize first value in time-map - - better default-model - - change automation-pattern to NULL if opened in automation editor - during destruction - - improved default-label - - when used in track-container with fixed TCOs, update length - - * src/core/track.cpp: - * src/tracks/bb_track.cpp: - * src/tracks/instrument_track.cpp: - * src/tracks/sample_track.cpp: - save/restore name-property inside track-class - - * src/tracks/automation_track.cpp: - set a proper name per default - - * src/gui/automation_editor.cpp: - queued connections for models for not getting signaled at - destruction-time - - * include/bb_editor.h: - * src/gui/bb_editor.cpp: - made it possible to add automation-tracks to BB-editor - - * include/automation_pattern.h: - * include/inline_automation.h: - * include/note.h: - * src/core/inline_automation.cpp: - * src/core/note.cpp: - fixed inlineAutomation::hasAutomation() - - * data/themes/default/style.css: - common font-size for various push-buttons - - * src/core/config_mgr.cpp: - ask whether to create working-directory if it does not exist - - * src/core/fx_mixer.cpp: - reset mute-model in fxMixer::clear() - - * include/track.h: - * src/core/track.cpp: - - removed obsolete static members - - more simple QPen-initialization for not making Qt leak - - * include/combobox_model.h: - pass _default_constructed-parameter to base-class - - * src/gui/lfo_controller_dialog.cpp: - renamed constants so one-unit-compiling is possible - - * src/gui/widgets/envelope_and_lfo_view.cpp: - * src/core/envelope_and_lfo_parameters.cpp: - do not duplicate constants - - * src/gui/widgets/group_box.cpp: - make sure LED's default-model is being deleted when changing model - - * src/core/plugin.cpp: - made initialization of dummy-plugin pixmap-loder static - - * src/core/mixer.cpp: - properly terminate worker-threads at mixer-destruction - - * src/core/main.cpp: - fixed various leaks - - * src/core/mmp.cpp: - replaced compat-code by proper code in multimediaProject::upgrade() - - * src/core/effect.cpp: - added missing initialization of m_processors member variable - - * src/core/instrument_functions.cpp: - removed obsolete constants - - * src/core/sample_buffer.cpp: - fixed broken logic when updating sample-data - - * src/core/automation_pattern.cpp: - in automationPattern::valueAt() check whether the time-map is empty - - * src/core/fx_mixer.cpp: - save/load mute-settings for FX-lines - - * src/core/peak_controller.cpp: - return default-value if there's no peak-effect - - * configure.in: - * Makefile.am: - * include/sample_buffer.h: - * src/core/sample_buffer.cpp: - removed support for SDL_sound-library as libsndfile and libvorbis do - everything we need - - * include/automatable_model.h: - * include/combobox_model.h: - * include/mv_base.h: - * include/piano_roll.h: - * src/core/base64.cpp: - * src/core/effect.cpp: - * src/core/engine.cpp: - * src/core/fx_mixer.cpp: - * src/core/instrument_functions.cpp: - * src/core/ladspa_manager.cpp: - * src/core/mv_base.cpp: - * src/gui/automation_editor.cpp: - * src/gui/main_window.cpp: - * src/gui/piano_roll.cpp: - * src/gui/widgets/combobox.cpp: - * src/gui/widgets/group_box.cpp: - * plugins/ladspa_effect/ladspa_effect.cpp: - fixed various leaks I found using Valgrind - -2008-06-30 Paul Giblock - - * plugins/ladspa_browser/ladspa_browser.cpp: - * include/automation_editor.h: - * src/gui/piano_roll.cpp: - * src/gui/fx_mixer_view.cpp: - * src/gui/widgets/controller_rack_view.cpp: - * src/gui/widgets/controller_view.cpp: - * src/gui/automation_editor.cpp: - * src/tracks/instrument_track.cpp: - Remove maximize and resize capability from many windows and set proper - minimum and intial sizes - -2008-06-29 Javier Serrano Polo - - * data/locale/ca.ts: - updated translation - -2008-06-29 Tobias Doerffel - - * include/track.h: - * include/sample_track.h: - * src/gui/widgets/effect_label.cpp: - * src/tracks/sample_track.cpp: - * src/core/sample_play_handle.cpp: - * src/core/track.cpp: - * Makefile.am: - finally resurrected sample-tracks - - * src/gui/automation_editor.cpp: - - improved drawing/erasing values - - fixed moving selected values - - * src/core/automation_pattern.cpp: - when drawing automation, do not overpaint border - - * data/themes/default/fx_mixer.png: - new icon at 32x32 px to make it scale better to 16x16 - -2008-06-29 Paul Giblock - - * plugins/sf2_player/sf2_player.cpp: - Initialize gain at 1.0 - - * src/core/automation_pattern.cpp: - - Correctly draw automation TCO for negative minValues. - - Add some shading - - * src/gui/controller_connection_dialog.cpp: - - Connect cancel button - - Make mapping function read-only for alpha release - - Initialize MIDI Controller name when adding a MIDI Controller - - * src/gui/widgets/tempo_sync_knob.cpp: - Make tempoSyncKnob really sync to tempo again - - * plugins/peak_controller_effect/peak_controller_effect.cpp: - * plugins/peak_controller_effect/peak_controller_effect_controls.cpp: - * plugins/peak_controller_effect/peak_controller_effect.h: - * include/peak_controller.h: - * src/core/peak_controller.cpp: - Fix loading/saving for peak controller - - * src/core/effect.cpp: - Correct comments - - * data/themes/default/style.css: - Make toolbar colors a little more clear - - * src/core/automation_pattern.cpp: - Save and load pattern position from project - - * include/automation_track.h: - * src/tracks/automation_track.cpp: - Allow dragging automatable views directly onto an automation-track - - * configure.in: - Fix LIBDIR for when people do not use --prefix - - * include/automation_editor.h: - * src/gui/automation_editor.cpp: - - Don't miss points when scribbling quickly - - Shift-Click to draw a line - - * include/lfo_controller.h: - * src/gui/lfo_controller_dialog.cpp: - * data/themes/default/lfo_controller_artwork.png: - Add LFO artwork (except it doesn't work for some odd reason) - - * plugins/stereo_matrix/stereomatrix_control_dialog.cpp: - * plugins/stereo_matrix/artwork.png: - Add StereoMatrix artwork - - * plugins/bit_invader/artwork.png: - Remove author name from artwork. No other artwork has author names. The - name on the main GUI makes LMMS looks less professional. AUTHORS. - - * plugins/patman/logo.png: - * plugins/stereo_matrix/artwork.png: - * plugins/audio_file_processor/logo.png: - * plugins/vestige/logo.png: - * plugins/spectrum_analyzer/log_x_axis.png: - * plugins/spectrum_analyzer/log_y_axis.png: - Update plugin artwork - - * plugins/live_tool/live_tool.cpp: - * src/gui/plugin_browser.cpp: - * src/gui/main_window.cpp: - * src/gui/automation_editor.cpp: - * src/gui/bb_editor.cpp: - * src/tracks/bb_track.cpp: - * src/core/mmp.cpp: - * data/locale/nl.ts: - * data/locale/it.ts: - * data/locale/ca.ts: - * data/locale/ru.ts: - * data/locale/de.ts: - * data/locale/sv.ts: - Rename Baseline to Bassline - -2008-06-28 Tobias Doerffel - - * plugins/Makefile.am: - * configure.in: - removed SingerBot-references - - * plugins/live_tool/live_tool.cpp: - * src/core/tool.cpp: - cleanups - - * src/gui/main_window.cpp: - * src/tracks/bb_track.cpp: - * src/tracks/pattern.cpp: - * src/core/automation_pattern.cpp: - * data/themes/default/project_new_from_template.png: - * data/themes/default/project_new.png: - * data/themes/default/project_import.png: - * data/themes/default/project_open_recent.png: - * data/themes/default/edit_rename.png: - * data/themes/default/rename.png: - splitted "new project"-button and added "recently opened - project"-button - - * src/gui/main_window.cpp: - * src/gui/song_editor.cpp: - * src/tracks/instrument_track.cpp: - * data/themes/default/edit_draw.png: - * data/themes/default/add_bb_track.png: - * data/themes/default/edit_arrow.png: - * data/themes/default/stop.png: - * data/themes/default/mute_off_disabled.png: - * data/themes/default/mute_on_disabled.png: - * data/themes/default/style.css: - * data/themes/default/play.png: - * data/themes/default/mute_on.png: - * data/themes/default/record.png: - * data/themes/default/automation.png: - * data/themes/default/help.png: - * data/themes/default/sample_track.png: - * data/themes/default/track_op_menu_disabled.png: - * data/themes/default/edit_select.png: - * data/themes/default/effect_board.png: - * data/themes/default/mute_off.png: - * data/themes/default/pause.png: - * data/themes/default/bb_track.png: - * data/themes/default/add_automation.png: - * data/themes/default/edit_erase.png: - * data/themes/default/record_accompany.png: - * data/themes/default/edit_move.png: - * data/themes/default/add_sample_track.png: - * data/themes/default/songeditor.png: - * data/themes/default/fx_mixer.png: - improved artwork and maintoolbar - -2008-06-28 Paul Giblock - - * configure.in: - * src/core/config_mgr.cpp: - * src/core/ladspa_manager.cpp: - Search LIBDIR before any other directories - - * acinclude.m4: - Search $QTDIR before any other directories - - * data/themes/default/style.css: - Update CSS for new QToolBar support - -2008-06-28 Tobias Doerffel - - * src/core/song.cpp: - * src/core/project_renderer.cpp: - - confirm overwrite when exporting file - - set filter when selecting output-file for export - - * include/audio_file_device.h: - * include/audio_file_ogg.h: - * include/audio_file_wave.h: - * include/project_renderer.h: - * src/core/audio/audio_file_device.cpp: - * src/core/audio/audio_file_ogg.cpp: - * src/core/audio/audio_file_wave.cpp: - * src/core/main.cpp: - * src/core/project_renderer.cpp: - * src/gui/export_project_dialog.cpp: - added support for exporting WAVE-files with 32-bit-float format - - * include/automation_editor.h: - fixed node-name - - * Makefile.am: - * include/automation_pattern.h: - * include/detuning_helper.h: - * include/inline_automation.h: - * include/note_play_handle.h: - * src/core/automation_pattern.cpp: - * src/core/inline_automation.cpp: - * src/core/note.cpp: - * src/core/note_play_handle.cpp: - * src/core/track.cpp: - * src/gui/piano_roll.cpp: - made note-detuning-automation work by making automationPatterns also - work without a parent-track and writing a generic inlineAutomation-class - - * src/gui/file_browser.cpp: - fixed crash when encountering invalid samplePlayHandle while - previewing (closes #2004875) - -2008-06-27 Tobias Doerffel - - * include/instrument_track.h: - * src/tracks/instrument_track.cpp: - added panning-knob to track-settings-widget - - * include/fx_mixer.h: - * include/fx_mixer_view.h: - * src/core/fx_mixer.cpp: - * src/gui/fx_mixer_view.cpp: - added mute-button for each FX-line - - * include/led_checkbox.h: - * src/gui/peak_controller_dialog.cpp: - * src/gui/widgets/instrument_function_views.cpp: - * src/gui/widgets/ladspa_control_view.cpp: - * src/gui/widgets/led_checkbox.cpp: - made enumeration match current coding style - - * src/core/track.cpp: - * src/core/plugin.cpp: - * Makefile.am: - cleanups - -2008-06-25 Tobias Doerffel - - * src/tracks/instrument_track.cpp: - overwrite-confirm when saving instrument-settings - - * src/core/effect_chain.cpp: - when clear()ing, also disable FX-chain (closes #1994482) - - * src/core/song.cpp: - always load FX-mixer-settings even if there's no GUI - - * src/core/track_container.cpp: - fixed broken clearAllTracks() - - * include/track.h: - * include/pattern.h: - * include/bb_track.h: - * src/tracks/bb_track.cpp: - * src/tracks/pattern.cpp: - * src/core/track.cpp: - name-property in trackContentObject-class - - * include/automation_pattern.h: - * src/core/automation_pattern.cpp: - - added submenu for removing connections - - made automation-pattern rename working - - * src/core/automation_pattern.cpp: - fixed loading song-global automation - -2008-06-24 Tobias Doerffel - - * plugins/vibed/vibrating_string.h: - * plugins/vibed/nine_button_selector.h: - * plugins/vibed/vibed.h: - * plugins/vibed/vibrating_string.cpp: - * plugins/vibed/string_container.h: - * plugins/vibed/nine_button_selector.cpp: - * plugins/vibed/Makefile.am: - * plugins/vibed/vibed.cpp: - * plugins/singerbot/singerbot.h: - * plugins/audio_file_processor/audio_file_processor.cpp: - * plugins/flp_import/flp_import.cpp: - * include/note_play_handle.h: - * src/tracks/instrument_track.cpp: - * src/core/note_play_handle.cpp: - * src/core/audio/audio_device.cpp: - * src/core/audio/audio_oss.cpp: - - fixed wrong config.h-inclusion and deprecated macro-names from - config.h - makes Vibed plugin work again (closes #2000590) - - various coding-style fixes - - * plugins/bit_invader/bit_invader.cpp: - * plugins/vibed/vibed.cpp: - fixed plugin-instantiation - - * include/graph.h: - * src/gui/widgets/graph.cpp: - * plugins/vibed/vibed.cpp: - * plugins/vibed/vibed.h: - * plugins/bit_invader/bit_invader.cpp: - * plugins/bit_invader/bit_invader.h: - use int instead of Uint32 - - * plugins/plucked_string_synth/logo.png: - * plugins/plucked_string_synth/plucked_string_synth.cpp: - * plugins/plucked_string_synth/plucked_string_synth.h: - * plugins/plucked_string_synth/Makefile.am: - * plugins/plucked_string_synth/artwork.png: - * plugins/polyb302/polyb302.h: - * plugins/polyb302/logo.png: - * plugins/polyb302/Makefile.am: - * plugins/polyb302/polyb302.cpp: - * plugins/polyb302/artwork.png: - removed obsolete plugins - - * plugins/spectrum_analyzer/spectrumanalyzer_control_dialog.cpp: - * plugins/spectrum_analyzer/spectrum_analyzer.cpp: - * plugins/spectrum_analyzer/Makefile.am: - * plugins/spectrum_analyzer/spectrum_analyzer.h: - * configure.in: - use float-based FFTW-library - - * Makefile.am: - * include/peak_controller.h: - * include/tempo_sync_knob.h: - fixes for win32-build - -2008-06-23 Tobias Doerffel - - * plugins/ladspa_effect/ladspa_effect.cpp: - * plugins/ladspa_effect/ladspa_controls.cpp: - * plugins/ladspa_effect/ladspa_controls.h: - * plugins/organic/organic.cpp: - * plugins/organic/organic.h: - * plugins/lb302/lb302.cpp: - * plugins/vibed/nine_button_selector.cpp: - * plugins/triple_oscillator/triple_oscillator.h: - * plugins/triple_oscillator/triple_oscillator.cpp: - * plugins/audio_file_processor/audio_file_processor.cpp: - * plugins/stk/mallets/mallets.cpp: - * plugins/kicker/kicker.cpp: - * plugins/midi_import/midi_import.cpp: - * include/effect.h: - * include/meter_model.h: - * include/track.h: - * include/automatable_model.h: - * include/instrument_functions.h: - * include/ladspa_control.h: - * include/audio_port.h: - * include/automation_pattern.h: - * include/effect_view.h: - * include/graph.h: - * include/song.h: - * include/pattern.h: - * include/envelope_and_lfo_parameters.h: - * include/song_editor.h: - * include/journalling_object.h: - * include/automatable_model_view.h: - * include/surround_area.h: - * include/mv_base.h: - * include/controller_view.h: - * include/effect_controls.h: - * include/midi_port.h: - * include/automation_editor.h: - * include/effect_chain.h: - * include/automation_track.h: - * include/track_container.h: - * include/plugin_view.h: - * src/gui/piano_roll.cpp: - * src/gui/track_container_view.cpp: - * src/gui/controller_dialog.cpp: - * src/gui/automatable_model_view.cpp: - * src/gui/effect_control_dialog.cpp: - * src/gui/fx_mixer_view.cpp: - * src/gui/song_editor.cpp: - * src/gui/widgets/ladspa_control_view.cpp: - * src/gui/widgets/graph.cpp: - * src/gui/widgets/combobox.cpp: - * src/gui/widgets/midi_port_menu.cpp: - * src/gui/widgets/controller_rack_view.cpp: - * src/gui/widgets/instrument_sound_shaping_view.cpp: - * src/gui/widgets/envelope_and_lfo_view.cpp: - * src/gui/widgets/knob.cpp: - * src/gui/widgets/instrument_function_views.cpp: - * src/gui/widgets/instrument_midi_io_view.cpp: - * src/gui/widgets/automatable_slider.cpp: - * src/gui/widgets/group_box.cpp: - * src/gui/widgets/lcd_spinbox.cpp: - * src/gui/widgets/controller_view.cpp: - * src/gui/widgets/fader.cpp: - * src/gui/widgets/effect_rack_view.cpp: - * src/gui/widgets/tempo_sync_knob.cpp: - * src/gui/widgets/automatable_button.cpp: - * src/gui/widgets/meter_dialog.cpp: - * src/gui/automation_editor.cpp: - * src/tracks/automation_track.cpp: - * src/tracks/sample_track.cpp: - * src/tracks/bb_track.cpp: - * src/tracks/instrument_track.cpp: - * src/tracks/pattern.cpp: - * src/core/effect_chain.cpp: - * src/core/project_journal.cpp: - * src/core/midi/midi_controller.cpp: - * src/core/midi/midi_port.cpp: - * src/core/note_play_handle.cpp: - * src/core/song.cpp: - * src/core/track_container.cpp: - * src/core/bb_track_container.cpp: - * src/core/journalling_object.cpp: - * src/core/automatable_model.cpp: - * src/core/audio/audio_port.cpp: - * src/core/sample_play_handle.cpp: - * src/core/envelope_and_lfo_parameters.cpp: - * src/core/mmp.cpp: - * src/core/instrument_sound_shaping.cpp: - * src/core/meter_model.cpp: - * src/core/instrument_functions.cpp: - * src/core/track.cpp: - * src/core/ladspa_control.cpp: - * src/core/note.cpp: - * src/core/piano.cpp: - * src/core/surround_area.cpp: - * src/core/mv_base.cpp: - * src/core/automation_pattern.cpp: - * src/core/fx_mixer.cpp: - * data/themes/default/add_automation.png: - - completely new automation-system with automation-tracks and - automation-patterns as well as song-global automation - - made modelView take a QWidget-pointer argument - - trackContentObject-ctor now calls track::addTCO() directly - - optimize various loops to use iterators/const_iterators instead of - a running index variable - - drag'n'drop doesn't fool around with pointers anymore - instead use - unique journalling-IDs - - moved drag'n'drop handling code from knob to automatableModelView so - that all controls can benefit from that - -2008-06-23 Paul Giblock - - * include/lfo_controller.h: - * src/gui/lfo_controller_dialog.cpp: - * src/core/lfo_controller.cpp: - * data/themes/default/lfo_d100_active.png: - * data/themes/default/lfo_d100_inactive.png: - * data/themes/default/lfo_x100_active.png: - * data/themes/default/lfo_x100_inactive.png: - * data/themes/default/lfo_x1_active.png: - * data/themes/default/lfo_x1_inactive.png: - Add multiplier to lfo-controller and fix tempo-sync knob. Breaks old - projects that use LFO, but shouldn't matter since 0.4 hasn't been - released - - * src/gui/widgets/tempo_sync_knob.cpp: - Allow tempo-sync knob to work with ranges other than [0..1] - - * src/core/envelope_and_lfo_parameters.cpp: - Remove hardcoded literal, use already defined const int instead - - * data/projects/templates/CR8000.mpt: - * data/projects/templates/TR808.mpt: - Added two drumsynth templates - -2008-06-20 Tobias Doerffel - - * include/automatable_model_view.h: - * src/core/piano.cpp: - full context-menu for piano-basenote so it can be automated as well as - controlled via controller - - * src/gui/widgets/knob.cpp: - - when linking knobs via Shift+Drag do not use pointer to model as - drag-data rather than model-ID which can be resolved via - project-journal - - fixed displayValue() - - * Makefile.am: - * include/knob.h: - * include/volume_knob.h: - * plugins/organic/organic.cpp: - * plugins/organic/organic.h: - * plugins/vibed/vibed.h: - * plugins/vibed/vibed.cpp: - * plugins/triple_oscillator/triple_oscillator.h: - * plugins/triple_oscillator/triple_oscillator.cpp: - * plugins/audio_file_processor/audio_file_processor.cpp: - * plugins/audio_file_processor/audio_file_processor.h: - * src/tracks/instrument_track.cpp: - * src/gui/widgets/knob.cpp: - * src/gui/widgets/volume_knob.cpp: - removed volumeKnob-class and added volumeKnob-property to knob-class - instead - - * plugins/flp_import/flp_import.cpp: - * include/controller_connection.h: - * include/lcd_spinbox.h: - * include/controller.h: - * include/automatable_model.h: - * include/instrument_track.h: - * include/instrument_functions.h: - * include/note_play_handle.h: - * include/instrument_sound_shaping.h: - * include/basic_filters.h: - * include/sample_track.h: - * include/surround_area.h: - * src/core/note_play_handle.cpp: - * src/core/automatable_model.cpp: - * src/core/main.cpp: - * src/core/instrument_sound_shaping.cpp: - * src/core/piano.cpp: - * src/core/surround_area.cpp: - reduced header-dependencies and various cleanups - - * include/tempo_sync_knob.h: - * src/gui/widgets/tempo_sync_knob.cpp: - - do not re-implement private event-handlers and use knob's signals - instead - - fixed crash when closing meterDialog and choosing custom-sync - afterwards - - * src/gui/fx_mixer_view.cpp: - better initial position of FX-mixer view - - * src/gui/song_editor.cpp: - removed obsolete headers - - * include/setup_dialog.h: - * src/gui/bb_editor.cpp: - * src/gui/main_window.cpp: - * src/gui/setup_dialog.cpp: - * src/gui/song_editor.cpp: - * src/gui/widgets/controller_rack_view.cpp: - * src/gui/widgets/knob.cpp: - - removed obsolete non-MDI-mode - - removed classical knob-usability - - removed show-wizard-after-upgrade setting - - other cleanups - -2008-06-20 Paul Giblock - - * src/core/piano.cpp: - make SVN compile again - -2008-06-20 Paul Wayper - - * src/core/piano.cpp: - added Doxygen documentation. - -2008-06-19 Paul Wayper - - * src/core/track.cpp: - added Doxygen documentation. - -2008-06-16 Tobias Doerffel - - * plugins/Makefile.am: - * configure.in: - added libfftw3-detection - - * plugins/bass_booster/bassbooster_control_dialog.cpp: - * plugins/bass_booster/artwork.png: - * plugins/peak_controller_effect/peak_controller_effect_control_dialog.cpp: - * plugins/peak_controller_effect/artwork.png: - added metal-brushed background-artwork - - * src/tracks/instrument_track.cpp: - added unit to pitch-knob - -2008-06-15 Paul Giblock - - * plugins/stereo_matrix/stereo_matrix.cpp: - update author email address - - * src/gui/widgets/graph.cpp: - * src/gui/lfo_controller_dialog.cpp: - code cleanup - - * src/gui/widgets/fade_button.cpp: - * src/tracks/instrument_track.cpp: - improve appearance of fade buttons - - * include/tool_button.h: - * src/gui/widgets/tool_button.cpp: - * src/gui/lmms_style.cpp: - * data/themes/default/style.css: - remove styling, rely on QStyle and stylesheets now - - * include/song_editor.h: - * include/main_window.h: - * include/timeline.h: - * src/gui/main_window.cpp: - * src/gui/song_editor.cpp: - * src/gui/widgets/nstate_button.cpp: - * src/core/timeline.cpp: - - * data/themes/default/main_toolbar_bg.png: - * data/themes/default/toolbar_bg.png: - Enlarge images for resizable toolbars - quick fix. Could just clamp the - texture at the bottom - -2008-06-15 Tobias Doerffel - - * include/knob.h: - * src/gui/widgets/knob.cpp: - - cache pixmap - - only redraw if angle has changed by more than 3 degrees - - cleanups - - * src/core/midi/midi_alsa_seq.cpp: - cleanups and small optimizations - - * include/instrument_midi_io_view.h: - * include/instrument_track.h: - * include/midi_port.h: - * src/core/midi/midi_port.cpp: - * src/tracks/instrument_track.cpp: - * src/gui/widgets/instrument_midi_io_view.cpp: - refactored midiPortMenu-creation and -management - fixes crash when - removing track which had MIDI-in enabled and enabled MIDI-in for - another track afterwards - - * src/gui/file_browser.cpp: - do not load MIDI-settings when loading preset as this might break - existing instrument tracks - - * include/automatable_model.h: - * src/tracks/instrument_track.cpp: - directly handle MIDI-pitch-bend events - - * include/instrument_track.h: - * src/core/note_play_handle.cpp: - * src/tracks/instrument_track.cpp: - - added pitch-knob to instrument-track - - fixed activity indicator - - * plugins/stk/voices/flute/flute_model.cpp: - * plugins/stk/voices/flute/flute_model.h: - * plugins/stk/voices/flute/flute_instrument.cpp: - * plugins/stk/voices/resonate/resonate_model.cpp: - * plugins/stk/voices/resonate/resonate_model.h: - * plugins/stk/voices/resonate/resonate_instrument.cpp: - * plugins/stk/voices/include/stk_instrument.h: - * plugins/stk/voices/include/stk_processor.h: - * plugins/stk/voices/include/stk_model.h: - * plugins/stk/voices/include/stk_voice.h: - * plugins/stk/voices/wurley/wurley_instrument.cpp: - * plugins/stk/voices/wurley/wurley_model.cpp: - * plugins/stk/voices/wurley/wurley_model.h: - * plugins/stk/voices/src/stk_model.cpp: - * plugins/stk/voices/percflute/percflute_model.h: - * plugins/stk/voices/percflute/percflute_instrument.cpp: - * plugins/stk/voices/percflute/percflute_model.cpp: - * plugins/stk/voices/rhodey/rhodey_model.h: - * plugins/stk/voices/rhodey/rhodey_instrument.cpp: - * plugins/stk/voices/rhodey/rhodey_model.cpp: - * plugins/stk/voices/tubebell/tubebell_model.cpp: - * plugins/stk/voices/tubebell/tubebell_model.h: - * plugins/stk/voices/tubebell/tubebell_instrument.cpp: - * plugins/stk/voices/bowed/bowed_model.cpp: - * plugins/stk/voices/bowed/bowed_model.h: - * plugins/stk/voices/bowed/bowed_instrument.cpp: - * plugins/stk/voices/clarinet/clarinet_model.cpp: - * plugins/stk/voices/clarinet/clarinet_model.h: - * plugins/stk/voices/clarinet/clarinet_instrument.cpp: - * plugins/stk/voices/moog/moog_model.cpp: - * plugins/stk/voices/moog/moog_model.h: - * plugins/stk/voices/moog/moog_instrument.cpp: - * plugins/stk/voices/metal/metal_model.cpp: - * plugins/stk/voices/metal/metal_model.h: - * plugins/stk/voices/metal/metal_instrument.cpp: - * plugins/stk/voices/b3/b3_model.cpp: - * plugins/stk/voices/b3/b3_model.h: - * plugins/stk/voices/b3/b3_instrument.cpp: - * plugins/stk/voices/blow_hole/blow_hole_model.h: - * plugins/stk/voices/blow_hole/blow_hole_instrument.cpp: - * plugins/stk/voices/blow_hole/blow_hole_model.cpp: - * plugins/stk/voices/brass/brass_model.h: - * plugins/stk/voices/brass/brass_instrument.cpp: - * plugins/stk/voices/brass/brass_model.cpp: - * plugins/stk/voices/fmvoices/fmvoices_model.h: - * plugins/stk/voices/fmvoices/fmvoices_instrument.cpp: - * plugins/stk/voices/fmvoices/fmvoices_model.cpp: - * plugins/stk/voices/bandedwg/bandedwg_model.h: - * plugins/stk/voices/bandedwg/bandedwg_instrument.cpp: - * plugins/stk/voices/bandedwg/bandedwg_model.cpp: - * plugins/stk/voices/blow_bottle/blow_bottle_model.h: - * plugins/stk/voices/blow_bottle/blow_bottle_instrument.cpp: - * plugins/stk/voices/blow_bottle/blow_bottle_model.cpp: - made STK-voices-plugins compile after they've not been maintained for - a while - - * include/pixmap_button.h: - * src/gui/widgets/pixmap_button.cpp: - removed removed obsolete ctrlClick() signal - - * include/track_container.h: - * src/core/track_container.cpp: - removed obsolete setMutedOfAllTracks() method - - * src/core/song.cpp: - - lock mixer while loading project - fixes crashes when loading projects - with FX-mixer settings - - update BB-track-container after creating a new project - fixes - non-existing TCOs (i.e. patterns) in BB-Editor in new projects - - * include/config_mgr.h: - added missing include - - * src/tracks/bb_track.cpp: - unregister BB-track-view from BB-editor at destruction - fixes crash - when removing BB-tracks - - * src/core/bb_track_container.cpp: - cleanups and more optimized loops - - * include/track.h: - * src/core/track.cpp: - - fixed issue when moving BB-tracks up/down where actual BB-TCOs were - not moved (closes #1994468) - - in trackContentObjectView and trackView, handle deletion of models - more gracefully - -2008-06-14 Tobias Doerffel - - * plugins/spectrum_analyzer/spectrum_analyzer.cpp: - don't apply window-function to data as this seems to make things only - even worse - - * plugins/spectrum_analyzer/log_x_axis.png: - * plugins/spectrum_analyzer/log_y_axis.png: - * plugins/spectrum_analyzer/background.png: - * plugins/spectrum_analyzer/spectrum_background.png: - * plugins/spectrum_analyzer/spectrum_background_plain.png: - * plugins/spectrum_analyzer/spectrumanalyzer_control_dialog.cpp: - * plugins/spectrum_analyzer/spectrum_analyzer.cpp: - * plugins/spectrum_analyzer/spectrumanalyzer_controls.cpp: - * plugins/spectrum_analyzer/spectrumanalyzer_control_dialog.h: - labeled axes and correct logarithmic view - - * plugins/spectrum_analyzer/background.png: - * plugins/spectrum_analyzer/spectrum_background.png: - * plugins/spectrum_analyzer/spectrum_background_plain.png: - * plugins/spectrum_analyzer/spectrumanalyzer_control_dialog.cpp: - * plugins/spectrum_analyzer/spectrum_analyzer.h: - improved appearence of Spectrum Analzyer - - * configure.in: - * plugins/Makefile.am: - * plugins/spectrum_analyzer/Makefile.am: - * plugins/spectrum_analyzer/logo.png: - * plugins/spectrum_analyzer/spectrum_analyzer.h: - * plugins/spectrum_analyzer/spectrum_analyzer.cpp: - * plugins/spectrum_analyzer/spectrumanalyzer_controls.h: - * plugins/spectrum_analyzer/spectrumanalyzer_controls.cpp: - * plugins/spectrum_analyzer/spectrumanalyzer_control_dialog.h: - * plugins/spectrum_analyzer/spectrumanalyzer_control_dialog.cpp: - added initial version of spectrum analyzer - very basic at the moment! - - * plugins/bass_booster/bass_booster.cpp: - * plugins/bass_booster/bass_booster.h: - * plugins/bass_booster/bassbooster_controls.h: - * plugins/ladspa_effect/ladspa_controls.h: - * plugins/peak_controller_effect/peak_controller_effect_controls.h: - * plugins/stereo_enhancer/stereoenhancer_controls.h: - * plugins/stereo_matrix/stereomatrix_controls.h: - * plugins/vst_effect/vst_effect_controls.h: - * include/dummy_effect.h: - * include/effect_controls.h: - changed return-type of effectControls::getControlCount() - -2008-06-12 Tobias Doerffel - - * include/project_renderer.h: - * src/gui/dialogs/export_project.ui: - * src/gui/export_project_dialog.cpp: - * src/core/audio/audio_file_ogg.cpp: - * src/core/main.cpp: - * src/core/project_renderer.cpp: - improved support for different file-formats when exporting and fixed - bug which made LMMS crash when exporting to OGG-file - -2008-06-10 Tobias Doerffel - - * src/core/song.cpp: - fixed loading files in no-GUI mode - - * include/mixer.h: - * src/core/audio/audio_device.cpp: - * src/core/mixer.cpp: - * src/core/project_renderer.cpp: - don't use fifoWriter when rendering as we do not have realtime issues - here - fixes lockups on various systems when exporting project - - * plugins/sf2_player/sf2_player.cpp: - enabled LCD-Spinboxes for easily switching banks/patches - I know that - this way you can select banks/patches that do not exist but opening - patch-dialog each time is much more inconvenient - maybe we can - subclass lcdSpinBox one day so that it automatically "skips" wholes - when scrolling - - * include/instrument_track.h: - * src/tracks/instrument_track.cpp: - removed obsolete instrumentTrackView::updateName() and made - track-button update on name-changes - -2008-06-10 Paul Giblock - - * plugins/sf2_player/artwork.png: - * plugins/sf2_player/chorus_off.png: - * plugins/sf2_player/chorus_on.png: - * plugins/sf2_player/fileselect_off.png: - * plugins/sf2_player/fileselect_on.png: - * plugins/sf2_player/patches_on.png: - * plugins/sf2_player/patches_off.png: - * plugins/sf2_player/reverb_off.png: - * plugins/sf2_player/reverb_on.png: - * plugins/sf2_player/sf2_player.cpp: - * plugins/sf2_player/sf2_player.h: - * data/themes/default/style.css: - * data/themes/default/lcd_21pink.png: - integrate new sf2 artwork, for the most part at least - -2008-06-09 Tobias Doerffel - - * src/gui/main_window.cpp: - also show *.xiz files in preset-browser - - * src/gui/file_browser.cpp: - classify .xml-files always as presets and do not examine them more - detailed - also improves LMMS-startup-times - - * Makefile.am: - added a few files to LMMS-headers - -2008-06-08 Paul Giblock - - * src/gui/widgets/graph.h: - * src/gui/widgets/graph.cpp: - - Fix graph widget "scrolling" - - Add styles so it can be drawn un-interpolated - - * include/mv_base.h: - * src/core/mv_base.cpp: - Add recursive fullDisplayName function - - * include/combobox_model.h: - * src/gui/widgets/automatable_button.cpp: - * src/gui/widgets/combobox.cpp: - * src/gui/widgets/tempo_sync_knob.cpp: - * src/gui/widgets/effect_view.cpp: - * src/gui/lfo_controller_dialog.cpp: - * src/core/midi/midi_port.cpp: - * src/core/fx_mixer.cpp: - * src/core/lfo_controller.cpp: - * src/core/effect.cpp: - extend more models and views for displayName - - * include/instrument.h: - * src/gui/widgets/instrument_sound_shaping_view.cpp: - * src/gui/widgets/envelope_and_lfo_view.cpp: - * src/gui/widgets/instrument_function_views.cpp: - * src/gui/widgets/instrument_midi_io_view.cpp: - * src/core/envelope_and_lfo_parameters.cpp: - * src/core/instrument_sound_shaping.cpp: - * src/core/instrument_functions.cpp: - * src/core/instrument.cpp: - extend instrument stuff for displayName - - * include/controller_connection_dialog.h: - * src/gui/controller_connection_dialog.cpp: - improve interface slightly - - * plugins/bit_invader/bit_invader.cpp: - change graph style mode when toggling interpolation - - * plugins/peak_controller_effect: - * plugins/peak_controller_effect/peak_controller_effect_control_dialog.cpp: - * plugins/peak_controller_effect/peak_controller_effect.cpp: - * plugins/peak_controller_effect/logo.png: - * plugins/peak_controller_effect/peak_controller_effect_controls.cpp: - * plugins/peak_controller_effect/peak_controller_effect_control_dialog.h: - * plugins/peak_controller_effect/peak_controller_effect.h: - * plugins/peak_controller_effect/peak_controller_effect_controls.h: - * plugins/peak_controller_effect/Makefile.am: - * plugins/Makefile.am: - * include/peak_controller.h: - * include/controller.h: - * include/automatable_model.h: - * src/gui/peak_controller_dialog.cpp: - * src/core/peak_controller.cpp: - * src/core/controller.cpp: - * configure.in: - * Makefile.am: - - Very first implementation of peak-controller - - Create one by adding it in the effect-chain, then connecting a widget to - the controller - - There is no sample-exactness, smoothing, or anything like that yet - -2008-06-08 Tobias Doerffel - - * plugins/ladspa_effect/tap/tap_deesser.c: - * plugins/ladspa_effect/tap/tap_sigmoid.c: - * plugins/ladspa_effect/tap/tap_doubler.c: - * plugins/ladspa_effect/tap/ladspa-local.h: - * plugins/ladspa_effect/tap/tap_eqbw.c: - * plugins/ladspa_effect/tap/tap_pinknoise.c: - * plugins/ladspa_effect/tap/tap_chorusflanger.c: - * plugins/ladspa_effect/tap/tap_eq.c: - * plugins/ladspa_effect/tap/tap_limiter.c: - * plugins/ladspa_effect/tap/ladspa.h: - * plugins/ladspa_effect/tap/tap_vibrato.c: - * plugins/ladspa_effect/tap/tap_autopan.c: - * plugins/ladspa_effect/tap/tap_pitch.c: - * plugins/ladspa_effect/tap/tap_dynamics_st.c: - * plugins/ladspa_effect/tap/tap_echo.c: - * plugins/ladspa_effect/tap/tap_tremolo.c: - * plugins/ladspa_effect/tap/tap_tubewarmth.c: - * plugins/ladspa_effect/tap/tap_dynamics_m.c: - * plugins/ladspa_effect/tap/Makefile.am: - * plugins/ladspa_effect/tap/tap_reflector.c: - * plugins/ladspa_effect/tap/tap_reverb.c: - * plugins/ladspa_effect/tap/tap_rotspeak.c: - * plugins/ladspa_effect/caps/basics.h: - * plugins/ladspa_effect/caps/Makefile.am: - * plugins/vst_base/lvsl_client.cpp: - * plugins/vst_base/lvsl_server.cpp: - * plugins/vst_base/communication.h: - * plugins/midi_import/midi_import.h: - * include/effect.h: - * include/midi_dummy.h: - * include/endian_handling.h: - * include/track.h: - * include/note.h: - * include/engine.h: - * include/sweep_oscillator.h: - * include/debug.h: - * include/midi_alsa_raw.h: - * include/config_mgr.h: - * include/import_filter.h: - * include/audio_file_wave.h: - * include/mixer.h: - * include/audio_file_ogg.h: - * include/ladspa_manager.h: - * include/ladspa_control.h: - * include/sample_buffer.h: - * include/fx_mixer.h: - * include/nstate_button.h: - * include/audio_pulseaudio.h: - * include/clipboard.h: - * include/audio_sdl.h: - * include/micro_timer.h: - * include/midi_event_processor.h: - * include/audio_jack.h: - * include/piano_roll.h: - * include/volume.h: - * include/oscillator.h: - * include/export.h: - * include/midi_alsa_seq.h: - * include/tool.h: - * include/setup_dialog.h: - * include/tab_bar.h: - * include/audio_device.h: - * include/audio_oss.h: - * include/audio_alsa.h: - * src/gui/piano_roll.cpp: - * src/gui/main_window.cpp: - * src/gui/song_editor.cpp: - * src/gui/setup_dialog.cpp: - * src/gui/about_dialog.cpp: - * src/tracks/instrument_track.cpp: - * src/core/plugin.cpp: - * src/core/song.cpp: - * src/core/config_mgr.cpp: - * src/core/audio/audio_oss.cpp: - * src/core/envelope_and_lfo_parameters.cpp: - * src/core/main.cpp: - * src/core/mmp.cpp: - * src/core/ladspa_manager.cpp: - * src/core/ladspa_control.cpp: - * src/core/sample_buffer.cpp: - * Makefile.am: - use lmmsconfig.h rather than config.h and use prefixed macro-names - - * acinclude.m4: - * configure.in: - create include/lmmsconfig.h which contains prefixed config.h defines - -2008-06-07 Tobias Doerffel - - * src/core/song.cpp: - reset m_modified after loading a project, creating a new one or saving - - * src/core/song.cpp: - in song::setModified() only call mainWindow::resetWindowTitle() when - being called with GUI-thread affinity - - * include/automatable_model.h: - * src/core/automatable_model.cpp: - * src/core/automation_pattern.cpp: - added fast and more leight-weight setAutomatedValue() which omits - things like journalling - makes things faster and doesn't introduce - threading-problems - - * src/core/mmp.cpp: - handle renamed midi-node ("midi" -> "midiport") - - * src/tracks/instrument_track.cpp: - fixed MIDI-IO when using raw MIDI client - - * plugins/midi_import/midi_import.cpp: - * include/song.h: - added support for importing time-signature settings - - * Makefile.am: - * plugins/midi_import/midi_import.cpp: - * plugins/vestige/vestige.cpp: - * plugins/vst_base/lvsl_client.cpp: - * plugins/vst_base/lvsl_server.cpp: - * include/meter_model.h: - * include/midi.h: - * src/core/note_play_handle.cpp: - * src/core/piano.cpp: - * src/core/midi/midi_alsa_seq.cpp: - * src/core/midi/midi_client.cpp: - * src/core/midi/midi_controller.cpp: - * src/core/midi/midi_port.cpp: - * src/tracks/instrument_track.cpp: - * src/gui/controller_connection_dialog.cpp: - * src/gui/piano_roll.cpp: - made MidiEventTypes-enum conform coding-style, i.e. MidiNoteOn instead - of NOTE_ON etc. - - * include/controller_connection_dialog.h: - * include/instrument_midi_io_view.h: - * include/instrument_track.h: - * include/midi_alsa_raw.h: - * include/midi_alsa_seq.h: - * include/midi_client.h: - * include/midi_controller.h: - * include/midi_io_model.h: - * include/midi_oss.h: - * include/midi_port.h: - * include/midi_port_menu.h: - * src/core/note_play_handle.cpp: - * src/core/preset_preview_play_handle.cpp: - * src/core/song.cpp: - * src/core/midi/midi_client.cpp: - * src/core/midi/midi_controller.cpp: - * src/core/midi/midi_port.cpp: - * src/core/midi/midi_io_model.cpp: - * src/core/midi/midi_alsa_seq.cpp: - * src/gui/piano_roll.cpp: - * src/gui/controller_connection_dialog.cpp: - * src/gui/widgets/instrument_midi_io_view.cpp: - * src/tracks/instrument_track.cpp: - * Makefile.am: - rewrote management of MIDI-ports and MIDI-port subscriptions - now - it's central and easy to use - -2008-06-06 Tobias Doerffel - - * include/note.h: - * include/serializing_object.h: - * include/instrument_track.h: - * include/sample_buffer.h: - * include/journalling_object.h: - * src/gui/automation_editor.cpp: - * src/core/serializing_object.cpp: - * src/core/journalling_object.cpp: - * src/core/note.cpp: - * Makefile.am: - splitted basic functionality of journallingObject into - serializingObject so that creating note objects, notePlayHandles etc. - does not have all the journalling-overhead (assigning/freeing ID etc.) - -2008-06-06 Paul Giblock - - * include/knob.h: - * include/automatable_slider.h: - * include/controller_connection.h: - * include/midi_controller.h: - * include/automatable_model.h: - * include/automatable_button.h: - * include/tempo_sync_knob.h: - * include/controller_connection_dialog.h: - * include/pixmap_button.h: - * include/automatable_model_view.h: - * include/mv_base.h: - * include/volume_knob.h: - * src/gui/automatable_model_view.cpp: - * src/gui/controller_connection_dialog.cpp: - * src/gui/widgets/knob.cpp: - * src/gui/widgets/automatable_slider.cpp: - * src/gui/widgets/group_box.cpp: - * src/gui/widgets/lcd_spinbox.cpp: - * src/gui/widgets/tempo_sync_knob.cpp: - * src/gui/widgets/automatable_button.cpp: - * src/core/midi/midi_controller.cpp: - * src/core/automatable_model.cpp: - * src/core/controller_connection.cpp: - - add support for sequenced midi in midi-controllers - - add displayName field to model / autoModel for descriptive model trees - - use displayName for midiController and contextMenus - - * src/core/ladspa_control.cpp: - * plugins/lb302/lb302.cpp: - * plugins/organic/organic.cpp: - * plugins/organic/organic.h: - * plugins/bass_booster/bassbooster_control_dialog.cpp: - * plugins/bass_booster/bassbooster_controls.cpp: - * plugins/stereo_matrix/stereomatrix_control_dialog.cpp: - * plugins/stereo_matrix/stereomatrix_controls.cpp: - * plugins/bit_invader/bit_invader.cpp: - * plugins/vibed/nine_button_selector.cpp: - * plugins/vibed/vibed.cpp: - * plugins/audio_file_processor/audio_file_processor.cpp: - * plugins/stereo_enhancer/stereoenhancer_control_dialog.cpp: - * plugins/stereo_enhancer/stereoenhancer_controls.cpp: - * plugins/sf2_player/sf2_player.cpp: - * plugins/kicker/kicker.cpp: - * plugins/stk/mallets/mallets.cpp: - * plugins/triple_oscillator/triple_oscillator.h: - * plugins/triple_oscillator/triple_oscillator.cpp: - - Update plugins to use displayName for child widgets - - Still need to do this to all of LMMS core - - * include/effect_lib.h: - * src/core/lfo_controller.cpp: - Fix compile time warnings - - * include/automatable_model.h: - * include/instrument_track.h: - * include/controller_connection_dialog.h: - * src/gui/controller_connection_dialog.cpp: - * src/tracks/instrument_track.cpp: - Test to see if we can now generate reasonable midi-port names. We can, - the feature is very beta right now (no screenupdating, loading, etc..) - -2008-06-05 Tobias Doerffel - - * include/track.h: - * include/track_container_view.h: - * src/core/track.cpp: - * src/gui/track_container_view.cpp: - remove track from within slot in trackContainerView for not deleting - object inside its own method - fixes Qt-warning and closes #1981812 - - * src/tracks/instrument_track.cpp: - when freeing instrument-window, also free view immediately - fixes - crash when removing instrument-track while instrument-track window was - open - - * include/automatable_model.h: - * include/automation_editor.h: - * src/gui/piano_roll.cpp: - * src/gui/widgets/graph.cpp: - * src/gui/widgets/knob.cpp: - * src/gui/widgets/fader.cpp: - * src/gui/automation_editor.cpp: - fixed various GCC-warnings - -2008-06-05 Paul Giblock - - * include/automatable_model.h: - * include/mv_base.h: - * src/gui/automatable_model_view.cpp: - * src/gui/widgets/knob.cpp: - add setDisplayName to model, but doesn't work right for some reason - -2008-06-05 Tobias Doerffel - - * include/note.h: - * include/note_play_handle.h: - removed obsolete FASTCALL-attributes - - * include/project_journal.h: - * src/core/project_journal.cpp: - * src/core/song.cpp: - heavily optimized journal-cleanup - project unloading is now - unbelievable fast! - -2008-06-05 Paul Giblock - - * data/themes/default/style.css: - fix check-marks on menus. They used to all appear checked no matter what - -2008-06-05 Tobias Doerffel - - * include/track.h: - * src/core/track.cpp: - re-arranged mute- and solo-buttons - - * plugins/ladspa_effect/tap/tap_deesser.c: - * plugins/ladspa_effect/tap/tap_reverb.h: - * plugins/ladspa_effect/tap/tap_sigmoid.c: - * plugins/ladspa_effect/tap/tap_doubler.c: - * plugins/ladspa_effect/tap/tap_eqbw.c: - * plugins/ladspa_effect/tap/tap_pinknoise.c: - * plugins/ladspa_effect/tap/tap_reverb_presets.h: - * plugins/ladspa_effect/tap/tap_chorusflanger.c: - * plugins/ladspa_effect/tap/ladspa.h: - * plugins/ladspa_effect/tap/tap_limiter.c: - * plugins/ladspa_effect/tap/tap_utils.h: - * plugins/ladspa_effect/tap/tap_eq.c: - * plugins/ladspa_effect/tap/tap_vibrato.c: - * plugins/ladspa_effect/tap/tap_autopan.c: - * plugins/ladspa_effect/tap/tap_pitch.c: - * plugins/ladspa_effect/tap/CREDITS: - * plugins/ladspa_effect/tap/README: - * plugins/ladspa_effect/tap/tap_dynamics_st.c: - * plugins/ladspa_effect/tap/tap_echo.c: - * plugins/ladspa_effect/tap/tap_tremolo.c: - * plugins/ladspa_effect/tap/tap_dynamics_presets.h: - * plugins/ladspa_effect/tap/tap_tubewarmth.c: - * plugins/ladspa_effect/tap/COPYING: - * plugins/ladspa_effect/tap/tap_dynamics_m.c: - * plugins/ladspa_effect/tap/Makefile.am: - * plugins/ladspa_effect/tap/tap_reflector.c: - * plugins/ladspa_effect/tap/tap_reverb.c: - * plugins/ladspa_effect/tap/tap_rotspeak.c: - * plugins/ladspa_effect/Makefile.am: - * configure.in: - * Makefile.am: - integrated TAP-plugins to be shipped with LMMS - -2008-06-04 Paul Giblock - - * src/gui/lmms_style.cpp: - Shrink the titlebars - -2008-06-03 Tobias Doerffel - - * plugins/vibed/nine_button_selector.cpp: - * plugins/live_tool/live_tool.cpp: - * include/note_play_handle.h: - * include/track_container.h: - * include/track.h: - * src/tracks/bb_track.cpp: - * src/tracks/instrument_track.cpp: - * src/tracks/pattern.cpp: - * src/core/sample_play_handle.cpp: - * src/core/track.cpp: - renamed muted() to isMuted() and other coding-style fixes - - * src/gui/widgets/automatable_slider.cpp: - * src/gui/widgets/lcd_spinbox.cpp: - * src/gui/widgets/automatable_button.cpp: - use automatableModelView::addDefaultActions() - - * src/gui/widgets/tooltip.cpp: - re-enabled tooltips - - * include/track.h: - * include/track_container.h: - * src/core/track.cpp: - * data/themes/default/led_red.png: - added fully-functional solo-button - - * include/automation_editor.h: - * src/gui/automation_editor.cpp: - fixed broken automation-drawing for floatModels - - * configure.in: - * Makefile.am: - support for building win32-version with OGG/vorbis-support - - * src/gui/main_window.cpp: - added separator in edit-menu - - * src/core/config_mgr.cpp: - fixed paths for win32-build - - * src/core/sample_buffer.cpp: - fixed platform-dependent sampleBuffer::tryToMakeAbsolute(...) - - * lmms.rc.in: - * Makefile.am: - * data/lmms.ico: - added icon and resource-file - - * Makefile.am: - added win32-pkg target - -2008-06-02 Paul Giblock - - * plugins/sf2_player/sf2_player.cpp: - * plugins/sf2_player/sf2_player.h: - * src/gui/main_window.cpp: - Support loading of sf2 files from the sidebar sample browser - - * include/knob.h: - * include/automatable_model_view.h: - * src/gui/automatable_model_view.cpp: - * src/gui/widgets/knob.cpp: - * Makefile.am: - - move context menu stuff to automatableModelView - - add automatableModelViewSlots for slots we may wish to call from AMV - - * include/midi_controller.h: - code style - - * src/core/midi/midi_controller.cpp: - name midiControllers after their channel/controller - - * src/gui/widgets/fader.cpp: - Use default context menu - - * src/gui/controller_connection_dialog.cpp: - don't choose the controller if the user didn't actually choose anything - -2008-06-02 Tobias Doerffel - - * src/core/mixer.cpp: - try all audio-drivers at startup even if dummy-driver is selected - - * configure.in: - * Makefile.am: - properly link against win32-libsndfile - - * plugins/patman/patman.cpp: - * plugins/patman/Makefile.am: - * plugins/ladspa_effect/ladspa_effect.cpp: - * plugins/ladspa_effect/caps/Makefile.am: - * plugins/ladspa_effect/Makefile.am: - * plugins/organic/organic.cpp: - * plugins/organic/Makefile.am: - * plugins/lb302/lb302.cpp: - * plugins/lb302/Makefile.am: - * plugins/bass_booster/bass_booster.cpp: - * plugins/bass_booster/Makefile.am: - * plugins/stereo_matrix/stereo_matrix.cpp: - * plugins/stereo_matrix/Makefile.am: - * plugins/bit_invader/bit_invader.cpp: - * plugins/bit_invader/Makefile.am: - * plugins/vibed/Makefile.am: - * plugins/vibed/vibed.cpp: - * plugins/live_tool/Makefile.am: - * plugins/live_tool/live_tool.cpp: - * plugins/stereo_enhancer/stereo_enhancer.cpp: - * plugins/stereo_enhancer/Makefile.am: - * plugins/sf2_player/patches_dialog.cpp: - * plugins/sf2_player/sf2_player.cpp: - * plugins/sf2_player/Makefile.am: - * plugins/sf2_player/patches_dialog.h: - * plugins/ladspa_browser/ladspa_browser.cpp: - * plugins/ladspa_browser/Makefile.am: - * plugins/ladspa_browser/ladspa_browser.h: - * plugins/kicker/Makefile.am: - * plugins/kicker/kicker.cpp: - * plugins/flp_import/Makefile.am: - * plugins/flp_import/flp_import.cpp: - * plugins/midi_import/Makefile.am: - * plugins/midi_import/midi_import.cpp: - build win32-DLLs properly - - * include/mmp.h: - * include/effect.h: - * include/lcd_spinbox.h: - * include/engine.h: - * include/embed.h: - * include/bb_track_container.h: - * include/config_mgr.h: - * include/import_filter.h: - * include/ladspa_manager.h: - * include/ladspa_control.h: - * include/automation_pattern.h: - * include/graph.h: - * include/effect_control_dialog.h: - * include/pattern.h: - * include/string_pair_drag.h: - * include/caption_menu.h: - * include/envelope_and_lfo_parameters.h: - * include/bb_track.h: - * include/project_notes.h: - * include/export.h: - * include/tooltip.h: - * include/ladspa_control_view.h: - * include/journalling_object.h: - * include/tool.h: - * include/tab_bar.h: - * include/types.h: - * include/mv_base.h: - * include/track_container.h: - * include/led_checkbox.h: - * include/ladspa_2_lmms.h: - * src/3rdparty/samplerate/samplerate.h: - export more symbols in order to build all plugins - - * configure.in: - added code for detecting fluidsynth-DLL - - * src/core/config_mgr.cpp: - customized path to LADSPA-plugins under win32 - - * src/core/midi/midi_alsa_seq.cpp: - do not free port_info-structure before actually (un)subscribing - - fixes non-working automatic port-subscription - - * src/core/ladspa_manager.cpp: - win32-compat - - * src/core/instrument_midi_io.cpp: - coding style - -2008-06-02 Paul Giblock - - * include/automatable_model.h: - * include/controller_connection.h: - * src/core/automatable_model.cpp: - * src/core/controller_connection.cpp: - Support for automatic deletion of controller if owned by connection - - * include/controller.h: - * include/midi_controller.h: - * include/controller_connection_dialog.h: - * src/gui/widgets/knob.cpp: - * src/gui/controller_connection_dialog.cpp: - * src/core/midi/midi_controller.cpp: - * src/core/controller.cpp: - * Makefile.am: - - Add midi-controller support - - Allow editing of connection through context menu - - Code clean-up - - * include/midi.h: - add const for max controller ID and add bytes array to the midiEvent - m_data union - - * src/core/midi/midi_client.cpp: - Don't subtract octave from control change events - - * src/tracks/instrument_track.cpp: - Ignore unhandled control change events - - * src/tracks/pattern.cpp: - Minor pixel adjustment to TCO drawing - - * src/core/track.cpp: - Correct misleading textFloat - - * src/core/song.cpp: - Code style - -2008-06-01 Paul Giblock - - * src/tracks/pattern.cpp: - Improve drawing of tact lines, so it is more obvious where a pattern - ends - - * src/core/track.cpp: - Display floating text underneith the current track so you can actually - see what you are doing - - * src/core/config_mgr.cpp: - Gracefully handle default lmmsrc.xml creation instead of aborting - -2008-06-01 Tobias Doerffel - - * plugins/ladspa_effect/caps/basics.h: - * plugins/ladspa_effect/caps/interface.cc: - win32-build fixes - - * plugins/triple_oscillator/Makefile.am: - * plugins/triple_oscillator/triple_oscillator.cpp: - * plugins/audio_file_processor/audio_file_processor.cpp: - * plugins/audio_file_processor/Makefile.am: - made ready for building plugins as DLLs - - * plugins/kicker/kicker.h: - include QtCore/QObject rather than QObject - - * include/mmp.h: - * include/knob.h: - * include/track.h: - * include/engine.h: - * include/note.h: - * include/embed.h: - * include/instrument_view.h: - * include/config_mgr.h: - * include/automatable_model.h: - * include/mixer.h: - * include/instrument_track.h: - * include/instrument.h: - * include/sample_buffer.h: - * include/plugin.h: - * include/note_play_handle.h: - * include/song.h: - * include/string_pair_drag.h: - * include/oscillator.h: - * include/automatable_button.h: - * include/tooltip.h: - * include/journalling_object.h: - * include/pixmap_button.h: - * include/automatable_model_view.h: - * include/mv_base.h: - * include/volume_knob.h: - * include/plugin_view.h: - export according classes for making them accessibly by plugins - - * src/core/main.cpp: - dont set opacity for splashscreen - - * src/core/config_mgr.cpp: - customized paths for win32 (plugins in same directory as executable) - - * src/core/song.cpp: - initialize m_length member to 0 - - * src/core/plugin.cpp: - under win32 filter for DLL-files - - * include/types.h: - added macros for export-declaration - - * src/gui/plugin_browser.cpp: - * src/gui/effect_select_dialog.cpp: - * src/gui/main_window.cpp: - * src/core/track.cpp: - minor coding style issues - - * build_mingw32: - * acinclude.m4: - * Makefile.am: - better support for win32-builds - - * buildtools/bin2res.cpp: - open files in binary mode - fixes win32-build - - * configure.in: - * Makefile.am: - * include/audio_pulseaudio.h: - * src/core/audio/audio_pulseaudio.cpp: - * src/core/mixer.cpp: - * src/gui/setup_dialog.cpp: - added PulseAudio-support - -2008-05-30 Paul Giblock - - * src/gui/piano_roll.cpp: - - Improve selection of volume-bars on a chord. Select closest note - instead of whichever one was created first. - - Display volume-change handles on top of the bars instead of possibly - underneith other bars when dealing with chords - - * AUTHORS: - Add Juan (Fabi) to authors, organize names more alphabetically - -2008-05-30 Tobias Doerffel - - * plugins/ladspa_effect/ladspa_effect.cpp: - fixed wrong item in effect blacklist - - * include/mixer.h: - * src/core/mixer.cpp: - use less complex worker-thread-synchronization - -2008-05-29 Tobias Doerffel - - * src/core/mixer.cpp: - use QAtomicInt instead of volatile bool + queue-global mutex for - worker-thread jobqueues - -2008-05-28 Tobias Doerffel - - * plugins/organic/organic.cpp: - * plugins/lb302/lb302.cpp: - * plugins/bass_booster/bass_booster.cpp: - * plugins/bass_booster/bassbooster_controls.cpp: - * plugins/stereo_matrix/stereomatrix_controls.cpp: - * plugins/vibed/nine_button_selector.h: - * plugins/vibed/nine_button_selector.cpp: - * plugins/vibed/vibed.cpp: - * plugins/triple_oscillator/triple_oscillator.cpp: - * plugins/audio_file_processor/audio_file_processor.cpp: - * plugins/stereo_enhancer/stereoenhancer_controls.cpp: - * plugins/sf2_player/sf2_player.cpp: - * plugins/kicker/kicker.cpp: - * plugins/midi_import/midi_import.cpp: - * include/knob.h: - * include/automatable_slider.h: - * include/lcd_spinbox.h: - * include/automatable_model.h: - * include/combobox_model.h: - * include/automation_pattern.h: - * include/note_play_handle.h: - * include/detuning_helper.h: - * include/group_box.h: - * include/automatable_button.h: - * include/automatable_model_templates.h: - * include/level_object.h: - * include/automatable_model_view.h: - * include/fader.h: - * include/combobox.h: - * src/gui/piano_roll.cpp: - * src/gui/automatable_model_view.cpp: - * src/gui/widgets/combobox.cpp: - * src/gui/widgets/knob.cpp: - * src/gui/widgets/envelope_and_lfo_view.cpp: - * src/gui/widgets/automatable_slider.cpp: - * src/gui/widgets/group_box.cpp: - * src/gui/widgets/lcd_spinbox.cpp: - * src/gui/widgets/volume_knob.cpp: - * src/gui/widgets/fader.cpp: - * src/gui/widgets/tempo_sync_knob.cpp: - * src/gui/widgets/automatable_button.cpp: - * src/gui/automation_editor.cpp: - * src/tracks/instrument_track.cpp: - * src/core/effect_chain.cpp: - * src/core/note_play_handle.cpp: - * src/core/song.cpp: - * src/core/automatable_model.cpp: - * src/core/audio/audio_alsa.cpp: - * src/core/audio/audio_oss.cpp: - * src/core/audio/audio_jack.cpp: - * src/core/envelope_and_lfo_parameters.cpp: - * src/core/combobox_model.cpp: - * src/core/meter_model.cpp: - * src/core/instrument_functions.cpp: - * src/core/instrument_midi_io.cpp: - * src/core/track.cpp: - * src/core/ladspa_control.cpp: - * src/core/note.cpp: - * src/core/piano.cpp: - * src/core/surround_area.cpp: - * src/core/automation_pattern.cpp: - * src/core/lfo_controller.cpp: - * Makefile.am: - reworked automatableModel (not template-based anymore), removed - levelObject, splitted comboBox/comboBoxModel-source-files, began to - unify context-menu-creation for controls - - diffstat: 63 files changed, 1145 insertions(+), 1170 deletions(-) - -2008-05-27 Paul Giblock - - * plugins/sf2_player/sf2_player.cpp: - restore gain setting when loading a project and keep gain setting when - changing sample rate - - * include/controller_view.h: - * src/gui/widgets/controller_view.cpp: - reverted toby's controllerView changes. - - * src/core/mmp.cpp: - add compat-code for time-signature support - -2008-05-26 Tobias Doerffel - - * include/controller_view.h: - * src/gui/widgets/controller_view.cpp: - made LMMS compile + cleanups - -2008-05-26 Paul Giblock - - * include/automatable_model.h: - * include/automatable_model_templates.h: - * include/controller.h: - * include/controller_connection.h: - * src/gui/widgets/knob.cpp: - * src/core/song.cpp: - * src/core/controller.cpp: - * src/core/controller_connection.cpp: - * Makefile.am: - - add controller connection class for storing controller links. Used to - specify linkage for loading/saving as well as a model for all the options - in the dialog (mapping function, smoothing, etc..) - - add dummyController for unfinalized or missing controllers. Faster than - adding a branch to value() or currentValue() - - save controller links to project - - incomplete, experimental! - - * include/controller_view.h: - * src/gui/lfo_controller_dialog.cpp: - * src/gui/widgets/controller_rack_view.cpp: - * data/themes/default/controller_bg.png: - Show name in controller view and make it renamable - - * data/themes/default/style.css: - A hint of blue in menu highlight - - * src/core/song.cpp: - Add data-changed event so lfo-rack can update - -2008-05-25 Tobias Doerffel - - * plugins/singerbot/singerbot.cpp: - * include/meter_model.h: - * include/song.h: - * include/pattern.h: - * include/piano_roll.h: - * include/song_editor.h: - * include/midi_time.h: - * include/types.h: - * include/timeline.h: - * src/core/bb_track_container.cpp: - * src/core/meter_model.cpp: - * src/core/song.cpp: - * src/core/timeline.cpp: - * src/core/track.cpp: - * src/gui/automation_editor.cpp: - * src/gui/piano_roll.cpp: - * src/gui/song_editor.cpp: - * src/gui/track_container_view.cpp: - * src/gui/widgets/tempo_sync_knob.cpp: - * src/tracks/bb_track.cpp: - * src/tracks/pattern.cpp: - implemented support for time-signatures other than 4/4 - still - incomplete and experimental! - - * include/controller_dialog.h: - * src/core/lfo_controller.cpp: - * src/gui/controller_dialog.cpp: - * src/gui/widgets/controller_view.cpp: - fixed order of member-initialization and miscellanous coding-style - corrections - - * plugins/patman/select_file.png: - * plugins/patman/logo.png: - * plugins/patman/artwork.png: - * plugins/ladspa_effect/logo.png: - * plugins/organic/logo.png: - * plugins/organic/randomise.png: - * plugins/organic/randomise_pressed.png: - * plugins/organic/artwork.png: - * plugins/lb302/artwork.png: - * plugins/bass_booster/logo.png: - * plugins/stereo_matrix/logo.png: - * plugins/bit_invader/logo.png: - * plugins/bit_invader/wavegraph.png: - * plugins/bit_invader/wavegraph3.png: - * plugins/bit_invader/artwork.png: - * plugins/bit_invader/smooth.png: - * plugins/vst_effect/logo.png: - * plugins/vibed/button_7_on.png: - * plugins/vibed/button_9_on.png: - * plugins/vibed/logo.png: - * plugins/vibed/button_-1_off.png: - * plugins/vibed/button_-2_off.png: - * plugins/vibed/button_-1_on.png: - * plugins/vibed/smooth_active.png: - * plugins/vibed/wavegraph4.png: - * plugins/vibed/button_f_off.png: - * plugins/vibed/button_f_on.png: - * plugins/vibed/button_up.png: - * plugins/vibed/normalize_inactive.png: - * plugins/vibed/button_1_off.png: - * plugins/vibed/button_2_off.png: - * plugins/vibed/button_3_off.png: - * plugins/vibed/button_2_on.png: - * plugins/vibed/button_4_off.png: - * plugins/vibed/artwork.png: - * plugins/vibed/button_5_off.png: - * plugins/vibed/button_6_off.png: - * plugins/vibed/button_4_on.png: - * plugins/vibed/normalize_active.png: - * plugins/vibed/button_7_off.png: - * plugins/vibed/button_8_off.png: - * plugins/vibed/button_6_on.png: - * plugins/vibed/button_9_off.png: - * plugins/vibed/button_8_on.png: - * plugins/vibed/button_down.png: - * plugins/vibed/button_-2_on.png: - * plugins/vibed/button_1_on.png: - * plugins/vibed/button_3_on.png: - * plugins/vibed/button_5_on.png: - * plugins/vibed/smooth_inactive.png: - * plugins/triple_oscillator/logo.png: - * plugins/triple_oscillator/am_active.png: - * plugins/triple_oscillator/artwork.png: - * plugins/triple_oscillator/sync_inactive.png: - * plugins/triple_oscillator/sync_active.png: - * plugins/live_tool/logo.png: - * plugins/live_tool/artwork.png: - * plugins/singerbot/logo.png: - * plugins/singerbot/artwork.png: - * plugins/audio_file_processor/select_file.png: - * plugins/audio_file_processor/logo.png: - * plugins/audio_file_processor/artwork.png: - * plugins/stk/mallets/logo.png: - * plugins/stk/mallets/artwork.png: - * plugins/stk/voices/flute/logo.png: - * plugins/stk/voices/flute/artwork.png: - * plugins/stk/voices/resonate/logo.png: - * plugins/stk/voices/resonate/artwork.png: - * plugins/stk/voices/wurley/logo.png: - * plugins/stk/voices/wurley/artwork.png: - * plugins/stk/voices/percflute/logo.png: - * plugins/stk/voices/percflute/artwork.png: - * plugins/stk/voices/rhodey/logo.png: - * plugins/stk/voices/rhodey/artwork.png: - * plugins/stk/voices/tubebell/logo.png: - * plugins/stk/voices/tubebell/artwork.png: - * plugins/stk/voices/bowed/logo.png: - * plugins/stk/voices/bowed/artwork.png: - * plugins/stk/voices/clarinet/logo.png: - * plugins/stk/voices/clarinet/artwork.png: - * plugins/stk/voices/moog/logo.png: - * plugins/stk/voices/moog/artwork.png: - * plugins/stk/voices/metal/logo.png: - * plugins/stk/voices/metal/artwork.png: - * plugins/stk/voices/b3/logo.png: - * plugins/stk/voices/b3/artwork.png: - * plugins/stk/voices/blow_hole/logo.png: - * plugins/stk/voices/blow_hole/artwork.png: - * plugins/stk/voices/brass/logo.png: - * plugins/stk/voices/brass/artwork.png: - * plugins/stk/voices/fmvoices/logo.png: - * plugins/stk/voices/fmvoices/artwork.png: - * plugins/stk/voices/bandedwg/logo.png: - * plugins/stk/voices/bandedwg/artwork.png: - * plugins/stk/voices/blow_bottle/logo.png: - * plugins/stk/voices/blow_bottle/artwork.png: - * plugins/plucked_string_synth/logo.png: - * plugins/plucked_string_synth/artwork.png: - * plugins/stereo_enhancer/logo.png: - * plugins/sf2_player/logo.png: - * plugins/sf2_player/artwork.png: - * plugins/vestige/select_file.png: - * plugins/vestige/logo.png: - * plugins/vestige/artwork.png: - * plugins/ladspa_browser/logo.png: - * plugins/kicker/logo.png: - * plugins/kicker/artwork.png: - * plugins/polyb302/artwork.png: - * data/themes/blue_scene/led_off.png: - * data/themes/blue_scene/back_to_zero.png: - * data/themes/blue_scene/project_export.png: - * data/themes/blue_scene/hourglass.png: - * data/themes/blue_scene/triangle_wave_inactive.png: - * data/themes/blue_scene/hq_mode.png: - * data/themes/blue_scene/usr_wave_inactive.png: - * data/themes/blue_scene/main_toolbar_bg.png: - * data/themes/blue_scene/add_bb_track.png: - * data/themes/blue_scene/tempo_sync.png: - * data/themes/blue_scene/edit_paste.png: - * data/themes/blue_scene/midi_file.png: - * data/themes/blue_scene/analysis.png: - * data/themes/blue_scene/zoom.png: - * data/themes/blue_scene/playpos_marker.png: - * data/themes/blue_scene/wizard_workingdir.png: - * data/themes/blue_scene/step_btn_off_light.png: - * data/themes/blue_scene/square_wave_inactive.png: - * data/themes/blue_scene/auto_limit.png: - * data/themes/blue_scene/exp_wave_active.png: - * data/themes/blue_scene/exit.png: - * data/themes/blue_scene/step_btn_on.png: - * data/themes/blue_scene/toolbar_bg.png: - * data/themes/blue_scene/keep_stop_position.png: - * data/themes/blue_scene/whatsthis.png: - * data/themes/blue_scene/output_graph.png: - * data/themes/blue_scene/wizard_files.png: - * data/themes/blue_scene/note_none.png: - * data/themes/blue_scene/black_key.png: - * data/themes/blue_scene/text_center.png: - * data/themes/blue_scene/stop.png: - * data/themes/blue_scene/error.png: - * data/themes/blue_scene/sin_wave_inactive.png: - * data/themes/blue_scene/loop_points_on.png: - * data/themes/blue_scene/play.png: - * data/themes/blue_scene/folder_opened.png: - * data/themes/blue_scene/mute_on.png: - * data/themes/blue_scene/ports.png: - * data/themes/blue_scene/project_saveas.png: - * data/themes/blue_scene/loop_point_disabled.png: - * data/themes/blue_scene/folder.png: - * data/themes/blue_scene/arp_random_on.png: - * data/themes/blue_scene/arp_sync.png: - * data/themes/blue_scene/edit_copy.png: - * data/themes/blue_scene/white_noise_wave_inactive.png: - * data/themes/blue_scene/track_op_grip.png: - * data/themes/blue_scene/background_artwork.png: - * data/themes/blue_scene/help.png: - * data/themes/blue_scene/unknown_file.png: - * data/themes/blue_scene/edit_redo.png: - * data/themes/blue_scene/exp_wave_inactive.png: - * data/themes/blue_scene/arp_down_on.png: - * data/themes/blue_scene/project_file.png: - * data/themes/blue_scene/sample_track.png: - * data/themes/blue_scene/note_quarter.png: - * data/themes/blue_scene/surround_area.png: - * data/themes/blue_scene/black_key_pressed.png: - * data/themes/blue_scene/project_notes.png: - * data/themes/blue_scene/project_new.png: - * data/themes/blue_scene/master_pitch.png: - * data/themes/blue_scene/edit_select.png: - * data/themes/blue_scene/track_op_menu.png: - * data/themes/blue_scene/colorize.png: - * data/themes/blue_scene/white_key.png: - * data/themes/blue_scene/splash.png: - * data/themes/blue_scene/note_double_whole.png: - * data/themes/blue_scene/envelope_graph.png: - * data/themes/blue_scene/saw_wave_inactive.png: - * data/themes/blue_scene/note_sixteenth.png: - * data/themes/blue_scene/lfo_graph.png: - * data/themes/blue_scene/frozen.png: - * data/themes/blue_scene/effect_board.png: - * data/themes/blue_scene/arp_down_off.png: - * data/themes/blue_scene/mute_off.png: - * data/themes/blue_scene/reload.png: - * data/themes/blue_scene/text_italic.png: - * data/themes/blue_scene/arp_random_off.png: - * data/themes/blue_scene/pause.png: - * data/themes/blue_scene/freeze.png: - * data/themes/blue_scene/triangle_wave_active.png: - * data/themes/blue_scene/combobox_arrow.png: - * data/themes/blue_scene/root.png: - * data/themes/blue_scene/apply.png: - * data/themes/blue_scene/usr_wave_active.png: - * data/themes/blue_scene/icon.png: - * data/themes/blue_scene/clock.png: - * data/themes/blue_scene/setup_directories.png: - * data/themes/blue_scene/text_left.png: - * data/themes/blue_scene/text_block.png: - * data/themes/blue_scene/plugins/tripleoscillator_fm_inactive.png: - * data/themes/blue_scene/plugins/bitinvader_artwork.png: - * data/themes/blue_scene/plugins/tripleoscillator_mix_active.png: - * data/themes/blue_scene/plugins/tripleoscillator_am_active.png: - * data/themes/blue_scene/plugins/tripleoscillator_artwork.png: - * data/themes/blue_scene/plugins/bitinvader_logo.png: - * data/themes/blue_scene/plugins/tripleoscillator_fm_active.png: - * data/themes/blue_scene/plugins/tripleoscillator_sync_inactive.png: - * data/themes/blue_scene/plugins/audiofileprocessor_artwork.png: - * data/themes/blue_scene/plugins/bitinvader_wavegraph3.png: - * data/themes/blue_scene/plugins/vestige_artwork.png: - * data/themes/blue_scene/plugins/bitinvader_smooth.png: - * data/themes/blue_scene/plugins/audiofileprocessor_logo.png: - * data/themes/blue_scene/plugins/tripleoscillator_sync_active.png: - * data/themes/blue_scene/plugins/pluckedstringsynth_logo.png: - * data/themes/blue_scene/plugins/audiofileprocessor_loop_off.png: - * data/themes/blue_scene/plugins/audiofileprocessor_reverse_off.png: - * data/themes/blue_scene/plugins/audiofileprocessor_loop_on.png: - * data/themes/blue_scene/plugins/vestige_logo.png: - * data/themes/blue_scene/plugins/tripleoscillator_am_inactive.png: - * data/themes/blue_scene/plugins/tripleoscillator_mix_inactive.png: - * data/themes/blue_scene/plugins/bitinvader_wavegraph.png: - * data/themes/blue_scene/cpuload_bg.png: - * data/themes/blue_scene/note_half.png: - * data/themes/blue_scene/wizard.png: - * data/themes/blue_scene/preset_file.png: - * data/themes/blue_scene/hint.png: - * data/themes/blue_scene/note.png: - * data/themes/blue_scene/timeline.png: - * data/themes/blue_scene/bb_track.png: - * data/themes/blue_scene/white_key_pressed.png: - * data/themes/blue_scene/arp_up_off.png: - * data/themes/blue_scene/autoscroll_off.png: - * data/themes/blue_scene/setup_audio.png: - * data/themes/blue_scene/text_right.png: - * data/themes/blue_scene/project_open.png: - * data/themes/blue_scene/arp_up_and_down_off.png: - * data/themes/blue_scene/note_eighth.png: - * data/themes/blue_scene/note_whole.png: - * data/themes/blue_scene/note_thirtysecond.png: - * data/themes/blue_scene/edit_erase.png: - * data/themes/blue_scene/sin_wave_active.png: - * data/themes/blue_scene/saw_wave_active.png: - * data/themes/blue_scene/rename.png: - * data/themes/blue_scene/drum.png: - * data/themes/blue_scene/edit_undo.png: - * data/themes/blue_scene/edit_move.png: - * data/themes/blue_scene/wizard_intro.png: - * data/themes/blue_scene/add_sample_track.png: - * data/themes/blue_scene/combobox_bg.png: - * data/themes/blue_scene/setup_performance.png: - * data/themes/blue_scene/loop_point.png: - * data/themes/blue_scene/autoscroll_on.png: - * data/themes/blue_scene/unfreeze.png: - * data/themes/blue_scene/cancel.png: - * data/themes/blue_scene/sound_file.png: - * data/themes/blue_scene/arp_sort.png: - * data/themes/blue_scene/white_noise_wave_active.png: - * data/themes/blue_scene/arp_up_and_down_on.png: - * data/themes/blue_scene/folder_locked.png: - * data/themes/blue_scene/setup_general.png: - * data/themes/blue_scene/loop_points_off.png: - * data/themes/blue_scene/setup_midi.png: - * data/themes/blue_scene/uhoh.png: - * data/themes/blue_scene/step_btn_off.png: - * data/themes/blue_scene/songeditor.png: - * data/themes/blue_scene/square_wave_active.png: - * data/themes/blue_scene/project_open_down.png: - * data/themes/blue_scene/moog_saw_wave_inactive.png: - * data/themes/blue_scene/back_to_start.png: - * data/themes/blue_scene/text_under.png: - * data/themes/blue_scene/arp_up_on.png: - * data/themes/blue_scene/arp_free.png: - * data/themes/blue_scene/moog_saw_wave_active.png: - * data/themes/blue_scene/home.png: - * data/themes/blue_scene/knob01.png: - * data/themes/default/lcd_19green.png: - * data/themes/default/knob03.png: - * data/themes/default/back_to_zero.png: - * data/themes/default/edit_draw.png: - * data/themes/default/triangle_wave_inactive.png: - * data/themes/default/filter_hp.png: - * data/themes/default/zoom_y.png: - * data/themes/default/usr_wave_inactive.png: - * data/themes/default/muted.png: - * data/themes/default/add_bb_track.png: - * data/themes/default/fader_background.png: - * data/themes/default/tempo_sync.png: - * data/themes/default/plugins.png: - * data/themes/default/midi_file.png: - * data/themes/default/analysis.png: - * data/themes/default/zoom.png: - * data/themes/default/edit_arrow.png: - * data/themes/default/wizard_workingdir.png: - * data/themes/default/lcd_19red.png: - * data/themes/default/toolbar_bg.png: - * data/themes/default/whatsthis.png: - * data/themes/default/filter_notch.png: - * data/themes/default/output_graph.png: - * data/themes/default/wizard_files.png: - * data/themes/default/controller.png: - * data/themes/default/note_none.png: - * data/themes/default/black_key.png: - * data/themes/default/stop.png: - * data/themes/default/fader_knob.png: - * data/themes/default/mute_off_disabled.png: - * data/themes/default/mute_on_disabled.png: - * data/themes/default/sin_wave_inactive.png: - * data/themes/default/play.png: - * data/themes/default/folder_opened.png: - * data/themes/default/filter_bp.png: - * data/themes/default/ports.png: - * data/themes/default/loop_point_disabled.png: - * data/themes/default/folder.png: - * data/themes/default/arp_random_on.png: - * data/themes/default/arp_sync.png: - * data/themes/default/automation.png: - * data/themes/default/white_noise_wave_inactive.png: - * data/themes/default/track_op_grip.png: - * data/themes/default/pr_black_key.png: - * data/themes/default/help.png: - * data/themes/default/background_artwork.png: - * data/themes/default/factory_files.png: - * data/themes/default/unknown_file.png: - * data/themes/default/exp_wave_inactive.png: - * data/themes/default/project_file.png: - * data/themes/default/arp_down_on.png: - * data/themes/default/piano.png: - * data/themes/default/midi_in.png: - * data/themes/default/black_key_pressed.png: - * data/themes/default/surround_area.png: - * data/themes/default/track_op_menu_disabled.png: - * data/themes/default/project_new.png: - * data/themes/default/master_pitch.png: - * data/themes/default/led_green.png: - * data/themes/default/edit_select.png: - * data/themes/default/colorize.png: - * data/themes/default/white_key.png: - * data/themes/default/knob02.png: - * data/themes/default/note_double_whole.png: - * data/themes/default/envelope_graph.png: - * data/themes/default/saw_wave_inactive.png: - * data/themes/default/lfo_graph.png: - * data/themes/default/groupbox_led_bg.png: - * data/themes/default/frozen.png: - * data/themes/default/arp_down_off.png: - * data/themes/default/effect_board.png: - * data/themes/default/reload.png: - * data/themes/default/zoom_x.png: - * data/themes/default/pause.png: - * data/themes/default/freeze.png: - * data/themes/default/filter_lp.png: - * data/themes/default/combobox_arrow.png: - * data/themes/default/triangle_wave_active.png: - * data/themes/default/root.png: - * data/themes/default/apply.png: - * data/themes/default/usr_wave_active.png: - * data/themes/default/icon.png: - * data/themes/default/clock.png: - * data/themes/default/add_controller.png: - * data/themes/default/setup_directories.png: - * data/themes/default/cpuload_bg.png: - * data/themes/default/quantize.png: - * data/themes/default/wizard.png: - * data/themes/default/preset_file.png: - * data/themes/default/hint.png: - * data/themes/default/filter_ap.png: - * data/themes/default/timeline.png: - * data/themes/default/bb_track.png: - * data/themes/default/effect_plugin.png: - * data/themes/default/white_key_pressed.png: - * data/themes/default/arp_up_off.png: - * data/themes/default/autoscroll_off.png: - * data/themes/default/setup_audio.png: - * data/themes/default/arp_up_and_down_off.png: - * data/themes/default/combobox_arrow_selected.png: - * data/themes/default/cpuload_leds.png: - * data/themes/default/note_whole.png: - * data/themes/default/edit_erase.png: - * data/themes/default/wizard_intro.png: - * data/themes/default/add_sample_track.png: - * data/themes/default/combobox_bg.png: - * data/themes/default/setup_performance.png: - * data/themes/default/sound_file.png: - * data/themes/default/arp_sort.png: - * data/themes/default/white_noise_wave_active.png: - * data/themes/default/arp_up_and_down_on.png: - * data/themes/default/controller_bg.png: - * data/themes/default/folder_locked.png: - * data/themes/default/setup_general.png: - * data/themes/default/loop_points_off.png: - * data/themes/default/filter_2lp.png: - * data/themes/default/setup_midi.png: - * data/themes/default/uhoh.png: - * data/themes/default/midi_out.png: - * data/themes/default/songeditor.png: - * data/themes/default/moog_saw_wave_inactive.png: - * data/themes/default/arp_free.png: - * data/themes/default/home.png: - * data/themes/default/fader_leds.png: - * data/themes/default/knob01.png: - * data/themes/llama/background_artwork.png: - shrinked file-sizes via optipng - - * include/main_window.h: - * src/gui/main_window.cpp: - * src/core/main.cpp: - * data/themes/default/splash.png: - new transparent splash-screen without obsolete text-messages - -2008-05-25 Paul Giblock - - * include/embed.h: - Fix missing distructor warning - - * include/controller.h: - * include/song.h: - * include/lfo_controller.h: - * src/core/controller.cpp: - * src/core/lfo_controller.cpp: - Save and load controllers to project files. - - * src/core/song.cpp: - - Save and load controllers to project files. - - emit dataChanged() on clearProject() do we need this anywhere else? - -2008-05-24 Tobias Doerffel - - * include/song.h: - * include/song_editor.h: - * src/core/song.cpp: - * src/gui/song_editor.cpp: - added meterModel and meterDialog (which actually is just a widget) as - preparation for time-signature-support - it doesn't actually work yet! - - * data/themes/default/style.css: - improved appearence of menu in general - - * Makefile.am: - * include/tempo_sync_knob.h: - * include/meter_model.h: - * include/meter_dialog.h: - * src/core/meter_model.cpp: - * src/gui/widgets/meter_dialog.cpp: - splitted source-files for meterModel and meterDialog and added - "simple"-mode for meterDialog - -2008-05-22 Paul Giblock - - * include/lfo_controller.h: - * src/gui/lfo_controller_dialog.cpp: - * src/core/lfo_controller.cpp: - Add more wave shapes to LFO controller - - * src/gui/widgets/controller_view.cpp: - Set sub-window's icon to the icon of the controllerDialog - - * src/gui/widgets/controller_rack_view.cpp: - Add icon to window - -2008-05-21 Paul Giblock - - * plugins/sf2_player/Makefile.am: - * plugins/Makefile.am: - * configure.in: - Add fluidsynth detection to configure - -2008-05-21 Paul Giblock - - * plugins/vestige/select_file.png: - * plugins/vestige/logo.png: - * plugins/vestige/vestige.cpp: - * plugins/vestige/artwork.png: - Integrate new vestige artwork - - * src/core/track.cpp: - Improve background drawing/scaling - - * plugins/audio_file_processor/audio_file_processor.cpp: - * plugins/audio_file_processor/select_file.png: - * plugins/audio_file_processor/logo.png: - * plugins/audio_file_processor/loop_off.png: - * plugins/audio_file_processor/loop_on.png: - * plugins/audio_file_processor/reverse_off.png: - * plugins/audio_file_processor/reverse_on.png: - * plugins/audio_file_processor/artwork.png: - Integrate new audio file processor artwork - - * src/gui/widgets/volume_knob.cpp: - Fix placement of tooltop in styled knobs - - * src/gui/widgets/knob.cpp: - Minor graphical enhancement for styled knobs - - * src/gui/piano_roll.cpp: - * include/piano_roll.h: - * data/themes/default/record_accompany.png: - - Fix annoying bug where changing patterns would scroll to bar 2 instead - of bar 1 - - Add record-with-accompaniment feature because it was easier to just add - a toolbutton then to strip out the code. At least now there is some - starting point for this feature should we ever decide to release it. - - * plugins/organic/organic.cpp: - * plugins/organic/organic.h: - Complete organic gui - - * data/themes/default/style.css: - AFP and organic knob styles - - * plugins/sf2_player/artwork.png: - New sf2-player artwork - -2008-05-21 Tobias Doerffel - - * src/core/main.cpp: - only create core-application for --help and -h - - * plugins/ladspa_effect/ladspa_effect.cpp: - * plugins/patman/patman.cpp: - * plugins/lb302/lb302.cpp: - * plugins/organic/organic.cpp: - * plugins/stereo_matrix/stereo_matrix.cpp: - * plugins/bass_booster/bass_booster.cpp: - * plugins/bit_invader/bit_invader.cpp: - * plugins/vst_effect/vst_effect.cpp: - * plugins/vibed/vibed.cpp: - * plugins/triple_oscillator/triple_oscillator.cpp: - * plugins/singerbot/singerbot.cpp: - * plugins/live_tool/live_tool.cpp: - * plugins/audio_file_processor/audio_file_processor.cpp: - * plugins/stk/mallets/mallets.cpp: - * plugins/stereo_enhancer/stereo_enhancer.cpp: - * plugins/sf2_player/sf2_player.cpp: - * plugins/vestige/vestige.cpp: - * plugins/vst_base/vst_base.cpp: - * plugins/ladspa_browser/ladspa_browser.cpp: - * plugins/kicker/kicker.cpp: - * plugins/Makefile.am: - * plugins/flp_import/flp_import.cpp: - * plugins/midi_import/midi_import.cpp: - * include/track.h: - * src/gui/piano_roll.cpp: - * src/gui/plugin_browser.cpp: - * src/gui/main_window.cpp: - * src/core/plugin.cpp: - * src/core/bb_track_container.cpp: - * src/core/tool.cpp: - * src/core/instrument_sound_shaping.cpp: - * src/core/instrument_functions.cpp: - * src/core/track.cpp: - * src/core/instrument.cpp: - use new pluginPixmapLoader - - * include/lmms_style.h: - * src/gui/lmms_style.cpp: - load stylesheet here - - * include/combobox.h: - * src/gui/widgets/combobox.cpp: - use pixmapLoader-pointers rather than QPixmap-pointers in comboBoxModel - - * include/plugin.h: - in plugin-descriptor, hold a pointer to pixmapLoader instead of - QPixmap itself - - * include/embed.h: - * src/gui/embed.cpp: - introduced pixmapLoader and pluginPixmapLoader-classes for abstracting - QPixmap-instantiation - models can hold pixmapLoaders without actually - instantiating a QPixmap-object and views can access the pixmap - - * src/gui/main_window.cpp: - removed settings-menu and moved setup-dialog to edit-menu - - * Makefile.am: - * include/config_mgr.h: - * src/core/config_mgr.cpp: - removed all the obsolete first-startup-wizard-code - -2008-05-19 Tobias Doerffel - - * configure.in: - * plugins/vst_base/lvsl_client.cpp: - call waitpid(...) when closing plugin - fixes zombie processes - - * plugins/vst_effect/vst_effect_controls.h: - * plugins/vst_effect/vst_subplugin_features.cpp: - * plugins/vst_effect/vst_subplugin_features.h: - * plugins/vst_effect/vst_effect_control_dialog.cpp: - * plugins/vst_effect/Makefile.am: - * plugins/vst_effect/vst_effect.cpp: - * plugins/vst_effect/vst_effect_controls.cpp: - * plugins/vst_effect/vst_effect_control_dialog.h: - * plugins/vst_effect/vst_effect.h: - * plugins/vst_base/lvsl_client.h: - * plugins/vst_base/lvsl_client.cpp: - finally made VST-effect plugin work - - * src/core/track_container.cpp: - * src/core/main.cpp: - when rendering from command-line, only create a QCoreApplication - needs - further work - - * include/config_mgr.h: - * src/gui/widgets/effect_rack_view.cpp: - minor coding-style stuff - - * plugins/singerbot/singerbot.h: - * plugins/singerbot/singerbot.cpp: - integrated patches from William Steidtmann - which makes Singerbot at least compile - doesn't seem to work yet though - -2008-05-19 Paul Giblock - - * triple_oscillator.cpp: - * am_active.png: - * am_inactive.png: - * artwork.png: - * btn_mask.png: - * exp_shape_active.png: - * exp_shape_inactive.png: - * fm_active.png: - * fm_inactive.png: - * logo.png: - * mix_active.png: - * mix_inactive.png: - * moog_saw_shape_active.png: - * moog_saw_shape_inactive.png: - * pm_active.png: - * pm_inactive.png: - * saw_shape_active.png: - * saw_shape_inactive.png: - * sin_shape_active.png: - * sin_shape_inactive.png: - * square_shape_active.png: - * square_shape_inactive.png: - * sync_active.png: - * sync_inactive.png: - * triangle_shape_active.png: - * triangle_shape_inactive.png: - * usr_shape_active.png: - * usr_shape_inactive.png: - * white_noise_shape_active.png: - * white_noise_shape_inactive.png: - Updated Triple-oscillator artwork - - * src/core/track.cpp: - Darkened the tracks so it doesn't hurt to look at - - * src/gui/lfo_controller_dialog.cpp: - * src/gui/widgets/controller_view.cpp: - Remove stray line - - * plugins/kicker/kicker.cpp: - * plugins/kicker/kicker.h: - * data/themes/default/style.css: - Including stylesheet changes I forgot to commit, fixes knobs in 3xOsc - -2008-05-18 Paul Giblock - - * src/gui/widgets/knob.cpp: - * include/knob.h: - First version of stylable knobs. Perhaps can be overlayed with current - knobs to add line coloring/width in other places around the GUI. - - * src/core/track.cpp: - - Re-enabled alternating background, better appearance AND performance - - Fixed more of the flickering by disabling updates when moving - - Toby will probably want to change background colors, I just used - something simple since it will end up changing probably. It do like the - gradient dark on top, looks like a "channel" or "groove". - - * plugins/patman/artwork.png: - Fixed artwork again - - * plugins/singerbot/artwork.png: - * plugins/singerbot/logo.png: - Updated SingerBot artwork - -2008-05-18 Tobias Doerffel - - * plugins/stk/mallets/mallets.cpp: - added missing initialization of member-variables which made Mallets - play nothing until GUI has been opened - - * include/bb_track.h: - * src/gui/widgets/combobox.cpp: - * src/gui/widgets/name_label.cpp: - * src/tracks/bb_track.cpp: - * src/tracks/pattern.cpp: - * data/themes/default/track_op_grip.png: - improved overall appearence - - * src/core/track.cpp: - - disabled flipped painting of track-view-BG - - optimized changePosition()-method for much faster drawing - - * src/gui/fx_mixer_view.cpp: - do not destroy FX-mixer-view when closing - - * plugins/ladspa_effect/ladspa_effect.cpp: - added "Notch Filter" to blacklist - - * plugins/ladspa_effect/ladspa_effect.h: - * plugins/ladspa_effect/ladspa_effect.cpp: - * plugins/bass_booster/bass_booster.cpp: - * plugins/stereo_matrix/stereo_matrix.cpp: - * plugins/stereo_enhancer/stereo_enhancer.cpp: - - replaced old code with effect::checkGate() call - - various cleanups and minor optimizations - - * src/core/effect_chain.cpp: - added debugging-code for determining buggy effect-plugins at higher - samplerates - - * include/plugin.h: - introduced changable publicName-property - - * include/effect.h: - * src/core/effect.cpp: - added checkGate()-function for reducing redundant code in effect-plugins - -2008-05-17 Tobias Doerffel - - * plugins/ladspa_effect/ladspa_effect.cpp: - * plugins/ladspa_effect/ladspa_effect.h: - improved handling of effects which only work at limited samplerates - - * include/audio_port.h: - * src/core/audio/audio_port.cpp: - small optimizations - - * src/core/mixer.cpp: - removed obsolete idle-property of worker-threads - - * src/core/fx_mixer.cpp: - protect individual buffers of FX-channels from being processed by more - than one thread - -2008-05-17 Paul Giblock - - * plugins/stereo_matrix/stereomatrix_controls.cpp: - Allow knobs to invert phase as well - - * plugins/patman/patman.cpp: - * plugins/patman/patman.h: - * plugins/patman/artwork.png: - * plugins/patman/loop_off.png: - * plugins/patman/loop_on.png: - * plugins/patman/tune_off.png: - * plugins/patman/tune_on.png: - * plugins/patman/select_file_on.png: - * plugins/patman/select_file.png: - - Integrate new patman artwork. - - Make file selection button highlight when clicked. - - * include/pixmap_button.h: - * src/gui/widgets/pixmap_button.cpp: - Make button pixmap "activate" on click - - * src/gui/widgets/automatable_button.cpp: - Noted bug in automatable button - - * src/gui/piano_roll.cpp: - Fix bug when trying to select note on first beat. However, still breaks - if the cursor moves quickly from right to left (i.e: if it skips the - pixel position) - -2008-05-14 Tobias Doerffel - - * include/project_renderer.h: - * src/core/main.cpp: - * src/core/project_renderer.cpp: - added a lot of options for rendering via command-line and finally made - it working with new projectRenderer-class - - * include/mixer.h: - removed 16x oversampling - -2008-05-13 Tobias Doerffel - - * include/track.h: - * include/pixmap_button.h: - * src/core/track.cpp: - * src/gui/widgets/pixmap_button.cpp: - toggle solo via Ctrl+left mouse button - - * src/gui/fx_mixer_view.cpp: - set window-icon - - * src/gui/widgets/tab_widget.cpp: - use colors from active palette - - * src/gui/widgets/project_notes.cpp: - hide per default - - * src/gui/main_window.cpp: - * src/core/timeline.cpp: - * data/themes/default/project_export.png: - * data/themes/default/hourglass.png: - * data/themes/default/hq_mode.png: - * data/themes/default/edit_paste.png: - * data/themes/default/text_bold.png: - * data/themes/default/project_save.png: - * data/themes/default/playpos_marker.png: - * data/themes/default/exit.png: - * data/themes/default/text_center.png: - * data/themes/default/error.png: - * data/themes/default/edit_cut.png: - * data/themes/default/mute_on.png: - * data/themes/default/project_saveas.png: - * data/themes/default/loop_point_disabled.png: - * data/themes/default/arp_random_on.png: - * data/themes/default/edit_copy.png: - * data/themes/default/edit_redo.png: - * data/themes/default/arp_down_on.png: - * data/themes/default/track_op_menu_disabled.png: - * data/themes/default/project_notes.png: - * data/themes/default/track_op_menu.png: - * data/themes/default/groupbox_led_bg.png: - * data/themes/default/arp_down_off.png: - * data/themes/default/mute_off.png: - * data/themes/default/text_italic.png: - * data/themes/default/arp_random_off.png: - * data/themes/default/root.png: - * data/themes/default/apply.png: - * data/themes/default/text_block.png: - * data/themes/default/text_left.png: - * data/themes/default/arp_up_off.png: - * data/themes/default/text_right.png: - * data/themes/default/project_open.png: - * data/themes/default/arp_up_and_down_off.png: - * data/themes/default/edit_undo.png: - * data/themes/default/loop_point.png: - * data/themes/default/cancel.png: - * data/themes/default/add.png: - * data/themes/default/arp_up_and_down_on.png: - * data/themes/default/project_open_down.png: - * data/themes/default/text_under.png: - * data/themes/default/fx_mixer.png: - * data/themes/default/arp_up_on.png: - * data/themes/default/home.png: - integrated improved artwork (more to come) - - * src/core/track.cpp: - do not crash when removing TCOs - - * plugins/ladspa_effect/ladspa_effect.cpp: - use new resampling-methods in case we're processing plugins which are - known not to work at higher samplerates - - * include/main_window.h: - made resetWindowTitle() a slot - - * src/gui/widgets/effect_view.cpp: - coding-style stuff - - * include/effect.h: - * src/core/effect.cpp: - added simple way for plugins to process at lower sample-rates - - * src/core/ladspa_manager.cpp: - added hard-coded path in case LMMS is installed into /usr/local - - * include/export_project_dialog.h: - * src/gui/export_project_dialog.cpp: - update main-window title-bar while rendering - - * src/gui/widgets/visualization_widget.cpp: - do not update while song-export - - * src/gui/dialogs/export_project.ui: - improved usability - - * include/audio_device.h: - * src/core/audio/audio_device.cpp: - * src/core/audio/audio_alsa.cpp: - * src/core/audio/audio_sdl.cpp: - * src/core/audio/audio_oss.cpp: - * src/core/audio/audio_jack.cpp: - after changed quality-settings also update interpolation for - samplerate-conversion - -2008-05-12 Tobias Doerffel - - * plugins/bass_booster/bassbooster_controls.cpp: - * plugins/sf2_player/sf2_player.cpp: - * src/core/audio/audio_device.cpp: - cleanups and the like - - * include/mixer.h: - in draft-mode use zero-order-hold interpolation instead of linear - interpolation - fixes some issues with resampling - - * plugins/bass_booster/bassbooster_controls.cpp: - made bass-booster HQ-mode-capable - - * include/effect_lib.h: - changed float's in bassbooster to SAMPLE - -2008-05-11 Tobias Doerffel - - * plugins/sf2_player/sf2_player.cpp: - retrieve resampling-interpolation from current mixer quality settings - - * include/mixer.h: - made m_writing-variable in fifoWriter volatile - - * include/project_renderer.h: - * src/core/project_renderer.cpp: - change audio-device to file-device from within GUI-thread in order to - make slots being connected to sampleRateChanged()-signal being called - immediately - - * src/tracks/instrument_track.cpp: - cleanups - - * src/core/mixer.cpp: - initialize quality with draft-preset - - * include/setup_dialog.h: - * include/audio_device.h: - * src/gui/main_window.cpp: - * src/gui/setup_dialog.cpp: - * src/core/audio/audio_device.cpp: - * src/core/audio/audio_alsa.cpp: - * src/core/audio/audio_sdl.cpp: - * src/core/audio/audio_oss.cpp: - * src/core/audio/audio_jack.cpp: - made HQ-mode for audio-devices optional - - * include/controller.h: - * include/song.h: - * include/audio_file_device.h: - * include/song_editor.h: - * include/export.h: - * include/export_project_dialog.h: - * src/gui/dialogs/export_project.ui: - * src/gui/song_editor.cpp: - * src/gui/export_project_dialog.cpp: - * src/core/song.cpp: - * src/core/main.cpp: - * Makefile.am: - introduced new project-export dialog - - * include/project_renderer.h: - * src/core/project_renderer.cpp: - new class for easily rendering a project into a file - - * include/mixer.h: - * include/audio_sdl.h: - * include/audio_jack.h: - * include/audio_device.h: - * include/audio_oss.h: - * include/audio_alsa.h: - * src/core/audio/audio_alsa.cpp: - * src/core/audio/audio_device.cpp: - * src/core/audio/audio_file_wave.cpp: - * src/core/audio/audio_jack.cpp: - * src/core/audio/audio_oss.cpp: - * src/core/audio/audio_sdl.cpp: - * src/core/mixer.cpp: - when changing quality-settings tell audio-devices about it so that - they can adjust their output-samplerate - -2008-05-05 Tobias Doerffel - - * plugins/ladspa_effect/ladspa_effect.cpp: - * plugins/organic/organic.cpp: - * plugins/lb302/lb302.cpp: - * plugins/bit_invader/bit_invader.cpp: - * plugins/vibed/vibrating_string.cpp: - * plugins/vibed/vibed.cpp: - * plugins/triple_oscillator/triple_oscillator.cpp: - * plugins/live_tool/live_tool.cpp: - * plugins/audio_file_processor/audio_file_processor.cpp: - * plugins/stk/mallets/mallets.cpp: - * plugins/sf2_player/sf2_player.cpp: - * plugins/vst_base/lvsl_client.cpp: - * plugins/ladspa_browser/ladspa_port_dialog.cpp: - * plugins/kicker/kicker.cpp: - * include/effect.h: - * include/controller.h: - * include/mixer.h: - * include/sample_buffer.h: - * include/audio_dummy.h: - * include/audio_sdl.h: - * include/song.h: - * include/audio_file_device.h: - * include/audio_jack.h: - * include/audio_device.h: - * include/audio_oss.h: - * include/audio_sample_recorder.h: - * include/audio_alsa.h: - * src/gui/piano_roll.cpp: - * src/gui/song_editor.cpp: - * src/gui/setup_dialog.cpp: - * src/gui/file_browser.cpp: - * src/gui/widgets/envelope_and_lfo_view.cpp: - * src/gui/automation_editor.cpp: - * src/gui/export_project_dialog.cpp: - * src/gui/bb_editor.cpp: - * src/tracks/instrument_track.cpp: - * src/tracks/pattern.cpp: - * src/core/song.cpp: - * src/core/bb_track_container.cpp: - * src/core/audio/audio_file_device.cpp: - * src/core/audio/audio_device.cpp: - * src/core/audio/audio_alsa.cpp: - * src/core/audio/audio_sdl.cpp: - * src/core/audio/audio_oss.cpp: - * src/core/audio/audio_sample_recorder.cpp: - * src/core/audio/audio_jack.cpp: - * src/core/sample_play_handle.cpp: - * src/core/envelope_and_lfo_parameters.cpp: - * src/core/mixer.cpp: - * src/core/instrument_sound_shaping.cpp: - * src/core/instrument_functions.cpp: - * src/core/engine.cpp: - * src/core/sample_buffer.cpp: - * src/core/oscillator.cpp: - * src/core/controller.cpp: - * src/core/lfo_controller.cpp: - made quality-settings (internal processing samplerate, interpolation - and so on) independent of audio-devices (final output) and added new - qualitySettings-structure to mixer - might be still buggy and HQ-mode - is currently not working, this is going to be fixed tomorrow, anyways - important preparation for new project-export-dialog - -2008-05-04 Tobias Doerffel - - * src/gui/fx_mixer_view.cpp: - added spacing below FX-bank-selector - - * include/effect_select_dialog.h: - * include/plugin.h: - * src/gui/effect_select_dialog.cpp: - fixed crash when adding an effect although none is selected and - improved overall usability - - * plugins/organic/organic.cpp: - fixed knob-inheritance problems - -2008-05-04 Paul Giblock - - * plugins/kicker/kicker.cpp: - * plugins/kicker/artwork.png: - Add new kicker artwork - - * plugins/organic/organic.cpp: - * plugins/organic/randomise.png: - * plugins/organic/randomise_pressed.png: - * plugins/organic/artwork.png: - * plugins/organic/logo.png: - Add new organic artwork - - * include/knob.h: - * src/gui/widgets/knob.cpp: - Seperate some drawing functionality to simplify subclasses - - * src/tracks/instrument_track.cpp: - Change plugin size from 246px back to 250px - -2008-05-03 Tobias Doerffel - - * src/core/track.cpp: - fixed move of TCO-selections - -2008-04-30 Paul Giblock - - * src/gui/piano_roll.cpp: - - Fixed moving of selected notes. - - TODO: Quantanize the movement to selected "Q" - -2008-04-29 Paul Giblock - - * include/main_window.h: - * src/gui/main_window.cpp: - Add button for toggling FX Window. Can use a better icon. - -2008-04-28 Paul Giblock - - * plugins/sf2_player/sf2_player.cpp: - * plugins/sf2_player/sf2_player.h: - Add gain, chorus, and reverb controls - - * include/instrument_functions.h: - * src/core/instrument_functions.cpp: - Fixed arpeggio direction loading - - * src/gui/widgets/effect_rack_view.cpp: - Display effect window and enable fx-chain when adding an effect - - * src/gui/widgets/effect_view.cpp: - Make effect controls window non-resizeable and remove maximize button - -2008-04-26 Tobias Doerffel - - * plugins/stereo_enhancer/stereo_enhancer.cpp: - * plugins/stereo_enhancer/stereo_enhancer.h: - - made delay-buffer a simple stereo-buffer instead of - surround-frame-buffer - - added missing call in constructor to clear newly created - delay-buffer - fixes bad distorted sound in various scenarios - -2008-04-25 Paul Giblock - - * plugins/bit_invader/bit_invader.cpp: - Fixed samplelength loading - -2008-04-24 Paul Giblock - - * src/core/song.cpp: - Reset LFO counter on song play - - * src/core/controller.cpp: - * include/controller.h: - Change counter from signed int to unsigned - - * src/gui/piano_roll.cpp: - - Allow volume bars to be modified by clicking one bar, then - sweeping the mouse - - shade volume bars according to volume - - fixed drawing of background while scrolling - - * plugins/stereo_matrix/stereo_matrix.cpp: - Made wet/dry knob do something. Acts as a nice panning knob when the - matrix has the channels swapped. - - * src/tracks/instrument_track.cpp: - * src/gui/fx_mixer_view.cpp: - * include/fx_mixer_view.h: - - Made bank-buttons easier to hit - - Double click on fx-channel LCD in ITW to warp to the proper FX-line - -2008-04-20 Tobias Doerffel - - * src/gui/widgets/group_box.cpp: - * plugins/sf2_player/sf2_player.cpp: - small cleanups - - * data/themes/default/style.css: - * include/fx_mixer_view.h: - * src/gui/fx_mixer_view.cpp: - improved layouting and made FX-lines being organized in 4 banks - instead of one big scrollarea - - * src/core/engine.cpp: - create FX-mixer after song - - * Makefile.am: - * include/fx_mixer.h: - * include/fx_mixer_view.h: - * src/core/fx_mixer.cpp: - * src/core/song.cpp: - * src/gui/fx_mixer_view.cpp: - splitted source-files for FX-mixer and its view - - * include/fader.h: - * src/gui/widgets/fader.cpp: - made faders automatable - - * include/song.h: - made automation-track public accessible - - * include/visualization_widget.h: - * src/gui/widgets/visualization_widget.cpp: - use new timer-framework - - * include/song_editor.h: - * src/gui/song_editor.cpp: - added fast and leightweight timer-framework - widgets requiring - periodic updates can simply connect their update-slots to - songEditor::periodicUpdate() - -2008-04-20 Paul Giblock - - * plugins/stereo_matrix/stereomatrix_controls.cpp: - Fixed saveSettings - -2008-04-16 Paul Giblock - - * plugins/sf2_player/sf2_player.cpp: - * plugins/sf2_player/sf2_player.h: - rewrote reference-sharing. Should return near-100% memory on unload, and - should properly handle samplerate changes. Now we can render large - sf2-based projects without consuming a gig of ram :) - -2008-04-15 Tobias Doerffel - - * src/gui/file_browser.cpp: - check type of preview-play-handle via type() instead of blindly using - dynamic_cast - probably fixes random crashes when previewing a lot of - samples and presets - - * src/tracks/instrument_track.cpp: - delete instrument-instance *after* removing all play-handles from - mixer as several play-handle-methods rely on instrument - fixes crash - when removing track while playing - - * src/core/track.cpp: - directly delete view before removing model - fixes crash when - removing instrument-track with instrument-track-window open - -2008-04-15 Paul Giblock - - * plugins/stereo_matrix/stereomatrix_control_dialog.cpp: - Fix layout - -2008-04-14 Paul Giblock - - * plugins/stereo_matrix: - * plugins/stereo_matrix/stereo_matrix.cpp: - * plugins/stereo_matrix/stereo_matrix.h: - * plugins/stereo_matrix/stereomatrix_controls.cpp: - * plugins/stereo_matrix/stereomatrix_controls.h: - * plugins/stereo_matrix/stereomatrix_control_dialog.cpp: - * plugins/stereo_matrix/stereomatrix_control_dialog.h: - * plugins/stereo_matrix/logo.png: - * plugins/stereo_matrix/Makefile.am: - * configure.in: - * plugins/Makefile.am: - Add stereo matrix plugin for real panning and stereo-swapping - -2008-04-14 Tobias Doerffel - - * plugins/sf2_player/sf2_player.cpp: - * plugins/sf2_player/sf2_player.h: - added resampling with Sinc-interpolation in case LMMS processes with - higher sample-rate than 96 KHz - -2008-04-14 Paul Giblock - - * plugins/sf2_player/sf2_player.cpp: - * plugins/sf2_player/sf2_player.h: - support HQ-mode except for interpolation for sampleRates > 96k - - * include/controller_dialog.h: - * include/controller_view.h: - * src/gui/controller_dialog.cpp: - * src/gui/widgets/controller_view.cpp: - * Makefile.am: - fix segfault when trying to show a controller dialog the second time - -2008-04-12 Tobias Doerffel - - * plugins/lb302/lb302.cpp: - replaced LB_HZ with engine::getMixer()->sampleRate()-calls in order to - have a correct pitch in HQ-mode - - * plugins/ladspa_effect/ladspa_effect.cpp: - * plugins/ladspa_effect/ladspa_control_dialog.cpp: - * plugins/ladspa_effect/ladspa_effect.h: - * plugins/ladspa_effect/ladspa_controls.cpp: - * plugins/ladspa_effect/Makefile.am: - * plugins/ladspa_effect/ladspa_control_dialog.h: - * plugins/ladspa_effect/ladspa_controls.h: - * include/effect_control_dialog.h: - made LADSPA-effect-hoster handle samplerate-changes so that we've - proper effect-processing in HQ-mode - - * include/lmms_constants.h: - more accurate constants - - * src/gui/export_project_dialog.cpp: - fixed progress-bar after change of tick-resolution from 64 to 192 - - * include/mixer.h: - * src/core/mixer.cpp: - made clearAudioBuffer() static - - * include/song.h: - * src/core/ladspa_manager.cpp: - coding-style-stuff - - * src/core/oscillator.cpp: - do not synthesize anything if frequency is above half of samplerate - -2008-04-09 Tobias Doerffel - - * plugins/flp_import/flp_import.cpp: - * plugins/midi_import/midi_import.cpp: - * include/engine.h: - * include/song.h: - * include/pattern.h: - * include/piano_roll.h: - * include/midi_time.h: - * include/types.h: - * include/timeline.h: - * include/automation_editor.h: - * configure.in: - * src/gui/piano_roll.cpp: - * src/gui/song_editor.cpp: - * src/gui/automation_editor.cpp: - * src/tracks/bb_track.cpp: - * src/tracks/instrument_track.cpp: - * src/tracks/pattern.cpp: - * src/core/note_play_handle.cpp: - * src/core/song.cpp: - * src/core/bb_track_container.cpp: - * src/core/mixer.cpp: - * src/core/mmp.cpp: - * src/core/track.cpp: - * src/core/engine.cpp: - * src/core/timeline.cpp: - * src/core/automation_pattern.cpp: - changed internal MIDI-time-resolution from 64th to 192th resulting for - example in better MIDI-import and allowing to use triplet-notes in LMMS - -2008-04-09 Paul Giblock - - * include/controller.h: - * src/core/controller.cpp: - fit values between 0.0 and 1.0 - - * include/lfo_controller.h: - * src/gui/lfo_controller_dialog.cpp: - * src/core/lfo_controller.cpp: - add more parameters to LFO controller - -2008-04-08 Paul Giblock - - * include/engine.h: - * src/core/engine.cpp: - add static accessor to the controller rack. I'm sure this won't be it's - own MDISubWindow very long.. - - * include/controller.h: - * include/controller_dialog.h: - * src/gui/widgets/knob.cpp: - * src/core/controller.cpp: - add gui accesssor and split off LFO - - * include/song.h: - * src/core/song.cpp: - make song the model for user-created controllers - - * src/gui/song_editor.cpp: - added icon. Was going to add controller rack as a QSplitter but found - this would take too much time right now - - * src/gui/widgets/visualization_widget.cpp: - drop back from 40 to an arbitrary 24fps - - * include/lfo_controller.h: - * src/gui/lfo_controller.cpp: - * src/gui/lfo_controller_dialog.cpp: - - add beginnings of an LFO controller and dialog - - don't mind the unoptimized code, it will be fixed - - * include/controller_view.h: - * include/controller_rack_view.h: - * src/gui/widgets/controller_view.cpp: - * src/gui/widgets/controller_rack_view.cpp: - * data/themes/default/controller_bg.png: - The beginning of the controller rack and controller items. This is an - absolute bare minimum interface at the moment. Also ulta-buggy. - - * include/controller_connection_dialog.h: - * src/gui/controller_connection_dialog.cpp: - This is the connection dialog. Will allow users to create and modify - connections between a controller and model. The lineEdit will be for - editing a mapping function to scale, offset, trig-ify, etc. - - * Makefile.am: - add controller related files - -2008-04-07 Tobias Doerffel - - * src/gui/effect_select_dialog.cpp: - fixed wrong model-index (=>wrong description-widget) when filtering - - * src/gui/lmms_style.cpp: - decreased button-icon-size to 20px - - * src/core/fx_mixer.cpp: - process FX-channels until effects signal that there's nothing more to - process - closes #1935872 - - * configure.in: - integrated changes from libsamplerate-0.1.3/configure.ac - - * include/effect_select_dialog.h: - * src/gui/effect_select_dialog.cpp: - - cleanups - - fixed broken connection for "Add"-button - - * src/3rdparty/samplerate/common.h: - * src/3rdparty/samplerate/fastest_coeffs.h: - * src/3rdparty/samplerate/float_cast.h: - * src/3rdparty/samplerate/high_qual_coeffs.h: - * src/3rdparty/samplerate/mid_qual_coeffs.h: - * src/3rdparty/samplerate/samplerate.c: - * src/3rdparty/samplerate/samplerate.h: - * src/3rdparty/samplerate/src_linear.c: - * src/3rdparty/samplerate/src_sinc.c: - * src/3rdparty/samplerate/src_zoh.c: - integrated libsamplerate 0.1.3 source which has various improvements - over 4-year-old version 0.1.2 - - * src/gui/widgets/combobox.cpp: - set correct value for model when selecting an item whose strings - occurs multiple times in the combobox - -2008-04-06 Tobias Doerffel - - * include/effect_select_dialog.h: - * src/gui/effect_select_dialog.cpp: - changed list-widget to be a list-view and added a line-edit for - filtering the list - -2008-04-06 Paul Giblock - - * include/lmms_style.h: - * src/gui/lmms_style.cpp: - Fix icon size for buttons etc... - -2008-04-05 Tobias Doerffel - - * plugins/patman/patman.cpp: - * plugins/patman/patman.h: - * plugins/lb302/lb302.cpp: - * plugins/lb302/lb302.h: - * plugins/organic/organic.cpp: - * plugins/organic/organic.h: - * plugins/bit_invader/bit_invader.cpp: - * plugins/bit_invader/bit_invader.h: - * plugins/vibed/vibed.h: - * plugins/vibed/vibed.cpp: - * plugins/triple_oscillator/triple_oscillator.h: - * plugins/triple_oscillator/triple_oscillator.cpp: - * plugins/audio_file_processor/audio_file_processor.cpp: - * plugins/audio_file_processor/audio_file_processor.h: - * plugins/stk/mallets/mallets.cpp: - * plugins/stk/mallets/mallets.h: - * plugins/sf2_player/sf2_player.cpp: - * plugins/sf2_player/sf2_player.h: - * plugins/vestige/vestige.cpp: - * plugins/vestige/vestige.h: - * plugins/kicker/kicker.cpp: - * plugins/kicker/kicker.h: - * include/instrument_play_handle.h: - * include/mixer.h: - * include/instrument_track.h: - * include/instrument.h: - * include/note_play_handle.h: - * include/sample_play_handle.h: - * include/dummy_instrument.h: - * include/preset_preview_play_handle.h: - * include/play_handle.h: - * src/tracks/instrument_track.cpp: - * src/core/preset_preview_play_handle.cpp: - * src/core/note_play_handle.cpp: - * src/core/sample_play_handle.cpp: - * src/core/mixer.cpp: - * src/core/instrument.cpp: - made rendering happen with one global working-buffer per thread - - hopefully improves L1/L2-cache-efficiency - - * include/file_browser.h: - * src/gui/file_browser.cpp: - do not examine directories for being empty when adding them - speeds - up LMMS-startup a lot! - -2008-04-04 Paul Giblock - - * include/knob.h: - * src/gui/widgets/knob.cpp: - Add friendlyUpdates slot and override doConnections - - * include/song_editor.h: - Add button for managing controller to songEditor - - * include/mv_base.h: - * include/core/mv_base.cpp: - Make doConnections virtual - - * include/combobox.h: - Fixed tabs - - * src/core/mixer.cpp: - Couldn't easily convert from void* to int on a 64bit machine. Instead, - we now use a union. We should change any enqueueing code to use the - union as well - - * data/themes/add_controller.png: - * data/themes/controller.png: - Some new images for controllers - -2008-04-04 Tobias Doerffel - - * src/core/mixer.cpp: - implemented parallelization of FX-channel-processing - - * include/automatable_model.h: - * include/automatable_model_templates.h: - cleanups and optimizations in value( int ) - -2008-04-04 Paul Giblock - - * include/controller.h: - * src/core/controller.cpp: - * Makefile.am: - Add controller class to LMMS - - * include/knob.h: - * src/gui/widgets/knob.cpp: - Add Connect to Controller item to context menu for future dialog - - * include/automatable_model.h: - * include/automatable_model_templates.h: - - add controller pointer to class - - add value(int offset) function for sample-exact value fetching - - use controller in value() if set - - * src/tracks/pattern.cpp: - Fixed length of notes according to PaulWay - - * src/core/mixer.cpp: - trigger controller's frame counter - - * data/themes/llama: - * data/themes/llama/background_artwork.png: - * data/themes/Makefile.am: - start a theme with my preferences - -2008-04-03 Tobias Doerffel - - * include/song.h: - * src/core/song.cpp: - * src/gui/export_project_dialog.cpp: - * src/gui/song_editor.cpp: - made song-length being cached and only updated upon changed length or - position of TCOs - - * src/core/track.cpp: - optimized track::length()-method - - * src/core/mixer.cpp: - great improvements on multithreading - one global job-queue protected by - a simple mutex where threads pull their jobs from - - * src/core/engine.cpp: - delete LADSPA-manager after mixer and FX-mixer as LADSPA-effects in - FX-mixer access LADSPA-manger at destruction - - * plugins/ladspa_effect/ladspa_effect.cpp: - * plugins/ladspa_effect/ladspa_effect.h: - * plugins/bass_booster/bass_booster.cpp: - * plugins/bass_booster/bass_booster.h: - * plugins/stereo_enhancer/stereo_enhancer.cpp: - * plugins/stereo_enhancer/stereo_enhancer.h: - * include/effect.h: - - made effect::processAudioBuffer(...) process a sampleFrame- instead of - surroundSampleFrame-array - - divide out_sum by number of frames processed to have a - period-size-independent value - - * src/core/note_play_handle.cpp: - * include/automatable_model.h: - renamed value( int ) to levelToValue( int ) as preparation for - controller-framework - - * include/mixer.h: - * src/core/mixer.cpp: - - made mixer::buffertToPort accept a stereoVolumeVector as audio-buffers - have stereo-audio-buffers now - - made peakValueLeft() and peakValueRight() take a sampleFrame-pointer - - process in stereo internally - - * include/instrument_track.h: - * src/tracks/instrument_track.cpp: - replaced surroundArea with panning-knob - - * include/audio_port.h: - * src/core/audio/audio_port.cpp: - use sampleFrame-array instead of surroundSampleFrame-array for - processing - - * src/core/fx_mixer.cpp: - * include/fx_mixer.h: - made mixToChannel() take a sampleFrame-pointer - - * include/volume.h: - * src/core/sample_play_handle.cpp: - * src/core/surround_area.cpp: - added stereoVolumeVector and surroundVolumeVector-declarations - - * include/dummy_effect.h: - implement pure-virtual processAudioBuffer()-method - - * include/panning.h: - new panningToVolumeVector()-inline-method - - * include/effect_chain.h: - * src/core/effect_chain.cpp: - made processAudioBuffer() take a sampleFrame-pointer - - * include/visualization_widget.h: - * src/gui/widgets/visualization_widget.cpp: - use sampleFrame-array instead of surroundSampleFrame-array internally - -2008-04-02 Tobias Doerffel - - * include/automatable_model.h: - added castValue()-method - -2008-04-01 Tobias Doerffel - - * plugins/ladspa_effect/Makefile.am: - * plugins/patman/Makefile.am: - * plugins/lb302/Makefile.am: - * plugins/organic/Makefile.am: - * plugins/bass_booster/Makefile.am: - * plugins/bit_invader/Makefile.am: - * plugins/vst_effect/Makefile.am: - * plugins/vibed/Makefile.am: - * plugins/triple_oscillator/Makefile.am: - * plugins/live_tool/Makefile.am: - * plugins/live_tool/live_tool.cpp: - * plugins/singerbot/Makefile.am: - * plugins/audio_file_processor/Makefile.am: - * plugins/stk/mallets/Makefile.am: - * plugins/stereo_enhancer/Makefile.am: - * plugins/vestige/Makefile.am: - * plugins/sf2_player/Makefile.am: - * plugins/ladspa_browser/Makefile.am: - * plugins/kicker/Makefile.am: - * plugins/polyb302/Makefile.am: - * plugins/flp_import/flp_import.cpp: - corrected paths / includes - - * include/engine.h: - * include/instrument_track.h: - * include/preset_preview_play_handle.h: - * src/tracks/instrument_track.cpp: - * src/core/preset_preview_play_handle.cpp: - * src/core/track_container.cpp: - * src/core/engine.cpp: - added dummyTrackContainer with dummyInstrumentTrack in order to have a - default-model for cached inactive instrument-track-windows - fixes - regular crashes - - * include/engine.h: - * include/bb_track_container.h: - * include/track_container_view.h: - * include/song_editor.h: - * include/bb_editor.h: - * include/track_container.h: - * src/gui/track_container_view.cpp: - * src/gui/bb_editor.cpp: - * src/tracks/bb_track.cpp: - * src/tracks/pattern.cpp: - * src/core/preset_preview_play_handle.cpp: - * src/core/track_container.cpp: - * src/core/song.cpp: - * src/core/bb_track_container.cpp: - * src/core/file_browser.cpp: - * src/core/track.cpp: - * src/core/engine.cpp: - * src/core/automation_editor.cpp: - * Makefile.am: - - splitted track_container.h into track_container.h and - track_container_view.h - - splitted bb_editor.h into bb_track_container.h and bb_editor.h - - moved view-component-implementations of trackContainer and - bbTrackContainer to src/gui/ - - added dummyInstrumentTrack-implementation - - * plugins/ladspa_effect/caps/README.ardour: - * plugins/ladspa_effect/caps/README.dist: - * plugins/ladspa_effect/caps/Makefile.am: - added README-files - - * plugins/ladspa_effect/ladspa_effect.cpp: - * plugins/bass_booster/bass_booster.cpp: - decreased minimal gate from 0.0001f to 0.00001f as it turned out that - some effects were cut off with previous value - - * include/endian_handling.h: - * include/note.h: - * include/effect_select_dialog.h: - * include/midi.h: - * include/effect_view.h: - * include/side_bar.h: - * include/micro_timer.h: - * include/midi_event_processor.h: - * include/instrument_function_views.h: - * include/instrument_midi_io.h: - * include/export.h: - * include/dummy_instrument.h: - * include/level_object.h: - added missing includes when compiling headers itself - - * Makefile.am: - added single-binary-target for testing-purposes - -2008-03-30 Tobias Doerffel - - * src/core/song_editor.cpp: - removed obsolete SIGNAL/SLOT-connection - - * plugins/bass_booster/bass_booster.cpp: - * plugins/ladspa_effect/ladspa_effect.cpp: - compare out_sum against getGate()+0.0001f as getGate() might be 0 - while out_sum in many cases never will reach 0,0...0 again - fixes - high CPU-usage even after stop playing - - * include/effect_chain.h: - * plugins/ladspa_effect/ladspa_effect.cpp: - made controls have a track to allow automation of LADSPA-controls - - * include/automatable_button.h: - * src/widgets/automatable_button.cpp: - on model-change, ensure QPushButton's state is correct - - * src/widgets/effect_rack_view.cpp: - properly handle changed models - - * src/tracks/instrument_track.cpp: - when model has changed, also set new model for effect-view - - * src/core/effect_chain.cpp: - - use track as parent - - correct initialization of m_enabledModel which fixes crashes on - model-updates - -2008-03-30 Paul Giblock - - * plugins/sf2_player/sf2_player.cpp: - * plugins/sf2_player/sf2_player.h: - Fix patch dialog error when viewing dialog before file has loaded - - all we had to do is diable the button while a file is loading - -2008-03-30 Tobias Doerffel - - * plugins/sf2_player/sf2_player.cpp: - duplicate char-pointer returned by qPrintable - fixes bugs when - loading sound-fonts - -2008-03-24 Tobias Doerffel - - * src/core/fx_mixer.cpp: - completed recent changes to saveSettings() / loadSettings() - -2008-03-22 Tobias Doerffel - - * data/themes/default/main_toolbar_bg.png: - * data/themes/default/toolbar_bg.png: - made toolbar-backgrounds a bit more blue-ish - - * src/core/main.cpp: - tuned colors a bit - - * src/core/fx_mixer.cpp: - moved effect-chain to right side of window - - * src/core/ladspa_control.cpp: - added missing break in switch which made a lot of messages appear in - console when time-based knobs were used by LADSPA-plugins - - * plugins/organic/organic.cpp: - * plugins/organic/organic.h: - * plugins/vibed/vibed.h: - * plugins/vibed/vibed.cpp: - * plugins/triple_oscillator/triple_oscillator.cpp: - * plugins/audio_file_processor/audio_file_processor.cpp: - * plugins/vestige/vestige.cpp: - * plugins/vestige/vestige.h: - * plugins/sf2_player/artwork.png: - * plugins/midi_import/midi_import.cpp: - * include/note.h: - * include/mixer.h: - * include/instrument_track.h: - * include/sample_buffer.h: - * include/fx_mixer.h: - * include/piano.h: - * include/volume.h: - * include/midi_port.h: - * include/panning.h: - * src/midi/midi_client.cpp: - * src/midi/midi_port.cpp: - * src/midi/midi_alsa_seq.cpp: - * src/lib/sample_buffer.cpp: - * src/widgets/instrument_midi_io_view.cpp: - * src/tracks/instrument_track.cpp: - * src/core/preset_preview_play_handle.cpp: - * src/core/note_play_handle.cpp: - * src/core/mixer.cpp: - * src/core/piano_roll.cpp: - * src/core/instrument_functions.cpp: - * src/core/instrument_midi_io.cpp: - * src/core/note.cpp: - * src/core/piano.cpp: - * src/core/fx_mixer.cpp: - - merged note's tone and octave-property into one key-property which - makes us save calculations in a lot of places and also shrinks - sizes of XML-files - - renamed various note-related constants and enums to match current - coding-style - - * data/themes/default/effect_plugin.png: - improved effect-plugin-artwork made with Inkscape - -2008-03-22 Paul Giblock - - * plugins/organic/organic.cpp: - Removed debug printf - - * include/instrument_track.h: - * src/tracks/instrument_track.cpp: - - First version of cache for hidden instrumentTrackWindows - - Need to delete the cache and any remaining ITW's upon application close - - * src/core/lmms_style.cpp: - Applied border to more primatives. Still some known issues.. - - * src/core/main.cpp: - Just playing around with palette colors. - -2008-03-16 Paul Giblock - - * Makefile.am: - Added lmmsStyle to the Makefile again. - - * src/widgets/lcd_spinbox.cpp: - * include/lcd_spinbox.h: - - Added separate function for deriving control size - - Added property for side-margins - - Fixed memory leak with the pixmap - - Added yours truly to the copyright - - * src/core/lmms_style.cpp: - * include/lmms_style.h: - - Re-added lmmsStyle. I don't know why these files disappeared - - Improve appearance of sunken borders - - * plugins/sf2_player/sf2_player.cpp: - * plugins/sf2_player/sf2_player.h: - - Hopefully plugged some leaks caused by the leaky fluidSynth. It seems - to run fine, but only time will tell - - Added sfont file sharing between instances of sf2Player - - Added synthMutex to keep play() from freezing while we are recreating - the synth due to a file load. - - * src/widgets/combobox.cpp: - Draw styled border. - - * src/core/fx_mixer.cpp: - Improved drawing of LCD Channel numbers. - - * .: - * m4: - * buildtools: - * plugins: - * plugins/ladspa_effect: - * plugins/ladspa_effect/caps: - * plugins/ladspa_effect/caps/waves: - * plugins/ladspa_effect/caps/dsp: - * plugins/ladspa_effect/caps/dsp/tonestack: - * plugins/patman: - * plugins/lb302: - * plugins/organic: - * plugins/bass_booster: - * plugins/bit_invader: - * plugins/vst_effect: - * plugins/vibed: - * plugins/triple_oscillator: - * plugins/singerbot: - * plugins/live_tool: - * plugins/audio_file_processor: - * plugins/stk: - * plugins/stk/mallets: - * plugins/stk/voices: - * plugins/stk/voices/flute: - * plugins/stk/voices/resonate: - * plugins/stk/voices/include: - * plugins/stk/voices/wurley: - * plugins/stk/voices/src: - * plugins/stk/voices/percflute: - * plugins/stk/voices/rhodey: - * plugins/stk/voices/tubebell: - * plugins/stk/voices/bowed: - * plugins/stk/voices/clarinet: - * plugins/stk/voices/moog: - * plugins/stk/voices/metal: - * plugins/stk/voices/b3: - * plugins/stk/voices/blow_hole: - * plugins/stk/voices/brass: - * plugins/stk/voices/fmvoices: - * plugins/stk/voices/bandedwg: - * plugins/stk/voices/blow_bottle: - * plugins/plucked_string_synth: - * plugins/stereo_enhancer: - * plugins/sf2_player: - * plugins/vestige: - * plugins/vst_base: - * plugins/ladspa_browser: - * plugins/kicker: - * plugins/polyb302: - * plugins/flp_import: - * plugins/flp_import/unrtf: - * plugins/midi_import: - * include: - * src: - * src/audio: - * src/midi: - * src/lib: - * src/widgets: - * src/tracks: - * src/3rdparty: - * src/3rdparty/samplerate: - * src/core: - * data: - * data/locale: - * data/track_icons: - * data/midi-maps: - * data/samples: - * data/samples/effects: - * data/samples/stringsnpads: - * data/samples/basses: - * data/samples/shapes: - * data/samples/latin: - * data/samples/bassloopes: - * data/samples/drums: - * data/samples/instruments: - * data/samples/misc: - * data/samples/drumsynth: - * data/samples/drumsynth/effects: - * data/samples/drumsynth/misc_synth: - * data/samples/drumsynth/tr606: - * data/samples/drumsynth/cr78: - * data/samples/drumsynth/magnetboy: - * data/samples/drumsynth/tr808: - * data/samples/drumsynth/tr909: - * data/samples/drumsynth/misc_fx: - * data/samples/drumsynth/misc: - * data/samples/drumsynth/electro: - * data/samples/drumsynth/linn: - * data/samples/drumsynth/ferraro: - * data/samples/drumsynth/r_b: - * data/samples/drumsynth/misc_bass: - * data/samples/drumsynth/tr77: - * data/samples/drumsynth/misc_perc: - * data/samples/drumsynth/latin: - * data/samples/drumsynth/instrument: - * data/samples/drumsynth/misc_electro: - * data/samples/drumsynth/acoustic: - * data/samples/drumsynth/misc_hats: - * data/samples/drumsynth/farfisa: - * data/samples/drumsynth/jorgensohn: - * data/samples/drumsynth/cr8000: - * data/samples/drumsynth/misc_claps: - * data/samples/beats: - * data/presets: - * data/presets/AudioFileProcessor: - * data/presets/LB302: - * data/presets/Organic: - * data/presets/PluckedStringSynth: - * data/presets/VeSTige: - * data/presets/BitInvader: - * data/presets/Vibed: - * data/presets/TripleOscillator: - * data/themes: - * data/themes/blue_scene: - * data/themes/blue_scene/plugins: - * data/themes/default: - * data/projects: - * data/projects/covers: - * data/projects/recorded_loops: - * data/projects/cool_songs: - * data/projects/tutorials: - * data/projects/demos: - * data/projects/misc: - * data/projects/templates: - Added svn:ignore property for temporary buildtime files. Prevents - dozens of items showing in diff and status. The file - .svnignore describes which files are ignored. - - * .svnignore: - Can change this file to ignore more stuff. Reapply by running: - svn -R propset svn:ignore -F .svnignore . - -2008-03-16 Tobias Doerffel - - * src/widgets/visualization_widget.cpp: - improved signal-visualization and increased update-ratio from 20 to 40 - fps - - * include/mixer.h: - * src/core/mixer.cpp: - * src/core/song_editor.cpp: - * data/themes/default/auto_limit.png: - removed obsolete and broken auto-limit-feature - - * src/core/engine.cpp: - * src/core/fx_mixer.cpp: - proper cleanup of fxMixer and its view at exit - - * src/widgets/effect_view.cpp: - * data/themes/default/effect_plugin.png: - improved effect-view-artwork - -2008-03-15 Tobias Doerffel - - * src/core/mixer.cpp: - fixed peak-calculation for negative signal-values - - * include/effect_view.h: - * src/widgets/effect_view.cpp: - - fixed random crashes when removing effect-views - - improved painting of effect-view - - * plugins/ladspa_effect/ladspa_controls.cpp: - fixed LADSPA-controls which internally were not linked per default - although they should be - - * include/fx_mixer.h: - * include/effect_rack_view.h: - * include/effect_chain.h: - * src/widgets/effect_rack_view.cpp: - * src/tracks/instrument_track.cpp: - * src/core/effect_chain.cpp: - * src/core/song.cpp: - * src/core/fx_mixer.cpp: - implemented save- and load-functionality for FX-mixer - -2008-03-14 Tobias Doerffel - - * include/engine.h: - * include/mixer.h: - * include/fx_mixer.h: - * include/fader.h: - * include/effect_chain.h: - * src/audio/audio_port.cpp: - * src/widgets/fader.cpp: - * src/tracks/instrument_track.cpp: - * src/core/effect_chain.cpp: - * src/core/mixer.cpp: - * src/core/engine.cpp: - * src/core/fx_mixer.cpp: - * data/themes/default/fader_background.png: - * data/themes/default/fader_knob.png: - * data/themes/default/fader_leds.png: - * Makefile.am: - added initial FX-mixer implementation - not perfect and very usable - yet but the basics work so far :) - - * src/widgets/instrument_midi_io_view.cpp: - fixed segfault when using raw MIDI-client - -2008-03-08 Tobias Doerffel - - * data/locale/de.ts: - * data/locale/de.qm: - updated German localization - - * include/effect_board.h: - removed - - * include/fx_mixer.h: - * src/tracks/instrument_track.cpp: - added definition for upcoming FX-mixer - - * plugins/triple_oscillator/triple_oscillator.h: - * include/meter_dialog.h: - * include/instrument_functions.h: - * include/instrument_sound_shaping.h: - * include/instrument_function_views.h: - * include/bb_track.h: - * include/ladspa_control_view.h: - * include/instrument_sound_shaping_view.h: - * src/midi/midi_client.cpp: - * src/widgets/ladspa_control_view.cpp: - * src/widgets/instrument_sound_shaping_view.cpp: - * src/widgets/instrument_function_views.cpp: - * src/core/instrument_sound_shaping.cpp: - * src/core/instrument_functions.cpp: - * Makefile.am: - added missing Q_OBJECT-macros for views which made localizations not - work - - * plugins/sf2_player/logo.png: - replaced Kicker-logo with actual logo - - * src/core/track.cpp: - * include/track.h: - fixed crash when removing TCO via context-menu - - * include/instrument_track.h: - * src/core/file_browser.cpp: - made "Send to active instrument-track" work again - - * include/instrument_midi_io_view.h: - * include/instrument_midi_io.h: - * src/widgets/instrument_midi_io_view.cpp: - * src/core/instrument_midi_io.cpp: - made MIDI-port-menu work again - - * plugins/kicker/kicker.cpp: - set track for knobs in order to make them automatable - - * include/automatable_model_templates.h: - fixed missing automationPattern-initialization (i.e. - setFirstValue()-call) which made automation-editor not work properly - if no events were drawn so far - - * include/piano_roll.h: - * include/automation_editor.h: - * src/core/piano_roll.cpp: - * src/core/automation_editor.cpp: - made micro-draw-operations use 32-bit-ints instead of 16-bit-integers - for performing better on 32-bit-platforms - - * data/locale/de.qm: - * data/locale/de.ts: - * include/mv_base.h: - * src/widgets/combobox.cpp: - * src/widgets/knob.cpp: - * src/widgets/automatable_button.cpp: - * src/core/mv_base.cpp: - also connect model-signals with view when using default-constructed - model - fixes missing updates on things like button-groups when using - automation - -2008-03-07 Tobias Doerffel - - * plugins/vst_base/lvsl_server.cpp: - show window before determining X-Window-ID as newer WINE-versions do - not create X-windows before actually showing window - - * plugins/vst_base/lvsl_client.cpp: - * plugins/vst_base/lvsl_client.h: - properly insert VST-editor-window into QMdiArea - - * plugins/vestige/vestige.cpp: - * plugins/vestige/vestige.h: - M/V-split - - * plugins/kicker/kicker.h: - * include/sample_buffer.h: - * configure.in: - * src/lib/sample_buffer.cpp: - misc coding-style-fixes - - * include/sample_buffer.h: - * src/lib/sample_buffer.cpp: - made sampleBuffer reentrant so that several threads can use - sampleBuffer::play() simultanously - fixes crashes when using - AudioFileProcessor or Patman in multithreaded mode - -2008-03-06 Tobias Doerffel - - * plugins/sf2_player/sf2_player.h: - * plugins/sf2_player/sf2_player.cpp: - added m_runningNotes-array to track overlapping or edge-to-edge notes - and act accordingly - -2008-03-04 Tobias Doerffel - - * src/widgets/graph.cpp: - fixed compiler-warnings - - * include/automatable_model.h: - * include/graph.h: - * include/surround_area.h: - * src/audio/audio_file_device.cpp: - * src/audio/audio_alsa.cpp: - * src/audio/audio_oss.cpp: - * src/audio/audio_port.cpp: - * src/audio/audio_jack.cpp: - * src/midi/midi_alsa_seq.cpp: - * src/lib/project_journal.cpp: - * src/lib/mmp.cpp: - * src/lib/oscillator.cpp: - * src/widgets/ladspa_control_view.cpp: - * src/widgets/envelope_and_lfo_view.cpp: - * src/widgets/instrument_midi_io_view.cpp: - * src/widgets/lcd_spinbox.cpp: - * src/widgets/group_box.cpp: - * src/widgets/volume_knob.cpp: - * src/tracks/automation_track.cpp: - * src/tracks/bb_track.cpp: - * src/tracks/instrument_track.cpp: - * src/core/preset_preview_play_handle.cpp: - * src/core/track_container.cpp: - * src/core/effect_control_dialog.cpp: - * src/core/import_filter.cpp: - * src/core/setup_dialog.cpp: - * src/core/sample_play_handle.cpp: - * src/core/envelope_and_lfo_parameters.cpp: - * src/core/main.cpp: - * src/core/mixer.cpp: - * src/core/effect.cpp: - * src/core/instrument_midi_io.cpp: - * src/core/track.cpp: - * src/core/timeline.cpp: - * src/core/instrument.cpp: - * src/core/surround_area.cpp: - * src/core/effect_select_dialog.cpp: - * src/core/automation_editor.cpp: - * src/core/meter_dialog.cpp: - reduced dependencies from automatable_model_templates.h and fixed - according compiler-warnings - - * include/shared_object.h: - added mutex to protect reference-counter - -2008-03-03 Tobias Doerffel - - * src/core/piano_roll.cpp: - - fixed and improved painting of volume-lines - - fixed painting of note-detuning-dots - - fixed KEY_PRESSURE-events when changing volume of a note - - pass keyboard-events to piano-class if appropriate - - * include/piano.h: - * src/core/piano.cpp: - moved MIDI-event-code to piano-class - - * src/core/piano_roll.cpp: - * src/core/automation_editor.cpp: - set focus-policy in order to receive key-events - - * plugins/sf2_player/sf2_player.cpp: - - fixed open-file-dialog - - fixed order of member-variable-initialization - - * src/lib/sample_buffer.cpp: - added MP3-files to file-dialog-filter as they theoretically should be - supported through SDL_sound-library - - * src/core/mixer.cpp: - always process all note-play-handles of monophonic instruments by the - same thread serially - fixes problems with monophonic instruments - which rely on notes being processed in correct order - - * src/core/instrument_sound_shaping.cpp: - fixed out-of-range initial value of filter-frequency-model - - * src/core/main_window.cpp: - set directory before selecting file in QFileDialog - - * src/widgets/knob.cpp: - removed relative painting - fixes badly draw knobs in several cases - - * src/core/song_editor.cpp: - * src/core/track.cpp: - * src/widgets/knob.cpp: - * src/widgets/volume_knob.cpp: - made textFloat's work properly and displayed at correct position - - * src/widgets/text_float.cpp: - * include/text_float.h: - always use main-window as parent and make sure to be moved relative to - it, i.e. do not show outside of moved main-window - - * include/mmp.h: - * src/lib/mmp.cpp: - * src/core/song.cpp: - removed overwrite-check as in Qt4 QFileDialog does this on its own - - * include/midi_event_processor.h: - * include/instrument_track.h: - * src/tracks/instrument_track.cpp: - do not lock mixer and call notePlayHandle::noteOff() in - instrumentTrack::processInEvent() when processing monophonic - instruments in playNote() - fixes lockups in LB302 in multithreaded - mode - -2008-03-02 Tobias Doerffel - - * include/ladspa_control.h: - * src/widgets/ladspa_control_view.cpp: - * src/widgets/tempo_sync_knob.cpp: - fixed wrong integration of tempoSyncKnobModel - - * src/core/mv_base.cpp: - made dataChanged()->update() connection queued - -2008-03-01 Tobias Doerffel - - * plugins/patman/patman.cpp: - do not crash in patmanInstrument::playNote() when no file is set - - * include/ladspa_control.h: - * src/core/ladspa_control.cpp: - fixed missing tempoSyncKnobModel for not crashing when instantiating - LADSPA-plugins with time-knobs inside - - * src/lib/sample_buffer.cpp: - do not set global mixer lock in update() if no data has been set yet - - * plugins/patman/patman.cpp: - do not crash when loading settings where no file is set - - * plugins/triple_oscillator/triple_oscillator.cpp: - in saveSettings() fixed wrong integer-to-string-conversion which made - LMMS save broken files - -2008-02-29 Tobias Doerffel - - * src/widgets/text_float.cpp: - set Qt::ToolTip-window-flag in order to display correctly - some other - positioning code still needs to be fixed - - * include/import_filter.h: - fixed importFilter::readByte() to return proper integer instead of - signed char - makes import-filters finally work - - * plugins/midi_import/midi_import.cpp: - * plugins/flp_import/flp_import.cpp: - fixed parameter-list of lmms_plugin_main to work properly - -2008-02-29 Paul Giblock - - * include/lcd_spinbox.h: - * src/widgets/lcd_spinbox.cpp: - * data/themes/default/lcd_19red.png: - * data/themes/default/lcd_19green.png: - new non-QLcdSpinBox pixmap-based LCD spinbox - - * include/lmms_style.h: - * src/core/main.cpp: - * Makefile.am: - added lmmsStyle to aim for a consistant interface. Some Qt themes - make LMMS look really bad. Hopefully, over time, we can make a style - the unifies all our gui elements - - * src/core/track.cpp: - playing with alternating colors per tact - - * include/combobox.h: - * src/widgets/combobox.cpp: - * data/themes/default/combobox_bg.png: - * data/themes/default/combobox_arrow_selected.png: - - combobox now updates when incremented or decrementing. - - draw combo box with styled border, change arrow when pressed - -2008-02-28 Tobias Doerffel - - * src/core/plugin.cpp: - warn if LMMS-plugin does not have required _plugin_descriptor - field - -2008-02-28 Paul Giblock - - * plugins/sf2_player: - * plugins/sf2_player/patches_dialog.ui: - * plugins/sf2_player/logo.png: - * plugins/sf2_player/patches_dialog.cpp: - * plugins/sf2_player/sf2_player.cpp: - * plugins/sf2_player/Makefile.am: - * plugins/sf2_player/artwork.png: - * plugins/sf2_player/patches_dialog.h: - * plugins/sf2_player/sf2_player.h: - * plugins/Makefile.am: - * configure.in: - added beta of SoundFont player - -2008-02-28 Danny McRae - - * plugins/stk/Makefile.am: - removed voices from the default build - -2008-02-28 Tobias Doerffel - - * configure.in: - back in trunk - LMMS-MV is now default, so removed "mv"-suffix - -2008-02-27 Tobias Doerffel - - * plugins/ladspa_effect/caps/Compress.cc: - * plugins/ladspa_effect/caps/ToneStack.cc: - * plugins/ladspa_effect/caps/Compress.h: - * plugins/ladspa_effect/caps/ToneStack.h: - * plugins/ladspa_effect/caps/Roessler.h: - * plugins/ladspa_effect/caps/HRTF.cc: - * plugins/ladspa_effect/caps/HRTF.h: - * plugins/ladspa_effect/caps/basics.h: - * plugins/ladspa_effect/caps/Lorenz.cc: - * plugins/ladspa_effect/caps/Lorenz.h: - * plugins/ladspa_effect/caps/Amp.cc: - * plugins/ladspa_effect/caps/Amp.h: - * plugins/ladspa_effect/caps/Pan.h: - * plugins/ladspa_effect/caps/Phaser.cc: - * plugins/ladspa_effect/caps/White.h: - * plugins/ladspa_effect/caps/Preamp.cc: - * plugins/ladspa_effect/caps/Click.cc: - * plugins/ladspa_effect/caps/VCO.cc: - * plugins/ladspa_effect/caps/Clip.cc: - * plugins/ladspa_effect/caps/Click.h: - * plugins/ladspa_effect/caps/VCO.h: - * plugins/ladspa_effect/caps/ToneControls.cc: - * plugins/ladspa_effect/caps/Sin.cc: - * plugins/ladspa_effect/caps/Clip.h: - * plugins/ladspa_effect/caps/Sin.h: - * plugins/ladspa_effect/caps/Scape.cc: - * plugins/ladspa_effect/caps/Scape.h: - * plugins/ladspa_effect/caps/Roessler.cc: - * plugins/ladspa_effect/caps/interface.cc: - * plugins/ladspa_effect/caps/waves/click.h: - * plugins/ladspa_effect/caps/waves/money.h: - * plugins/ladspa_effect/caps/dsp/ToneStack.h: - * plugins/ladspa_effect/caps/dsp/LatFilt.h: - * plugins/ladspa_effect/caps/dsp/TDFII.h: - * plugins/ladspa_effect/caps/dsp/RMS.h: - * plugins/ladspa_effect/caps/dsp/OnePole.h: - * plugins/ladspa_effect/caps/dsp/tonestack/tables.h: - * plugins/ladspa_effect/caps/dsp/tonestack/vs_tab.h: - * plugins/ladspa_effect/caps/dsp/tonestack/ks_tab.h: - * plugins/ladspa_effect/caps/dsp/Eq.h: - * plugins/ladspa_effect/caps/dsp/BiQuad.h: - * plugins/ladspa_effect/caps/dsp/util.h: - * plugins/ladspa_effect/caps/dsp/FPTruncateMode.h: - * plugins/ladspa_effect/caps/dsp/TwelveAX7.h: - * plugins/ladspa_effect/caps/Chorus.cc: - * plugins/ladspa_effect/caps/Cabinet.cc: - * plugins/ladspa_effect/caps/Chorus.h: - * plugins/ladspa_effect/caps/Eq.cc: - * plugins/ladspa_effect/caps/Cabinet.h: - * plugins/ladspa_effect/caps/Eq.h: - * plugins/ladspa_effect/caps/README: - * plugins/ladspa_effect/caps/Pan.cc: - * plugins/ladspa_effect/caps/SweepVF.cc: - * plugins/ladspa_effect/caps/Descriptor.h: - * plugins/ladspa_effect/caps/White.cc: - * plugins/ladspa_effect/caps/SweepVF.h: - * plugins/ladspa_effect/caps/Phaser.h: - * plugins/ladspa_effect/caps/Reverb.cc: - * plugins/ladspa_effect/caps/Makefile.am: - * plugins/ladspa_effect/caps/Reverb.h: - integrated new version of CAPS and fixed miscompilation with GCC 4.3 - - * include/audio_port.h: - * src/audio/audio_port.cpp: - * src/core/mixer.cpp: - lock audioPort-buffers before writing them - - * include/export_project_dialog.h: - * src/core/song.cpp: - * src/core/main.cpp: - * src/core/export_project_dialog.cpp: - * src/core/engine.cpp: - * src/core/automation_pattern.cpp: - rendering from commandline is now done without creating main-window - and all the other UI-stuff - - * include/mixer.h: - * src/core/mixer.cpp: - distribute whole job-queue instead of single jobs and re-assign - unprocessed jobs to idle worker-threads - improves multi-threading - behaviour a lot - -2008-02-26 Tobias Doerffel - - * include/mixer.h: - * src/core/mixer.cpp: - initial support for parallel rendering via worker-threads - far from - being perfect (especially with small mixer-period-sizes) but seems to - help even on a DualCore machine - -2008-02-25 Tobias Doerffel - - * plugins/ladspa_browser/ladspa_browser.cpp: - * plugins/ladspa_browser/ladspa_browser.h: - incorporated recent API-changes - - * include/effect.h: - * include/instrument_functions.h: - * include/envelope_and_lfo_parameters.h: - * include/tempo_sync_knob.h: - * src/widgets/envelope_and_lfo_view.cpp: - * src/widgets/tempo_sync_knob.cpp: - * src/core/envelope_and_lfo_parameters.cpp: - * src/core/effect.cpp: - * src/core/instrument_functions.cpp: - splitted tempoSyncKnob into tempoSyncKnobModel and tempoSyncKnob - - * include/meter_dialog.h: - * src/core/meter_dialog.cpp: - splitted into meterModel and meterDialog - - * plugins/flp_import/flp_import.cpp: - * include/instrument_track.h: - * include/piano.h: - * src/tracks/instrument_track.cpp: - * src/core/piano_roll.cpp: - * src/core/piano.cpp: - * Makefile.am: - renamed piano_widget.{h,cpp} to piano.{h,cpp} - - * include/instrument_view.h: - * include/instrument_track.h: - * src/widgets/instrument_function_views.cpp: - * src/widgets/group_box.cpp: - * src/widgets/automatable_button.cpp: - * src/tracks/instrument_track.cpp: - fixed various crashes when removing instrument-track with visible - instrument-track-window or loading another instrument/preset - - * src/core/instrument.cpp: - * include/oscillator.h: - cleanups - - * src/lib/mmp.cpp: - fixed tag-renaming-loops - - * include/automatable_model_templates.h: - instantiate automation-pattern before loading settings of it - fixes - crashes when loading projects with automation inside - - * include/instrument_track.h: - * src/tracks/instrument_track.cpp: - track-window-creation on-demand - makes loading/unloading projects - ultra-fast!! - - * plugins/triple_oscillator/triple_oscillator.cpp: - fixed wrong index for saving/restoring modulation-algo-settings - - now projects sound like they did in pre-MV - - * include/automation_editor.h: - * include/combobox.h: - * src/core/song.cpp: - * src/core/piano_roll.cpp: - * src/core/track.cpp: - * src/core/automation_editor.cpp: - fixed zooming-comboboxes in automation-editor and header-dependencies - - * src/widgets/combobox.cpp: - update() after wheelEvent - - * include/tool.h: - * src/core/tool.cpp: - * plugins/live_tool/live_tool.h: - * plugins/live_tool/live_tool.cpp: - made live-tool work after M/V-split - - * include/track.h: - * src/core/track.cpp: - - connect track's m_mutedModel to m_muteBtn of trackOperationsWidget - - set track for m_mutedModel - -2008-02-24 Paul Giblock - - * plugins/bit_invader/bit_invader.cpp: - * plugins/bit_invader/bit_invader.h: - * plugins/bit_invader/Makefile.am: - M/V-split of Bit Invader instrument. - - * plugins/vibed/nine_button_selector.cpp: - Removed debug output - - * src/widgets/graph.cpp: - * include/graph.h: - Fixed some graph issues. Still more left to do - -2008-02-22 Paul Giblock - - * plugins/vibed/vibed.cpp: - * plugins/vibed/vibed.h: - * plugins/vibed/string_container.cpp: - * plugins/vibed/string_container.h: - * plugins/vibed/nine_button_selector.cpp: - * plugins/vibed/nine_button_selector.h: - * plugins/vibed/Makefile.am: - M/V-split of Vibed-instrument. Lacks user-specified wave, to be added on - my next commit. Also has an audio output bug, certain notes make weird - noises - - * plugins/stereo_enhancer/stereoenhancer_controls.cpp: - * plugins/stereo_enhancer/stereoenhancer_controls.h: - * plugins/stereo_enhancer/stereo_enhancer.cpp: - * plugins/stereo_enhancer/stereo_enhancer.h: - * plugins/stereo_enhancer/stereoenhancer_control_dialog.cpp: - * plugins/stereo_enhancer/stereoenhancer_control_dialog.h: - * plugins/stereo_enhancer/Makefile.am: - M/V-split of Stereo-enhancer effect. - - * src/core/piano_roll.cpp: - Changed quantization to change on the gridlines, instead of nearest-point - in the middle. Made this change here, because MIDI events should still be - quantized to nearest-point (I think) - - * src/widgets/graph.cpp: - * include/graph.h: - * Makefile.am: - Split graph and moved it to the shared widgets. Supports variable ranges, - sample-lengths, smoothing, normalizing, and is antialiased - -2008-02-18 Tobias Doerffel - - * plugins/ladspa_effect/ladspa_subplugin_features.h: - * plugins/ladspa_effect/ladspa_subplugin_features.cpp: - * plugins/vst_effect/vst_control_dialog.h: - * plugins/audio_file_processor/audio_file_processor.cpp: - * plugins/audio_file_processor/audio_file_processor.h: - * include/plugin.h: - * include/audio_file_device.h: - * include/export.h: - * include/export_project_dialog.h: - * src/core/song.cpp: - * src/core/export_project_dialog.cpp: - coding-style improvements - - * src/core/main_window.cpp: - made song-export work again - - * plugins/patman/patman.cpp: - * plugins/patman/patman.h: - M/V-split of Patman-instrument - -2008-02-18 Tobias Doerffel - - * plugins/flp_import/flp_import.h: - * plugins/flp_import/flp_import.cpp: - * plugins/midi_import/midi_import.h: - * plugins/midi_import/midi_import.cpp: - * include/instrument_functions.h: - * include/song.h: - * include/envelope_and_lfo_parameters.h: - * include/instrument_sound_shaping.h: - made MIDI- and FLP-import-filter work - -2008-02-15 Paul Giblock - * plugins/plucked_string_synth/plucked_string_synth.cpp: - * plugins/plucked_string_synth/plucked_string_synth.h: - * plugins/organic/organic.cpp: - * plugins/organic/organic.h: - - Updated some instruments for M/V. Unfortunately one is an old version - and the other is obsoleted - -2008-02-16 Tobias Doerffel - - * plugins/ladspa_effect/ladspa_controls.cpp: - * plugins/audio_file_processor/audio_file_processor.cpp: - * plugins/stk/Makefile.am: - * include/mmp.h: - * include/instrument_midi_io_view.h: - * include/track.h: - * include/engine.h: - * include/name_label.h: - * include/instrument_track.h: - * include/instrument_functions.h: - * include/piano_widget.h: - * include/song.h: - * include/pattern.h: - * include/file_browser.h: - * include/envelope_and_lfo_parameters.h: - * include/envelope_and_lfo_view.h: - * include/instrument_sound_shaping.h: - * include/instrument_function_views.h: - * include/instrument_midi_io.h: - * include/bb_track.h: - * include/song_editor.h: - * include/dummy_instrument.h: - * include/journalling_object.h: - * include/sample_track.h: - * include/timeline.h: - * include/main_window.h: - * include/mv_base.h: - * include/bb_editor.h: - * include/arp_and_chords_tab_widget.h: - * include/automation_track.h: - * include/track_container.h: - * include/instrument_sound_shaping_view.h: - * configure.in: - * src/midi/midi_alsa_seq.cpp: - * src/lib/project_journal.cpp: - * src/lib/mmp.cpp: - * src/lib/journalling_object.cpp: - * src/widgets/instrument_sound_shaping_view.cpp: - * src/widgets/envelope_and_lfo_view.cpp: - * src/widgets/instrument_function_views.cpp: - * src/widgets/instrument_midi_io_view.cpp: - * src/widgets/project_notes.cpp: - * src/widgets/effect_rack_view.cpp: - * src/widgets/automatable_button.cpp: - * src/widgets/tempo_sync_knob.cpp: - * src/tracks/automation_track.cpp: - * src/tracks/sample_track.cpp: - * src/tracks/bb_track.cpp: - * src/tracks/instrument_track.cpp: - * src/tracks/pattern.cpp: - * src/core/arp_and_chords_tab_widget.cpp: - * src/core/preset_preview_play_handle.cpp: - * src/core/note_play_handle.cpp: - * src/core/track_container.cpp: - * src/core/song.cpp: - * src/core/import_filter.cpp: - * src/core/file_browser.cpp: - * src/core/envelope_and_lfo_parameters.cpp: - * src/core/mixer.cpp: - * src/core/main.cpp: - * src/core/export_project_dialog.cpp: - * src/core/instrument_sound_shaping.cpp: - * src/core/piano_roll.cpp: - * src/core/instrument_functions.cpp: - * src/core/instrument_midi_io.cpp: - * src/core/track.cpp: - * src/core/engine.cpp: - * src/core/timeline.cpp: - * src/core/instrument.cpp: - * src/core/piano_widget.cpp: - * src/core/main_window.cpp: - * src/core/song_editor.cpp: - * src/core/mv_base.cpp: - * src/core/automation_pattern.cpp: - * src/core/name_label.cpp: - * src/core/automation_editor.cpp: - * src/core/bb_editor.cpp: - * Makefile.am: - finally splitted rest of LMMS, i.e. tracks, track-containers, - track-content-objects, whole instrument-track/instrument-track-window - and so on - still a bit unstable but I'm sure we'll manage to get this - one very stable! - - diffstat says: - 79 files changed, 8019 insertions(+), 6226 deletions(-) - -2008-02-01 Danny McRae - - * Makefile.am: - * src/tracks/instrument_track.cpp: - * src/core/note_play_handle.cpp: - * src/core/envelope_and_lfo_parameters.cpp: - * src/core/mixer.cpp: - * src/core/instrument_sound_shaping.cpp: - * src/core/instrument_midi_io.cpp: - * src/core/song_editor.cpp: - Some of the files have been renamed, so I updated the - include references to get the build to work again. - - * include/basic_filters.h: - Added the ability to clear the filter taps to support - a LPF where the threshold is set by the velocity of - the note. - - * configure.in: - * plugins/stk/voices/resonate/resonate_processor.h: - * plugins/stk/voices/voices/resonate/resonate_instrument.h: - * plugins/stk/voices/voices/resonate/resonate_model.cpp: - * plugins/stk/voices/voices/resonate/resonate_instrument_view.cpp: - * plugins/stk/voices/voices/resonate/artwork.png: - * plugins/stk/voices/voices/resonate/resonate_processor.cpp: - * plugins/stk/voices/voices/resonate/resonate_instrument_view.h: - * plugins/stk/voices/voices/resonate/resonate_instrument.cpp: - * plugins/stk/voices/voices/resonate/logo.png: - * plugins/stk/voices/voices/resonate/resonate_model.h: - * plugins/stk/voices/voices/resonate/Makefile.am: - * plugins/stk/voices/voices/flute/artwork.png: - * plugins/stk/voices/voices/flute/flute_processor.cpp: - * plugins/stk/voices/voices/flute/flute_instrument_view.h: - * plugins/stk/voices/voices/flute/flute_model.h: - * plugins/stk/voices/voices/flute/flute_processor.h: - * plugins/stk/voices/voices/flute/flute_model.cpp: - * plugins/stk/voices/voices/flute/logo.png: - * plugins/stk/voices/voices/flute/flute_instrument.h: - * plugins/stk/voices/voices/flute/Makefile.am: - * plugins/stk/voices/voices/flute/flute_instrument_view.cpp: - * plugins/stk/voices/voices/flute/flute_instrument.cpp: - * plugins/stk/voices/voices/metal/metal_processor.h: - * plugins/stk/voices/voices/metal/metal_instrument.cpp: - * plugins/stk/voices/voices/metal/metal_processor.cpp: - * plugins/stk/voices/voices/metal/artwork.png: - * plugins/stk/voices/voices/metal/metal_instrument_view.cpp: - * plugins/stk/voices/voices/metal/metal_instrument.h: - * plugins/stk/voices/voices/metal/logo.png: - * plugins/stk/voices/voices/metal/metal_instrument_view.h: - * plugins/stk/voices/voices/metal/metal_model.cpp: - * plugins/stk/voices/voices/metal/Makefile.am: - * plugins/stk/voices/voices/metal/metal_model.h: - * plugins/stk/voices/voices/fmvoices/fmvoices_instrument.cpp: - * plugins/stk/voices/voices/fmvoices/fmvoices_processor.h: - * plugins/stk/voices/voices/fmvoices/fmvoices_instrument.h: - * plugins/stk/voices/voices/fmvoices/artwork.png: - * plugins/stk/voices/voices/fmvoices/fmvoices_instrument_view.h: - * plugins/stk/voices/voices/fmvoices/fmvoices_instrument_view.cpp: - * plugins/stk/voices/voices/fmvoices/logo.png: - * plugins/stk/voices/voices/fmvoices/fmvoices_processor.cpp: - * plugins/stk/voices/voices/fmvoices/fmvoices_model.cpp: - * plugins/stk/voices/voices/fmvoices/fmvoices_model.h: - * plugins/stk/voices/voices/fmvoices/Makefile.am: - * plugins/stk/voices/voices/moog/moog_instrument_view.h: - * plugins/stk/voices/voices/moog/moog_instrument_view.cpp: - * plugins/stk/voices/voices/moog/moog_model.cpp: - * plugins/stk/voices/voices/moog/moog_processor.h: - * plugins/stk/voices/voices/moog/artwork.png: - * plugins/stk/voices/voices/moog/logo.png: - * plugins/stk/voices/voices/moog/moog_model.h: - * plugins/stk/voices/voices/moog/moog_instrument.h: - * plugins/stk/voices/voices/moog/moog_instrument.cpp: - * plugins/stk/voices/voices/moog/moog_processor.cpp: - * plugins/stk/voices/voices/moog/Makefile.am: - * plugins/stk/voices/voices/include/stk_instrument_view.h: - * plugins/stk/voices/voices/include/stk_voice.h: - * plugins/stk/voices/voices/include/stk_instrument.h: - * plugins/stk/voices/voices/include/stk_model.h: - * plugins/stk/voices/voices/include/stk_processor.h: - * plugins/stk/voices/voices/wurley/wurley_instrument.h: - * plugins/stk/voices/voices/wurley/wurley_instrument_view.cpp: - * plugins/stk/voices/voices/wurley/wurley_model.cpp: - * plugins/stk/voices/voices/wurley/wurley_instrument_view.h: - * plugins/stk/voices/voices/wurley/wurley_model.h: - * plugins/stk/voices/voices/wurley/artwork.png: - * plugins/stk/voices/voices/wurley/wurley_processor.h: - * plugins/stk/voices/voices/wurley/logo.png: - * plugins/stk/voices/voices/wurley/Makefile.am: - * plugins/stk/voices/voices/wurley/wurley_processor.cpp: - * plugins/stk/voices/voices/wurley/wurley_instrument.cpp: - * plugins/stk/voices/voices/bowed/bowed_instrument.cpp: - * plugins/stk/voices/voices/bowed/bowed_model.cpp: - * plugins/stk/voices/voices/bowed/bowed_instrument_view.cpp: - * plugins/stk/voices/voices/bowed/bowed_model.h: - * plugins/stk/voices/voices/bowed/bowed_processor.h: - * plugins/stk/voices/voices/bowed/artwork.png: - * plugins/stk/voices/voices/bowed/bowed_processor.cpp: - * plugins/stk/voices/voices/bowed/logo.png: - * plugins/stk/voices/voices/bowed/bowed_instrument_view.h: - * plugins/stk/voices/voices/bowed/Makefile.am: - * plugins/stk/voices/voices/bowed/bowed_instrument.h: - * plugins/stk/voices/voices/blow_hole/blow_hole_instrument.cpp: - * plugins/stk/voices/voices/blow_hole/blow_hole_instrument_view.cpp: - * plugins/stk/voices/voices/blow_hole/artwork.png: - * plugins/stk/voices/voices/blow_hole/blow_hole_model.h: - * plugins/stk/voices/voices/blow_hole/blow_hole_processor.h: - * plugins/stk/voices/voices/blow_hole/logo.png: - * plugins/stk/voices/voices/blow_hole/blow_hole_processor.cpp: - * plugins/stk/voices/voices/blow_hole/blow_hole_instrument_view.h: - * plugins/stk/voices/voices/blow_hole/blow_hole_model.cpp: - * plugins/stk/voices/voices/blow_hole/Makefile.am: - * plugins/stk/voices/voices/blow_hole/blow_hole_instrument.h: - * plugins/stk/voices/voices/rhodey/rhodey_instrument_view.h: - * plugins/stk/voices/voices/rhodey/rhodey_processor.h: - * plugins/stk/voices/voices/rhodey/rhodey_processor.cpp: - * plugins/stk/voices/voices/rhodey/rhodey_instrument_view.cpp: - * plugins/stk/voices/voices/rhodey/artwork.png: - * plugins/stk/voices/voices/rhodey/rhodey_model.cpp: - * plugins/stk/voices/voices/rhodey/rhodey_model.h: - * plugins/stk/voices/voices/rhodey/rhodey_instrument.h: - * plugins/stk/voices/voices/rhodey/logo.png: - * plugins/stk/voices/voices/rhodey/rhodey_instrument.cpp: - * plugins/stk/voices/voices/rhodey/Makefile.am: - * plugins/stk/voices/voices/tubebell/tubebell_processor.cpp: - * plugins/stk/voices/voices/tubebell/tubebell_instrument_view.h: - * plugins/stk/voices/voices/tubebell/artwork.png: - * plugins/stk/voices/voices/tubebell/tubebell_instrument.h: - * plugins/stk/voices/voices/tubebell/tubebell_instrument.cpp: - * plugins/stk/voices/voices/tubebell/tubebell_model.h: - * plugins/stk/voices/voices/tubebell/logo.png: - * plugins/stk/voices/voices/tubebell/tubebell_model.cpp: - * plugins/stk/voices/voices/tubebell/tubebell_instrument_view.cpp: - * plugins/stk/voices/voices/tubebell/Makefile.am: - * plugins/stk/voices/voices/tubebell/tubebell_processor.h: - * plugins/stk/voices/voices/clarinet/clarinet_instrument.cpp: - * plugins/stk/voices/voices/clarinet/artwork.png: - * plugins/stk/voices/voices/clarinet/clarinet_processor.h: - * plugins/stk/voices/voices/clarinet/clarinet_processor.cpp: - * plugins/stk/voices/voices/clarinet/clarinet_instrument.h: - * plugins/stk/voices/voices/clarinet/clarinet_model.cpp: - * plugins/stk/voices/voices/clarinet/logo.png: - * plugins/stk/voices/voices/clarinet/clarinet_instrument_view.cpp: - * plugins/stk/voices/voices/clarinet/clarinet_model.h: - * plugins/stk/voices/voices/clarinet/Makefile.am: - * plugins/stk/voices/voices/clarinet/clarinet_instrument_view.h: - * plugins/stk/voices/voices/b3/b3_instrument.cpp: - * plugins/stk/voices/voices/b3/b3_model.h: - * plugins/stk/voices/voices/b3/b3_model.cpp: - * plugins/stk/voices/voices/b3/artwork.png: - * plugins/stk/voices/voices/b3/b3_instrument_view.h: - * plugins/stk/voices/voices/b3/logo.png: - * plugins/stk/voices/voices/b3/b3_processor.h: - * plugins/stk/voices/voices/b3/b3_instrument_view.cpp: - * plugins/stk/voices/voices/b3/b3_instrument.h: - * plugins/stk/voices/voices/b3/b3_processor.cpp: - * plugins/stk/voices/voices/b3/Makefile.am: - * plugins/stk/voices/voices/src/stk_model.cpp: - * plugins/stk/voices/voices/percflute/percflute_instrument.h: - * plugins/stk/voices/voices/percflute/percflute_model.h: - * plugins/stk/voices/voices/percflute/percflute_instrument_view.h: - * plugins/stk/voices/voices/percflute/percflute_processor.cpp: - * plugins/stk/voices/voices/percflute/percflute_processor.h: - * plugins/stk/voices/voices/percflute/artwork.png: - * plugins/stk/voices/voices/percflute/percflute_instrument_view.cpp: - * plugins/stk/voices/voices/percflute/percflute_instrument.cpp: - * plugins/stk/voices/voices/percflute/logo.png: - * plugins/stk/voices/voices/percflute/percflute_model.cpp: - * plugins/stk/voices/voices/percflute/Makefile.am: - * plugins/stk/voices/voices/blow_bottle/blow_bottle_processor.cpp: - * plugins/stk/voices/voices/blow_bottle/blow_bottle_model.h: - * plugins/stk/voices/voices/blow_bottle/blow_bottle_model.cpp: - * plugins/stk/voices/voices/blow_bottle/artwork.png: - * plugins/stk/voices/voices/blow_bottle/blow_bottle_processor.h: - * plugins/stk/voices/voices/blow_bottle/blow_bottle_instrument.h: - * plugins/stk/voices/voices/blow_bottle/blow_bottle_instrument_view.cpp: - * plugins/stk/voices/voices/blow_bottle/logo.png: - * plugins/stk/voices/voices/blow_bottle/blow_bottle_instrument_view.h: - * plugins/stk/voices/voices/blow_bottle/blow_bottle_instrument.cpp: - * plugins/stk/voices/voices/blow_bottle/Makefile.am: - * plugins/stk/voices/voices/Makefile.am: - * plugins/stk/voices/voices/brass/brass_instrument_view.h: - * plugins/stk/voices/voices/brass/brass_instrument.cpp: - * plugins/stk/voices/voices/brass/brass_processor.h: - * plugins/stk/voices/voices/brass/brass_processor.cpp: - * plugins/stk/voices/voices/brass/brass_instrument_view.cpp: - * plugins/stk/voices/voices/brass/artwork.png: - * plugins/stk/voices/voices/brass/brass_instrument.h: - * plugins/stk/voices/voices/brass/logo.png: - * plugins/stk/voices/voices/brass/brass_model.cpp: - * plugins/stk/voices/voices/brass/brass_model.h: - * plugins/stk/voices/voices/brass/Makefile.am: - * plugins/stk/voices/voices/bandedwg/bandedwg_processor.h: - * plugins/stk/voices/voices/bandedwg/bandedwg_instrument_view.h: - * plugins/stk/voices/voices/bandedwg/bandedwg_processor.cpp: - * plugins/stk/voices/voices/bandedwg/artwork.png: - * plugins/stk/voices/voices/bandedwg/bandedwg_model.h: - * plugins/stk/voices/voices/bandedwg/bandedwg_instrument.h: - * plugins/stk/voices/voices/bandedwg/bandedwg_instrument.cpp: - * plugins/stk/voices/voices/bandedwg/bandedwg_instrument_view.cpp: - * plugins/stk/voices/voices/bandedwg/logo.png: - * plugins/stk/voices/voices/bandedwg/bandedwg_model.cpp: - * plugins/stk/voices/voices/bandedwg/Makefile.am: - Started working on a multitimbral instrument that uses all of the - voices available in STK. Need to work out the differences in - level among the voices and figure out what the controls actually - do. Simplist way to do that was to build them as individual - instruments first. The models, views, and processors should be - reusable for the larger instrument. Except for bandedwg and - flute they all work, so if you're curious, add "voices" to the - Makefile.am in plugins/stk to get them to build. - -2007-01-30 Paul Giblock - - * plugins/organic/organic.cpp: - * plugins/organic/organic.h: - Began split on Organic. But doesn't show in instrument list - - * plugins/lb302/lb302.cpp: - Fixed comments - -2008-01-28 Paul Giblock - - * plugins/lb302/lb302.cpp: - * plugins/lb302/lb302.h: - finished LB302 M/V-split. however, more changes can be made to meet - the coding guidelines. Let's save this job for LB303 - - * include/automatable_model.h: - cleaned up code for boolModel - -2008-01-26 Tobias Doerffel - - * src/widgets/automatable_button.cpp: - - call updateButtons() after model-change - - use model()->value() rather than value() - - * plugins/triple_oscillator/triple_oscillator.cpp: - fixed upper boundaries for wave-shape- and modulation-algo-models - -2008-01-26 Tobias Doerffel - - * plugins/triple_oscillator/triple_oscillator.h: - * plugins/triple_oscillator/triple_oscillator.cpp: - initial M/V-split - lots of debugging and cleanups pending, however - basically works :) - - * include/transformable_auto_model.h: - added transformableAutoModel-class which is not used yet but might be - helpful in some cases in the future - - * include/oscillator.h: - * src/lib/oscillator.cpp: - - changed coding-style for enum-constants - - use model for external wave-shape- and modulation-algo-parameter - - * src/widgets/ladspa_control_view.cpp: - added missing header - - * src/widgets/automatable_button.cpp: - update buttons after changing button-group's value - -2008-01-24 Tobias Doerffel - - * include/types.h: - replaced own buggy valueRanges-calculations by numeric_limits-class - - * plugins/lb302/lb302.cpp: - fixed broken plugin-entry-point - - * configure.in: - * plugins/bass_booster/bass_booster.cpp: - * plugins/bass_booster/bassbooster_controls.cpp: - * plugins/stk/mallets/mallets.cpp: - * include/automatable_model.h: - * include/journalling_object.h: - * src/audio/audio_file_device.cpp: - * src/audio/audio_alsa.cpp: - * src/audio/audio_oss.cpp: - * src/audio/audio_port.cpp: - * src/audio/audio_jack.cpp: - * src/midi/midi_alsa_seq.cpp: - * src/lib/project_journal.cpp: - * src/lib/mmp.cpp: - * src/lib/drumsynth.cpp: - * src/widgets/group_box.cpp: - * src/tracks/instrument_track.cpp: - * src/core/effect_chain.cpp: - * src/core/preset_preview_play_handle.cpp: - * src/core/effect_control_dialog.cpp: - * src/core/setup_dialog.cpp: - * src/core/main.cpp: - * src/core/mixer.cpp: - * src/core/effect.cpp: - * src/core/timeline.cpp: - * src/core/effect_select_dialog.cpp: - * src/core/automation_editor.cpp: - * src/core/meter_dialog.cpp: - various fixes for GCC 4.3 - - * README: - cleanups / fixes - - * include/automatable_model.h: - cleanups / coding-style fixes - -2008-01-24 Paul Giblock - - * include/automatable_model.h: - * src/widgets/knob.cpp: - * src/core/arp_and_chords_tab_widget.cpp: - * src/core/effect.cpp: - * src/core/ladspa_control.cpp: - * src/core/envelope_tab_widget.cpp: - * plugins/audio_file_processor/audio_file_processor.cpp: - add boolModel subclass in order to simplify the constructor - - * plugins/lb302/lb302.cpp: - * plugins/lb302/lb302.h: - split lb302 for M/V. However, lmms_plugin_main() receives null data, - which means the instrumentTrack cannot be set.. - -2008-01-18 Tobias Doerffel - - * src/core/effect_chain.cpp: - * src/lib/mmp.cpp: - added upgrade-path in order to properly load projects not using the - new effect-data-structure - - * plugins/bass_booster/bass_booster.h: - * plugins/ladspa_effect/ladspa_effect.h: - * plugins/vst_effect/vst_effect.h: - removed nodeName()-function as effects must not overload it (they have - descriptors with they unique name in it) - - * include/effect_rack_view.h: - * src/widgets/effect_rack_view.cpp: - renamed updateView() to update() in order to also track - dataChanged()-signals of model without an additional connection - - * src/widgets/combobox.cpp: - fixed painting - - * src/widgets/ladspa_control_view.cpp: - * plugins/ladspa_effect/ladspa_control_dialog.cpp: - made control-layouting work again (did not work at all after Qt4-port) - - * src/core/ladspa_control.cpp: - added initialization for m_link-member-variable, optimized - linkEnabledModel-initialization - - * src/widgets/knob.cpp: - * plugins/ladspa_effect/ladspa_controls.cpp: - coding style fixes - - * Makefile.am: - moved ladspa_control_view.cpp to src/widgets/ - -2008-01-17 Tobias Doerffel - - * plugins/ladspa_effect/Makefile.am: - * plugins/ladspa_effect/ladspa_effect.h: - * plugins/ladspa_effect/ladspa_effect.cpp: - * plugins/ladspa_effect/ladspa_controls.h: - * plugins/ladspa_effect/ladspa_controls.cpp: - * plugins/ladspa_effect/ladspa_control_dialog.h: - * plugins/ladspa_effect/ladspa_control_dialog.cpp: - made work again after all the changes in the last days... - - * Makefile.am: - * include/ladspa_control.h: - * include/ladspa_control_view.h: - * src/core/ladspa_control.cpp: - * src/core/ladspa_control_view.cpp: - splitted ladspaControl-class into ladspaControl and ladspaControlView - -2008-01-14 Tobias Doerffel - - * plugins/bass_booster/bassbooster_controls.h: - * plugins/bass_booster/bass_booster.cpp: - * plugins/bass_booster/bassbooster_control_dialog.cpp: - * plugins/bass_booster/Makefile.am: - * plugins/bass_booster/bassbooster_controls.cpp: - * plugins/bass_booster/bass_booster.h: - * plugins/bass_booster/bassbooster_control_dialog.h: - made work with M/V as well as rewritten effect-framework - - * include/effect.h: - * include/effect_control_dialog.h: - * include/dummy_effect.h: - * include/effect_controls.h: - * src/widgets/effect_view.cpp: - * src/core/effect_control_dialog.cpp: - * src/core/effect.cpp: - * Makefile.am: - split off effectControlDialog into effectControlDialog and - effectControls - - * src/core/song_editor.cpp: - also connect to dataUnchanged()-signal of tempo-model in order to - setup everything correct by connected slot - - * configure.in: - - removed single-source-compile-feature - - made FASTCALL-usage optional for the time being - - * data/locale/de.ts: - * data/locale/de.qm: - updated German localization - -2008-01-09 Paul Giblock - - * acinclude.m4: - use pkg-config for more accurate Qt directory detection - -2008-01-06 Tobias Doerffel - - * plugins/ladspa_effect/ladspa_effect.cpp: - * plugins/ladspa_effect/ladspa_effect.h: - * plugins/bass_booster/bass_booster.cpp: - * plugins/bass_booster/bass_booster.h: - * plugins/vst_effect/vst_effect.cpp: - changes for making effects work again with new effect-framework - - * plugins/audio_file_processor/audio_file_processor.cpp: - * plugins/audio_file_processor/audio_file_processor.h: - * plugins/stk/mallets/mallets.cpp: - * plugins/stk/mallets/mallets.h: - * plugins/ladspa_browser/ladspa_browser.cpp: - * plugins/ladspa_browser/ladspa_browser.h: - * plugins/kicker/kicker.cpp: - * plugins/kicker/kicker.h: - * include/dummy_plugin.h: - * include/instrument.h: - * include/plugin.h: - * include/tool.h: - * include/main_window.h: - * include/mv_base.h: - * include/dummy_instrument.h: - * src/core/plugin.cpp: - * src/core/tool.cpp: - * src/core/import_filter.cpp: - * src/core/instrument.cpp: - * src/core/surround_area.cpp: - * src/core/main_window.cpp: - moved createView()-functionality from instrument- to plugin-class - - * include/tab_widget.h: - code-formatting stuff - - * include/audio_port.h: - * include/instrument_track.h: - * include/sample_track.h: - * src/audio/audio_port.cpp: - * src/core/sample_play_handle.cpp: - * src/tracks/instrument_track.cpp: - * src/tracks/sample_track.cpp: - integrated new effect-framework - - * Makefile.am: - * include/dummy_effect.h: - * include/effect.h: - * include/effect_chain.h: - * include/effect_control_dialog.h: - * include/effect_label.h: - * include/effect_rack_view.h: - * include/effect_select_dialog.h: - * include/effect_tab_widget.h: - * include/effect_view.h: - * src/core/effect.cpp: - * src/core/effect_chain.cpp: - * src/core/effect_control_dialog.cpp: - * src/core/effect_select_dialog.cpp: - * src/core/effect_tab_widget.cpp: - * src/widgets/effect_label.cpp: - * src/widgets/effect_view.cpp: - * src/widgets/effect_rack_view.cpp: - rewrote view-component of effect-framework and removed effectTabWidget - - * include/automatable_model.h: - * src/widgets/automatable_slider.cpp: - * src/widgets/group_box.cpp: - * src/widgets/lcd_spinbox.cpp: - * src/widgets/combobox.cpp: - * src/widgets/knob.cpp: - * src/widgets/automatable_button.cpp: - pass model-pointer to modelView-constructor - -2008-01-05 Tobias Doerffel - - * plugins/organic/organic.cpp: - * plugins/bit_invader/bit_invader.cpp: - * plugins/vibed/vibed.cpp: - * plugins/triple_oscillator/triple_oscillator.cpp: - * plugins/stk/mallets/mallets.cpp: - make sure, pluginData-pointer is always initialized in playNote() - - * src/core/envelope_and_lfo_widget.cpp: - simple range-checking - -2008-01-04 Tobias Doerffel - - * plugins/ladspa_effect/ladspa_effect.cpp: - * plugins/ladspa_effect/ladspa_control_dialog.cpp: - * plugins/ladspa_effect/ladspa_control_dialog.h: - minor fixes in order to compile again with lately changed effect-API - - * src/core/effect_tab_widget.cpp: - * src/lib/mmp.cpp: - renabled XML-attribute "fxdisabled" to "fxenabled" - - * src/core/effect_tab_widget.cpp: - * include/effect_tab_widget.h: - made effects working again by using effect-chain's m_enabledModel as - model for effect-groupbox - - * include/effect_chain.h: - * src/core/effect_chain.cpp: - * src/core/effect_tab_widget.cpp: - removed bypassed-property and introduced m_enabledModel - - * include/effect.h: - - made lot of methods const - - renamed enabled() to isEnabled() - -2008-01-04 Tobias Doerffel - - * src/core/bb_editor.cpp: - fix missing pattern in new projects by also tracking - dataUnchanged()-signals of bbComboBoxModel - - * include/automatable_model_templates.h: - * include/mv_base.h: - added dataUnchanged()-signal which should be emitted in case new data - was not set for the model because it's been equal to old data - -2008-01-04 Tobias Doerffel - - * plugins/stk/mallets/mallets.h: - * plugins/stk/mallets/mallets.cpp: - fixed outstanding issues with LED-checkbox and its model - -2008-01-04 Tobias Doerffel - - * include/group_box.h: - * src/widgets/group_box.cpp: - removed animation-functionality as it's useless - - * src/core/arp_and_chords_tab_widget.cpp: - * src/core/envelope_tab_widget.cpp: - fixed boolModel-initializations - makes filter, arpeggio and chords - work again - -2008-01-03 Danny McRae - - * plugins/stk/mallets/mallets.h: - * plugins/stk/mallets/mallets.cpp: - made plugin work with M/V-architecture - -2008-01-03 Tobias Doerffel - - * plugins/audio_file_processor/audio_file_processor.cpp: - * plugins/audio_file_processor/audio_file_processor.h: - made plugin work with M/V-architecture - - * include/engine.h: - * include/plugin.h: - * src/core/engine.cpp: - fixes regarding coding style guidelines - -2008-01-02 Tobias Doerffel - - * plugins/kicker/kicker.cpp: - * plugins/kicker/kicker.h: - made plugin work with M/V-architecture - - * include/instrument.h: - * include/dummy_instrument.h: - * include/mv_base.h: - * src/tracks/instrument_track.cpp: - * src/core/instrument.cpp: - M/V-split for instrument-tracks - -2008-01-02 Tobias Doerffel - - * include/dummy_effect.h: - * src/core/effect.cpp: - make dummyEffect really work in case we need it - -2008-01-02 Tobias Doerffel - - * include/knob.h: - * include/effect.h: - * include/automatable_slider.h: - * include/lcd_spinbox.h: - * include/meter_dialog.h: - * include/midi_tab_widget.h: - * include/instrument_track.h: - * include/ladspa_control.h: - * include/piano_widget.h: - * include/detuning_helper.h: - * include/sample_play_handle.h: - * include/piano_roll.h: - * include/group_box.h: - * include/envelope_tab_widget.h: - * include/song_editor.h: - * include/automatable_button.h: - * include/tempo_sync_knob.h: - * include/journalling_object.h: - * include/setup_dialog.h: - * include/export_project_dialog.h: - * include/pixmap_button.h: - * include/sample_track.h: - * include/surround_area.h: - * include/volume_knob.h: - * include/bb_editor.h: - * include/rack_plugin.h: - * include/arp_and_chords_tab_widget.h: - * include/envelope_and_lfo_widget.h: - * include/combobox.h: - * include/led_checkbox.h: - * configure.in: - * src/audio/audio_alsa.cpp: - * src/audio/audio_oss.cpp: - * src/audio/audio_jack.cpp: - * src/widgets/rack_plugin.cpp: - * src/widgets/automatable_slider.cpp: - * src/widgets/lcd_spinbox.cpp: - * src/widgets/group_box.cpp: - * src/widgets/combobox.cpp: - * src/widgets/led_checkbox.cpp: - * src/widgets/volume_knob.cpp: - * src/widgets/pixmap_button.cpp: - * src/widgets/knob.cpp: - * src/widgets/automatable_button.cpp: - * src/widgets/tempo_sync_knob.cpp: - * src/tracks/sample_track.cpp: - * src/tracks/instrument_track.cpp: - * src/core/arp_and_chords_tab_widget.cpp: - * src/core/envelope_and_lfo_widget.cpp: - * src/core/preset_preview_play_handle.cpp: - * src/core/note_play_handle.cpp: - * src/core/midi_tab_widget.cpp: - * src/core/setup_dialog.cpp: - * src/core/sample_play_handle.cpp: - * src/core/export_project_dialog.cpp: - * src/core/effect.cpp: - * src/core/piano_roll.cpp: - * src/core/track.cpp: - * src/core/ladspa_control.cpp: - * src/core/note.cpp: - * src/core/envelope_tab_widget.cpp: - * src/core/instrument.cpp: - * src/core/piano_widget.cpp: - * src/core/surround_area.cpp: - * src/core/song_editor.cpp: - * src/core/automation_pattern.cpp: - * src/core/effect_tab_widget.cpp: - * src/core/automation_editor.cpp: - * src/core/bb_editor.cpp: - * src/core/meter_dialog.cpp: - * Makefile.am: - adaption of M/V-architecture - - * include/automatable_object_templates.h: - * include/automatable_object.h: - removed as replaced by automatable_model.h and - automatable_model_templates.h - - * include/mv_base.h: - * src/core/mv_base.cpp: - * include/automatable_model.h: - * include/automatable_model_templates.h: - added base-files for new M/V-architecture - - * src/widgets/rack_plugin.cpp: - fixed wrong signal-slot-connection which made gate-parameter of - effects not working - - * src/core/track_container.cpp: - when removing tracks start removing at the end of track-vector (i.e. - use m_trackWidgets.last() instead of m_trackWidgets.first()) - speeds - up things *a lot* - - * README: - * src/core/about_dialog.cpp: - fixed version and extended copyright from 2007 to 2008 - -2007-12-18 Tobias Doerffel - - * plugins/midi_import/midi_import.cpp: - load Patman-plugin instead of TripleOsc and try to load patch - according to program-change-events - -2007-12-14 Paul Wayper - - * include/volume_knob.h: - * src/widgets/volume_knob.cpp: - * src/core/setup_dialog.cpp: - * data/locale/nl.ts: - * data/locale/it.ts: - * data/locale/ca.ts: - * data/locale/ru.ts: - * data/locale/de.ts: - * data/locale/sv.ts: - Changed dbV to dBV throughout - -2007-12-12 Javier Serrano Polo - - * include/setup_dialog.h: - * src/core/setup_dialog.cpp: - - removed negative wording in general settings - - removed GIMP references - - * data/locale/ca.ts: - updated translation - -2007-12-11 Javier Serrano Polo - - * include/automation_editor.h: - * include/piano_roll.h: - * src/core/automation_editor.cpp: - * src/core/piano_roll.cpp: - optimized paint events - - * data/themes/default/style.css: - * src/core/automation_editor.cpp: - * src/core/piano_roll.cpp: - use styled background - - * src/core/track_container.cpp: - update display after loading settings - -2007-12-07 Javier Serrano Polo - - * include/main_window.h: - * include/song_editor.h: - * src/core/file_browser.cpp: - * src/core/main_window.cpp: - * src/core/song_editor.cpp: - use custom modified project indicator, fixed - - * include/bb_editor.h: - * include/song_editor.h: - * include/track.h: - * include/track_container.h: - * src/core/bb_editor.cpp: - * src/core/song_editor.cpp: - * src/core/track.cpp: - * src/core/track_container.cpp: - * src/tracks/pattern.cpp: - * src/tracks/sample_track.cpp: - added layouts, fixes scrolling - - * include/track.h: - * include/track_container.h: - * src/core/bb_editor.cpp: - * src/core/song_editor.cpp: - * src/core/track.cpp: - * src/core/track_container.cpp: - * src/tracks/bb_track.cpp: - associate track containers with tracks directly - - * src/core/track.cpp: - * src/core/track_container.cpp: - * src/tracks/bb_track.cpp: - * src/tracks/instrument_track.cpp: - * src/tracks/sample_track.cpp: - simplified updateAfterTrackAdd() calls - - * data/themes/default/style.css: - * src/core/track.cpp: - use style sheet painting - - * include/track.h: - * src/core/track.cpp: - removed discouraged repaint() - - * include/bb_editor.h: - * include/song_editor.h: - * src/core/bb_editor.cpp: - * src/core/song_editor.cpp: - * src/widgets/project_notes.cpp: - use default close event handler - - * src/core/bb_editor.cpp: - * src/core/track.cpp: - removed trivial asserts - - * data/locale/ca.ts: - updated translation - -2007-11-27 Tobias Doerffel - - * include/plugin.h: - * include/base64.h: - * src/lib/base64.cpp: - fixed loading of base64-encoded data being generated via Qt3-version - of QDataStream-class - -2007-11-27 Javier Serrano Polo - - * include/main_window.h: - * include/song_editor.h: - * src/core/engine.cpp: - * src/core/main_window.cpp: - * src/core/song_editor.cpp: - * src/lib/project_journal.cpp: - added modified project indicator - - * include/ladspa_base.h: - * include/plugin.h: - * plugins/ladspa_effect/ladspa_effect.cpp: - * plugins/ladspa_effect/ladspa_subplugin_features.cpp: - * plugins/ladspa_effect/ladspa_subplugin_features.h: - fixed invalid key segfault - - * src/core/main_window.cpp: - fixed instrument track visual glitches when loading - - * include/instrument_track.h: - * src/tracks/instrument_track.cpp: - removed QMdiSubWindow inheritance, fixes MDI focus segfault - - * src/core/track_container.cpp: - fixed interrupted loading segfault - - * plugins/ladspa_effect/ladspa_effect.cpp: - * plugins/ladspa_effect/ladspa_effect.h: - removed singleton reference - - * src/core/config_mgr.cpp: - integrated mkPath() calls - - * plugins/ladspa_browser/ladspa_browser.cpp: - centralized title change - - * include/song_editor.h: - * src/core/song_editor.cpp: - reduced dependencies - - * data/locale/ca.ts: - updated translation - -2007-11-26 Paul Giblock - - * plugins/lb302/lb302.cpp: - * plugins/lb302/lb302.h: - reverted to old lb302. There is a bug in sound output, will look - into it, but I'd rather have a working repository - - * data/presets/LB302/Oh Synth.cs.xml: - new preset - -2007-11-24 Paul Giblock - - * plugins/lb302/lb302.cpp: - re-enabled lb302 background - - * plugins/lb302/artwork.png: - updated skin I had sitting around - -2007-11-23 Paul Giblock - - * plugins/lb302/lb302.cpp: - * plugins/lb302/lb302.h: - reformated code to match code style rules - - * src/widgets/tool_button.cpp: - improved appearance of toolbar buttons - -2007-11-23 Tobias Doerffel - - * plugins/ladspa_browser/ladspa_browser.cpp: - improved layout - - * src/widgets/tab_bar.cpp: - - improved layout - - change icon-size-property for tabButtons in order to make them look - as in 0.3.x - -2007-11-23 Javier Serrano Polo - - * Makefile.am: - * plugins/ladspa_browser/ladspa_browser.cpp: - * plugins/ladspa_browser/ladspa_browser.h: - * plugins/ladspa_browser/ladspa_description.cpp: - * plugins/ladspa_browser/ladspa_description.h: - * plugins/ladspa_browser/ladspa_port_dialog.cpp: - * plugins/ladspa_browser/ladspa_port_dialog.h: - * plugins/ladspa_browser/logo.png: - * plugins/ladspa_browser/Makefile.am: - * plugins/Makefile.am: - resurrected LADSPA browser - - * plugins/ladspa_effect/ladspa_subplugin_features.cpp: - minor simplification - - * src/core/song_editor.cpp: - * src/widgets/automatable_slider.cpp: - upgraded automatable sliders to Qt4 - - * configure.in: - * include/engine.h: - * plugins/Makefile.am: - * src/core/config_mgr.cpp: - * src/core/engine.cpp: - removed references to optional LADSPA support - - * data/themes/default/style.css: - * src/core/main_window.cpp: - moved workspace background to style sheet - - * src/core/main_window.cpp: - added workspace scroll bars - - * include/track_container.h: - * src/core/song_editor.cpp: - removed obsolete centralWiget() - - * plugins/live_tool/live_tool.cpp: - * plugins/live_tool/live_tool.h: - fixed i18n - - * plugins/live_tool/live_tool.cpp: - cosmetic changes - - * data/locale/ca.ts: - updated translation - - * resources/*: - removed unused images - -2007-11-22 Paul Giblock - - * src/widgets/text_float.cpp: - * src/core/track.cpp: - - fixed segfaults from clicking on track content objects after loading a - project. - - I don't have a copy of 3.1 to reference, so I don't know where the - textFloat is normally displayed. Feel free to adjust. - -2007-11-21 Tobias Doerffel - - * src/lib/sample_buffer.cpp: - - duplicate ASCII-string from file.toAscii().constData() in order to not - get corrupted - fixes random problems with loading OGG-files - - sample-visualization now floating-point-based - - * src/widgets/combobox.cpp: - fixed text-drawing - - * src/widgets/led_checkbox.cpp: - * src/widgets/tab_widget.cpp: - added workarounds for obviously non-working font-property - - * src/widgets/knob.cpp: - - knob::drawKnob( ... ) now completely works with floats - - use anti-aliasing when drawing tick - - * src/tracks/sample_track.cpp: - fixed painting of sample-TCO's - - * src/core/arp_and_chords_tab_widget.cpp: - removed obviously non-working comboBox::setFont( ... )-calls - - * src/core/envelope_and_lfo_widget.cpp: - use line-width of 1.5 instead of 2 for drawing LFO - - * src/core/main.cpp: - do not set default font-size - - * data/locale/de.ts: - * data/locale/de.qm: - fixed German localization - -2007-11-20 Javier Serrano Polo - - * include/drumsynth.h: - * licenses/drumsynth.LICENSE: - * src/lib/drumsynth.cpp: - relicensed under GPL, thanks to Paul Kellett. - - * src/lib/sample_buffer.cpp: - fixed Vorbis loading - - * include/effect_label.h: - * plugins/live_tool/live_tool.cpp: - * src/core/automation_editor.cpp: - * src/core/bb_editor.cpp: - * src/core/effect_tab_widget.cpp: - * src/core/main_window.cpp: - * src/core/song_editor.cpp: - * src/core/tool.cpp: - * src/widgets/effect_label.cpp: - * src/widgets/project_notes.cpp: - fixed MDI windows - - * include/main_window.h: - * src/core/automation_editor.cpp: - * src/core/main_window.cpp: - * src/core/piano_roll.cpp: - * src/core/song_editor.cpp: - fixed non-MDI mode - - * include/automatable_button.h: - * src/widgets/automatable_button.cpp: - inherit from QPushButton - - * include/tool.h: - * plugins/live_tool/live_tool.cpp: - * plugins/live_tool/live_tool.h: - * src/core/main_window.cpp: - * src/core/tool.cpp: - simplified tool interface - - * plugins/live_tool/live_tool.cpp: - fixed instrument toggling - - * plugins/live_tool/live_tool.cpp: - * plugins/live_tool/live_tool.h: - fixed focus bug - - * include/effect_label.h: - * src/widgets/effect_label.cpp: - simplified window management - - * include/effect_label.h: - * include/main_window.h: - * plugins/vst_base/lvsl_client.cpp: - * plugins/vst_effect/vst_effect.h: - * src/core/track_container.cpp: - reduced dependencies - - * data/samples/drumsynth/misc_bass/Makefile.am: - * data/samples/drumsynth/misc_claps/Makefile.am: - * data/samples/drumsynth/misc_electro/Makefile.am: - * data/samples/drumsynth/misc_fx/Makefile.am: - * data/samples/drumsynth/misc_hats/Makefile.am: - * data/samples/drumsynth/misc_perc/Makefile.am: - * data/samples/drumsynth/misc_synth/Makefile.am: - * data/samples/drumsynth/r_b/Makefile.am: - replaced more filenames with underscores, thanks to Vik. - -2007-11-20 Paul Giblock - - * src/core/main_window: - fixed flashing/moving windows on project load - - * src/core/song_editor.cpp: - inverted direction of master-volume and master-pitch sliders - -2007-11-19 Paul Giblock - - * plugins/midi_import/midi_import.cpp: - fixed debugging code so file would compile - -2007-11-18 Paul Giblock - - * include/track_container.h: - removed some obsolete functions - -2007-11-18 Tobias Doerffel - - * plugins/vst_base/lvsl_client.cpp: - fixed usage of QMdiArea instead of QWorkspace - - * include/main_window.h: - added inclusion of QMdiArea-header - - * include/track_container.h: - fixed some code to match coding-style-guidelines - - * acinclude.m4: - reverted Paul's private changes - -2007-11-18 Paul Giblock - - * plugins/ladspa_effect/ladspa_effect.h: - * plugins/bass_booster/bass_booster.h: - * plugins/stereo_enhancer/stereoenhancer_control_dialog.cpp - * plugins/stereo_enhancer/stereoenhancer_control_dialog.h - * include/main_window.h: - * include/instrument_track.h: - * include/track_container.h: - * src/widgets/rack_plugin.cpp: - * src/widgets/project_notes.cpp: - * src/widgets/tempo_sync_knob.cpp: - * src/tracks/instrument_track.cpp: - * src/tracks/pattern.cpp: - * src/core/track_container.cpp: - * src/core/tool.cpp: - * src/core/file_browser.cpp: - * src/core/main.cpp: - * src/core/piano_roll.cpp: - * src/core/main_window.cpp: - * src/core/song_editor.cpp: - * src/core/automation_pattern.cpp: - * src/core/automation_editor.cpp: - * src/core/bb_editor.cpp: - Replaced references to QWorkspace, made everything work with QMdiArea - - * include/main_window.h: - mainWindow::workspace() now returns a QMdiArea - - * include/rack_plugin.h: - Add m_subWindow to track QMdiSubWindow independently of the - control dialog - - * include/track_container.h: - Emulate centralWidget by returning this pointer - - * AUTHORS: - Added Paul Giblock as an author - - * src/core/track_container.cpp: - Adding a subwindow before the widget is fully constructed causes - problems: no icon, no geometry, and sometime multiple windows. - Force each subclass to do their own workspace()->addWindow() - - * src/core/main_window.cpp: - toggling of subWindows is performed on the parentWidgets. However, - things like instrumentTrack are actually QMdiSubWindows themselves - -2007-11-14 Javier Serrano Polo - - * configure.in: - * data/samples/drumsynth/*: - * data/samples/Makefile.am: - * include/drumsynth.h: - * include/sample_buffer.h: - * licenses/drumsynth.LICENSE: - * Makefile.am: - * plugins/audio_file_processor/audio_file_processor.cpp: - * src/lib/drumsynth.cpp: - * src/lib/sample_buffer.cpp: - imported DrumSynth from 0.3 branch - - * include/sample_buffer.h: - * plugins/audio_file_processor/artwork.png: - * plugins/audio_file_processor/audio_file_processor.cpp: - * plugins/audio_file_processor/audio_file_processor.h: - * src/lib/sample_buffer.cpp: - dropped dot drawing method - - * src/lib/sample_buffer.cpp: - - fixed DrumSynth support when missing Vorbis - - use working line drawing method from 0.3 branch - - * plugins/audio_file_processor/audio_file_processor.cpp: - fixed sample display - - * src/core/track.cpp: - * src/core/track_container.cpp: - fixed track removal segfault - - * data/locale/ca.ts: - updated translation - -2007-11-12 Tobias Doerffel - - * plugins/stereo_enhancer/stereo_enhancer.h: - * plugins/stereo_enhancer/stereo_enhancer.cpp: - * plugins/stereo_enhancer/stereoenhancer_control_dialog.h: - * plugins/stereo_enhancer/stereoenhancer_control_dialog.cpp: - * plugins/stereo_enhancer/Makefile.am: - added StereoEnhancer-plugin from - Lou Herard - -2007-11-12 Tobias Doerffel - - * plugins/ladspa_effect/caps/basics.h: - * plugins/ladspa_effect/caps/interface.cc: - * configure.in: - small fixes for cross-compilation - - * Makefile.am: - * src/core/ladspa_base.cpp: - removed as obsolete - -2007-11-10 Javier Serrano Polo - - * Makefile.am: - * include/envelope_and_lfo_widget.h: - * include/pixmap_button.h: - * include/spc_bg_hndl_widget.h: - * include/tab_widget.h: - * plugins/audio_file_processor/audio_file_processor.cpp: - * plugins/audio_file_processor/audio_file_processor.h: - * plugins/bit_invader/bit_invader.cpp: - * plugins/bit_invader/bit_invader.h: - * plugins/organic/organic.cpp: - * plugins/organic/organic.h: - * plugins/patman/patman.cpp: - * plugins/patman/patman.h: - * plugins/vestige/vestige.cpp: - * plugins/vestige/vestige.h: - * src/core/envelope_and_lfo_widget.cpp: - * src/widgets/group_box.cpp: - * src/widgets/knob.cpp: - * src/widgets/led_checkbox.cpp: - * src/widgets/pixmap_button.cpp: - * src/widgets/tab_widget.cpp: - removed obsolete specialBgHandlingWidget - - * src/core/main_window.cpp: - fixed label in save project dialog - - * data/themes/default/style.css: - * include/track.h: - * src/core/track.cpp: - turned more code into style sheet - - * data/themes/default/style.css: - * src/core/track.cpp: - reverted positioning in style sheet - - * data/themes/default/style.css: - restricted style inheritance - - * plugins/bass_booster/bassbooster_control_dialog.cpp: - * plugins/flp_import/unrtf/parse.c: - * plugins/vestige/vestige.h: - * plugins/vst_effect/vst_control_dialog.cpp: - * plugins/vst_effect/vst_effect.cpp: - * plugins/vst_effect/vst_subplugin_features.cpp: - removed Qt3 code - - * plugins/bit_invader/bit_invader.cpp: - * plugins/bit_invader/bit_invader.h: - * plugins/organic/organic.cpp: - * plugins/organic/organic.h: - * plugins/vestige/vestige.cpp: - reduced dependencies - - * plugins/bit_invader/bit_invader.cpp: - removed deprecated code - -2007-11-06 Javier Serrano Polo - - * include/track.h: - * src/core/track.cpp: - optimized trackOperationsWidget paint event - - * data/themes/default/style.css: - * src/core/track.cpp: - turned some code into style sheet - -2007-11-03 Javier Serrano Polo - - * plugins/singerbot/singerbot_proxy.cpp: - initial release, separate process to deal with Festival - - * plugins/singerbot/file.h: - initial release, file descriptor wrapper - - * plugins/singerbot/Makefile.am: - * plugins/singerbot/singerbot.cpp: - * plugins/singerbot/singerbot.h: - use external proxy - - * include/main_window.h: - * src/core/main_window.cpp: - upgraded recently opened files feature - - * include/main_window.h: - * src/core/main_window.cpp: - * src/core/song_editor.cpp: - fixed recently opened files segfault - - * include/mmp.h: - * src/lib/mmp.cpp: - simplified save extension handling - - * src/core/song_editor.cpp: - * src/lib/mmp.cpp: - fixed recently opened files bug (#1800364) - - * data/themes/default/style.css: - * data/themes/Makefile.am: - * include/config_mgr.h: - * src/core/config_mgr.cpp: - * src/core/main_window.cpp: - added style sheet support - - * include/caption_menu.h: - * src/widgets/caption_menu.cpp: - initial release, context menu with a caption - - * plugins/vibed/impulse_editor.cpp: - * plugins/vibed/nine_button_selector.cpp: - * plugins/vibed/vibed.cpp: - * src/core/piano_widget.cpp: - * src/core/surround_area.cpp: - * src/widgets/automatable_button.cpp: - * src/widgets/automatable_slider.cpp: - * src/widgets/combobox.cpp: - * src/widgets/knob.cpp: - * src/widgets/lcd_spinbox.cpp: - * src/widgets/rack_plugin.cpp: - * src/widgets/tempo_sync_knob.cpp: - use caption menu - - * src/core/main_window.cpp: - set workspace's background with its own method - - * acinclude.m4: - * include/file_browser.h: - * src/core/file_browser.cpp: - * src/core/main_window.cpp: - replaced Qt3-based file browser implementation - - * src/core/file_browser.cpp: - enabled match in directory content filter - - * src/widgets/automatable_slider.cpp: - fixed mouse release segfault - - * acinclude.m4: - * src/core/main.cpp: - assume Qt translations are properly configured - - * src/core/main.cpp: - use standard return values - - * src/core/config_mgr.cpp: - removed line breaks inside paragraphs, wrapping should work - - * src/audio/audio_alsa.cpp: - * src/midi/midi_alsa_seq.cpp: - removed discouraged alloca calls - - * include/main_window.h: - * include/rack_plugin.h: - * plugins/bass_booster/bass_booster.h: - * plugins/ladspa_effect/ladspa_effect.h: - * plugins/vst_base/lvsl_client.cpp: - * plugins/vst_effect/vst_effect.h: - * src/core/automation_editor.cpp: - * src/core/file_browser.cpp: - * src/core/main_window.cpp: - * src/core/piano_roll.cpp: - * src/core/surround_area.cpp: - * src/core/tool.cpp: - * src/core/track_container.cpp: - * src/tracks/instrument_track.cpp: - * src/widgets/combobox.cpp: - * src/widgets/effect_label.cpp: - * src/widgets/knob.cpp: - * src/widgets/project_notes.cpp: - * src/widgets/rack_plugin.cpp: - * src/widgets/tempo_sync_knob.cpp: - reduced include dependencies - - * plugins/flp_import/unrtf/attr.c: - * plugins/flp_import/unrtf/attr.h: - * plugins/flp_import/unrtf/convert.c: - * plugins/flp_import/unrtf/error.c: - * plugins/flp_import/unrtf/error.h: - * plugins/flp_import/unrtf/html.c: - * plugins/flp_import/unrtf/malloc.c: - * plugins/flp_import/unrtf/malloc.h: - * plugins/flp_import/unrtf/output.c: - * plugins/flp_import/unrtf/output.h: - * src/audio/audio_file_ogg.cpp: - replaced deprecated string conversions - - * plugins/lb302/lb302.cpp: - * src/widgets/kmultitabbar.cpp: - fixed different signedness comparison - - * plugins/lb302/lb302.cpp: - * plugins/midi_import/midi_import.cpp: - commented out unused variables - - * plugins/flp_import/unrtf/convert.c: - replaced empty conditional - - * src/widgets/kmultitabbar.cpp: - added copyright notice - - * src/core/automation_pattern.cpp: - * src/core/config_mgr.cpp: - * src/core/import_filter.cpp: - * src/core/ladspa_manager.cpp: - * src/core/setup_dialog.cpp: - * src/core/track.cpp: - * src/core/track_container.cpp: - * src/lib/sample_buffer.cpp: - * src/midi/midi_mapper.cpp: - * src/widgets/tab_bar.cpp: - * src/widgets/text_float.cpp: - removed old undefs - - * configure.in: - readded unsafe-loop-optimizations warning - - * data/locale/ca.ts: - updated translation - - * data/locale/qt_*.qm: - removed old Qt3 translations - -2007-10-30 Tobias Doerffel - - * src/core/note_play_handle.cpp: - fixed crash in case of framesLeft() being less or equal zero while - instrument::playNote is being called (e.g. when decreasing release - while a note is active) - -2007-10-04 Javier Serrano Polo - - * configure.in: - * plugins/vst_base/lvsl_client.cpp: - * plugins/vst_base/lvsl_server.cpp: - * plugins/vst_base/Makefile.am: - * src/lib/journalling_object.cpp: - amd64 fixes - - * plugins/vestige/vestige.cpp: - fixed loading deadlock - - * plugins/vst_base/Makefile.am: - renamed lvsl_server.c to lvsl_server.cpp - - * plugins/vst_base/lvsl_server.cpp: - restricted shared memory permissions - - * plugins/vst_base/communication.h: - improved string communication - - * configure.in: - look for wine header in system folder too - - * configure.in: - * Makefile.am: - * plugins/Makefile.am: - added extra plugins support - - * include/main_window.h: - * src/core/main_window.cpp: - use desktop services for online help - - * src/core/main_window.cpp: - - use background artwork - - updated wiki URL - - * src/core/automation_editor.cpp: - * src/core/piano_roll.cpp: - * src/tracks/instrument_track.cpp: - * src/widgets/effect_label.cpp: - fixed null workspace segfaults - - * plugins/stk/mallets/mallets.cpp: - enabled missing files message - - * src/core/main.cpp: - use processed argc/argv rather than deprecated functions - - * plugins/singerbot/singerbot.cpp: - detected heap corruption - - * data/locale/ca.ts: - updated translation - - * plugins/polyb302/polyb302.cpp: - * plugins/polyb302/polyb302.h: - dropped Qt3-support - - * plugins/polyb302/polyb302.cpp: - applied relevant LB302 changes - -2007-09-25 Tobias Doerffel - - * include/mixer.h: - * include/visualization_widget.h: - * src/core/mixer.cpp: - * src/widget/visualization_widget.cpp: - reworked code for retrieving current mixer-buffer for visualizing it - - do not use signal/slot-mechanism for passing pointer and use - currentReadBuffer() + mixer-mutex instead which probably fixes some - mixer-related crashes - - * src/widget/effect_label.cpp: - set window-title for effect-chain-windows of a sample-track etc. - -2007-09-16 Tobias Doerffel - - * plugins/ladspa_effect/ladspa_subplugin_features.cpp: - * include/effect_select_dialog.h: - * src/core/effect_select_dialog.cpp: - replaced Q3ListBox with QListWidget and made layouting-stuff of - plugin-description-widget working properly - - * data/locale/de.ts: - fixed some strings in German localization - -2007-09-03 Tobias Doerffel - - * plugins/patman/patman.cpp: - * plugins/audio_file_processor/audio_file_processor.cpp: - cleanups - - * plugins/ladspa_base: - * plugins/ladspa_base/Makefile.am: - removed - - * configure.in: - * Makefile.am: - * plugins/ladspa_effect/Makefile.am: - * src/core/engine.cpp: - * src/core/ladspa_base.cpp: - * src/core/ladspa_port_dialog.cpp: - * src/core/ladspa_2_lmms.cpp: - * src/core/ladspa_manager.cpp: - * src/core/ladspa_control.cpp: - * include/ladspa_manager.h: - * include/ladspa_2_lmms.h: - * include/ladspa_control.h: - * include/ladspa_port_dialog.h: - * include/ladspa_base.h: - moved all code from LADSPA-base-library into LMMS-core - -2007-09-02 Javier Serrano Polo - - * include/project_notes.h: - * src/widgets/project_notes.cpp: - made usable with Qt4 - -2007-08-26 Tobias Doerffel - - * plugins/patman/patman.cpp: - * plugins/patman/patman.h: - * plugins/ladspa_effect/ladspa_effect.cpp: - * plugins/ladspa_effect/ladspa_control_dialog.cpp: - * plugins/ladspa_effect/ladspa_effect.h: - * plugins/ladspa_effect/ladspa_control_dialog.h: - * plugins/ladspa_effect/ladspa_subplugin_features.cpp: - * plugins/organic/organic.cpp: - * plugins/lb302/lb302.cpp: - * plugins/bit_invader/graph.cpp: - * plugins/bit_invader/bit_invader.cpp: - * plugins/bit_invader/graph.h: - * plugins/vst_effect/vst_effect.h: - * plugins/vibed/graph.cpp: - * plugins/vibed/impulse_editor.h: - * plugins/vibed/nine_button_selector.h: - * plugins/vibed/vibed.h: - * plugins/vibed/graph.h: - * plugins/vibed/string_container.h: - * plugins/vibed/impulse_editor.cpp: - * plugins/vibed/nine_button_selector.cpp: - * plugins/vibed/vibed.cpp: - * plugins/triple_oscillator/triple_oscillator.cpp: - * plugins/singerbot/singerbot.h: - * plugins/singerbot/singerbot.cpp: - * plugins/live_tool/live_tool.cpp: - * plugins/ladspa_base/ladspa_manager.cpp: - * plugins/ladspa_base/ladspa_2_lmms.h: - * plugins/ladspa_base/ladspa_manager.h: - * plugins/ladspa_base/ladspa_control.cpp: - * plugins/ladspa_base/ladspa_port_dialog.cpp: - * plugins/ladspa_base/ladspa_control.h: - * plugins/ladspa_base/ladspa_port_dialog.h: - * plugins/ladspa_base/ladspa_2_lmms.cpp: - * plugins/audio_file_processor/audio_file_processor.cpp: - * plugins/audio_file_processor/audio_file_processor.h: - * plugins/stk/mallets/mallets.cpp: - * plugins/stk/mallets/mallets.h: - * plugins/vestige/vestige.cpp: - * plugins/vst_base/lvsl_client.cpp: - * plugins/vst_base/lvsl_client.h: - * plugins/kicker/kicker.cpp: - * plugins/Makefile.am: - * plugins/flp_import/flp_import.h: - * plugins/flp_import/flp_import.cpp: - * plugins/midi_import/midi_import.h: - * plugins/midi_import/midi_import.cpp: - * include/mmp.h: - * include/knob.h: - * include/cpuload_widget.h: - * include/fade_button.h: - * include/templates.h: - * include/automatable_slider.h: - * include/lcd_spinbox.h: - * include/track.h: - * include/spc_bg_hndl_widget.h: - * include/note.h: - * include/tool_button.h: - * include/embed.h: - * include/name_label.h: - * include/midi_alsa_raw.h: - * include/gui_templates.h: - * include/visualization_widget.h: - * include/tab_widget.h: - * include/config_mgr.h: - * include/midi_tab_widget.h: - * include/import_filter.h: - * include/mixer.h: - * include/instrument_track.h: - * include/audio_port.h: - * include/instrument.h: - * include/text_float.h: - * include/piano_widget.h: - * include/sample_buffer.h: - * include/effect_select_dialog.h: - * include/automation_pattern.h: - * include/midi_mapper.h: - * include/nstate_button.h: - * include/plugin.h: - * include/clipboard.h: - * include/note_play_handle.h: - * include/side_bar.h: - * include/rack_view.h: - * include/pattern.h: - * include/string_pair_drag.h: - * include/audio_file_device.h: - * include/kmultitabbar.h: - * include/file_browser.h: - * include/base64.h: - * include/audio_jack.h: - * include/about_dialog.h: - * include/piano_roll.h: - * include/group_box.h: - * include/envelope_tab_widget.h: - * include/rubberband.h: - * include/bb_track.h: - * include/song_editor.h: - * include/project_notes.h: - * include/effect_tab_widget.h: - * include/kmultitabbar-qt3.h: - * include/automatable_button.h: - * include/midi_alsa_seq.h: - * include/tab_button.h: - * include/journalling_object.h: - * include/setup_dialog.h: - * include/export_project_dialog.h: - * include/rename_dialog.h: - * include/pixmap_button.h: - * include/tab_bar.h: - * include/effect_label.h: - * include/automatable_object_templates.h: - * include/sample_track.h: - * include/timeline.h: - * include/surround_area.h: - * include/main_window.h: - * include/audio_device.h: - * include/midi_client.h: - * include/automatable_object.h: - * include/automation_editor.h: - * include/midi_port.h: - * include/audio_sample_recorder.h: - * include/bb_editor.h: - * include/effect_chain.h: - * include/arp_and_chords_tab_widget.h: - * include/project_journal.h: - * include/plugin_browser.h: - * include/envelope_and_lfo_widget.h: - * include/preset_preview_play_handle.h: - * include/qt3support.h: - * include/track_container.h: - * include/combobox.h: - * include/side_bar_widget.h: - * include/play_handle.h: - * include/qxembed.h: - * include/xqmap.h: - * configure.in: - * src/audio/audio_file_device.cpp: - * src/audio/audio_alsa.cpp: - * src/audio/audio_oss.cpp: - * src/audio/audio_jack.cpp: - * src/midi/midi_client.cpp: - * src/midi/midi_mapper.cpp: - * src/midi/midi_oss.cpp: - * src/midi/midi_alsa_seq.cpp: - * src/midi/midi_alsa_raw.cpp: - * src/lib/string_pair_drag.cpp: - * src/lib/base64.cpp: - * src/lib/mmp.cpp: - * src/lib/journalling_object.cpp: - * src/lib/sample_buffer.cpp: - * src/lib/embed.cpp: - * src/widgets/rack_plugin.cpp: - * src/widgets/automatable_slider.cpp: - * src/widgets/visualization_widget.cpp: - * src/widgets/group_box.cpp: - * src/widgets/lcd_spinbox.cpp: - * src/widgets/rubberband.cpp: - * src/widgets/tool_button.cpp: - * src/widgets/combobox.cpp: - * src/widgets/text_float.cpp: - * src/widgets/tab_widget.cpp: - * src/widgets/rack_view.cpp: - * src/widgets/led_checkbox.cpp: - * src/widgets/side_bar_widget.cpp: - * src/widgets/project_notes.cpp: - * src/widgets/volume_knob.cpp: - * src/widgets/kmultitabbar.cpp: - * src/widgets/qxembed.cpp: - * src/widgets/rename_dialog.cpp: - * src/widgets/pixmap_button.cpp: - * src/widgets/nstate_button.cpp: - * src/widgets/knob.cpp: - * src/widgets/automatable_button.cpp: - * src/widgets/tempo_sync_knob.cpp: - * src/widgets/fade_button.cpp: - * src/widgets/cpuload_widget.cpp: - * src/widgets/tab_bar.cpp: - * src/widgets/tooltip.cpp: - * src/tracks/sample_track.cpp: - * src/tracks/bb_track.cpp: - * src/tracks/instrument_track.cpp: - * src/tracks/pattern.cpp: - * src/core/plugin.cpp: - * src/core/arp_and_chords_tab_widget.cpp: - * src/core/plugin_browser.cpp: - * src/core/envelope_and_lfo_widget.cpp: - * src/core/preset_preview_play_handle.cpp: - * src/core/track_container.cpp: - * src/core/config_mgr.cpp: - * src/core/midi_tab_widget.cpp: - * src/core/effect_control_dialog.cpp: - * src/core/import_filter.cpp: - * src/core/setup_dialog.cpp: - * src/core/file_browser.cpp: - * src/core/main.cpp: - * src/core/mixer.cpp: - * src/core/export_project_dialog.cpp: - * src/core/about_dialog.cpp: - * src/core/piano_roll.cpp: - * src/core/track.cpp: - * src/core/engine.cpp: - * src/core/note.cpp: - * src/core/timeline.cpp: - * src/core/envelope_tab_widget.cpp: - * src/core/surround_area.cpp: - * src/core/piano_widget.cpp: - * src/core/effect_select_dialog.cpp: - * src/core/main_window.cpp: - * src/core/song_editor.cpp: - * src/core/automation_pattern.cpp: - * src/core/name_label.cpp: - * src/core/effect_tab_widget.cpp: - * src/core/automation_editor.cpp: - * src/core/bb_editor.cpp: - * acinclude.m4: - * Makefile.am: - dropped Qt3-support and improved Qt4-support - -2007-08-23 Tobias Doerffel - - * configure.in: - bumped to 0.4.x development series - -2007-08-20 Tobias Doerffel - - * configure.in: - * README: - * lmms.spec.in: - finally made 0.3.0 release :) - - * Makefile.am: - added missing entry for 3rd-party samplerate.h - - * data/projects/cool_songs/Makefile.am: - * data/projects/covers/Makefile.am: - * data/projects/demos/Makefile.am: - * data/projects/misc/Makefile.am: - * data/projects/tutorials/Makefile.am: - added missing mmpz-wildcard - - * data/projects/covers/MonkeyIsland1-Intro.mmpz: - another cool cover - - * data/projects/covers/J.S.Bach-Preludium_and_Fugue_A-Minor.mmp: - removed - - * data/projects/covers/J.S.Bach-Preludium_and_Fugue_A-Minor.mmpz: - reworked - - * data/projects/demos/demo1.mmp: - * data/projects/demos/demo2.mmp: - * data/projects/demos/demo3.mmp: - * data/projects/cool_songs/Siegel-DreamWave.mmp: - updated - - * data/projects/misc/lb302quick.mmp: - * data/projects/demos/basses-demo.mmp: - removed because of really low-quality and/or duplicate - - * data/projects/demos/lb302quick.mmpz: - added another demo - - * data/projects/cool_songs/StrictProduction-Lamentelnes.mmp: - * data/projects/cool_songs/StrictProduction-DearJonDoe.mmp: - * data/projects/cool_songs/OrtalDj-FirstProyect.mmp: - * data/projects/cool_songs/Siegel-SpeedTrack.mmp: - * data/projects/cool_songs/Chris-RaveRiff.mmpz: - * data/projects/cool_songs/MysthR-Living.mmpz: - * data/projects/cool_songs/j1m-DingDong.mmp: - * data/projects/cool_songs/BlueWolf-DreamTravel.mmp: - * data/projects/cool_songs/Silva-ElvesCall.mmp: - added some more really cool projects - - * data/samples/drums/bassdrum04.ogg: - resampled to end at zero-level - fixes clicks in some projects - - * data/samples/drums/nasty_bass01.ogg: - * data/samples/drums/nasty_snare01.ogg: - * data/samples/drums/rim01.ogg: - * data/samples/drums/ride02.ogg: - * data/samples/drums/nasty_rim01.ogg: - * data/samples/drums/hihat_opened03.ogg - * data/samples/misc/applause01.ogg: - added samples - - * data/presets/TripleOscillator/SawLead.cs.xml: - * data/presets/TripleOscillator/SawLead2.cs.xml: - * data/presets/TripleOscillator/HardClipping.cs.xml: - * data/presets/TripleOscillator/PowerStrings.cs.xml: - * data/presets/TripleOscillator/SquareLead.cs.xml: - * data/presets/TripleOscillator/SquareLead2.cs.xml: - added some presets - - * plugins/lb302/lb302.cpp: - removed debug-out - - * plugins/audio_file_processor/audio_file_processor.h: - * plugins/audio_file_processor/audio_file_processor.cpp: - * plugins/bit_invader/bit_invader.h: - * plugins/bit_invader/bit_invader.cpp: - added applyRelease(...)-call in playNote(...) and - re-implemented desiredReleaseFrames()-method - - * include/mmp.h: - * src/lib/mmp.cpp: - * src/tracks/instrument_track.cpp: - * src/core/main_window.cpp: - * src/core/song_editor.cpp: - fixed some bugs concerning recent-files-list - -2007-08-20 dieEasy - - * data/locale/it.ts: - updated Italian localization-file - -2007-08-19 Tobias Doerffel - - * data/locale/de.ts: - * data/locale/de.qm: - updated German localization-file - - * Makefile.am: - fixed command for updating TS-files - - * include/config_mgr.h: - * include/main_window.h: - * src/core/config_mgr.cpp: - * src/core/main_window.cpp: - added support for "Recently opened files"-menu - - * src/core/main_window.cpp: - - cleanups - - limit x-coordinate of a widget to be >= 0 in - mainWindow::restoreWidgetState( ... ) - fixes bug with appearently - inacccessible title-bars of piano-roll, song-editor etc. after - loading project - - * include/config_mgr.h: - * src/core/engine.cpp: - also destroy config-manager at engine::destroy() - - * src/audio/audio_jack.cpp: - added define for support for per-track audio-ports - almost works - except that the buffers of the audio-port are already cleared again at - the time the callback fills the buffers - will need an additional - buffer in audio-ports or something like that - - * src/core/mixer.cpp: - * src/lib/journalling_object.cpp: - * src/lib/project_journal.cpp: - * src/widgets/knob.cpp: - removed debug-out - - * plugins/patman/patman.cpp: - set directory of sample-selection-dialog to /usr/share/midi/freepats - if it exists - - * configure.in: - * plugins/Makefile.am: - * plugins/vibed/vibed.cpp: - * lib/src/mmp.cpp: - replaced obsolete PluckedStringSynth with Vibed - - * configure.in: - * plugins/Makefile.am: - removed Polyb302 from build as the same results can be achieved either - via (improved and maintained) LB302 or TripleOsc+filter - Polyb302 - just increases redundancy and adds extra maintainance-work - - * plugins/stk/mallets/mallets.cpp: - do not crash if Stk-files are missing - -2007-08-18 Tobias Doerffel - - * plugins/lb302/lb302.cpp: - * plugins/lb302/lb302.h: - - rewrote code for monophonic behaviour (calculation of position at - which to resume states etc.) - - added some debugging-stuff - - * src/core/mixer.cpp: - remove play-handles *after* we played all play-handles - - * src/tracks/instrument_track.cpp: - fixed a bug in monophonic behaviour - -2007-08-16 Tobias Doerffel - - * include/instrument.h: - * src/tracks/instrument_track.cpp: - reverted previous changes (behaviour with monophonic instruments) - -2007-08-06 Tobias Doerffel - - * plugins/triple_oscillator/triple_oscillator.h: - * plugins/triple_oscillator/triple_oscillator.cpp: - use new applyRelease()-method - - * include/instrument.h: - * src/core/instrument.cpp: - added method instrument::applyRelease( ... ) which applies a release - on given buffer according to the value returned by - desiredReleaseFrames() - instruments can use this easily by simply - calling this method before calling - getInstrumentTrack()->processAudioBuffer() - - * src/core/preset_preview_play_handle.cpp: - * src/tracks/instrument_track.cpp: - use only half of valueRange::max because otherwise we have - overflows at several places - - * src/core/note_play_handle.cpp: - fixed framesLeft()-method to return correct values if plugin has - desiredReleaseFrames() > 0 - - * include/note_play_handle.h: - cleanups - - * configure.in: - bumped to 0.3.0-rc2 - - * src/lib/mmp.cpp: - added more compat-code to upgrade() for being able to properly open - files created by 0.0.9 and the whole 0.1.x-series - - * plugins/flp_import/flp_import.cpp: - * include/arp_and_chords_tab_widget.h: - * src/core/arp_and_chords_tab_widget.cpp: - * src/lib/mmp.cpp: - cleaned up all the arpeggio-direction-hacks - now the values are UP - (0) to RANDOM (3) at *all* places - required some compat-hacks in - mmp-upgrade()-method - - * include/file_browser.h: - * src/core/file_browser.cpp: - protect m_previewPlayHandle with mutex - fixes crash when releasing - mouse button on preset-file with VST-plugin/-effect while VST-plugin - is still loading - -2007-08-04 Tobias Doerffel - - * src/widget/visualization_widget.cpp: - proper visualization even with period-sizes < 128 - - * plugins/audio_file_processor/audio_file_processor.cpp: - * plugins/bit_invader/bit_invader.cpp: - * plugins/kicker/kicker.cpp: - * plugins/lb302/lb302.cpp: - * plugins/patman/patman.cpp: - * plugins/plucked_string_synth/plucked_string_synth.cpp: - * plugins/polyb302/polyb302.cpp: - * plugins/singerbot/singerbot.cpp: - * plugins/stk/mallets/mallets.cpp: - * plugins/vibed/vibed.cpp: - removed check for framesLeftForCurrentPeriod() being zero - fixed by - patch below - - * src/tracks/instrument_track.cpp: - - acquire mixer-lock while calling noteOff() in - instrumentTrack::processInEvent( ... ) - fixes asynchronously - modifications of variables in notePlayHandle which led to segfaults in - some cases - - when encountering old running notes on monophonic instruments only - clear the part of the audio-port-buffer where the new note will be - mixed in - -2007-08-03 Tobias Doerffel - - * plugins/audio_file_processor/audio_file_processor.cpp: - * plugins/bit_invader/bit_invader.cpp: - * plugins/kicker/kicker.cpp: - * plugins/lb302/lb302.cpp: - * plugins/patman/patman.cpp: - * plugins/plucked_string_synth/plucked_string_synth.cpp: - * plugins/polyb302/polyb302.cpp: - * plugins/singerbot/singerbot.cpp: - * plugins/stk/mallets/mallets.cpp: - * plugins/vibed/vibed.cpp: - added check for framesLeftForCurrentPeriod() being zero - fixes - segfault in some cases - - * src/tracks/instrument_track.cpp: - - do not simply pass-through _frames-parameter, use - notePlayHandle::framesLeftForCurrentPeriod() if possible - - disabled basic envelopes for the time being - - better handling of monophonic instruments - - do not play new notePlayHandles directly, set offset instead and let - mixer manage the rest - - * src/tracks/sample_track.cpp: - do not play new samplePlayHandles directly, set offset instead and let - mixer manage the rest - - * include/note_play_handle.h: - - removed framesAhead-property - now replaced by offset-property of - base-class - - introduced methods framesLeft() and framesLeftForCurrentPeriod() - - proper usage of them in plugins etc. fixes more clicks/pops especially - in monophonic instruments (LB302!) - - * src/core/mixer.cpp: - call songEditor::processNextBuffer() *before* playing all play-handles - - * src/core/mixer.cpp: - * include/mixer.h: - extended clearAudioBuffer()-methods by offset - - * include/play_handle.h: - added offset-property - - * include/mixer.h: - * most other files: - renamed "framesPerAudioBuffer()" to "framesPerPeriod()" - - * include/types.h: - * most other files: - renamed type "fpab_t" to "fpp_t" - -2007-07-30 Tobias Doerffel - - * plugins/singerbot/singerbot.h: - * include/sample_buffer.h: - * include/audio_device.h: - * configure.in: - * acinclude.m4: - * Makefile.am: - use 3rd-party code if libsamplerate is not available on system - - * src/3rdparty/samplerate/src_linear.c: - * src/3rdparty/samplerate/samplerate.h: - * src/3rdparty/samplerate/fastest_coeffs.h: - * src/3rdparty/samplerate/src_sinc.c: - * src/3rdparty/samplerate/float_cast.h: - * src/3rdparty/samplerate/mid_qual_coeffs.h: - * src/3rdparty/samplerate/src_zoh.c: - * src/3rdparty/samplerate/high_qual_coeffs.h: - * src/3rdparty/samplerate/samplerate.c: - * src/3rdparty/samplerate/common.h: - added libsamplerate-source-code - -2007-07-29 Tobias Doerffel - - * configure.in: - - made 0.3.0-rc1 release - - replaced "+=" operator by according X="$X ..." constructs as older - bashes have problems with it - - * configure.in: - * Makefile.am: - * include/audio_device.h: - * include/sample_buffer.h: - * src/audio/audio_device.cpp: - * src/lib/sample_buffer.cpp: - removed already broken support for building LMMS without libsamplerate - - * acinclude.m4: - disabled Qt4-support - re-enable it / rewrite Qt4-detection code in - 0.4.x-devel-branch - -2007-07-23 Tobias Doerffel - - * plugins/midi_import/midi_import.h: - * plugins/midi_import/midi_import.cpp: - - when adding notes to pattern *never* let them be quantized - fixes - bug where notes of imported MIDI-files were not where they should have - been - - added support for tempo-change-events by modifying - automation-pattern of tempo-knob of track-container (if such exists) - - import track-names - - proper handling of time-base, -division etc. - - * include/midi.h: - added midiMetaEvents-enum - - * include/song_editor.h: - * include/track_container.h: - * src/core/song_editor.cpp: - added virtual tempoAutomationPattern()-method which returns - automation-pattern of tempo-object (i.e. bpmSpinBox) if such exists - for a certain track-container - - * include/automation_pattern.h: - - added non-const version of object()-method - - made lot of other methods const - -2007-07-21 Tobias Doerffel - - * include/mixer.h: - * src/core/mixer.cpp: - added more mutexes to protect all important data-structures more - granularly and safely - fixes some potential segfaults - - * src/tracks/instrument_track.cpp: - - lock mixer while loading instrument / track-specific settings - fixes - segfault when dragging preset/instrument plugin to existing track - while playing - - remove effects in loadTrackSpecificSettings() if none were in preset - (e.g. old preset-file) - - * include/rack_view.h: - * include/effect_tab_widget.h: - * src/widgets/rack_view.cpp: - - delete all existing plugins before adding new ones in - rackView::loadSettings() - - cleanups - - * configure.in: - cleanups - -2007-07-20 Tobias Doerffel - - * lmms.spec.in: - merged changes found in - https://sourceforge.net/tracker/download.php?group_id=105168&atid=640436&file_id=225331&aid=1702303 - - * configure.in: - - cleaned up and improved detection of WINE-development-files and/or - single components of it and removed aeffectx.h-detection-stuff as - not needed anymore - - changed warning on missing STK-files - - several improvements of output-texts - -2007-07-17 Tobias Doerffel - - * configure.in: - - removed unsafe flags - - disabled single-source-compiling per default - - * src/audio/audio_port.cpp: - initialize all member-variables in initialization-list of - audioPort-constructor - this way the audio-port isn't being added to - the mixer before it's completely initialized - fixes some segfaults - - * include/midi.h: - * plugins/midi_import/midi_import.h: - * plugins/midi_import/midi_import.cpp: - - initial incomplete handling for tempo-events - - properly aligned imported notes - -2007-07-16 Tobias Doerffel - - * src/core/mixer.cpp: - fixed logical error in mixer::renderNextBuffer() which led to lot of - clicks and pops when using parallelization-level > 1 - - * include/note_play_handle.h: - * src/tracks/instrument_track-cpp: - fixed broken detection of last period of a note which resulted in - clicks and pops as the soft fade-out at the end sometimes was done twice - -2007-05-12 Javier Serrano Polo - - * include/clipboard.h: - * include/mmp.h: - * include/note.h: - * include/piano_roll.h: - * src/core/note.cpp: - * src/core/piano_roll.cpp: - * src/lib/clipboard.cpp: - * src/lib/mmp.cpp: - use the global clipboard to copy notes - - * include/group_box.h: - * src/core/arp_and_chords_tab_widget.cpp: - * src/core/envelope_tab_widget.cpp: - * src/lib/mmp.cpp: - * src/widgets/group_box.cpp: - save groupbox automation - - * include/surround_area.h: - * src/core/surround_area.cpp: - * src/core/track.cpp: - * src/lib/mmp.cpp: - calculate volume vector in a more consistent way - - * src/core/track.cpp: - fixed drag track onto another segfault - - * include/piano_widget.h: - * src/core/piano_widget.cpp: - fixed release invalid key segfault - - * src/tracks/instrument_track.cpp: - fixed freeze pattern segfault - - * include/preset_preview_play_handle.h: - * src/core/engine.cpp: - * src/core/preset_preview_play_handle.cpp: - fixed uninitialized preset preview container segfault - - * include/main_window.h: - * src/core/main_window.cpp: - added Qt4 menu implementations - - * include/file_browser.h: - * include/qt3support.h: - * src/core/file_browser.cpp: - fixed Qt4 context menu - - * data/locale/ca.ts: - * src/tracks/pattern.cpp: - hide irrelevant freeze options from context menu - -2007-05-07 Javier Serrano Polo - - * include/audio_jack.h: - * include/effect.h: - * include/effect_chain.h: - * include/envelope_and_lfo_widget.h: - * include/instrument_track.h: - * include/mixer.h: - * include/pattern.h: - * include/sample_buffer.h: - * include/shared_object.h: - * plugins/ladspa_base/ladspa_control.cpp: - * plugins/ladspa_base/ladspa_control.h: - * plugins/ladspa_effect/ladspa_effect.cpp: - * src/audio/audio_jack.cpp: - * src/core/effect.cpp: - * src/core/effect_chain.cpp: - * src/core/envelope_and_lfo_widget.cpp: - * src/core/envelope_tab_widget.cpp: - * src/core/file_browser.cpp: - * src/core/mixer.cpp: - * src/core/piano_roll.cpp: - * src/core/song_editor.cpp: - * src/core/track.cpp: - * src/core/track_container.cpp: - * src/lib/oscillator.cpp: - * src/lib/sample_buffer.cpp: - * src/tracks/instrument_track.cpp: - * src/tracks/pattern.cpp: - - removed process locks - - use mixer lock if necessary - - * include/detuning_helper.h: - initial release, light replacement for the note detuning knob - - * Makefile.am: - * include/automatable_object.h: - * include/automatable_object_templates.h: - * include/note.h: - * include/note_play_handle.h: - * src/core/note.cpp: - * src/core/note_play_handle.cpp: - use detuning helpers - - * Makefile.am: - * include/note_play_handle.h: - * src/core/note_play_handle.cpp: - dropped QObject inheritance - - * include/note_play_handle.h: - * src/core/arp_and_chords_tab_widget.cpp: - * src/core/note_play_handle.cpp: - simplified subnote creation - - * include/pattern.h: - * include/piano_roll.h: - * src/core/piano_roll.cpp: - * src/tracks/instrument_track.cpp: - note list became read-only - - * include/oscillator.h: - * plugins/organic/organic.cpp: - * plugins/triple_oscillator/triple_oscillator.cpp: - * src/lib/oscillator.cpp: - use references instead of pointers - - * include/oscillator.h: - * include/sample_buffer.h: - use read-only user waveform - - * include/custom_events.h: - initial release, custom events list - - * include/update_event.h: - initial release, allow thread-safe GUI updates - - * Makefile.am: - * include/fade_button.h: - * include/piano_widget.h: - * src/core/piano_widget.cpp: - * src/widgets/fade_button.cpp: - use thread-safe GUI updates - - * include/automation_editor.h: - * include/piano_roll.h: - * src/core/automation_editor.cpp: - * src/core/piano_roll.cpp: - simplified paint event - - * include/instrument.h: - * include/instrument_play_handle.h: - * include/mixer.h: - * include/note_play_handle.h: - * include/play_handle.h: - * include/preset_preview_play_handle.h: - * include/sample_play_handle.h: - * include/track.h: - * plugins/vestige/vestige.cpp: - * src/core/instrument.cpp: - * src/core/mixer.cpp: - * src/core/note_play_handle.cpp: - * src/core/preset_preview_play_handle.cpp: - * src/core/sample_play_handle.cpp: - * src/tracks/bb_track.cpp: - * src/tracks/instrument_track.cpp: - * src/tracks/sample_track.cpp: - simplified handle removal - - * include/mixer.h: - - removed duplicate playHandles() - - removed unnecessary private copy constructor - - * include/track.h: - * include/track_container.h: - * src/core/track.cpp: - * src/core/track_container.cpp: - simplified track clonation - - * include/track.h: - * src/core/track.cpp: - simplified track removal - - * include/instrument_track.h: - * include/note_play_handle.h: - * src/core/note_play_handle.cpp: - * src/tracks/instrument_track.cpp: - - moved piano widget control to instrument track - - calculate frequencies in note play handle - - * include/note_play_handle.h: - * plugins/organic/organic.cpp: - * plugins/triple_oscillator/triple_oscillator.cpp: - public note frequency became read-only - - * plugins/audio_file_processor/audio_file_processor.cpp: - * plugins/bit_invader/bit_invader.cpp: - * plugins/lb302/lb302.cpp: - * plugins/patman/patman.cpp: - * plugins/plucked_string_synth/plucked_string_synth.cpp: - * plugins/polyb302/polyb302.cpp: - * plugins/singerbot/singerbot.cpp: - * plugins/stk/mallets/mallets.cpp: - * plugins/vibed/vibed.cpp: - use precalculated note frequency - - * include/automatable_object_templates.h: - reduced XML size for single-valued patterns - - * src/core/automation_pattern.cpp: - * src/tracks/automation_pattern.cpp: - - moved to core - - initialize copy constructor - - * include/automation_pattern.h: - * src/core/automation_pattern.cpp: - - show read-only data - - disconnect single-valued patterns from track - - * include/level_object.h: - * src/core/automation_pattern.cpp: - added display name - - * include/project_version.h: - * src/lib/project_version.cpp: - initial release, compare application versions - - * include/mmp.h: - * src/core/arp_and_chords_tab_widget.cpp: - * src/core/song_editor.cpp: - * src/lib/mmp.cpp: - * src/tracks/sample_track.cpp: - added upgrade feature - - * Makefile.am: - * src/lmms_single_source.cpp: - - moved automation pattern to core - - added project version - - * include/arp_and_chords_tab_widget.h: - * include/audio_jack.h: - * include/audio_oss.h: - * include/audio_port.h: - * include/audio_sdl.h: - * include/automatable_slider.h: - * include/automation_editor.h: - * include/automation_pattern.h: - * include/config_mgr.h: - * include/effect.h: - * include/effect_control_dialog.h: - * include/effect_label.h: - * include/effect_tab_widget.h: - * include/engine.h: - * include/envelope_tab_widget.h: - * include/fifo_buffer.h: - * include/instrument.h: - * include/instrument_track.h: - * include/level_object.h: - * include/main_window.h: - * include/meter_dialog.h: - * include/midi_dummy.h: - * include/midi_event_processor.h: - * include/midi_port.h: - * include/mixer.h: - * include/note_play_handle.h: - * include/pattern.h: - * include/piano_roll.h: - * include/piano_widget.h: - * include/plugin.h: - * include/preset_preview_play_handle.h: - * include/rack_plugin.h: - * include/rack_view.h: - * include/sample_play_handle.h: - * include/sample_track.h: - * include/side_bar.h: - * include/surround_area.h: - * include/tempo_sync_knob.h: - * include/tool.h: - * include/track_container.h: - * include/volume_knob.h: - * plugins/audio_file_processor/audio_file_processor.cpp: - * plugins/bass_booster/bassbooster_control_dialog.cpp: - * plugins/bit_invader/bit_invader.cpp: - * plugins/flp_import/flp_import.cpp: - * plugins/kicker/kicker.cpp: - * plugins/ladspa_base/ladspa_control.cpp: - * plugins/ladspa_base/ladspa_control.h: - * plugins/ladspa_base/ladspa_manager.h: - * plugins/ladspa_effect/ladspa_control_dialog.h: - * plugins/lb302/lb302.cpp: - * plugins/lb302/lb302.h: - * plugins/organic/organic.cpp: - * plugins/patman/patman.cpp: - * plugins/plucked_string_synth/plucked_string_synth.cpp: - * plugins/polyb302/polyb302.cpp: - * plugins/polyb302/polyb302.h: - * plugins/singerbot/singerbot.cpp: - * plugins/singerbot/singerbot.h: - * plugins/stk/mallets/mallets.cpp: - * plugins/stk/mallets/mallets.h: - * plugins/triple_oscillator/triple_oscillator.cpp: - * plugins/vestige/vestige.cpp: - * plugins/vestige/vestige.h: - * plugins/vibed/impulse_editor.cpp: - * plugins/vibed/vibed.cpp: - * plugins/vst_effect/vst_control_dialog.cpp: - * plugins/vst_effect/vst_effect.cpp: - * plugins/vst_effect/vst_subplugin_features.cpp: - * src/core/automation_pattern.cpp: - * src/core/effect_control_dialog.cpp: - * src/core/effect_tab_widget.cpp: - * src/core/envelope_tab_widget.cpp: - * src/core/midi_tab_widget.cpp: - * src/core/piano_widget.cpp: - * src/core/plugin.cpp: - * src/core/surround_area.cpp: - * src/core/track.cpp: - * src/tracks/instrument_track.cpp: - * src/tracks/sample_track.cpp: - * src/widgets/automatable_slider.cpp: - * src/widgets/effect_label.cpp: - * src/widgets/rack_plugin.cpp: - * src/widgets/tempo_sync_knob.cpp: - reduced dependencies - - * plugins/ladspa_base/ladspa_manager.cpp: - * plugins/lb302/lb302.cpp: - * plugins/lb302/lb302.h: - * src/audio/audio_port.cpp: - * src/core/engine.cpp: - * src/midi/midi_client.cpp: - * src/tracks/instrument_track.cpp: - * src/widgets/knob.cpp: - * src/widgets/rack_view.cpp: - fixed memory leaks - - * include/automatable_object_templates.h: - * plugins/plucked_string_synth/plucked_string_synth.cpp: - * plugins/singerbot/singerbot.cpp: - * plugins/vibed/vibrating_string.cpp: - * src/core/envelope_and_lfo_widget.cpp: - * src/lib/sample_buffer.cpp: - simplified deletions - - * include/song_editor.h: - * src/core/song_editor.cpp: - improved destructor workaround (still a workaround) - - * src/core/timeline.cpp: - avoid invalid reference - - * src/core/config_mgr.cpp: - removed invariant condition - - * src/core/automation_editor.cpp: - * src/core/envelope_and_lfo_widget.cpp: - * src/core/piano_roll.cpp: - reordered inline functions - - * src/core/plugin.cpp: - initialize dummy plugin subfeatures - - * include/effect_chain.h: - * src/core/effect_chain.cpp: - - normalized destructor - - renamed deleteEffect() to removeEffect(), the effect isn't deleted - actually - - simplified removeEffect() - - * src/widgets/rack_view.cpp: - simplified deletePlugin() - - * include/rack_plugin.h: - * src/widgets/rack_plugin.cpp: - - fixed hot insertion/removal - - simplified context menu - - * src/lib/project_journal.cpp: - initialize journalling state - - * include/arp_and_chords_tab_widget.h: - arpeggio directions are public - - * src/core/midi_tab_widget.cpp: - spin boxes are initially disabled - - * plugins/ladspa_base/ladspa_control.cpp: - * plugins/ladspa_effect/ladspa_control_dialog.cpp: - disabled link automation - - * plugins/audio_file_processor/audio_file_processor.cpp: - * plugins/audio_file_processor/audio_file_processor.h: - - save/load start/end knobs automation - - don't reset start/end knob values when changing the sample file - - removed unused setStartAndEndKnob() - - * plugins/polyb302/polyb302.cpp: - * plugins/polyb302/polyb302.h: - removed slide toggle - - * include/effect_label.h: - * src/widgets/effect_label.cpp: - - delete related effect window - - display label text - - * include/audio_device.h: - * include/audio_dummy.h - * include/midi_client.h: - * include/midi_dummy.h: - hide empty settings box - - * include/pattern.h: - * plugins/flp_import/flp_import.cpp: - * src/tracks/pattern.cpp: - - simplified beat insertion/display - - removed unused functions - - * include/mixer.h: - * src/tracks/pattern.cpp: - render note tails in frozen patterns - - * plugins/organic/organic.cpp: - * plugins/organic/organic.h: - * plugins/triple_oscillator/triple_oscillator.cpp: - * plugins/triple_oscillator/triple_oscillator.h: - added oscillator objects - - * plugins/organic/organic.cpp: - * plugins/organic/organic.h: - - normalized member names - - simplified waveshape selection - - * include/automatable_object.h: - * include/knob.h: - * src/widgets/knob.cpp: - * src/widgets/volume_knob.cpp: - removed automatable object custom data - - * plugins/singerbot/singerbot.cpp: - * plugins/singerbot/singerbot.h: - - reworked play process without sample buffers - - retry wave generation on damaged environment - - * configure.in: - * plugins/ladspa_effect/Makefile.am: - added --without-caps configure option - - * configure.in: - added extra compilation warnings - - * include/qt3support.h: - removed (non-)bug comment - - * data/locale/ca.ts: - updated translation - -2007-04-25 Javier Serrano Polo - - * include/basic_filters.h: - * plugins/flp_import/flp_import.cpp: - * src/core/envelope_tab_widget.cpp: - simplified filtering - - * plugins/vst_base/lvsl_server.c: - clear output buffers before processing - - * plugins/vestige/vestige.cpp: - * plugins/vst_base/lvsl_client.cpp: - * plugins/vst_base/lvsl_client.h: - fixed sample rate change - - * data/locale/ca.ts: - updated translation - -2007-04-24 Javier Serrano Polo - - * include/buffer_allocator.h: - * src/lib/buffer_allocator.cpp: - removed, obsoleted by small audio buffers - - * Makefile.am: - * include/audio_device.h: - * plugins/audio_file_processor/audio_file_processor.cpp: - * plugins/bit_invader/bit_invader.cpp: - * plugins/kicker/kicker.cpp: - * plugins/ladspa_effect/ladspa_effect.cpp: - * plugins/lb302/lb302.cpp: - * plugins/organic/organic.cpp: - * plugins/patman/patman.cpp: - * plugins/plucked_string_synth/plucked_string_synth.cpp: - * plugins/polyb302/polyb302.cpp: - * plugins/singerbot/singerbot.cpp: - * plugins/stk/mallets/mallets.cpp: - * plugins/stk/mallets/mallets.h: - * plugins/triple_oscillator/triple_oscillator.cpp: - * plugins/vestige/vestige.cpp: - * plugins/vibed/vibed.cpp: - * plugins/vibed/vibed.h: - * plugins/vibed/vibrating_string.cpp: - * plugins/vibed/vibrating_string.h: - * plugins/vst_effect/vst_effect.cpp: - * src/lmms_single_source.cpp: - * src/audio/audio_alsa.cpp: - * src/audio/audio_device.cpp: - * src/audio/audio_file_device.cpp: - * src/audio/audio_file_wave.cpp: - * src/audio/audio_jack.cpp: - * src/audio/audio_oss.cpp: - * src/audio/audio_port.cpp: - * src/audio/audio_sample_recorder.cpp: - * src/audio/audio_sdl.cpp: - * src/core/main_window.cpp: - * src/core/mixer.cpp: - * src/core/sample_play_handle.cpp: - * src/tracks/pattern.cpp: - * src/widgets/visualization_widget.cpp: - removed buffer allocator - - * include/automatable_object_templates.h: - initial release, templates extracted from automatable_object.h - - * Makefile.am: - * include/automatable_object.h: - * plugins/ladspa_base/ladspa_control.cpp: - * plugins/ladspa_effect/ladspa_effect.h: - * plugins/patman/patman.cpp: - * plugins/singerbot/singerbot.cpp: - * src/core/automation_editor.cpp: - * src/core/bb_editor.cpp: - * src/core/envelope_and_lfo_widget.cpp: - * src/core/export_project_dialog.cpp: - * src/core/note.cpp: - * src/core/note_play_handle.cpp: - * src/core/piano_roll.cpp: - * src/core/piano_widget.cpp: - * src/core/setup_dialog.cpp: - * src/core/song_editor.cpp: - * src/core/surround_area.cpp: - * src/core/track.cpp: - * src/tracks/instrument_track.cpp: - * src/tracks/sample_track.cpp: - * src/widgets/automatable_button.cpp: - * src/widgets/automatable_slider.cpp: - * src/widgets/combobox.cpp: - * src/widgets/effect_label.cpp: - * src/widgets/knob.cpp: - * src/widgets/lcd_spinbox.cpp: - * src/widgets/led_checkbox.cpp: - * src/widgets/pixmap_button.cpp: - * src/widgets/rack_plugin.cpp: - * src/widgets/tempo_sync_knob.cpp: - * src/widgets/volume_knob.cpp: - reduced dependencies on automatable object - - * src/audio/audio_device.cpp: - * src/core/export_project_dialog.cpp: - * src/core/mixer.cpp: - fixed deadlocks - - * include/audio_dummy.h: - don't process buffers - - * src/audio/audio_sample_recorder.cpp: - fixed high quality - - * include/basic_filters.h: - * include/envelope_and_lfo_widget.h: - * src/core/envelope_tab_widget.cpp: - simplified envelope processing - - * include/basic_filters.h: - - use samplerate member as sample rate - - reformatted - - * plugins/ladspa_effect/ladspa_subplugin_features.cpp: - reverted layout changes in QT3, fixes descriptions - - * plugins/triple_oscillator/artwork.png: - * plugins/triple_oscillator/triple_oscillator.cpp: - updated GUI - - * include/tempo_sync_knob.h: - * src/widgets/tempo_sync_knob.cpp: - graceful shutdown - - * src/widgets/automatable_button.cpp: - fixed undef - - * plugins/ladspa_effect/caps/Makefile.am: - use DESTDIR - -2007-04-21 Javier Serrano Polo - - * plugins/singerbot/singerbot.cpp: - * src/audio/audio_jack.cpp: - * src/audio/audio_sdl.cpp: - assume 1-case semaphores, fixes single source compilation - - * configure.in: - fixed --enable options - -2007-04-20 Tobias Doerffel - - * plugins/ladspa_effect/ladspa_subplugin_features.cpp: - * plugins/patman/patman.cpp: - * plugins/singerbot/singerbot.h: - * plugins/singerbot/singerbot.cpp: - * plugins/live_tool/live_tool.cpp: - * plugins/polyb302/polyb302.cpp: - * include/fifo_buffer.h: - * include/bb_track.h: - * include/audio_device.h: - * include/midi_client.h: - * include/qt3support.h: - * src/audio/audio_sdl.cpp: - * src/audio/audio_jack.cpp: - * src/core/note_play_handle.cpp: - * src/core/track_container.cpp: - * src/core/tool.cpp: - * src/core/setup_dialog.cpp: - * src/core/track.cpp: - * src/core/effect_select_dialog.cpp: - * src/core/main_window.cpp: - * src/widgets/rack_plugin.cpp: - * src/widgets/tool_button.cpp: - * src/widgets/rack_view.cpp: - * src/widgets/effect_label.cpp: - fixes for Qt4-version - - * plugins/midi_import/midi_import.cpp: - * src/core/automation_editor.cpp: - * src/core/piano_roll.cpp: - added inclusion of debug.h which includes assert.h for not failing to - compile on several platforms - -2007-04-20 Javier Serrano Polo - - * executable files: - removed executable property - -2007-04-19 Javier Serrano Polo - - * include/audio_port.h: - * include/automatable_button.h: - * include/automatable_object.h: - * include/automatable_slider.h: - * include/automation_editor.h: - * include/automation_pattern.h: - * include/bb_editor.h: - * include/bb_track.h: - * include/combobox.h: - * include/cpuload_widget.h: - * include/dummy_plugin.h: - * include/effect.h: - * include/effect_chain.h: - * include/effect_label.h: - * include/effect_select_dialog.h: - * include/engine.h: - * include/envelope_and_lfo_widget.h: - * include/export_project_dialog.h: - * include/file_browser.h: - * include/group_box.h: - * include/import_filter.h: - * include/instrument.h: - * include/journalling_object.h: - * include/knob.h: - * include/lcd_spinbox.h: - * include/led_checkbox.h: - * include/main_window.h: - * include/midi_alsa_raw.h: - * include/midi_alsa_seq.h: - * include/midi_client.h: - * include/midi_dummy.h: - * include/midi_oss.h: - * include/mixer.h: - * include/name_label.h: - * include/note.h: - * include/pattern.h: - * include/piano_roll.h: - * include/pixmap_button.h: - * include/plugin.h: - * include/plugin_browser.h: - * include/preset_preview_play_handle.h: - * include/project_journal.h: - * include/project_notes.h: - * include/rack_view.h: - * include/sample_buffer.h: - * include/sample_play_handle.h: - * include/setup_dialog.h: - * include/song_editor.h: - * include/string_pair_drag.h: - * include/surround_area.h: - * include/tempo_sync_knob.h: - * include/timeline.h: - * include/track_container.h: - * include/visualization_widget.h: - * include/volume_knob.h: - * plugins/audio_file_processor/audio_file_processor.cpp: - * plugins/bass_booster/bass_booster.cpp: - * plugins/bass_booster/bass_booster.h: - * plugins/bass_booster/bassbooster_control_dialog.cpp - * plugins/bit_invader/bit_invader.cpp: - * plugins/bit_invader/graph.cpp: - * plugins/bit_invader/graph.h: - * plugins/flp_import/flp_import.cpp: - * plugins/kicker/kicker.cpp: - * plugins/ladspa_base/ladspa_2_lmms.cpp: - * plugins/ladspa_base/ladspa_2_lmms.h: - * plugins/ladspa_base/ladspa_base.h: - * plugins/ladspa_base/ladspa_control.cpp: - * plugins/ladspa_base/ladspa_control.h: - * plugins/ladspa_base/ladspa_manager.cpp: - * plugins/ladspa_base/ladspa_manager.h: - * plugins/ladspa_base/ladspa_port_dialog.cpp: - * plugins/ladspa_base/ladspa_port_dialog.h: - * plugins/ladspa_effect/ladspa_control_dialog.cpp: - * plugins/ladspa_effect/ladspa_effect.cpp: - * plugins/ladspa_effect/ladspa_effect.h: - * plugins/ladspa_effect/ladspa_subplugin_features.cpp: - * plugins/ladspa_effect/ladspa_subplugin_features.h: - * plugins/lb302/lb302.cpp: - * plugins/live_tool/live_tool.cpp: - * plugins/midi_import/midi_import.cpp: - * plugins/organic/organic.cpp: - * plugins/patman/patman.cpp: - * plugins/plucked_string_synth/plucked_string_synth.cpp: - * plugins/polyb302/polyb302.cpp: - * plugins/polyb302/polyb302.h: - * plugins/singerbot/singerbot.cpp: - * plugins/stk/mallets/mallets.cpp: - * plugins/triple_oscillator/triple_oscillator.cpp: - * plugins/vestige/vestige.cpp: - * plugins/vibed/graph.cpp: - * plugins/vibed/graph.h: - * plugins/vibed/impulse_editor.cpp: - * plugins/vibed/impulse_editor.h: - * plugins/vibed/nine_button_selector.cpp: - * plugins/vibed/nine_button_selector.h: - * plugins/vibed/vibed.cpp: - * plugins/vst_base/lvsl_client.cpp: - * plugins/vst_base/lvsl_client.h: - * plugins/vst_effect/vst_effect.cpp: - * plugins/vst_effect/vst_effect.h: - * plugins/vst_effect/vst_subplugin_features.cpp: - * plugins/vst_effect/vst_subplugin_features.h: - * src/audio/audio_alsa.cpp: - * src/audio/audio_jack.cpp: - * src/audio/audio_oss.cpp: - * src/audio/audio_port.cpp: - * src/audio/audio_sample_recorder.cpp: - * src/core/arp_and_chords_tab_widget.cpp: - * src/core/automation_editor.cpp: - * src/core/bb_editor.cpp: - * src/core/effect.cpp: - * src/core/effect_chain.cpp: - * src/core/effect_control_dialog.cpp: - * src/core/effect_select_dialog.cpp: - * src/core/effect_tab_widget.cpp: - * src/core/engine.cpp: - * src/core/envelope_and_lfo_widget.cpp: - * src/core/envelope_tab_widget.cpp: - * src/core/export_project_dialog.cpp: - * src/core/file_browser.cpp: - * src/core/import_filter.cpp: - * src/core/instrument.cpp: - * src/core/main.cpp: - * src/core/main_window.cpp: - * src/core/meter_dialog.cpp: - * src/core/midi_tab_widget.cpp: - * src/core/mixer.cpp: - * src/core/name_label.cpp: - * src/core/note.cpp: - * src/core/note_play_handle.cpp: - * src/core/piano_roll.cpp: - * src/core/piano_widget.cpp: - * src/core/plugin.cpp: - * src/core/plugin_browser.cpp: - * src/core/preset_preview_play_handle.cpp: - * src/core/sample_play_handle.cpp: - * src/core/setup_dialog.cpp: - * src/core/song_editor.cpp: - * src/core/surround_area.cpp: - * src/core/timeline.cpp: - * src/core/tool.cpp: - * src/core/track.cpp: - * src/core/track_container.cpp: - * src/lib/journalling_object.cpp: - * src/lib/project_journal.cpp: - * src/lib/sample_buffer.cpp: - * src/lib/string_pair_drag.cpp: - * src/midi/midi_alsa_raw.cpp: - * src/midi/midi_alsa_seq.cpp: - * src/midi/midi_client.cpp: - * src/midi/midi_oss.cpp: - * src/tracks/automation_pattern.cpp: - * src/tracks/bb_track.cpp: - * src/tracks/instrument_track.cpp: - * src/tracks/pattern.cpp: - * src/tracks/sample_track.cpp: - * src/widgets/automatable_button.cpp: - * src/widgets/automatable_slider.cpp: - * src/widgets/combobox.cpp: - * src/widgets/cpuload_widget.cpp: - * src/widgets/effect_label.cpp: - * src/widgets/group_box.cpp: - * src/widgets/knob.cpp: - * src/widgets/lcd_spinbox.cpp: - * src/widgets/led_checkbox.cpp: - * src/widgets/pixmap_button.cpp: - * src/widgets/project_notes.cpp: - * src/widgets/rack_plugin.cpp: - * src/widgets/rack_view.cpp: - * src/widgets/tempo_sync_knob.cpp: - * src/widgets/visualization_widget.cpp: - * src/widgets/volume_knob.cpp: - return of the singletons - - * include/fifo_buffer.h: - initial release, allows chunked audio buffer - - * include/audio_alsa.h: - * include/audio_device.h: - * include/audio_dummy.h: - * include/audio_jack.h: - * include/audio_oss.h: - * include/audio_sdl.h: - * include/mixer.h: - * src/audio/audio_alsa.cpp: - * src/audio/audio_device.cpp: - * src/audio/audio_jack.cpp: - * src/audio/audio_oss.cpp: - * src/audio/audio_sdl.cpp: - * src/core/mixer.cpp: - * src/core/setup_dialog.cpp: - use chunked audio buffer - - * src/core/mixer.cpp: - don't delete the audio device when changing quality, fixes JACK without - external server - - * include/sample_buffer.h: - * plugins/audio_file_processor/audio_file_processor.cpp: - * plugins/patman/patman.cpp: - * src/lib/sample_buffer.cpp: - handle different sample rates, fixes many looping patch samples - - * src/core/sample_play_handle.cpp: - fixed high quality - - * plugins/patman/patman.cpp: - automated Loop and Tune modes - - * plugins/audio_file_processor/audio_file_processor.cpp: - automated Loop mode - - * src/core/automation_editor.cpp: - fixed selections - - * src/core/track_container.cpp: - use modularized sample extensions - - * include/string_pair_drag.h: - * plugins/audio_file_processor/audio_file_processor.cpp: - * plugins/patman/patman.cpp: - * src/lib/string_pair_drag.cpp: - changed string pair MIME type - - * src/lib/mmp.cpp: - renamed root element - - * data/lmms.xml: - initial release, project MIME type - - * data/Makefile.am: - install project MIME type - - * data/lmms.desktop: - - added project MIME type - - added Catalan translation - - * include/oscillator.h: - * src/lib/oscillator.cpp: - got switches out of for-loops - - * include/arp_and_chords_tab_widget.h: - * include/effect_tab_widget.h: - * include/instrument_track.h: - * include/midi_tab_widget.h: - * include/track.h: - cleaned up dependencies - - * data/locale/ca.ts: - updated translation - -2007-04-07 Javier Serrano Polo - - * plugins/patman/artwork.png: - * plugins/patman/logo.png: - * plugins/patman/loop_off.png: - * plugins/patman/loop_on.png: - * plugins/patman/Makefile.am: - * plugins/patman/patman.cpp: - * plugins/patman/patman.h: - * plugins/patman/tune_off.png: - * plugins/patman/tune_on.png: - initial release, PatMan instrument plugin - - * include/sample_buffer.h: - * src/lib/sample_buffer.cpp: - - added start/end loop points, different from start/end sample points - - added sample frequency - - reworked resampling, fixes resampling underruns/clicks - - reused try-to-make-relative and try-to-make-absolute file handling - - reused samplerate conversion - - * include/sample_buffer.h: - * include/sample_play_handle.h: - * plugins/audio_file_processor/audio_file_processor.cpp: - * plugins/audio_file_processor/audio_file_processor.h: - * plugins/singerbot/singerbot.cpp: - * src/core/sample_play_handle.cpp: - * src/lib/sample_buffer.cpp: - added per handle state - - * include/engine.h: - * include/file_browser.h: - * include/plugin.h: - * plugins/audio_file_processor/audio_file_processor.cpp: - * plugins/audio_file_processor/audio_file_processor.h: - * src/core/engine.cpp: - * src/core/file_browser.cpp: - * src/core/main_window.cpp: - modularized sample extensions - - * plugins/audio_file_processor/audio_file_processor.cpp: - - check dragged file extension - - accept dragged files from desktop - - fit displayed file name in the background box - - * src/core/track_container.cpp: - fixed track swapping - - * src/tracks/bb_track.cpp: - fixed loading last bb-track name - - * include/pattern.h: - * src/tracks/pattern.cpp: - removed obsolete method - - * plugins/polyb302/polyb302.cpp: - * plugins/polyb302/polyb302.h: - simplified inclusions and comments - - * include/main_window.h: - cosmetic, grouped methods - - * data/locale/ca.ts: - updated translation - -2007-04-01 Tobias Doerffel - - * src/lmms_single_source.cpp: - moved inclusion of file_browser.cpp up as it has problems with headers - included by later files - -2007-03-28 Javier Serrano Polo - - * include/mixer.h: - * include/note_play_handle.h: - * src/core/note_play_handle.cpp: - * src/core/song_editor.cpp: - fixed notes with dynamic tempo - - * include/main_window.h: - * src/core/main_window.cpp: - added online help - - * include/file_browser.h: - * src/core/file_browser.cpp: - - filter directories without relevant content - - simplified entry retrieval - - * include/basic_filters.h: - limit Moog instability - - * src/core/main.cpp: - updated year - - * src/widgets/knob.cpp: - initialize members according to last arrangement - - * data/locale/ca.ts: - updated translation - -2007-03-26 Tobias Doerffel - - * configure.in: - fixed "typo" in help - -2007-03-25 Javier Serrano Polo - - * plugins/polyb302/artwork.png: - * plugins/polyb302/logo.png: - * plugins/polyb302/Makefile.am: - * plugins/polyb302/polyb302.cpp: - * plugins/polyb302/polyb302.h: - initial release, polyphonic version of lb302 plugin - - * include/instrument_track.h: - * include/note_play_handle.h: - * src/core/note_play_handle.cpp: - * src/tracks/instrument_track.cpp: - trigger detuning without signals - - * configure.in: - fixed singerbot error - - * include/knob.h: - arranged private/protected members - - * data/locale/ca.ts: - updated translation - -2007-03-07 Javier Serrano Polo - - * plugins/singerbot/singerbot.cpp: - fixed high quality play - - * data/locale/ca.ts: - shortened some words - -2007-02-28 Javier Serrano Polo - - * src/audio/audio_alsa.cpp: - * src/audio/audio_sdl.cpp: - fixed high quality play - - * include/audio_alsa.h: - * include/audio_device.h: - * include/audio_dummy.h: - * include/audio_jack.h: - * include/audio_oss.h: - * include/audio_sdl.h: - * include/midi_alsa_raw.h: - * include/midi_alsa_seq.h - * include/midi_client.h: - * include/midi_dummy.h: - * include/midi_oss.h: - * include/setup_dialog.h: - * src/core/setup_dialog.cpp: - save device names without localization - - * data/locale/ca.ts: - updated translation - - * plugins/lb302/lb302.cpp: - * src/audio/audio_alsa.cpp: - * src/audio/audio_oss.cpp: - fixed typos - -2007-02-27 Javier Serrano Polo - - * src/widgets/fade_button.cpp: - simplified timer usage, fixes frozen leds and hopefully the segfaults - - * src/core/config_mgr.cpp: - create widgets once - -2007-02-25 Javier Serrano Polo - - * plugins/singerbot/singerbot.cpp: - * plugins/singerbot/singerbot.h: - use libsamplerate - - * plugins/singerbot/singerbot.cpp: - - resample while playing, reduced start-up CPU usage - - joined scheme commands - - * configure.in: - - added libsamplerate dependency to singerbot - - don't add plugin libraries to global LIBS - - * src/core/automation_editor.cpp: - - fixed selection - - values moved at time 0 don't move horizontally - - * src/core/piano_roll.cpp: - little optimization when selecting all notes - - * src/tracks/instrument_track.cpp: - emit sentMidiTime always, pitch automation mustn't be disabled - - * plugins/ladspa_base/ladspa_control.cpp: - * plugins/ladspa_effect/ladspa_effect.cpp: - raise gain range up to 10 - - * include/effect_select_dialog.h: - * include/plugin.h: - * plugins/ladspa_effect/ladspa_subplugin_features.cpp: - * plugins/ladspa_effect/ladspa_subplugin_features.h: - * plugins/vst_effect/vst_subplugin_features.cpp: - * plugins/vst_effect/vst_subplugin_features.h: - * src/core/effect_select_dialog.cpp: - changed description layout - - * plugins/ladspa_effect/ladspa_subplugin_features.cpp: - simplified translations - - * plugins/live_tool/live_tool.cpp: - added what's-this-text - -2007-02-20 Alexey Kouznetsov - - * data/locale/ru.ts: - updated Russian translation - -2007-02-16 Tobias Doerffel - - * Makefile.am: - added include/effect_lib.h to sources-list - -2007-02-03 Paul Giblock - - * plugins/lb302/lb302.cpp: - * plugins/lb302/lb302.h: - * plugins/lb302/artwork.png: - * plugins/lb302/logo.png: - * plugins/lb302/Makefile.am: - * plugins/lb302/README: - Initial release. LB302 Bass Synth beta instrument plugin - - * configure.in: - * plugins/Makefile.am: - * src/tracks/instrument_track.cpp: - Added LB302 support - - * data/projects/misc/lb302_quick.mmp: - Added LB302 demo - - * src/widgets/knob.cpp: - Fixed compile-time bug caused by pointer casted to uint - -2007-01-21 Tobias Doerffel - - * src/core/note_play_handle.cpp: - removed obsolete support for monophonic instruments - - * src/tracks/instrument_track.cpp: - added new code for better support of monophonic instrument - -2007-01-20 Javier Serrano Polo - - * plugins/singerbot/artwork.png: - * plugins/singerbot/logo.png: - * plugins/singerbot/Makefile.am: - * plugins/singerbot/singerbot.h: - * plugins/singerbot/singerbot.cpp: - initial release, SingerBot (experimental) instrument plugin - - * configure.in: - * include/note_play_handle.h: - * plugins/Makefile.am: - * src/core/arp_and_chords_tab_widget.cpp: - * src/core/note_play_handle.cpp: - * src/tracks/instrument_track.cpp: - added singerbot support - - * include/sample_buffer.h: - deleteResampling methods made static - - * plugins/audio_file_processor/audio_file_processor.cpp: - * plugins/organic/organic.cpp: - * plugins/triple_oscillator/triple_oscillator.cpp: - * src/core/note_play_handle.cpp: - * src/tracks/instrument_track.cpp: - call deleteNotePluginData() only if there is plugin data, fixes - unprotected instruments - - * plugins/vestige/vestige.cpp: - trigger deleteNotePluginData() - - * src/tracks/instrument_track.cpp: - avoid double unlock - - * configure.in: - fixed configuring with --with-stk - - * acinclude.m4: - moved QT_TRANSLATIONS_DIR to config.h - - * plugins/flp_import/flp_import.cpp: - * plugins/flp_import/unrtf/word.c: - optimized unsafe loops - - * src/lib/sample_buffer.cpp: - * src/widgets/project_notes.cpp: - minor cosmetic changes - - * include/shared_object.h: - not really thread-safe, will be removed - -2007-01-02 Tobias Doerffel - - * src/core/note.cpp: - fixed segfault in hasDetuningInfo() if m_detuning was NULL - - * README: - * src/core/about_dialog.cpp: - extended copyright from 2006 to 2007 - -2006-12-28 Tobias Doerffel - - * configure.in: - some cleanups and fixes - - * src/tracks/instrument_track.cpp: - before calling mixer::addPlayHandle(), unlock m_notesMutex as in some - cases (when running into xruns) - instrumentTrack::deleteNotePluginData() is called while the mutex is - locked and the program was frozen - - * include/track.h: - * plugins/flp_import/flp_import.cpp: - * plugins/midi_import/midi_import.cpp: - * src/core/file_browser.cpp: - * src/core/preset_preview_play_handle.cpp: - * src/core/song_editor.cpp: - * src/core/track.cpp: - * src/core/track_container.cpp: - * src/tracks/instrument_track.cpp: - changed name of constant CHANNEL_TRACK to INSTRUMENT_TRACK - -2006-12-24 Tobias Doerffel - - * plugins/kicker/kicker.cpp: - changed minimal value for frequency-knobs from 40 to 5 Hz - -2006-12-23 Javier Serrano Polo - - * plugins/kicker/kicker.cpp: - fixed envelope segfault - -2006-12-21 Tobias Doerffel - - * include/note_play_handle.h: - * src/core/note_play_handle.cpp: - added parameter to nphsOfInstrumentTrack() which will cause the method - to add note-play-handles even if they're released - - * include/effect_lib.h: - - renamed bassBosst to fastBastBoost - - added new bassBoost-class based on audacity's bass-boost-effect - - * plugins/kicker/kicker.cpp: - * include/effect_lib.h: - introduced new distortion-class which sounds better than - foldback-distortion - -2006-12-20 Javier Serrano Polo - - * src/widgets/rack_plugin.cpp: - * src/widgets/tempo_sync_knob.cpp: - defer deletion of additional windows, fixes event-loop segfault - -2006-12-20 Tobias Doerffel - - * src/tracks/instrument_track.cpp: - fixed basic envelope - - * plugins/kicker/kicker.h: - * plugins/kicker/kicker.cpp: - * plugins/kicker/logo.png: - * plugins/kicker/artwork.png: - * plugins/kicker/Makefile.am: - * plugins/Makefile.am: - * configure.in: - added Kicker-plugin, a versatile kick- & bassdrum-synthesizer - - * include/sweep_oscillator.h: - added simple sweep-oscillator-class - - * include/effect_lib.h: - - added foldbackDistortion-class - - added process()-methods to monoBase- and stereoBase-class - - added bypass-classes for mono and stereo - - added effect-chaining-class - - * configure.in: - fail if -fomit-frame-pointer is found in compiler-flags and - VST-support is not disabled - -2006-12-19 Javier Serrano Polo - - * include/tool.h: - * src/core/tool.cpp: - initial release, base class for all tool plugins - - * include/plugin.h: - * plugins/ladspa_effect/ladspa_subplugin_features.cpp: - renamed AnalysisTools to Tool - - * include/main_window.h: - * src/core/main_window.cpp: - added tools menu - - * Makefile.am: - * src/lmms_single_source.cpp: - added tool plugins - - * configure.in: - * plugins/live_tool/artwork.png: - * plugins/live_tool/live_tool.cpp: - * plugins/live_tool/live_tool.h: - * plugins/live_tool/logo.png: - * plugins/live_tool/Makefile.am: - added live tool, an example tool plugin - - * plugins/Makefile.am: - - added live tool - - eased SVN merging - - * data/*/Makefile.am: - * data/*/*/Makefile.am: - * plugins/vst_base/Makefile.am: - - removed wildcard extension for POSIX compliance - - fixed additional automake 1.10 issues - -2006-12-18 Tobias Doerffel - - * plugins/bass_booster/bassboster_control_dialog.h: - * plugins/bass_booster/bassboster_control_dialog.cpp: - set changed parameters directly using new set...-methods of effect-lib - (preserves current effect-state and therefore avoids clicks in sound- - stream) - - * include/effect_lib.h: - - renamed class "base" to "monoBase" - - monoToStereoAdaptor can now have different effects for the two - channels - - added stereoToMonoAdaptor - - extended baseBoost-class by several methods - - * plugins/vestige/vestige.h: - * plugins/vestige/vestige.cpp: - added note-state-array for handling sequences of "note-on note-off" - events while the according note is already on which for example is the - case when placing the two notes at the same key next to each other - - until now the plugin started playing the second note but stopped - immediately as the note-off-event of the first note arrived later than - the note-on-event of the second one - - * src/core/instrument.cpp: - always call invalidate() in destructor so (instrumentPlayHandle- - driven) plugins do not have to care about it - - * src/tracks/instrument_track.cpp: - make sure value returned by masterKey() is within allowed range - - * src/core/mixer.cpp: - fixed bug which caused LMMS to crash when using parallelizing-level - above 1 and invalidated play-handles were existing - -2006-12-17 Tobias Doerffel - - * plugins/bass_booster/bassboster_control_dialog.cpp: - * plugins/bass_booster/bassboster_control_dialog.h: - * plugins/bass_booster/bass_boster.h: - * plugins/bass_booster/bass_boster.cpp: - * plugins/bass_booster/Makefile.am: - * plugins/Makefile.am: - * configure.in: - added bassbooster-effect-plugin - - * src/core/effect_select_dialog.cpp: - added support for effects without sub-plugin-support and fixed some - potential crashs - - * include/effect_lib.h: - added simple but powerful template-based effect-library with currently - two basic effects - -2006-12-11 Javier Serrano Polo - - * include/sample_buffer.h: - * src/lib/sample_buffer.cpp: - - fixed SDL_sound decoding - - enabled speex samples - - * src/core/file_browser.cpp: - * src/core/main_window.cpp: - enabled speex samples - - * plugins/ladspa_effect/ladspa_effect.cpp: - fixed adding effect segfault - -2006-12-09 Tobias Doerffel - - * configure.in: - check for ${prefix} before extending CFLAGS etc. - should fix issue - with make-problems when using older automake-versions - - * include/instrument.h: - * include/envelope_tab_widget.h: - * src/core/envelope_tab_widget.cpp: - support for instruments which want to define their own number of - release-frames - - * include/instrument_track.h: - * include/instrument.h: - * src/core/note_play_handle.cpp: - support for monophonic instruments - - * include/mixer.h: - * src/core/mixer.cpp: - made mixer::removePlayHandle() to accept const-pointers - -2006-12-06 Javier Serrano Polo - - * include/note.h: - * src/core/note.cpp: - show detuning in the piano roll - - * include/piano_roll.h: - * src/core/piano_roll.cpp: - - show note detuning - - save last key when starting to play, fixes held notes bug - - removed cursor enter/leave events, they could be ignored - - optimized unsafe loops - - * include/xqmap.h: - initial release, QMap with lowerBound for Qt3 - - * include/automation_pattern.h: - * src/tracks/automation_pattern.cpp: - - use lowerBound find, resets to proper values - - work with inverted midi time - - * include/automation_editor.h: - * src/core/automation_editor.cpp: - - work with inverted midi time - - fixed display of hidden values - - added red cross - - update detuning in the piano roll - - removed cursor enter/leave events, they could be ignored - - optimized unsafe loops - - minor optimizations - - * include/note_play_handle.h: - * src/core/arp_and_chords_tab_widget.cpp: - set subnotes' BB track - - * data/track_icons/*.png: - re-added corrupted images - - * src/core/name_label.cpp: - added bad pixmap protection - - * src/audio/audio_alsa.cpp: - - removed unnecessary asynchronous behaviour, fixes large audio buffers - - fill the whole period buffer, avoids underrun in synchronous mode - - * src/core/setup_dialog.cpp: - don't use the journal - - * include/journalling_object.h: - ease short disabling - - * include/automatable_object.h: - - use light journal disabling - - use the journal if necessary - - * src/widgets/knob.cpp: - * src/widgets/lcd_spinbox.cpp: - * src/widgets/volume_knob.cpp: - use the journal if necessary - - * src/widgets/tempo_sync_knob.cpp: - - change icon when changing mode, fixes automation crash - - disable the journal when calculating sync time - - * src/core/bb_editor.cpp: - don't create TCOs when there aren't any BB tracks - - * src/tracks/instrument_track.cpp: - removed temporary fix - -2006-12-05 Tobias Doerffel - - * plugins/ladspa_effect/caps/Makefile.am: - added include-path of LMMS for successfully compiling CAPS with shipped - LADSPA-header - - * src/tracks/instrument_track.cpp: - integrated patch from Jean-Yves Lefort - -2006-12-04 Tobias Doerffel - - * Makefile.am: - added ladspa-1.1.h to source-file-list - - * plugins/ladspa_effect/caps/basics.h: - include shipped LADSPA-header if none was found during configure - -2006-12-03 Alexey Kouznetsov - - * data/locale/ru.ts: - updated Russian translation - -2006-11-19 Tobias Doerffel - - * plugins/vst_base/lvsl_server.c: - proper handling of pitch-bend-events - - * plugins/vestige/vestige.h: - * plugins/vestige/vestige.cpp: - handle MIDI-events by forwarding them to VST-plugin - - * include/instrument.h: - * src/tracks/instrument_track.cpp: - if supported by according instrument, it now can handle all incoming - MIDI-events (except Noteon and Noteoff) - - * src/midi/midi_alsa_seq.cpp: - more complete implementation of MIDI-event-handling - -2006-11-15 Javier Serrano Polo - - * include/audio_alsa.h: - * src/audio/audio_alsa.cpp: - * src/audio/audio_device.cpp: - * src/audio/audio_file_wave.cpp: - convert-endian-based conversion instead of little-endian-based, - fixes OSS and SDL - - * include/audio_sdl.h: - * src/audio/audio_sdl.cpp: - fill the whole audio buffer - -2006-11-11 Javier Serrano Polo - - * src/core/piano_roll.cpp: - fixed pasting recorded notes segfault - - * configure.in: - turned EXTRAFLAGS into DEFAULTFLAGS - -2006-11-11 Tobias Doerffel - - * plugins/flp_import/flp_import.cpp: - include ctype.h - -2006-11-08 Javier Serrano Polo - - * include/bb_track.h: - * src/tracks/bb_track.cpp: - change color of selected group of TCOs - - * plugins/vst_base/lvsl_server.c: - fixed segfault when initializing some VST plugins - - * src/lib/sample_buffer.cpp: - fixed switching from normal play to resampling play - -2006-10-30 Tobias Doerffel - - * src/lib/string_pair_drag.cpp: - when decoding value of stringPairDrag-class use everything after ":" - instead of first section as the value (string) itself might contain - ":"-characters - makes it possible to drag'n'drop instrument-tracks - with VeSTige-instrument and avoids crash - - * src/core/piano_roll.cpp: - when checking cursor-position in edit-mode (move/resize note), do - comparisons in pixels instead of tact64th - fixes bug that 32th- and - 64th-notes could not be resized - - * src/core/file_browser.cpp: - also recognize "mmpz"-files as projects and load them when - double-clicking them - - * src/tracks/pattern.cpp: - when loading pattern, check type afterwards and correct if necessary - -2006-10-09 Mikael Freeman - - * data/locale/sv.ts: - updated Swedish translation - -2006-09-28 Tobias Doerffel - - * include/setup_dialog.h: - * src/core/main_window.cpp: - * src/core/setup_dialog.cpp: - * src/lib/mmp.cpp: - added support for compressed project ("mmpz"-extension), files are - compressed if extension given to multimediaProject::writeFile() is - mmpz or (if none given) user enabled compression as default - - * data/locale/de.ts: - updated German translation (still incomplete (mainly for - mallets-plugin)) - - * lmms.1: - updated manpage (added link to Wiki and updated description) - - * configure.in: - * include/ladspa-1.1.h: - * plugins/ladspa_base/ladspa_manager.h: - added the latest LADSPA-header to be shipped with LMMS for always - building LMMS with LADSPA-support, even if no ladspa.h was found on - system (still causes warning) - -2006-09-25 Tobias Doerffel - - * configure.in: - * plugins/ladspa_effect/Makefile.am: - * plugins/ladspa_effect/caps/Makefile.am: - added missing Makefile.am and re-added CAPS-support - -2006-09-25 Danny McRae - - * plugins/vibed/vibrating_string.cpp: - 2x oversampling in non-hq-mode to get the instument to sound the - same in both modes - - * configure.in: - * plugins/ladspa_effect/Makefile.am: - removed references to CAPS (sorry about that Toby, but I couldn't get - anything to build with them--there's no make info in the CAPS dir) - -2006-09-25 Tobias Doerffel - - * acinclude.m4: - * configure.in: - * Makefile.am: - * include/piano_roll.h: - * include/piano_widget.h: - * src/core/piano_roll.cpp: - * src/core/piano_widget.cpp: - made LMMS compile with mingw-cross-compiler - - * include/automatable_slider.h: - * plugins/stk/mallets/mallets.cpp: - * plugins/vst_effect/vst_subplugin_features.cpp: - * plugins/vst_effect/vst_subplugin_features.cpp: - * src/core/meter_dialog.cpp: - * src/widgets/automatable_slider.cpp: - * src/widgets/knob.cpp: - * src/widgets/volume_knob.cpp: - Qt4-fixes - - * plugins/audio_file_processor/audio_file_processor.cpp: - * src/lib/sample_buffer.cpp: - removed obsolete inclusion of paths.h - - * include/rack_view.h: - * plugins/ladspa_effect/ladspa_effect.cpp: - * src/core/effect_control_dialog.cpp: - include qt3-support-header first - - * plugins/vst_effect/vst_control_dialog.cpp: - do not try to reparent effect's plugin-widget in destructor - fixes - crash when deleting vst-effect from effect-chain - - * src/lib/mmp.cpp: - do not indent mmp-files anymore as it wastes *a lot* of unneccesary - space - - * data/projects/cool_songs/StrictProduction-Underline.mmp: - added another cool project - - * plugins/ladspa_base/ladspa_manager.cpp: - - always add /usr/lib/ladspa and /usr/local/lib/ladspa to directories - where to search for LADSPA-plugins - - also search in /usr/lib/lmms/ladspa for LADSPA-plugins (that's where - for example CAPS is installed) - - * plugins/ladspa_effect/caps/: - added CAPS (C Audio Plugin Suite) for providing a basic LADSPA-plugin- - collection - -2006-09-23 Tobias Doerffel - - * plugins/vst_effect/vst_control_dialog.cpp: - save and load settings of VST-effect - with this VST-effect-support is - complete for now - - * plugins/vst_base/lvsl_client.h: - * plugins/vst_base/lvsl_client.cpp: - * plugins/vestige/vestige.cpp: - moved code from vestigeInstrument::saveSettings() and - vestigeInstrument::loadSettings() to remoteVSTPlugin - - * plugins/ladspa_effect/ladspa_control_dialog.h: - changed node-name from "controls" to "ladspacontrols" to be more - consistent with naming-conventions - - * plugins/ladspa_effect/ladspa_subplugin_features.h: - * plugins/ladspa_effect/ladspa_subplugin_features.cpp: - moved ladspaSubPluginFeatures-code from LADSPA-base to where it - belongs/is used - in LADSPA-effect - - * data/projects/demos/Zvonsully-RaceTheZBeat.mmp: - * data/projects/cool_songs/Malex-Horizon4.mmp: - added two projects - - * plugins/ladspa_base/ladspa_browser.cpp: - * plugins/ladspa_base/ladspa_subplugin_features.cpp: - removed #ifdef SINGLE_SOURCE_COMPILE, as this doesn't affect plugins - - fixes bug with undefined symbol in libladspaeffect.so - - * configure.in: - enable VST-support per default - - * include/aeffectx.h: - added Javier's header (with dssi-vst-patch) - - * data/lmms: - * data/lmms.desktop: - * data/Makefile.am: - added desktop- and menu-entry-file for LMMS (thanks to Javier for the - latter one on debian-list) - -2006-09-23 Mikael Freeman - - * data/locale/sv.ts: - added first Swedish translation (very incomplete) - -2006-09-22 Tobias Doerffel - - * plugins/vst_base/lvsl_client.cpp: - m_initialized is now set before calling waitForProcessingFinished(), - makes VST-effects work - -2006-09-21 Tobias Doerffel - - * plugins/vst_effect/Makefile.am: - * plugins/vst_effect/logo.png: - * plugins/vst_effect/vst_effect.h: - * plugins/vst_effect/vst_effect.cpp: - * plugins/vst_effect/vst_control_dialog.h: - * plugins/vst_effect/vst_control_dialog.cpp: - * plugins/vst_effect/vst_subplugin_features.h: - * plugins/vst_effect/vst_subplugin_features.cpp: - added plugin for supporting VST-effects inside LMMS - currently very - experimental and incomplete, but it compiles and works somehow ;-) - - * plugins/ladspa_effect/Makefile.am: - generating ladspa_effect.moc not needed ynmore - - * plugins/vestige/Makefile.am: - - use new vstbase-library - - do not link against X11, as not needed anymore - - * plugins/Makefile.am: - * plugins/vst_base/Makefile.am: - * plugins/vst_base/communication.h: - * plugins/vst_base/lvsl_client.h: - * plugins/vst_base/lvsl_client.cpp: - * plugins/vst_base/lvsl_server.c: - * plugins/vst_base/vst_base.cpp: - moved LVSL-code into separate library for allowing multiple - LMMS-plugins to deal with VST-plugins - -2006-09-20 Tobias Doerffel - - * plugins/*/*.png: - * data/locale/*.qm: - * data/samples/*: - * data/themes/*: - re-added all binary files as they were corrupted during SVN-migration - for some reason - - * configure.in: - * Makefile.am: - * plugins/ladspa_base/*: - * include/config_mgr.h: - * include/engine.h: - * include/setup_dialog.h: - * src/audio/audio_port.cpp: - * src/core/config_mgr.cpp: - * src/core/engine.cpp: - * src/core/setup_dialog.cpp: - * src/lmms_single_source.cpp: - moved all LADSPA-related code into separate library against which LMMS - is linked when compiling with LADSPA-support - - * Makefile.cvs: - renamed to Makefile.svn as LMMS-CVS-repo was migrated to subversion - -2006-09-18 Tobias Doerffel - - * plugins/vestige/vestige.h: - * plugins/vestige/vestige.cpp: - * plugin/vestige/lvsl_client.h: - * plugin/vestige/lvsl_client.cpp: - take advantage of LMMS' new parallelizing-support - works indeed the - way expected! all VST-servers are now balanced all over available CPUs - - * plugins/audio_file_processor/audio_file_processor.h: - * plugins/audio_file_processor/audio_file_processor.cpp: - * plugins/bit_invader/bit_invader.h: - * plugins/bit_invader/bit_invader.cpp: - * plugins/organic/organic.h: - * plugins/organic/organic.cpp: - * plugins/plucked_string_synth/plucked_string_synth.h: - * plugins/plucked_string_synth/plucked_string_synth.cpp: - * plugins/mallets/mallets.h: - * plugins/mallets/mallets.cpp: - * plugins/vestige/vestige.h: - * plugins/vestige/vestige.cpp: - * plugins/vibed/vibed.h: - * plugins/vibed/vibed.cpp: - * include/instrument.h: - * include/instrument_play_handle.h: - * include/mixer.h: - * include/note_play_handle.h: - * include/play_handle.h: - * include/plugin.h: - * include/preset_preview_play_handle.h: - * include/sample_play_handle.h: - * include/setup_dialog.h: - * include/track.h: - * src/core/instrument.cpp: - * src/core/mixer.cpp: - * src/core/plugin.cpp: - * src/core/preset_preview_play_handle.cpp: - * src/core/sample_play_handle.cpp: - * src/core/setup_dialog.cpp: - * src/tracks/instrument_track.cpp: - added first simple support for parallelizing sound-processing for - using full power of SMP-systems (e.g. my new dual-core-notebook :-) - -2006-09-17 Javier Serrano Polo - - * include/tempo_sync_knob.h: - fixed save/load segfault in LADSPA controls - - * src/core/song_editor.cpp: - fixed looping when processing the audio buffer - - * include/timeline.h: - * src/core/timeline.cpp: - update loop points state button when loading a project - - * src/core/automation_editor.cpp: - fixed segfault when stopping without pattern - -2006-09-17 Tobias Doerffel - - * plugins/audio_file_processor/audio_file_processor.cpp: - * plugins/bit_invader/bit_invader.cpp: - * plugins/flp_import/flp_import.cpp: - * plugins/midi_import/midi_import.cpp: - * plugins/organic/organic.cpp: - * plugins/plucked_string_synth/plucked_string_synth.cpp: - * plugins/mallets/mallets.cpp: - * plugins/vestige/vestige.cpp: - * plugins/vibed/vibed.cpp: - extended plugin-descriptor by sub_plugin_features-field (for - non-effects likely NULL) - - * include/audio_port.h: - * include/effect.h: - * include/effect_chain.h: - * include/effect_label.h: - * include/effect_tab_widget.h: - * include/instrument.h: - * include/instrument_track.h: - * include/ladspa_browser.h: - * include/ladspa_manager.h: - * include/main_window.h: - * include/plugin.h: - * include/rack_plugin.h: - * include/rack_view.h: - * include/sample_track.h: - * src/lmms_single_source.cpp: - * src/audio/audio_port.cpp: - * src/core/effect.cpp: - * src/core/effect_chain.cp: - * src/core/effect_tab_widget.cpp: - * src/core/import_filter.cpp: - * src/core/ladspa_browser.cpp: - * src/core/main_window.cpp: - * src/core/mixer.cpp: - * src/core/plugin.cpp: - * src/core/plugin_browser.cpp: - * src/tracks/instrument_track.cpp: - * src/tracks/sample_track.cpp: - * src/widgets/effect_label.cpp: - * src/widgets/ladspa_control.cpp: - * src/widgets/rack_plugin.cpp: - * src/widgets/rack_view.cpp: - added generic effect-framework based on LADSPA-effect-code for using - arbitrary effects inside LMMS and using sub-plugins (such as - LADSPA-plugins) transparently at the same time, now writing of any - other effects an begin - - * plugins/ladspa_effect/ladspa_effect.h: - * plugins/ladspa_effect/ladspa_effect.cpp: - * plugins/ladspa_effect/ladspa_control_dialog.h: - * plugins/ladspa_effect/ladspa_control_dialog.cpp: - moved LADSPA-effect-support into separate plugin - - * include/dummy_effect.h: - * include/effect_control_dialog.h: - * include/effect_select_dialog.h: - * include/ladspa_base.h: - * include/ladspa_subplugin_features.h: - * src/core/effect_control_dialog.cpp: - * src/core/effect_select_dialog.cpp: - * src/core/ladspa_subplugin_features.cpp: - added (see description above) - - * include/ladspa_control_dialog.h: - * include/ladspa_description.h: - * include/ladspa_effect.h: - * include/select_ladspa_dialog.h: - * src/core/ladspa_control_dialog.cpp: - * src/core/ladspa_effect.cpp: - * src/core/select_ladspa_dialog.cpp: - removed - - * data/locale/de.ts: - updated German translation - - * configure.in: - - do not set wrong VST_SUPPORT-condition if winegcc was found and - --with-vst specified but VST-headers are missing - - LADSPA-support not experimental anymore and enabled per default when - header is found - - use -O2 per default - -2006-09-11 Javier Serrano Polo - - * plugins/vestige/lvsl_server.c: - save/load all plugin parameters - -2006-09-09 Javier Serrano Polo - - * src/core/automation_editor.cpp: - fixed single source compilation - -2006-09-08 Danny McRae - * configure.in: - fixed check for STK headers and library - - * plugins/stk/mallets/mallets.h: - removed the meaningless index boundary limiter for m_delayRead and - m_delayWrite - - * configure.in: - * plugins/Makefile.am: - * plugins/stk/Makefile.am: - began work on supporting STK instruments - - * plugins/stk/mallets/Makefile.am: - * plugins/stk/mallets/artwork.png: - * plugins/stk/mallets/logo.png: - * plugins/stk/mallets/mallets.h: - * plugins/stk/mallets/mallets.cpp: - added mallets instrument - - * include/config_mgr.h: - * src/core/config_mgr.cpp: - * include/setup_dialog.h: - * src/core/setup_dialog.cpp: - added STK rawwave to directory selector - -2006-09-03 Thomas Girard - - * src/core/file_browser.cpp: - fixed bad project browsing segfault - -2006-09-03 Javier Serrano Polo - - * include/bb_track.h: - * src/core/track.cpp: - integrated Toby's Qt4 fixes - - * src/widgets/tempo_sync_knob.cpp: - - integrated Toby's Qt4 fixes - - connect the meter dialog only when custom sync - - don't set the modified flag on automated changes - - * src/core/song_editor.cpp: - - integrated Toby's Qt4 fixes - - rely on objects to set the modified flag - - * src/core/meter_dialog.cpp: - added names to display in the automation editor - -2006-09-03 Tobias Doerffel - - * acinclude.m4: - * include/effect_tab_widget.h: - * include/ladspa_description.h: - * include/qt3support.h: - * include/rack_view.h: - * include/track.h: - * src/audio/audio_device.cpp: - * src/core/automation_editor.cpp: - * src/core/effect_tab_widget.cpp: - * src/core/envelope_and_lfo_widget.cpp: - * src/core/ladspa_control_dialog.cpp: - * src/core/ladspa_effect.cpp: - * src/core/ladspa_port_dialog.cpp: - * src/core/name_label.cpp: - * src/core/note.cpp: - * src/core/piano_roll.cpp: - * src/lib/ladspa_2_lmms.cpp: - * src/lib/ladspa_manager.cpp: - * src/tracks/automation_pattern.cpp: - * src/tracks/instrument_track.cpp: - * src/widgets/effect_label.cpp: - * src/widgets/ladspa_control.cpp: - * src/widgets/ladspa_description.cpp: - * src/widgets/rack_plugin.cpp: - * src/widgets/rack_view.cpp: - * src/widgets/volume_knob.cpp: - Qt4-compat fixes - -2006-08-30 Danny McRae - * src/widgets/ladspa_control.cpp: - added a lock to prevent segfaults when changing the values - while playing - - * src/core/ladspa_effect.cpp: - corrected the labeling of "(ms)" which were showing up as - "(ms))" - - * Makefile.am: - * src/lmms_single_source.cpp: - * include/meter_dialog.h: - * src/core/meter_dialog.cpp: - * include/tempo_sync_knob.h: - * src/widgets/tempo_sync_knob: - added user definable settings for tempo sync - - * src/core/arp_and_chords_tab_widget.cpp: - - changed arp time knob to save using new tempo sync format - - fixed a bug that was preventing the arp groupbox state from - being restored properly - - * src/core/envelope_and_lfo_widget.cpp: - changed lfo time knob to save using new tempo sync format - -2006-08-28 Javier Serrano Polo - - * COPYING: - updated GPL - - * README: - * source files: - updated FSF address - - * depcomp: - removed generated file - - * mkinstalldirs: - removed auxiliary automake file - -2006-08-27 Javier Serrano Polo - - * include/automation_track.h: - * include/bb_editor.h: - * include/bb_track.h: - * include/instrument_track.h: - * include/sample_track.h: - * src/core/bb_editor.cpp: - * src/core/song_editor.cpp: - * src/tracks/automation_track.cpp: - * src/tracks/bb_track.cpp: - * src/tracks/sample_track.cpp: - removed start frame from play() methods - - * src/tracks/instrument_track.cpp: - - removed start frame from play() methods - - removed checks when sending automation events - - * include/track.h: - - removed start frame from play() methods - - removed checks when sending automation events - - use update() instead of repaint() - - * src/core/track.cpp: - - fixed no bb-track case - - removed checks when sending automation events - - use update() instead of repaint() - - * src/core/track_container.cpp: - * src/widgets/kmultitabbar.cpp: - * src/widgets/text_float.cpp: - use update() instead of repaint() - - * include/automation_editor.h: - * include/piano_roll.h: - * src/core/automation_editor.cpp: - * src/core/piano_roll.cpp: - moved update() reimplementations to methods called from paintEvent() - - * include/envelope_and_lfo_widget.h: - * src/core/envelope_tab_widget.cpp: - optimized envelope and LFO computations - - * src/core/envelope_and_lfo_widget.cpp: - - optimized envelope and LFO computations - - separated sample variables updates from paint events - - * include/combobox.h: - clear the menu when the combobox is cleared - - * src/midi/midi_alsa_seq.cpp: - clean-up properly - -2006-08-24 Javier Serrano Polo - - * include/shared_object.h: - initial release, shared object for use among threads - - * include/sample_buffer.h: - became a shared object - - * src/tracks/instrument_track.cpp: - use sample handles to play frozen patterns, fixes crackling - - * include/pattern.h: - * src/tracks/pattern.cpp: - allow access to the frozen pattern - - * include/sample_play_handle.h: - * src/core/sample_play_handle.cpp: - - react to bb-track mute automation - - added constructor to handle frozen patterns - - use shared sample buffers - - * include/instrument_track.h: - getAudioPort() is required - - * include/sample_track.h: - * src/tracks/sample_track.cpp: - - removed obsolete play() in sampleTCO - - use shared sample buffers - - * src/core/envelope_and_lfo_widget.cpp: - fixed load settings deadlock - - * src/audio/audio_device.cpp: - graceful shutdown - - * include/midi_alsa_seq.h: - * src/midi/midi_alsa_seq.cpp: - added pipe to detect shutdown - - * Makefile.am: - added shared object - -2006-08-22 Tobias Doerffel - - * configure.in: - - changed package-maintainer-email-address to lmms-devel-list - - removed -floop-optimization2-flag as it is deprecated and not - supported by coming GCC 4.2 - -2006-08-20 Javier Serrano Polo - - * include/envelope_and_lfo_widget.h: - * src/core/envelope_and_lfo_widget.cpp: - * src/core/envelope_tab_widget.cpp: - changed busy flag into busy mutex, improves thread safety - -2006-08-18 Javier Serrano Polo - - * src/core/bb_editor.cpp: - removed disabled tracks - - * src/tracks/instrument_track.cpp: - added automation disabled - - * include/bb_track.h: - * include/track.h: - * src/core/track.cpp: - * src/tracks/bb_track.cpp: - renamed disabled track logic to automation disabled - - * include/pattern.h: - * src/tracks/pattern.cpp: - added empty() to check whether there is any relevant note - - * src/lib/oscillator.cpp: - check user waveform presence, fixes organic segfault - - * src/core/name_label.cpp: - changed icon selection, fixes loss of icon - -2006-08-17 Erwin Goossen - - * data/locale/nl.ts: - updated Dutch translation - -2006-08-16 Danny McRae - * src/widgets/tempo_sync_knob.cpp: - changed context menu to only display possible note length - options based on the knob's max value - - * include/ladspa_effect.h: - * src/core/ladspa_effect.cpp: - - added a new port data type TIME for port names containing - "(ms)", "(S)", or "(Seconds)" - - converts units to milliseconds for TIME ports - - * src/widgets/ladspa_control.cpp: - use a tempoSyncKnob for TIME ports - - * src/widgets/automatable_button.cpp: - remove toggled signal sent from method toggle--it's also sent - from setValue, and the double signal was wreaking havoc with - the channel linkings - - * include/ladspa_control.h: - * include/ladspa_control_dialog.h: - * src/core/ladspa_control_dialog.cpp: - * src/widgets/ladspa_control.cpp: - * src/widgets/rack_plugin.cpp: - - added channel link selectors for individual ports - - don't show control edit button for plugins with no controls - -2006-08-16 Erwin Goossen - - * data/locale/nl.ts: - added Dutch translation - -2006-08-15 Javier Serrano Polo - - * include/automatable_object.h: - fixed unlinking objects - - * include/automation_pattern.h: - added constructor for unlinking objects - - * src/tracks/automation_pattern.cpp: - - added constructor for unlinking objects - - don't remove value at position 0 - - * INSTALL: - * Makefile.cvs: - * install-sh: - * missing: - removed more generated files - -2006-08-15 Tobias Doerffel - - * src/widgets/knob.cpp: - support for linking knobs using + drag'n'drop (note that - connetions are not saved!) - -2006-08-15 Danny McRae - * src/widgets/ladspa_control.cpp: - doubled the number of steps in the knobs - - * src/core/ladspa_control_dialog.cpp: - changed linking to default on - - * data/themes/default/effect_plugin.png: - * src/widgets/rack_plugin.cpp: - * src/widgets/rack_view.cpp: - added some texture to the plugin widget - - * src/core/ladspa_control_dialog.cpp: - save and restore the channel link state - - * src/widgets/rack_plugin.cpp: - added deletion of the control view to the dtor to make it clean - up after itself - - * include/automatable_object.h: - * include/ladspa_control.h: - * include/ladspa_control_dialog.h: - * src/core/ladspa_control_dialog.cpp: - * src/core/ladspa_control.cpp: - - added a link channels option to the ladspa controls - - * All of the effects related files: - reformatted to respect the 80 characters per line convention - -2006-08-15 Tobias Doerffel - - * Makefile.cvs: - small makefile to be run before configure for creating/copying all - necessary files - - * config.sub: - * config.guess: - * configure: - * config.h.in: - * ltmain.sh: - removed - -2006-08-14 Danny McRae - * Makefile.am: - * include/ladspa_effect.h: - * src/core/ladspa_effect.cpp: - * include/effect.h: - * include/effect_chain.h: - * include/ladspa_browser: - * include/ladspa_control_dialog.h: - * include/rack_plugin.h: - * select_ladspa_dialog.h: - * src/core/effect.cpp: - * src/core/effect_chain.cpp: - * src/core/ladspa_browser.cpp: - * src/core/ladspa_control_dialog.cpp: - * src/core/select_ladspa_dialog.cpp: - * src/tracks/instrument_track.cpp: - * src/tracks/sample_track.cpp: - * src/widgets/ladspa_control.cpp: - * src/widgets/rack_plugin.cpp: - - separated ladspa specific stuff into a class derived from - effect - - changed the default value range for unhinted ports from - (-99999,99999) to (0,1) - -2006-08-13 Javier Serrano Polo - - * src/tracks/sample_track.cpp: - moved playing to samplePlayHandle, removes crackling - - * include/sample_track.h: - - allow sample buffer access - - getAudioPort() is required - - removed slots, moved playing to samplePlayHandle - - * include/sample_play_handle.h. - * src/core/sample_play_handle.cpp: - - became a QObject - - create handle from sampleTCO - - fill audio buffer from the requested base frame - - made automation-awared - - * Makefile.am: - samplePlayHandle is now a QObject - - * include/sample_buffer.h: - - use fast sample generation, rely on proper waveforms - - removed locks in sample generation - - added lock methods for use in higher levels - - * src/lib/oscillator.cpp: - lock user waveform once per loop - - * data/samples/shapes/low_sine.wav: - low frequency sine for use in the oscillator - - * include/lmms_math.h: - added fast pseudo-random integer generator - - * include/oscillator.h: - - use fast noise generation - - simplified user-wave call, frames must never be 0 - - * include/basic_filters.h: - - added minQ "constant" - - limit Q resonance - - * src/core/envelope_tab_widget.cpp: - added minQ "constant" - -2006-08-10 Danny McRae - * src/widgets/ladspa_control.cpp: - unfixed my misunderstood fix of the setting of sample rate - dependent ports - - * src/core/mixer: - got rid of the "more_effect |= ..." nonsense - - * src/widgets/effect_label.cpp: - * src/widgets/rack_plugin.cpp: - changed the parenting of the control dialog to main window - instead of NULL - -2006-08-11 Tobias Doerffel - - * configure.in: - added check for ctype.h to make LMMS work on Zenwalk-systems - -2006-08-10 Javier Serrano Polo - - * include/bb_track.h: - * include/track.h: - * src/core/bb_editor.cpp: - added disabled tracks - - * src/tracks/bb_track.cpp: - - added disabled tracks - - fixed BB-track 0 cloning bug - - * src/core/track.cpp: - - added disabled tracks - - update track operations menu - - simplified engine access - - fixed BB-track 0 cloning bug - - improved removing automation patterns - - * include/track_container.h: - - moved tracks() to public - - added node name - - * src/core/track_container.cpp: - added node name - - * data/themes/default/mute_on_disabled.png: - * data/themes/default/track_op_menu_disabled.png: - * data/themes/default/mute_off_disabled.png: - * resources/mute_on_disabled.png: - * resources/track_op_menu_disabled.png: - * resources/mute_off_disabled.png: - added disabled track artwork - -2006-08-10 Danny McRae - * include/effect.h: - * include/effect_chain.h: - * include/effect_label.h: - * include/effect_tab_widget.h: - * include/ladspa_control.h: - * include/ladspa_control_dialog.h: - * include/ladspa_description.h: - * include/rack_plugin.h: - * include/rack_view.h: - * src/core/effect.cpp: - * src/core/effect_tab_widget.cpp: - * src/core/ladspa_port_dialog.cpp: - * src/core/ladspa_control_dialog.cpp: - * src/widgets/ladspa_description.cpp: - * src/widgets/rack_plugin.cpp: - * src/widgets/rack_view.cpp: - added Qt4 includes - - * include/config_mgr.h: - * include/setup_dialog.h: - * src/core/config_mgr.cpp: - * src/core/setup_dialog.cpp: - * src/lib/ladspa_manager.cpp: - -added ladspa search path to user configuration - -made ladspa loader ignore all files not ending in "so" - - * include/effect.h: - * src/core/effect.cpp: - * src/widgets/ladspa_control.cpp: - corrected an error in setting the values for sample rate - dependent ports - - the crackling in the sample tracks is due to rounding errors - in the calculation of _start_frame in sampleTrack::play that - cause it to occasionally skip a sample. Don't know what to - do about it--just thought it should be noted somewhere. - -2006-08-09 Danny McRae - * Makefile.am: - * include/effect_label.h: - * include/effect_tab_widget.h: - * include/instrument_track.h: - * include/ladspa_control.h: - * include/ladspa_control_dialog.h: - * include/rack_plugin.h: - * include/rack_view.h: - * src/lmms_single_source.cpp: - * src/audio/audio_port.cpp: - * src/core/effect.cpp: - * src/core/effect_tab_widget.cpp: - * src/core/ladspa_control_dialog.cpp: - * src/core/ladspa_port_dialog.cpp: - * src/tracks/instrument_track.cpp: - * src/tracks/sample_track.cpp: - * src/widgets/ladspa_control.cpp: - * src/widgets/rack_plugin.cpp: - * src/widgets/rack_view.cpp: - -full save and load - -added effects to sample tracks - -fixed the knob twoddling segfaults (hopefully) - -somewhere between 0.2.1 and yesterday a crackling has been - introduced in the sample tracks. My largish checkins - look like an obvious culprit, but it would have to be - something I forgot to #ifdef LADSPA_SUPPORT out. - -2006-08-08 Danny McRae - * include/effect.h: - * include/effect_chain.h: - * include/effect_tab_widget.h: - * include/ladspa_browser.h: - * include/ladspa_control.h: - * include/ladspa_control_dialog.h: - * include/rack_plugin.h: - * include/rack_view.h: - * src/core/effect.cpp: - * src/core/effect_chain.cpp: - * src/core/effect_tab_widget.cpp: - * src/core/ladspa_browser.cpp: - * src/core/ladspa_control_dialog.cpp: - * src/tracks/instrument_track.cpp: - * src/widgets/ladspa_control.cpp: - * src/widgets/rack_plugin.cpp: - * src/widgets/rack_view.cpp: - -added ability to change the order of effects or delete them - -partial save and load support - -still getting spurious segfaults when twoddling with knobs, - the textFloat associated with the knob is being reparented to - NULL(?!), but works well enough to at least hear what things - sound like with effects - -2006-08-07 Danny McRae - * include/oscillator.h: - * plugins/vibed/vibrating_string.h: - * plugins/vibed/vibrating_string.cpp: - clean up some things that were preventing the getNextSample - methods from being inlined - - * configure: - * configure.in: - -made ladspa support default off - -must pass --with-ladspa to get it to build - - * Makefile.am: - * data/themes/default/add.png: - * data/themes/default/analysis.png: - * data/themes/default/ports.png: - * data/themes/default/uhoh.png: - * data/themes/default/unavailable_sound.png: - * data/themes/blue_scene/add.png: - * data/themes/blue_scene/analysis.png: - * data/themes/blue_scene/ports.png: - * data/themes/blue_scene/uhoh.png: - * data/themes/blue_scene/unavailable_sound.png: - * include/audio_port.h: - * include/effect_chain.h: - * include/effect_tab_widget.h: - * include/effect.h: - * include/engine.h: - * include/group_box.h: - * include/instrument_track.h: - * include/ladspa_2_lmms.h: - * include/ladspa_browser.h: - * include/ladspa_control.h: - * include/ladspa_control_dialog.h: - * include/ladspa_description.h: - * include/ladspa_manager.h: - * include/ladspa_port_dialog.h: - * include/main_window.h: - * include/rack_plugin.h: - * include/rack_view.h: - * include/select_ladspa_dialog.h: - * src/lmms_single_source.cpp: - * src/audio/audio_port.cpp: - * src/core/effect_chain.cpp: - * src/core/effect_tab_widget.cpp: - * src/core/effect.cpp: - * src/core/engine.cpp: - * src/core/ladspa_browser.cpp: - * src/core/ladspa_control.cpp: - * src/core/ladspa_port_dialog.cpp: - * src/core/main_window.cpp: - * src/core/mixer.cpp: - * src/core/select_ladspa_dialog.cpp: - * src/lib/ladspa_2_lmms.cpp: - * src/lib/ladspa_manager.cpp: - * src/tracks/instrument_track.cpp: - * src/widgets/group_box.cpp: - * src/widgets/ladspa_control.cpp: - * src/widgets/ladspa_description.cpp: - * src/widgets/rack_plugin.cpp: - * src/widgets/rack_view.cpp: - -added preliminary support for ladspa effects - -no load or save - -expect segfaults - -2006-08-07 Javier Serrano Polo - - * include/lcd_spinbox.h: - added manualChange signal - - * src/widgets/lcd_spinbox.cpp: - - added manualChange signal - - emit valueChanged whenever value is changed - - removed redundant journalling operations - - * src/core/song_editor.cpp: - - set modified flag if there's a manual BPM change - - set tempo if BPM value has changed - - allow further processing on muted tracks - - * include/note_play_handle.h: - * src/core/note_play_handle.cpp: - * src/tracks/instrument_track.cpp: - added bbTrack reference to check whether it's muted - - * src/tracks/bb_track.cpp: - send automation events - - * include/mixer.h: - * src/core/mixer.cpp: - fixed overflow when using big audio buffers - - * plugins/audio_file_processor/audio_file_processor.cpp: - use automation in start-/end-point knobs - - * plugins/vibed/vibed.cpp: - fixed reversed pan - -2006-08-06 Javier Serrano Polo - - * include/engine.h: - * include/midi_time.h: - * src/core/engine.cpp: - * src/core/note_play_handle.cpp: - * src/tracks/bb_track.cpp: - * src/tracks/sample_track.cpp: - frames computation based on 64th of a tact, fixes BB-pattern arbitrary - positioning in song editor - - * include/song_editor.h: - * src/core/song_editor.cpp: - - frames computation based on 64th of a tact - - changed playPos frame counter to float, improves timing precision - - * src/tracks/instrument_track.cpp: - - frames computation based on 64th of a tact - - simplified note playing - -2006-08-03 Javier Serrano Polo - - * src/core/automation_editor.cpp: - - fixed vertical bars in Auto view - - fixed selection frame drawing - - renamed some members and variables - - * include/automation_editor.h: - renamed some members - -2006-08-01 Javier Serrano Polo - - * include/automation_editor.h: - added "Auto" view - - * src/core/automation_editor.cpp: - - added "Auto" view - - improved labels display - - removed duplicate variable y_base - - * include/song_editor.h: - * src/core/engine.cpp: - * src/core/song_editor.cpp: - - moved framesPerTact() from songEditor to engine - - update frames per tact only when changes happen - - * include/engine.h: - * src/core/note_play_handle.cpp: - * src/tracks/bb_track.cpp: - * src/tracks/instrument_track.cpp: - * src/tracks/sample_track.cpp: - moved framesPerTact() from songEditor to engine - -2006-07-27 Tobias Doerffel - - * configure.in: - made 0.2.1 release - - * include/mixer.h: - * include/visualization_widget.h: - * src/widgets/visualization_widget.cpp: - fixed a bug in connection between mixer and visualization-widget - -2006-07-24 Javier Serrano Polo - - * src/tracks/instrument_track.cpp: - handle notes deleted when keys still pressed - - * include/song_editor.h: - * src/core/note.cpp: - * src/core/song_editor.cpp: - added checks to avoid segfaults when closing the application - -2006-07-23 Javier Serrano Polo - - * src/core/piano_widget.cpp: - initialize m_lastKey, fixes segfault - - * src/core/automation_editor.cpp: - * src/core/note_play_handle.cpp: - added checks to avoid segfaults when closing the application - -2006-07-22 Javier Serrano Polo - - * include/automatable_object.h: - avoid unnecessary level updates - - * include/track.h: - * src/tracks/instrument_track.cpp: - trigger automation only when time has changed - - * src/core/track.cpp: - - trigger automation only when time has changed - - remove references from patterns when closing the application - - * include/automation_pattern.h: - added method to avoid segfaults when closing the application - - * src/tracks/automation_pattern.cpp: - - added check to avoid segfaults when closing the application - - reverted processMidiTime(), that processing is needed - - * src/core/track_container.cpp: - * src/lib/journalling_object.cpp: - added checks to avoid segfaults when closing the application - - * include/engine.h: - * src/core/engine.cpp: - - do the clean-up in close() - - ensure deleted elements aren't accessed - - * src/core/main_window.cpp: - close the engine rather than delete it - - * include/instrument_track.h: - allow access to the piano widget - - * include/piano_widget.h: - moved key event handlers to public - - * include/piano_roll.h: - redirect events to the piano widget - - * src/core/piano_roll.cpp: - - changed some accelerators - - redirect keyboard events to the piano widget - - fixed segfault when pressing Ctrl with no pattern - - * src/core/automation_editor.cpp: - changed some accelerators - - * src/core/song_editor.cpp: - play the automation track only when playing song - - * include/automation_track.h: - removed unused signal section - - * data/locale/ca.ts: - updated translation - -2006-07-21 Danny McRae - - * configure.in: - - removed -fomit-frame-pointer flag--causes wine to crash on - Ubuntu - - added check for gcc 4.0 for optimization flags--left it - commented out--needs to be tested with 4.1 - -2006-07-20 Tobias Doerffel - - * src/tracks/automation_pattern.cpp: - automationPattern::processMidiTime(): do not start search on time-map if - empty - find() on maps is horribly slow and makes LMMS unusable (still - have to find a better solution without any find()s at all) - -2006-07-19 Tobias Doerffel - - * configure.in: - - added optimization-flags - - made 0.2.0 release - - * vst_sdk23_headers.diff: - - removed as not needed anymore - -2006-07-17 Tobias Doerffel - - * data/locale/de.ts: - * data/locale/de.qm: - updated German translation - - * include/automation_editor.h: - decreased DEFAULT_Y_DELTA - - * plugins/flp_import/flp_import.cpp: - removed some obsolete code - -2006-07-17 dieEasy - - * locale/it.ts: - updated Italian translation - -2006-07-16 Javier Serrano Polo - - * data/themes/default/automation.png: - * resources/automation.png: - * src/core/automation_editor.cpp: - * src/core/main_window.cpp: - * src/core/piano_roll.cpp: - * src/core/piano_widget.cpp: - * src/core/surround_area.cpp: - * src/widgets/automatable_button.cpp: - * src/widgets/automatable_slider.cpp: - * src/widgets/combobox.cpp: - * src/widgets/knob.cpp: - * src/widgets/lcd_spinbox.cpp: - * src/widgets/tempo_sync_knob.cpp: - added automation icon - -2006-07-15 Javier Serrano Polo - - * data/locale/ca.ts: - updated translation - - * src/core/automation_editor.cpp: - corrected help sentence - -2006-07-14 Javier Serrano Polo - - * include/note.h: - * src/core/note.cpp: - - added detuning knob - - added explicit constructor from another note - - * include/note_play_handle.h: - * src/core/note_play_handle.cpp: - handle detuning automation - - * include/instrument_track.h: - send a signal when handling automation - - * src/tracks/instrument_track.cpp: - - send a signal when handling automation - - use note detuning to calculate frequency - - * src/core/arp_and_chords_tab_widget.cpp: - extended detuning to chords and arpeggios - - * include/automation_pattern.h: - * src/tracks/automation_pattern.cpp: - - automation pattern can be initialized without track - - slots moved to public - - * include/automatable_object.h: - automation pattern can be initialized without track - - * src/core/song_editor.cpp: - * src/widgets/automatable_slider.cpp: - updated clear automation method name - - * include/piano_roll.h: - added open (note in editor) mode and support methods - - * src/core/piano_roll.cpp: - - added open (note in editor) mode and support methods - - clone detuning knobs when copying/pasting notes - - * src/core/automation_editor.cpp: - - improved display when no pattern - - play buttons can be used to play related note patterns - - improved play/pause button display - -2006-07-10 Javier Serrano Polo - - * include/combobox.h: - * src/widgets/combobox.cpp: - - use automation capabilities - - added context menu - - * src/core/arp_and_chords_tab_widget.cpp: - * src/core/automation_editor.cpp: - * src/core/envelope_tab_widget.cpp: - * src/core/export_project_dialog.cpp: - * src/core/piano_roll.cpp: - upgraded combo boxes - - * src/core/bb_editor.cpp: - - upgraded combo box - - improved bb-track management - - * src/tracks/bb_track.cpp: - - update bb editor combo box when removed - - moving track is the active one - - * src/core/song_editor.cpp: - - upgraded combo box - - use default template to create new projects - - * include/main_window.h: - * src/core/main_window.cpp: - - added user templates to templates menu - - update templates menu when accessed - -2006-07-09 Javier Serrano Polo - - * include/piano_widget.h: - * src/core/piano_widget.cpp: - - use automation capabilities using a helper knob - - added context menu - - added save/load methods - - use raw keycodes to play the piano - - * include/instrument_track.h: - * src/tracks/instrument_track.cpp: - - don't set song modified flag when playing automation - - use piano widget save/load methods - -2006-07-08 Javier Serrano Polo - - * include/automation_track.h: - * src/tracks/automation_track.cpp: - initial release, to handle automation of objects without a track - - * include/lcd_spinbox.h: - * src/widgets/lcd_spinbox.cpp: - - use automation capabilities - - added context menu - - * include/automatable_slider.h: - * src/widgets/automatable_slider.cpp: - initial release, slider with automation - - * include/song_editor.h: - * src/core/song_editor.cpp: - - use automatable sliders - - use automation track - - upgraded lcd spin box - - joined some slider creation code between QT versions - - show slider status on manual change only - - * include/track.h: - * src/core/track.cpp: - added automation track - - * src/audio/audio_alsa.cpp: - * src/audio/audio_jack.cpp: - * src/audio/audio_oss.cpp: - * src/core/midi_tab_widget.cpp: - * src/tracks/instrument_track.cpp: - upgraded lcd spin boxes - - * include/automatable_object.h: - check whether the automation editor has been created - - * src/core/surround_area.cpp: - fixed position rounding - - * Makefile.am: - * src/lmms_single_source.cpp: - added automatable_slider and automation_track - -2006-07-03 Javier Serrano Polo - - * plugins/audio_file_processor/audio_file_processor.cpp: - removed all automation - - * src/widgets/automatable_button.cpp: - button groups may not use automation - - * src/widgets/knob.cpp: - knobs may not use automation - - * include/automatable_object.h: - - moved update flag to automation pattern - - moved nullTrack() to public - - * include/automation_pattern.h: - * src/tracks/automation_pattern.cpp: - moved update flag from automatable object - -2006-07-02 Javier Serrano Polo - - * include/surround_area.h: - * src/core/surround_area.cpp: - - use automation capabilities using helper knobs - - added context menu - - added save/load methods - - * include/instrument_track.h: - * src/tracks/instrument_track.cpp: - use upgraded surround area - - * include/automatable_button.h: - * src/widgets/automatable_button.cpp: - - use automation capabilities in button and button group - - added button context menu - - * include/group_box.h: - * include/led_checkbox.h: - * include/pixmap_button.h: - * plugins/audio_file_processor/audio_file_processor.cpp: - * plugins/vestige/vestige.cpp: - * plugins/vibed/impulse_editor.cpp: - * plugins/vibed/impulse_editor.h: - * plugins/vibed/nine_button_selector.cpp: - * plugins/vibed/nine_button_selector.h: - * plugins/vibed/vibed.cpp: - * src/core/envelope_tab_widget.cpp: - * src/core/export_project_dialog.cpp: - * src/core/midi_tab_widget.cpp: - * src/core/setup_dialog.cpp: - * src/core/track.cpp: - * src/widgets/group_box.cpp: - * src/widgets/led_checkbox.cpp: - * src/widgets/pixmap_button.cpp: - upgraded buttons - - * plugins/bit_invader/bit_invader.cpp: - - upgraded buttons - - use sample length knob automation - - * plugins/organic/organic.cpp: - - upgraded button - - use waveshape knob automation - - * plugins/triple_oscillator/triple_oscillator.cpp: - * src/core/arp_and_chords_tab_widget.cpp: - * src/core/envelope_and_lfo_widget.cpp: - upgraded buttons and button groups - - * include/automatable_object.h: - - moved getAutomationPattern to public - - added some checks and minor fixes - - * src/core/automation_editor.cpp: - improved levels display - - * src/core/song_editor.cpp: - save/load automation editor state - - * src/widgets/tempo_sync_knob.cpp: - added automation editor option in context menu - -2006-06-29 Javier Serrano Polo - - * Makefile.am: - * include/automation_editor.h: - * include/automation_pattern.h: - * include/engine.h: - * include/main_window.h: - * include/song_editor.h: - * include/time_pattern.h: - * include/time_roll.h: - * include/track.h: - * src/lmms_single_source.cpp: - * src/core/automation_editor.cpp: - * src/core/engine.cpp: - * src/core/main_window.cpp: - * src/core/time_roll.cpp: - * src/core/track.cpp: - * src/tracks/automation_pattern.cpp: - * src/tracks/instrument_track.cpp: - * src/tracks/sample_track.cpp: - * src/tracks/time_pattern.cpp: - * src/widgets/knob.cpp: - renamed time* classes to automation* ones - - * include/automatable_object.h: - - renamed time* classes to automation* ones - - fixed int classes rounding - - * plugins/organic/organic.cpp: - save harmonic settings like before - - * data/presets/Organic/organ_risingsun.cs.xml: - * data/presets/Organic/organ_swish.cs.xml: - * data/presets/Organic/pad_ethereal.cs.xml: - * data/presets/Organic/pad_rich.cs.xml: - * data/presets/Organic/pad_sweep.cs.xml: - * data/presets/Organic/sequencer_64.cs.xml: - upgraded to new detuning algorithm - -2006-06-28 Javier Serrano Polo - - * include/level_object.h: - * src/tracks/time_pattern.cpp: - added level<->label methods - - * include/automatable_object.h: - - added level<->label methods - - minimized rounding errors - -2006-06-27 Tobias Doerffel - - * plugins/vestige/lvsl_server.c: - compatibility with older VST-headers (2.0) mentioned by configure - - * acinclude.m4: - * configure.in: - compat-fixes for FreeBSD - -2006-06-27 Javier Serrano Polo - - * include/time_pattern.h: - * src/tracks/time_pattern.cpp: - initial release, pattern for dynamic values - - * include/time_roll.h: - * src/core/time_roll.cpp: - initial release, time pattern editor - - * include/level_object.h: - initial release, mainly used by the time-roll - - * include/automatable_object.h: - - added levelObject inheritance and related functions - - added time pattern - - moved linkObject methods to private for safety - - save/load settings can use generic names and types other than double - - * include/engine.h: - * include/main_window.h: - * src/core/engine.cpp: - * src/core/main_window.cpp: - added time-roll - - * include/knob.h: - * src/widgets/knob.cpp: - - use automation capabilities - - added time-roll option in context menu - - * include/tempo_sync_knob.h: - * include/volume_knob.h: - * src/widgets/automatable_button.cpp: - * src/widgets/lcd_spinbox.cpp: - * src/widgets/tempo_sync_knob.cpp: - * src/widgets/volume_knob.cpp: - added automation - - * include/envelope_and_lfo_widget.h: - * plugins/audio_file_processor/audio_file_processor.cpp: - * plugins/bit_invader/bit_invader.cpp: - * plugins/organic/organic.cpp: - * plugins/plucked_string_synth/plucked_string_synth.cpp: - * plugins/triple_oscillator/triple_oscillator.cpp: - * plugins/vibed/vibed.cpp: - * src/core/arp_and_chords_tab_widget.cpp: - * src/core/envelope_and_lfo_widget.cpp: - * src/core/envelope_tab_widget.cpp: - added automation to many knobs - - * include/track.h: - * src/core/track.cpp: - - added time pattern - - added name methods - - * include/instrument_track.h: - * src/tracks/instrument_track.cpp: - - moved name scope to track - - added automation to knobs - - don't try to load a time pattern plugin - - * src/tracks/sample_track.cpp: - added automation to knob - - * include/note.h: - * src/core/note.cpp: - moved quantized() to public - - * include/qt3support.h: - added QPointer - - * include/song_editor.h: - added time pattern - - * src/core/piano_roll.cpp: - * src/core/song_editor.cpp: - simplified combobox numbers generation - - * data/themes/default/zoom_x.png: - * data/themes/default/zoom_y.png: - * resources/zoom_x.png: - * resources/zoom_y.png: - icons for the time-roll - - * Makefile.am: - * src/lmms_single_source.cpp: - added new files - -2006-06-12 Tobias Doerffel - - * plugins/organic/organic.cpp: - * plugins/organic/organic.h: - * plugins/triple_oscillator/triple_oscillator.cpp: - * plugins/triple_oscillator/triple_oscillator.h: - updated code which uses knob-identification-capabilities - - * include/knob.h: - * include/volume_knob.h: - * src/widgets/knob.cpp: - * src/widgets/volume_knob.cpp: - use data-property of automatableObject for identifying the knob - (replaces the id-stuff) - - * include/automatable_object.h: - added data-property in which any arbitrary information can be stored - -2006-06-10 Javier Serrano Polo - - * src/lib/sample_buffer.cpp: - - fixed bug when sample processor generates less frames than the audio - buffer size - - load full wav samples - - * data/presets/AudioFileProcessor/Fat-Reversed-Kick.cs.xml: - * data/presets/AudioFileProcessor/Kick-4-your-Subwoofer.cs.xml: - upgraded to newer version, end frame value caused segfault - -2006-06-09 Javier Serrano Polo - - * include/lmms_math.h: - * include/oscillator.h: - * include/sample_buffer.h: - * src/lib/oscillator.cpp: - - reverted to PM and added FM as a new modulation method - - improved performance, specially PM/FM - - moved fraction() to global scope - - removed absolute value from userWaveSample, it's handled by fraction() - - * plugins/triple_oscillator/pm_active.png: - * plugins/triple_oscillator/pm_inactive.png: - * plugins/triple_oscillator/triple_oscillator.cpp: - added PM buttons, hid FM ones - - * Makefile.am: - added lmms_math.h - - * data/locale/ca.ts: - updated translation - -2006-06-05 Javier Serrano Polo - - * include/oscillator.h: - * include/panning.h: - * plugins/organic/organic.cpp: - * plugins/organic/organic.h: - * plugins/triple_oscillator/triple_oscillator.cpp: - * plugins/triple_oscillator/triple_oscillator.h: - * src/lib/oscillator.cpp: - oscillator rewrite, now many parameters may be changed between audio - buffer updates - - * Makefile.am: - note_play_handle is now a QObject - - * data/projects/cool_songs/Djeezus-BeatRolls.mmp: - * data/projects/cool_songs/Djeezus-Oscilisous.mmp: - * data/projects/cool_songs/Marfil-MarfilDrum01.mmp: - * data/projects/cool_songs/Mart-Concave_flow.mmp: - * data/projects/cool_songs/Mart-Dirt_Track.mmp: - * data/projects/cool_songs/MaxFellner-Ease.mmp: - * data/projects/cool_songs/SharkyX-DeadManDancing.mmp: - * data/projects/cool_songs/SharkyX-Experiments.mmp: - * data/projects/cool_songs/Siegel-DreamWave.mmp: - * data/projects/cool_songs/TobyDox-Confused.mmp: - * data/projects/cool_songs/TobyDox-Psycho.mmp: - * data/projects/cool_songs/TobyDox-TheFourthDimension.mmp: - * data/projects/covers/J.S.Bach-Preludium_and_Fugue_A-Minor.mmp: - * data/projects/demos/basses-demo.mmp: - * data/projects/demos/beat-collection.mmp: - * data/projects/demos/demo1.mmp: - * data/projects/demos/demo3.mmp: - * data/projects/demos/demo5.mmp: - * data/projects/demos/demo6.mmp: - * data/projects/demos/loop_collection.mmp: - * data/projects/demos/some_basslines.mmp: - * data/projects/misc/1st.mmp: - * data/projects/misc/time_machine.mmp: - * data/projects/templates/AcousticDrumset.mpt: - * data/projects/templates/ClubMix.mpt: - * data/presets/AudioFileProcessor/Bass-Mania.cs.xml: - * data/presets/AudioFileProcessor/Fat-Reversed-Kick.cs.xml: - * data/presets/AudioFileProcessor/Kick-4-your-Subwoofer.cs.xml: - reverted audiofileprocessors to not point to /usr/local/share/lmms, they - should continue working - - * include/knob.h: - * include/volume_knob.h: - * src/widgets/knob.cpp: - * src/widgets/volume_knob.cpp: - added knob id - - * include/note_play_handle.h: - * src/core/note_play_handle.cpp: - update note frequency when changing base note in instrument track - - * include/instrument_track.h: - * plugins/flp_import/flp_import.cpp: - * src/core/piano_widget.cpp: - * src/tracks/instrument_track.cpp: - unify method to set a base note - -2006-06-03 Javier Serrano Polo - - * acinclude.m4: - * src/core/main.cpp: - detect and load standard Qt translations - -2006-05-29 Javier Serrano Polo - - * src/core/arp_and_chords_tab_widget.cpp: - fixed integer-overflow - - * include/oscillator.h: - * include/sample_buffer.h: - * plugins/organic/organic.cpp: - * plugins/triple_oscillator/triple_oscillator.cpp: - * src/core/envelope_and_lfo_widget.cpp: - * src/lib/oscillator.cpp: - - several segfault-fixes when while playing note - - volume-knob-changes take effect immediately - - * data/locale/ca.ts: - added catalan translation - -2006-05-26 Javier Serrano Polo - - * src/lib/sample_buffer.cpp: - corrected the calculation of f1 in play to prevent it from shifting - the start_frame out of bounds when resampling. - - * src/core/config_mgr.cpp: - * src/lib/mmp.cpp: - changed the xml output to use UTF8 encoding instead of ascii. - -2006-05-23 Danny McRae - - * include/oscillator.h: - FM mixing sometimes calculates a negative "time" for the sampling - which causes bad things to happen when pulling the data out of - a user defined wave. Changed userWaveSample to use the absolute - value of the sample, which fixes the segfaulting problem. Not - sure whether I should care about the negative times elsewhere. - -2006-05-22 Danny McRae - - * plugins/audio_file_processor/audio_file_processor.h: - * plugins/audio_file_processor/audio_file_processor.cpp: - added a switch to setAudioFile to force the track name to be - used for the track if a name already exists. Fixes the problem - of having tracks being renamed to the file name when loading a - saved song. - -2006-05-20 Tobias Doerffel - - * data/locale/de.ts: - updated German translation - - * src/core/bb_editor.cpp: - added button in bb-editor for adding new beat/bassline - - * include/track.h: - * src/core/track.cpp: - * src/tracks/bb_track.cpp: - * src/tracks/instrument_track.cpp: - * src/tracks/pattern.cpp: - * src/tracks/sample_track.cpp: - added "muted"-property to track-content-objects for being able to mute - single patterns, samples etc. either via context-menu or using - and middle mousebutton - -2006-05-19 Tobias Doerffel - - * src/core/track_container.cpp: - added missing #include (debug.h for assert(...) ) - -2006-04-18 Tobias Doerffel - - * plugins/flp_import/unrtf/output.c: - generally use bigger font-sizes - - * plugins/flp_import/unrtf/attr.c: - * plugins/flp_import/unrtf/attr.h: - * plugins/flp_import/flp_import.cpp: - do not crash when importing FLP-projects more than one time per - session (some vars need to be reset before unrtf works again) - - * plugins/flp_import/flp_import.cpp: - - limit number of bb-tracks for avoiding hangups - - set length of step-notes to -64 instead of -1 - - scale filter-resonance to smaller values - -2006-04-17 Tobias Doerffel - - * plugins/vibed/vibed.cpp: - some small optimizations in vibed::playNote( ... ) - -2006-04-16 Danny McRae - * Makefile.am: - * src/lmms_single_source.cpp: - * include/knob.h: - * include/instrument_track.h: - * src/tracks/instrument_track.cpp: - *+src/include/volume_knob.h: - *+src/widgets/volume_knob.cpp: - * include/setup_dialog.h: - * src/core/setup_dialog.cpp: - * include/sample_track.h: - * src/tracks/sample_track.cpp: - * plugins/audio_file_processor/audio_file_processor.h: - * plugins/audio_file_processor/audio_file_processor.cpp: - * plugins/organic/organic.h: - * plugins/organic/organic.cpp: - * plugins/triple_oscillator/triple_oscillator.h: - * plugins/triple_oscillator/triple_oscillator.cpp: - * plugins/vibed/vibed.h: - * plugins/vibed/vibed.cpp: - Added a volume knob widget that will display the volume level as - either a percentage or in dbV, which can be selected from the - general settings in the setup dialog. Changed vibed to use a - volume range from 0 to 200 to bring it in line with every other - volume knob in lmms. Unfortunately, this will break any existing - presets, but better to do it now before many of them actually - exist. - - * src/core/mixer.cpp: - Changed the number of channels processed from the fixed value of - SURROUND_CHANNELS to m_audioDev->channels() so that only the - number of channels that will be output get processed instead of - the maximum number of channels that could be defined. - -2006-04-15 Danny McRae - * include/mixer.h: - * src/core/mixer.cpp: - * src/core/song_editor.cpp: - *+data/themes/default/auto_limit.png: - *+data/themes/blue_scene/auto_limit.png: - Added auto limiter option. Main window now has a button next to - the high-quality button to toggle the auto limiter on and off - The limiter scales the whole section between zero crossings where - a clip occurs. This required adding another processing buffer - in the mixer, which will double the latency when the auto limiter - is being used, but when it's not being used, there is no change - to the latency. Because it's based on detecting the zero - crossings, the lowest frequency for which it is effective is - sample_rate/(4*buffer_len). - -2006-04-14 Tobias Doerffel - - * src/lib/mmp.cpp: - clean metadata-nodes when saving projects, project-templates or presets - - * plugins/vibed/vibed.cpp: - - in vibed::loadSettings(): - - simplified loading of wave-shape - - delete base64-decoded data at the end - - commented out code in destructor as it is not necessary - to be - removed someday - - * include/base64.h: - fixed fatal bug in Qt4-version of base64::decode(): memcpy()ed data to - _data instead of *_data - - * src/widgets/group_box.cpp: - * src/widgets/tab_widget.cpp: - some fine-tuning of Qt4-version of painting-code - - * src/widgets/lcd_spinbox.cpp: - explicitely set black background-color in Qt4-version - - * src/core/midi_tab_widget.cpp: - Qt4-version of MIDI-connection-code is now working - - * src/core/main_window.cpp: - * plugins/vibed/impulse_editor.cpp: - * plugins/vibed/nine_button_selector.cpp: - * plugins/vibed/vibed.cpp: - * plugins/plucked_string_synth/plucked_string_synth.cpp: - * plugins/triple_oscillator/triple_oscillator.cpp: - * plugins/bit_invader/bit_invader.cpp: - * plugins/organic/organic.cpp: - * src/core/song_editor.cpp: - * src/core/piano_roll.cpp: - * src/core/main_window.cpp: - * src/core/bb_editor.cpp: - * src/core/track.cpp: - * src/widgets/project_notes.cpp: - * src/widgets/group_box.cpp: - * src/widgets/tab_widget.cpp: - * src/widgets/tool_button.cpp: - added missing setAutoFillBackground( TRUE )-call for making QWidget - paint specified background-color/pixmap - makes Qt4-version of LMMS - almost usable - - * src/widgets/tab_widget.cpp: - per default hide newly added tabs - - * include/spc_bg_hndl_widget.h: - added missing code for painting pixmap-backgrounds in Qt4-version - - * plugins/vestige/lvsl_client.cpp: - use QX11EmbedContainer instead of QX11EmbedWidget in Qt4-version -> - working VST-support in Qt4-version of LMMS - - * include/sample_buffer.h: - * src/lib/sample_buffer.cpp: - - when loading sample, first look for it in user's working-directory, - then in LMMS' factory-samples-directory - - simplified making the path of a sample-file relative - - * include/config_mgr.h: - * src/core/config_mgr.cpp: - * src/core/main_window.cpp: - * src/tracks/instrument_track.cpp: - replaced methods projectsDir(), presetsDir() and samplesDir() with - userProjectsDir(), factoryProjectsDir(), userPresetsDir(), - factoryPresetsDir() etc. - - * include/file_browser.h: - * src/core/file_browser.cpp: - try to avoid duplicate "/" in paths - fixes some problems - -2006-04-10 Tobias Doerffel - - * most files: - Qt4-fixes: - - when including headers, specify qt-module too (QtCore, QtGui etc.) - - draw gradients using QLinearGradient etc. - - other opmizations (use QHash instead of QMap etc.) - -2006-04-10 Danny McRae - - * Makefile.am: - * include/lmms_constants.h: - * include/basic_filters.h: - * include/oscillator.h: - * include/interpolation.h: - converted calculations using PI to single precision - - * src/audio/audio_device.cpp: - * src/audio/audio_alsa.cpp: - * src/audio/audio_file_wave.cpp: - corrected handling of big endian data - - * plugins/vibed/vibed.h: - * plugins/vibed/vibed.cpp: - * plugins/vibed/nine_button_selector.h: - * plugins/vibed/nine_button_selector.cpp: - - added octave to save and restore settings - - removed mysterious m_sampleBuffer that was causing seg faults in the - deconstructor - - * src/core/main_window.cpp: - added checks to handle "gimp like windows" for save and restore widget - states to prevent seg fault - - * data/projects/cool_songs/Djeezus-BeatRolls.mmp: - * data/projects/cool_songs/Djeezus-Oscilisous.mmp: - * data/projects/cool_songs/Marfil-MarfilDrum01.mpp: - * data/projects/cool_songs/Mart-Concave_flow.mpp: - * data/projects/cool_songs/Mart-Dirt_Track.mpp: - * data/projects/cool_songs/MaxFellner-Ease.mpp: - * data/projects/cool_songs/SharkyX-DeadManDancing.mpp: - * data/projects/cool_songs/SharkyX-Experiments.mpp: - * data/projects/cool_songs/Siegel-DreamWave.mpp: - * data/projects/cool_songs/TobyDox-Confused.mpp: - * data/projects/cool_songs/TobyDox-Psycho.mpp: - * data/projects/cool_songs/TobyDox-TheFourthDimension.mpp: - * data/projects/covers/J.S.Bach-Preludium_and_Fuge_A-Minor.mmp: - * data/projects/demos/basses-demo.mpp: - * data/projects/demos/beat-collection.mpp: - * data/projects/demos/demo1.mpp: - * data/projects/demos/demo3.mpp: - * data/projects/demos/demo5.mpp: - * data/projects/demos/demo6.mpp: - * data/projects/demos/loop_collection.mpp: - * data/projects/demos/some_basslines.mpp: - * data/projects/misc/1st.mpp: - * data/projects/misc/time_machine.mpp: - * data/projects/templates/AccousticDrums.mpt: - * data/projects/templates/ClubMix.mpt: - * data/presets/AudioFileProcessor/Bass-Mainia.cs.xml: - * data/presets/AudioFileProcessor/Fat-Reversed-Kick.cs.xml: - * data/presets/AudioFileProcessor/Kick-4-your-Subwoofer.cs.xml: - updated audiofileprocessors to point to factory presets files in - /usr/local/share/lmms - -2006-04-09 Tobias Doerffel - - * src/core/envelope_and_lfo_widget.cpp: - do not show hint when loading settings in which lfo-shape is set to USER - - * src/core/preset_preview_play_handle.cpp: - disable project-journalling while loading preset - - * src/core/preset_preview_play_handle.cpp: - * src/tracks/instrument_track.cpp: - for generating infinite notes, pass valueRanges::max instead - of ~0 to note-play-handle-constructor as ~0 = 1 for signed ints - - * include/types.h: - - changed types of fpab_t and f_cnt_t to be signed - compiler - generates more optimized code this way - - added template-struct "valueRanges", containing members "min" and - "max" which hold the minimum and maximum value of the type the - template is instantiated with - - * plugins/bit_invader/bit_invader.cpp: - - fixed buffer-overflow when loading sample-data from base64 and more - bytes were decoded than allocated in wave-buffer - - delete decoded base64-data after copying it into wave-buffer - -2006-04-08 Tobias Doerffel - - * src/core/envelope_and_lfo_widget.cpp: - - connect valueChanged()-event of lfo-shape-buttongroup with - lfoWaveCh()-slot - fixes bug that clicks at the lfo-wave-buttons - were not recognized - - completely revised level()-method which doesn't have the bug - anymore, that in release-phase the envelope-level simply went down - from sustain-level to zero, now it goes down from the level at which - the note was released, new method is also much cleaner and more - optimized (and optmizable by compiler) - - * src/core/preset_preview_play_handle.cpp: - hide preview-instrument-track-window after loading settings - -2006-04-07 Tobias Doerffel - - * plugins/vibed/vibrating_string.h: - corrected type-names for resample()-method-parameters (f_cnt_t instead - of samplerate_t) - -2006-04-06 Tobias Doerffel - - * include/config_mgr.h: - * src/core/config_mgr.cpp: - use setup-wizard only for setting working-directory - - * src/core/main_window.cpp: - when creating file-browsers, pass 2 directories: - - factory-files - - user-files - this concerns projects, presets and samples - obsoletes - copying/linking files the first time, LMMS is run (new factory files in - new versions do not cause any trouble anymore) - - * include/file_browser.h: - * src/core/file_browser.cpp: - added support for merging several directory-trees into one view - -2006-04-05 Danny McRae - - * include/sample_track.h: - * src/tracks/sample_track.cpp: - - add volume knob to sample tracks - -2006-04-05 Danny McRae - - * plugins/vibed/impulse_editor.cpp: - - corrected mismatch sin/saw mismatch in initialization - - * plugins/vibed/string_container.h: - * plugins/vibed/string_container.cpp: - * plugins/vibed/vibed.h: - * plugins/vibed/vibed.cpp: - - added string id tracking to allow adding strings while playing - -2006-04-05 Tobias Doerffel - - * include/plugin_browser.h: - * src/core/plugin_browser.cpp: - - per default show small items for plugins in plugin-browser and show - details on mouse-over (nice animations!! ;-) - avoids problems with - hidden plugin-items because of too low screen-resolution and missing - scrollbars - - draw plugin-details-text using QPainter::drawText (not with old own - (buggy) algorithm for text-drawing with word-break-support) - -2006-04-04 Tobias Doerffel - - * plugins/flp_import/unrtf/*: - * plugins/flp_import/flp_import.cpp: - use integrated unrtf-source into FLP-import-filter for converting - RTF-comments to plain HTML which is usable with QTextEdit - -2006-04-02 Tobias Doerffel - - * src/core/song_editor.cpp: - set master-volume-slider correctly in songEditor::setMasterVolume() - - * include/envelope_tab_widget.h: - * src/core/envelope_tab_widget.cpp: - * src/core/note_play_handle.cpp: - - in envelopeTabWidget::releaseFrames(): - if the volume-envelope is used, do not check - release-frames of other envelope-targets, as it is not - interesting if they're beyond the end of the volume-envelope - (silent so or so) - may result in less CPU-usage in some - situations if the user set a bigger release to an envelope - other than the volume-env - - for arpeggio-base-notes only use number of release-frames of - volume-envelope for m_releaseFramesToDo (for not creating silent notes - in release-phase of arp-base-note) - - * plugins/vibed/impulse_editor.cpp: - use saw-wave as default shape for strings as it sounds much more like - a typical guitar-string than a sine-wave - - * plugins/triple_oscillator/triple_oscillator.h: - * plugins/triple_oscillator/triple_oscillator.cpp: - re-implement setParameter()-method for setting user-defined wave-shape - (used by FLP-import-filter) - - * plugins/flp_import/flp_import.cpp: - - convert 3x Osc params to TripleOscillator-settings and load them - - load Vibed-Plugin for Plucked!-instrument - - load arpeggio-settings of channel - - load filter-settings of channel - - handle base-note of each channel - - correct master-volume-calculation - -2006-04-01 Tobias Doerffel - - * plugins/flp_import/flp_import.cpp: - - hack for converting RTF-comment to HTML using unrtf (if installed) - -2006-03-30 Tobias Doerffel - - * plugins/flp_import/flp_import.h: - * plugins/flp_import/flp_import.cpp: - - try to load samples correctly using FL Studio installation - - recognize steps (not working properly yet) - - set current pattern of project - - separate handling of plugin-parameters (will allow support of FL - presets later!) - - added FLP_StepData (225) (not handled as format not known yet) - - added FLP_EnvLfoParams (218) (not handled as format not known yet) - - load envelope-settings of instrument-tracks - - * src/core/track_container.cpp: - disable journalling in destructor of trackContainer - - * include/config_mgr.h: - * include/setup_dialog.h: - * src/core/config_mgr.cpp: - * src/core/setup_dialog.cpp: - support for setting path to installation directory of FL Studio - -2006-03-29 Tobias Doerffel - - * include/song_editor.h: - * src/core/song_editor.cpp: - added setMasterVolume() and setMasterPitch() - - * plugins/flp_import/flp_import.h: - * plugins/flp_import/flp_import.cpp: - - read text-len correctly - - do not crash when creating new pattern before actual channels are - created - - stated event 224 to be FLP_PatternData - - extract information for creating notes out of pattern-data - - add playlist-items after all is done for resizing them correctly - -2006-03-28 Tobias Doerffel - - * plugins/flp_import/flp_import.h: - * plugins/flp_import/flp_import.cpp: - improvements for having a working flp-filter as soon as possible - -2006-03-28 Danny McRae - - * src/lib/sample_buffer.cpp: - corrected miscalculation of buffer size in resample - - * nine_button_selector.cpp: - * nine_button_selector.h: - * string_container.cpp: - * string_container.h: - * vibed.cpp: - * vibed.h: - changed QPtrList variables to vlist type to make things more - Qt4 friendly - -2006-03-27 Tobias Doerffel - - * plugins/flp_import/: - skeleton for FLP-import-filter and some first code (doesn't work yet) - - * include/midi.h: - * include/midi_port.h: - * include/midi_tab_widget.h: - * src/core/midi_tab_widget.cpp: - * src/midi/midi_port.cpp: - support for default-velocity for MIDI-in and/or -out-events - useful - when recording with constant velocity - -2006-03-26 Danny McRae - - * plugins/vibed/: - added "Vibed"-plugin, a powerful combination of PluckedStringSynth and - BitInvader that's capable of producing a surprisingly wide range of - sounds - -2006-03-26 Tobias Doerffel - - * src/lib/journalling_object.cpp: - in journallingObject::saveState(): append new dom-element to parent - before calling saveSettings() as some implementations of it depend on - knowing something about it's parent (e.g. whether it's the clipboard - etc.) - fixes several bugs related to clipboard-usage and drag'n'drop - -2006-03-25 Tobias Doerffel - - * include/instrument_track.h: - * src/core/preset_preview_play_handle.cpp: - disable journalling for all objects involved in preset-preview - - * src/tracks/instrument_track.cpp: - when saving preset, create new node below content-node of project, as - the behaviour of saveTrackSpecificSettings() was changed some days - before - - * src/lib/mmp.cpp: - bugfixes concerning project type-naming - - * src/core/arp_and_chords_tab_widget.cpp: - bugfixes concerning loading/saving settings - -2006-03-24 Tobias Doerffel - - * src/core/track.cpp: - in trackContentWidget::undoStep(): cast journalling object to - track-content-object and close it instead of deleting it - fixes crash - after undo of TCO-add - -2006-03-23 Tobias Doerffel - - * plugins/organic/organic.cpp: - * plugins/organic/randomise_pressed.png: - added pixmap for visual feedback when pressing randomise-button - - * plugins/midi_import/midi_import.cpp: - removed attribute FASTCALL from midiImport::tryImport() for not - crashing LMMS, as tryImport() is not defined as FASTCALL in - importFilter-API - - * src/core/export_project_dialog.cpp: - fixed bug causing LMMS to crash when trying to export a project - -2006-03-19 Tobias Doerffel - - * src/core/track.cpp: - * src/core/track_container.cpp: - * src/tracks/pattern.cpp: - in loadSettings(): do not get confused by meta-data (journal etc.) - - * src/lib/journalling_object.cpp: - - lot of bugfixes - - save/load data of journal-entry (QVariant) by encoding/decoding it - with base64 - - * include/base64.h: - * src/lib/base64.cpp: - support for encoding and decoding whole QVariant, independent of its - type (the result is one string, representing data of any type (int, - QMap, QVector QString...) - this is just awesome!!) - - * src/tracks/instrument_track.cpp: - do not crash in several situations if instrument is not loaded for - some reason (e.g. invalid preset) - - * src/core/track.cpp: - full support for undo/redo adding/removing a TCO (track-type - independent) - -2006-03-18 Tobias Doerffel - - * src/core/main_window.cpp: - avoid layouting-errors when restore widget-state by showing widget - while moving it - - * include/note.h: - * src/core/note.cpp: - undo/redo-support for note-properties - - * most files: - - derive from journallingObject instead of settings and/or engineObject - - in saveSettings() do not create own node, instead directly set - attributes of passed dom-element - - * include/journalling_object.h: - * src/lib/journalling_object.cpp: - - added saveSettings() and loadSettings()-method from former - settings-class - - new wrapper-functions around saveSettings() and loadSettings(): - saveState() - restoreState() - -> objects do not have to create a new node on their own, - saveState() does it for them using nodeName() as node-name - -> journal of object is saved/restored automatically - - * include/settings.h: - removed - -2006-03-16 Tobias Doerffel - - * include/journalling_object.h: - - renamed from editable_object.h - - renamed editStep to journalEntry - - renamed editableObject to journallingObject - - renamed other method-names - - * include/project_journal.h: - * src/lib/project_journal.cpp: - renamed editHistory to projectJournal and changed file-names - accordingly - - * most files: - renamed class channelTrack to instrumentTrack and changed other - method-names to match new naming-convention - - * include/instrument_track.h: - * src/tracks/instrument_track.cpp: - renamed channel_track.* to instrument_track.* - -2006-03-16 Andreas Brandmaier - - * plugins/organic/organic.cpp: - * plugins/organic/organic.h: - * plugins/organic/randomise.png: - added "randomise preset" button to organic plugin - -2006-03-14 Tobias Doerffel - - * include/types.h: - added type for editable-object-ID - - * include/track.h: - * src/core/track.cpp: - * src/tracks/bb_track.cpp: - * src/tracks/pattern.cpp: - * src/tracks/sample_track.cpp: - undo/redo-support for position- and size-changes of TCO - - * include/automatable_object.h: - added methods for saving step-recording-state on stack and restoring - it - - * include/automatable_object.h: - * include/automatable_button.h: - * include/knob.h: - * src/widgets/automatable_button.cpp: - * src/widgets/knob.cpp: - added second template-parameter to automatableObject which specifies - the type to be used for internal calculations (necessary for working - undo/redo-implementation for bool-objects like buttons) - - * include/led_checkbox.h: - * src/widgets/led_checkbox.cpp: - fixed some bugs - -2006-03-13 Tobias Doerffel - - * include/main_window.h: - * src/core/main_window.cpp: - added edit-menu with undo/redo-items - - * src/core/piano_roll.cpp: - * src/core/song_editor.cpp: - * src/core/track_container.cpp: - * src/tracks/channel_track.cpp: - * src/widgets/project_notes.cpp: - use mainWindow::saveWidgetState() and mainWindow::restoreWidgetState() - for saving widget-state in project-file - - * include/piano_roll.h: - * src/core/piano_roll.cpp: - made piano-roll a settings-object - - * include/main_window.h: - * src/core/main_window.cpp: - added static methods for saving and restoring state of a widget - (position, size, visibility etc.) to/from QDomElement - - * include/timeline.h: - * src/core/song_editor.cpp: - * src/core/timeline.cpp: - save loop-point-positions and loop-point-state in project - - * plugins/bit_invader/bit_invader.cpp: - added visual feedback when pressing wave-shape-buttons - - * include/combobox.h: - * include/led_checkbox.h: - * include/pixmap_button.h: - * src/widgets/combobox.cpp: - * src/widgets/led_checkbox.cpp: - * src/widgets/pixmap_button.cpp: - use automatableButton as new base-class - - * include/automatable_button.h: - * src/widgets/automatable_button.cpp: - - added class automatableButton to be the base-class for pixmapButton, - ledCheckBox etc. - - added automatableButtonGroup, a more powerful button-group, designed - to be used in conjunction with automatableButton-derived buttons - -2006-03-12 Tobias Doerffel - - * include/automatable_object.h: - - added setInitValue() to be used by ALL creators of automatable - objects for initializing object-value - otherwise edit-step-history - gets filled with steps to set object's value to init-value - - derive from editableObject and re-implement some methods for - transparent edit-history for all automatable objects (knobs etc.) - - * include/editable_object.h: - * include/edit_history.h: - * src/lib/edit_history.cpp: - added support for recording edit-steps, the base for a generic - undo/redo-system - -2006-03-09 Tobias Doerffel - - * include/settings.h: - * src/core/plugin_browser.cpp: - * src/core/song_editor.cpp: - * src/core/track_container.cpp: - * plugins/midi_import/midi_import.cpp: - * plugins/midi_import/midi_import.h: - made MIDI-file-code an import-filter - - * include/import_filter.h: - * src/core/import_filter.cpp: - support for import-filter-plugins - simply call - - importFilter::import( FILE_NAME, TRACK_CONTAINER ) - - for any file and the rest will be done fully automatically according - to installed import-filter-plugins - -2006-03-08 Zolo - - * data/themes/blue_scene/: - updated some pixmaps - - * data/themes/blue_scene/plugins/: - added pixmaps for plugins - -2006-03-08 Tobias Doerffel - - * src/core/timeline.cpp: - more logical loop-point-handling: - middle mouse button -> left loop-point - right mouse button -> right loop-point - - * plugins/audio_file_processor/audio_file_processor.cpp: - * plugins/bit_invader/bit_invader.cpp: - * plugins/organic/organic.cpp: - * plugins/plucked_string_synth/plucked_string_synth.cpp: - * plugins/triple_oscillator/triple_oscillator.cpp: - * plugins/vestige/vestige.cpp: - * include/plugin.h: - * src/core/instrument.cpp: - * src/core/plugin.cpp: - * src/lib/embed.cpp: - added support for plugin-theming - - * src/lib/embed.cpp: - - first search in artwork-directories before searching for embedded data - as most artwork is not linked into binary (except plugins) - - if pixmap not found, try to load according pixmap from - default-artwork-dir - - * include/embed.h: - * src/core/main.cpp: - * src/lib/embed.cpp: - as localizations are no longer embedded into binary, loadTranslation() - was moved to main.cpp and contains only some basic code for loading - appropriate translation from file - - * src/core/config_mgr.cpp: - several fixes concerning artwork-path - -2006-03-07 Tobias Doerffel - - * src/core/arp_and_chords_tab_widget.cpp: - more senseful range for arpeggio time: 25-2000 ms (instead of 10-1000ms) - - * src/audio/audio_alsa.cpp: - * src/audio/audio_oss.cpp: - * src/midi/midi_alsa_raw.cpp: - * src/midi/midi_alsa_seq.cpp: - * src/midi/midi_oss.cpp: - only specify threading-priority when using Qt 3.3.5 or above as older - versions cause problems when running the whole app with realtime - priority - fixes several lockups - - * src/widgets/knob.cpp: - when moving mouse while having shift pressed, increase/decrease by - single steps - - * src/core/envelope_tab_widget.cpp: - use 10 KHz as filter-maximum instead of 16 KHz - - * include/track.h: - * src/core/track.cpp: - added HACK to avoid crash because of bug in Qt (< 3.3.5) when removing - track - - * src/core/config_mgr.cpp: - - use default-theme-path if theme-path from config-file doesn't exist - - add "/" to theme-path if missing - -2006-03-06 Alexey Kouznetsov - - * locale/ru.ts: - updated Russian translation - -2006-03-05 Tobias Doerffel - - * src/core/main_window.cpp: - always set to configured-state before showing setup-dialog on first - startup - -2006-03-04 Tobias Doerffel - - * src/core/engine.cpp: - finalize main-window after having mixer to start its audio-devices - - fixes crash on first time LMMS is started - -2006-02-28 Tobias Doerffel - - * data/locale/de.ts: - updated German translation - - * src/core/timeline.cpp: - use note::toNearestTact() in timeLine::mouseMoveEvent() instead of own - calculations - - * src/core/track.cpp: - per default make TCO-ops (create, move, resize) aligned on tact- - boundaries, free positioning/resizing can be achieved by pressing - after pressing mouse-button - - * include/midi_time.h: - added note::toNearestTact()-method - - * include/pattern.h: - * src/core/piano_roll.cpp: - * src/track/pattern.cpp: - do not quantize note-position while moving selection of notes - - * src/core/song_editor.cpp: - some layout-fixes for looking good with "Blue Scene" as well - -2006-02-27 Zolo - - * data/themes/blue_scene/: - added new theme for LMMS - -2006-02-27 Tobias Doerffel - - * src/core/song_editor.cpp: - * src/tracks/pattern.cpp: - do not crash when playing a pattern which is deleted - - * src/core/track_container.cpp: - pause mixer when cloning tracks for avoiding side-effects, probably - fixes some crash-bugs - - * include/config_mgr.h: - * include/setup_dialog.h: - * src/core/config_mgr.cpp: - * src/core/setup_dialog.cpp: - * src/lib/embed.cpp: - first simple support for theming - - * Makefile.am: - * configure.in: - re-organized all data-directories (samples, presets, localizations, - artwork etc.) and put them into data/ dir to be all installed into - $prefix/share/lmms - -2006-02-25 Tobias Doerffel - - * src/tracks/channel_track.cpp: - apply a very basic envelope at the beginning and the end of a note for - avoiding these "typical" clicks which were there before - -2006-02-22 Tobias Doerffel - - * configure.in: - * Makefile.am: - * src/lmms_single_source.cpp: - added support for compiling LMMS from one source file which often - results in a better/more optimized executable - - * include/note.h: - * include/piano_roll.h: - * src/core/note.cpp: - * src/core/piano_roll.cpp: - - simple quantization-support - - fixed lengths for drawing notes can be selected in piano-roll - - * resources/black_key.png: - * resources/black_key_pressed.png: - * resources/pr_black_key.png: - * resources/pr_white_key_big.png: - * resources/pr_white_key_small.png: - * resources/white_key.png: - * resources/white_key_pressed.png: - replaced by new graphics - - * src/core/engine.cpp: - delete piano-roll after song-editor and bb-editor as patterns being - destroyed still depend on it - -2006-02-21 Tobias Doerffel - - * src/tracks/channel_track.cpp: - do not lock mutex in processOutEvent() as it causes a deadlock when - having channel-activity-indicators enabled - - * include/midi_mapper.h - * include/project_notes.h: - * src/lib/sample_buffer.cpp: - * src/midi/midi_file.cpp: - * src/midi/midi_mapper.cpp: - * src/widgets/project_notes.cpp: - misc fixes for being able to compile LMMS from one source-file - - * include/automatable_object.h: - * include/knob.h: - * include/lcd_spinbox.h: - * include/led_checkbox.h: - * src/widgets/knob.cpp: - * src/widgets/led_checkbox.cpp: - * src/widgets/lcd_spinbox.cpp: - introduced template-class automatableObject for central value- - manipulation, range-checking etc. and made some classes (e.g. knob, - ledCheckBox, lcdCheckBox) derive from it - preparations for full - automation-support in LMMS - - * Makefile.am: - do not strip executable when installing as it makes even basic debugging - impossible - -2006-02-20 Tobias Doerffel - - * src/widgets/combobox.cpp: - * src/widgets/knob.cpp: - * src/widgets/led_checkbox.cpp: - draw shadowed text - - * include/mixer.h: - * src/core/arp_and_chords_tab_widget.cpp: - * src/core/mixer.cpp: - better xrun-detection and -handling (still not perfect) - - * include/mixer.h: - * src/tracks/channel_track.cpp: - fixed critical bug which made LMMS crash if xruns were detected and - notes were discarded by mixer and therefore deleted twice - -2006-02-19 Andreas Brandmaier - - * plugins/organic/organic.cpp: - * plugins/organic/organic.h: - * presets/Organic: - * presets/Bitinvader: - added waveshape knob - changed distortion method from clipping to foldback - renamed and added presets for Organic and BitInvader - -2006-02-18 Andreas Brandmaier - - * plugins/organic/organic.cpp: - * plugins/organic/organic.h: - * presets/Organic: - added new plugin synthesizer plugin organic and some presets - -2006-02-09 Tobias Doerffel - - * plugins/triple_oscillator/triple_oscillator.cpp: - per default set volume of each osc to 33% - - * allmost all files: - use engine-technology - - * include/engine.h: - * src/core/engine.cpp: - added engine- and engineObject-class providing new "engine-technology" - which makes singleton-classes obsoletes and offers a lot of new - possibilities like GUI-data-separation and having several projects - open at the same time - -2006-02-06 Tobias Doerffel - - * include/mixer.h: - * include/song_editor.h: - * src/core/mixer.cpp: - * src/core/song_editor.cpp: - simple xrun-detection - do not accept new note-play-handles if xruns - are detected - -2006-02-06 Andreas Brandmaier - - * plugins/bitinvader/bitinvader.cpp: - * plugins/bitinvader/bitinvader.h: - * plugins/bitinvader/graph.cpp: - * plugins/bitinvader/graph.h: - - code cleanup - - added drag&drop support to wavegraph - - added new BitInvader presets and improved old ones - -2006-02-05 Tobias Doerffel - - * include/basic_filters.h: - small optimizations: do not divide by 2.0, instead multiply with 0.5 - - * src/core/main.cpp: - set SCHED_FIFO-priority for LMMS if possible - - * plugins/vestige/communication.h: - * plugins/vestige/lvsl_client.cpp: - * plugins/vestige/lvsl_server.c: - - set SCHED_FIFO-priority for VST-server if possible - - no X-calls needed anymore - - more complete host-callback-implementation - - support for geometry-changes of plugin - - use std::list instead of std::vector for enqueing MIDI-events (faster) - - support for telling plugin system's language - - * configure.in: - when checking for VST-SDK-headers, use C++ compiler instead of - C-compilers as headers fail to compile with it - -2006-02-04 Tobias Doerffel - - * include/types.h: - * most files: - more strict typing -> types for samplerate, bpm, frame-count, - channel-count etc. - - * src/core/track.cpp: - when creating a track, pause mixer for not causing any trouble because - of incompletely initialized track etc. - fixes several crashes when - adding track while playing - - * include/mixer.h: - * src/core/mixer.cpp: - more "intelligent" mix-mutex-management for allow multiple pause()- - calls without ending in deadlock or crash because of mutex being - unlocked to early - -2006-02-02 Tobias Doerffel - - * configure.in: - made 0.1.4 release - - * Makefile.am: - added -rdynamic-switch again to make LMMS able to load plugins - - * include/track_container.h: - fixed bug which caused LMMS not being compilable using GCC 3 - -2006-02-01 Tobias Doerffel - - * configure.in: - made 0.1.3 release - - * lmms.1: - added manpage (taken from debian-package and updated) - - * include/base64.h: - * include/rubberband.h: - * plugins/bit_invader/graph.cpp: - * src/core/name_label.cpp: - * src/widgets/combobox.cpp: - * src/widgets/rubberband.cpp: - Qt4-compat fixes - - * locale/de.ts: - updated German translation - - * src/core/main.cpp: - updated copyright-notice in help-text - -2006-01-30 Tobias Doerffel - - * plugins/vestige/fstclient.h: - * plugins/vestige/fstclient.cpp: - - renamed to lvsl_client.* - - when waiting for plugin to have finished process()ing, usleep() some - micro-seconds for allowing better scheduling - - * plugins/vestige/lvsl_server.c: - - merged code from fstserver.cpp, fstserver.h and fstcore.c into one - source-file and removed rests of the old FST-API which makes all - the VST-code MUCH more cleaner and less redundant (LVSL = LMMS VST - Support Layer) - - VST SDK 2.4 compatibility (no need to fix headers with 2.4!) - -2006-01-29 Tobias Doerffel - - * plugins/bit_invader/bit_invader.cpp: - - call graph::setSamplePointer() after loading settings - - memcpy() samples in bitInvader::smoothClicked() instead of copying - them in a loop - - * plugins/bit_invader/graph.cpp: - - update after setting new sample - - * src/tracks/pattern.cpp: - - disable auto-cleanup during pattern-freeze - - initialize member m_progress in patternFreezeStatusDialig-dtor - fixes - bug which sometimes closed the window before actual freezing was - started - - * include/buffer_allocator.h: - * src/lib/buffer_allocator.cpp: - - added possibility to disable auto-cleanup at certain times e.g. when - freezing a pattern - - cleanup only every 10th free()-call for decreasing overhead - - only start searching for free bufs if there're enough remaining - -2006-01-24 Andreas Brandmaier - - * plugins/bit_invader/bit_invader.cpp: - * plugins/bit_invader/bit_invader.h: - * presets/BitInvader: - - changed sample buffer encoding in presets to base64 - - added BitInvader various presets - -2006-01-23 Tobias Doerffel - - * include/sample_buffer.h: - * src/lib/sample_buffer.cpp: - * plugins/audio_file_processor/audio_file_processor.cpp: - use new base64-code - - * include/base64.h: - * src/lib/base64.cpp: - added methods for encoding/decoding binary data to/from base64-encoded - data (wrapper-implementation for Qt4) - -2006-01-23 Andreas Brandmaier - - * plugins/bit_invader/bit_invader.cpp: - * plugins/bit_invader/bit_invader.h: - * plugins/bit_invader/graph.cpp: - * plugins/bit_invader/graph.h: - - improved mouse handling. - - replaced waveform generation methods by those of toby's oscillator - class - - added user-loadable waveform - - code cleanup - -2006-01-22 Tobias Doerffel - - * include/timeline.h: - * src/core/song_editor.cpp: - * src/core/timeline.cpp: - updates are now completely done by timeline/QTimer without being - called from song-editor out of non-GUI-thread which caused segfaults - etc. sometimes - - * include/name_label.h: - * src/core/name_label.cpp: - * src/tracks/bb_track.cpp: - * src/tracks/sample_track.cpp: - added support for user-defined track-icons - - * artwork/track_icons/*png: - added several icons to be used as track-icons - - * include/track.h: - * src/core/track.cpp: - * src/core/track_container.cpp: - do not hide track for completely repainting it, use special method for - it - - * include/pattern.h: - * src/tracks/pattern.cpp: - only repaint if necessary, otherwise just paint the pixmap we painted - before - - * include/bb_editor.h: - * src/core/bb_editor.cpp: - added combobox for selecting bb-track inside bb-editor - - * include/combobox.h: - * src/widgets/combobox.cpp: - - added clear()-method - - do not crash when having no items - - scale pixmap to fit into combobox - - place menu below combobox if possible - -2006-01-21 Tobias Doerffel - - * include/track.h: - * src/core/track.cpp: - * src/tracks/pattern.cpp: - * src/tracks/sample_track.cpp: - added support for used-defined track-height by pressing and - move mouse (with pressed button) - - * include/song_editor.h: - * include/track.h: - * include/track_container.h: - * src/core/song_editor.cpp: - * src/core/track.cpp: - * src/core/track_container.cpp: - take advantage of new rubberband: - - selecting track-content-objects of any type either via rubberband or - by clicking while pressing - - move selected track-content-objects - - delete selected track-content-objects - - * include/rubberband.h: - * src/widgets/rubberband.cpp: - added rubberband which either acts as wrapper for Qt4's QRubberBand or - as a widget imitating a rubberband - - * include/track.h: - * src/core/track.cpp: - draw vertical lines for each bar - - * include/bb_editor.h: - * include/song_editor.h: - * include/track_container.h: - * src/core/bb_editor.cpp: - * src/core/song_editor.cpp: - * src/core/track.cpp: - * src/core/track_container.cpp: - fixed all that stuff with annoying scrollbars which partly hid important - widgets - -2006-01-21 Andreas Brandmaier - - * plugins/bit_invader/bit_invader.cpp: - * plugins/bit_invader/bit_invader.h: - added smooth button - -2006-01-20 Tobias Doerffel - - * src/tracks/pattern.cpp: - also update after clearing all notes - - * include/piano_roll.h: - * include/song_editor.h: - * src/core/piano_roll.cpp: - * src/core/song_editor.cpp: - use new combobox for zooming-comboboxes - - * include/export_project_dialog.h: - * src/core/export_project_dialog.cpp: - - reject() dialog when pressing cancel - - use new combobox - - * include/arp_and_chords_tab_widget.h: - * src/core/arp_and_chords_tab_widget.cpp: - use new combobox with according arpeggio-mode-icons - - * include/envelope_tab_widget.h: - * src/core/envelope_tab_widget.cpp: - * resources/filter_2lp.png: - * resources/filter_ap.png: - * resources/filter_bp.png: - * resources/filter_hp.png: - * resources/filter_lp.png: - use new combobox with according filter-icons - - * include/combobox.h: - * src/widgets/combobox.cpp: - added own cool-looking combobox with menu-extension which basically - has the same API as QComboBox - -2006-01-19 Andreas M. Brandmaier - - * plugins/bit_invader/bit_invader.h: - * plugins/bit_invader/bit_invader.cpp: - * plugins/bit_invader/graph.h: - * plugins/bit_invader/graph.cpp: - added "BitInvader"-plugin, an usereditable wavetable-synthesizer - -2006-01-16 Tobias Doerffel - - * src/lib/mmp.cpp: - do not add "mmp"-extensions if there's already "mpt" (multimedia- - project-template) as extension - - * include/arp_and_chords_tab_widget.h: - * src/core/arp_and_chords_tab_widget.cpp: - - added new sync-mode to arpeggiator - - arpeggiator-modes are now selectable from combobox - -2006-01-15 Tobias Doerffel - - * src/core/file_browser.cpp: - use 7.5 instead of 8 as font-size - - * src/widgets/led_checkbox.cpp: - use 7.5 instead of 7 as font-size - - * include/gui_templates.h: - - added more precise pointSizeF()-method - - more precise point-size-calculation for pointSize()-method which - makes all fonts inside LMMS a bit bigger and everything more - readable - - * include/setup_dialog.h: - * src/core/note_play_handle.cpp: - * src/core/setup_dialog.cpp: - * src/tracks/channel_track.cpp: - added switches for disabling several UI-effects for a better - performance even on older hardware - - * include/preset_preview_play_handle.h: - * src/core/preset_preview_play_handle.cpp: - global-data-mutex is not a pointer anymore, instead it's a normal - QMutex - fixes crashes with sort-arpeggio if no preset was previewed - before - -2006-01-14 Tobias Doerffel - - * src/widgets/kmultitabbar.cpp: - made KMultiTabBar working with Qt4 - - * src/audio/audio_jack.cpp: - return if connection to JACK-server failed with old JACK-API - (jack_client_new(...)) - fixes crash when using old JACK-API with - LMMS and JACK-server is not running - - * include/preset_preview_play_handle.h: - * src/core/arp_and_chords_tab_widget.cpp: - * src/core/preset_preview_play_handle.cpp: - as preset-note-play-handle is not registered at mixer, it cannot be - returned in notePlayHandle::nphsOfChannelTrack() and therefore - previewing presets with sort-mode arpeggios doesn't work - now the - arpeggiator also checks preview-note for being the only note there - - * src/core/arp_and_chords_tab_widget.cpp: - fixed some bugs in arpeggiator - - * src/core/piano_roll.cpp: - lock qapp-thread in recordNote() - hopefully fixes some - xlib-async-errors - - * src/tracks/channel_track.cpp: - - do not process note-on-out-events if according key is already pressed - - when invalidating note-play-handles, also reset m_notes-array for not - crashing when applying another preset while key is pressed and - released afterwards - -2006-01-10 Alexey Kouznetsov - - * locale/ru.ts: - updated Russian translation - -2006-01-10 Tobias Doerffel - - * src/core/piano_roll.cpp: - update pattern after changing volume of step-note - -2006-01-09 Tobias Doerffel - - * include/setup_dialog.h: - * src/core/config_mgr.cpp: - * src/core/setup_dialog.cpp: - made appearence of two dialogs switchable (question whether to re-run - wizard after up-/downgrade and message after accepting setup-dialog) - -2006-01-08 Tobias Doerffel - - * include/piano_roll.h: - * src/core/piano_roll.cpp: - * src/tracks/pattern.cpp: - simple support for editing (existing) steps in piano-roll, e.g. for - changing key of a step - - * plugins/vestige/vestige.cpp: - per default switch to users VST-plugin-directory when opening plugin - - * include/config_mgr.h: - * include/setup_dialog.h: - * src/core/config_mgr.cpp: - * src/core/setup_dialog.cpp: - added possibility to setup working-directory and location of VST-plugins - - * src/widgets/tempo_sync_knob.cpp: - removed a lot of obsolete #include's - - * include/piano_widget.h: - * src/core/note_play_handle.cpp: - * src/core/piano_widget.cpp: - display played keys as if they were pressed - - * include/arp_and_chords_tab_widget.h: - * include/note_play_handle.h: - * src/core/arp_and_chords_tab_widget.cpp: - * src/core/note_play_handle.cpp: - added sort-mode for more powerful arpeggios - - * src/core/arp_and_chords_tab_widget.cpp: - fixed bug which made the arpeggiator skipping notes sometimes at - certain arpeggio-times - - * src/core/lmms_main_win.cpp: - commented out code for creating effect-board-window-button - - * src/core/channel_track.cpp: - removed inclusion of paths.h which isn't part of LMMS for quite a long - while... - there were no problems because Linux has paths.h too - -2006-01-06 dieEasy - - * locale/it.ts: - added Italian translation - -2006-01-02 Tobias Doerffel - - * plugins/vestige/vestige.cpp: - set vestige-logo as window-icon of plugin-GUI-window - - * src/core/instrument.cpp: - set logo of plugin as window-icon of channel-track - - * include/dummy_instrument.h: - * include/dummy_plugin.h: - * include/instrument.h: - * include/plugin.h: - * src/core/instrument.cpp: - * src/core/plugin.cpp: - small changes in plugin-API: plugin now always has to pass pointer to - plugin-descriptor to plugin-dtor to make the latter one able to - provide several information - - * src/core/plugin.cpp: - search for plugin-libs in configManager::pluginDir() which is - $prefix/lib/lmms - hopefully solves problems with finding plugins on - some systems - - * include/channel_track.h: - * include/midi_tab_widget.h: - * src/core/midi_tab_widget.cpp: - * src/tracks/channel_track.cpp: - when using Raw-MIDI-client, make items "MIDI input/output" checkable - and enable/disable MIDI-input/output accordingly if user - checked/unchecked it and update check-state if user changed MIDI-mode - in midi-tab-widget in channel-track - - * src/core/midi_tab_widget.cpp: - set MIDI-output-channel to 1 per default - - * src/lib/sample_buffer.cpp: - added flac-files to filter of file-selection-dialog - - * include/note_play_handle.h: - * src/core/note_play_handle.cpp: - when invalidating note-play-handle, do some stuff which actually would - be done by dtor if m_channelTrack wouldn't be NULL - -2006-01-01 Tobias Doerffel - - * src/core/track.cpp: - added tooltip to track-op-widget telling the user something about - drag'n'drop-functionality... - - * include/lmms_main_win.h: - * src/core/lmms_main_win.cpp: - * src/lib/string_pair_drag.cpp: - if main-window looses focus or a drag is completed, clear - key-modifiers of LMMS-main-window, because we might have lost - key-release-events in these cases and therefore our modifier-state-map - could be incorrect - fixes several bugs concerning drag'n'drop - - * README: - * src/core/about_dialog.cpp: - extended copyright from 2005 to 2006 - Happy New Year! - -2005-12-31 Tobias Doerffel - - * include/channel_track.h: - * src/tracks/channel_track.cpp: - removed surround-area in track-settings-widget and added button with - MIDI-connection-menu instead - -2005-12-30 Tobias Doerffel - - * include/track.h: - * include/track_container.h: - * src/core/track.cpp: - * src/core/track_container.cpp: - revised all the things around track-operations: - - tracks are now directly movable via the grip at the beginning of a - track - replaces "move up/down"-buttons and is much more usable - - actions (clone/delete track) are now part of a popup-menu - - * src/core/lmms_main_win.cpp: - - corrected file-description at the beginning - - add space at left side before adding tool-buttons - - * src/core/midi_tab_widget.cpp: - use smaller font for connection-selection-menu - -2005-12-29 Tobias Doerffel - - * src/widgets/fade_button.cpp: - do not update() directly in nextState(), use QTimer instead for avoiding - xlib-threading-errors - -2005-12-28 Tobias Doerffel - - * plugins/vestige/communication.h: - * plugins/vestige/fstclient.cpp: - * plugins/vestige/fstclient.h: - * plugins/vestige/fstserver.cpp: - * plugins/vestige/vestige.cpp: - * plugins/vestige/vestige.h: - - support for telling plugin current BPM, also catches BPM-changes - - handle plugins without GUI correctly - - * include/tool_button.h: - * src/widgets/tool_button.cpp: - catch toggle-signals to emit clicked()-signal which is necessary if a - button is checked using setChecked()-method and not by the user - - fixes some bugs with piano-roll - - * include/piano_roll.h: - * src/core/piano_roll.cpp: - - show text-float after user copied notes - - do not play note when just moving selection - - when update()ing paint everything in a pixmap which is painted in - paintEvent() - saves all the repaints everytime mouse-cursor is moved - and makes painting tool-cursor possible again - - * src/tracks/channel_track.cpp: - corrected calculation in channelTrack::masterKey() - -2005-12-27 Tobias Doerffel - - * include/piano_roll.h: - * src/core/piano_roll.cpp: - always reset cursor when receiving leave-event - - * include/channel_track.h: - * src/tracks/channel_track.cpp: - use new fade-button as MIDI-event-indicator as well as simple - play-default-tone-button - - * include/fade_button.h: - * src/widgets/fade_button.cpp: - added fade-button which can be activated and fades back to - default-color afterwards - - * src/core/arp_and_chords_tab_widget.cpp: - * src/core/envelope_and_lfo_widget.cpp: - * src/core/envelope_tab_widget.cpp: - * src/core/midi_tab_widget.cpp: - * src/core/note.cpp: - * src/core/song_editor.cpp: - * src/core/track.cpp: - * src/tracks/bb_track.cpp: - * src/tracks/channel_track.cpp: - * src/tracks/sample_track.cpp: - do not use QString::number() for saving scalar value with - setAttribute() as it is obsolete - - * src/audio/audio_alsa.cpp: - * src/audio/audio_oss.cpp: - start audio-thread with QThread::HightestPriority for having less xruns - - * src/tracks/pattern.cpp: - save m_steps-property, otherwise restoring it in loadSettings() makes - no sense... - fixes bug which caused LMMS to always reset number of - steps to 16 when loading files, even if the user created patterns - containing more than 16 steps - - * include/audio_dummy.h: - - fixed missing implementation of thread running the whole time and - calling audioDevice::processNextBuffer() -> fixes bugs & lockups when - using audio-dummy-driver - - thread now always waits the amount of time that is left for the - current buffer, so if rendering of current buffer went faster than - in realtime, the song doesn't play at a higher speed - -2005-12-26 Tobias Doerffel - - * plugins/vestige/vestige.cpp: - determine real key of note using channelTrack::masterKey - - * include/micro_timer.h: - moved micro-timer-class from mixer.cpp in separate header for being - available to all modules of LMMS - - * src/core/mixer.cpp: - added metronome-sounds when recording in piano-roll - - * src/lib/sample_buffer.cpp: - - added resample()-method for resampling whole sample-buffer - - after libsndfile try to load sample with libvorbis instead of - SDL_sound as the latter one seems to be buggy on few systems and - leads to unexpected crashes - - if sample-decoder doesn't resample sample automatically, do it - afterwards using resample() - - * src/core/track_container.cpp: - accept drops of type samplefile and sampledata too and create new - channel-track with AudioFileProcessor - - * plugins/audio_file_processor/audio_file_processor.cpp: - save/load sample-data which was dragged on plugin in settings - - * src/core/track.cpp: - display correct length and now additionally start- and end-position of - track-content-object - - * include/bb_track.h: - * src/tracks/bb_track.cpp: - do not align position and length of bb-track-objects on tact-boundaries - as it offers an interesting new feature (incomplete/start beats etc.!) - -2005-12-25 Tobias Doerffel - - * src/widgets/visualization_widget.cpp: - enable visualization-widget per default - - * plugins/vestige/vestige.cpp: - - do not crash when loading settings with empty plugin-attribute (e.g. - older projects/presets) - - set channel-name according to plugin-name - - added note-off-button for being able to note off hanging notes - (which sometimes occurs in combination with arpeggios) - -2005-12-24 Tobias Doerffel - - * plugins/vestige/vestige.cpp: - use new parameter-saving/loading-feature when saving/loading settings - - * plugins/vestige/communication.h: - * plugins/vestige/fstclient.cpp: - * plugins/vestige/fstclient.h: - * plugins/vestige/fstserver.cpp: - * plugins/vestige/fstserver.h: - * plugins/vestige/fstcore.c: - - added support for saving/loading parameters which almost completes - LMMS's rudimentary VST-support - - support for querying parameter-properties - - some changes in initialization of plugin - - * src/tracks/pattern.cpp: - pass unused wheel-events to trackContentObect for being able to scroll - within song-editor - -2005-12-23 Tobias Doerffel - - * plugins/vestige/fstcore.c: - a lot of clean-ups and other bug-fixes making VeSTige almost usable - and stable - - * plugins/vestige/fstclient.h: - * plugins/vestige/fstclient.cpp: - save PID of children when fork()ing XFST-server which is used for - sending SIGTERM when destroying everything - - * plugins/vestige/communication.h: - * plugins/vestige/fstclient.cpp: - * plugins/vestige/fstserver.cpp: - * plugins/vestige/fstcore.c: - do not show editor until client created x11-embed-widget - solves - problems with not-embedded plugins under KDE - - * plugins/vestige/fstserver.cpp: - rewrote MIDI-enqueueing-code as the old one was very buggy and - unreliable - - * plugins/vestige/vestige.h: - * plugins/vestige/vestige.cpp: - added mutex for plugin which solves some problems - - * include/mixer.h: - * src/core/mixer.cpp: - per default clear all play-handles but instrument-play-handles in - mixer::clear() as instrument-playhandles normally exist during the - whole life-time of a certain plugin and must not be deleted when just - stopping song etc. - - * include/play_handle.h: - added type-information, so every derived class has to pass a - type-constant to playHandle-constructor - -2005-12-22 Tobias Doerffel - - * configure.in: - made 0.1.2 release - -2005-12-21 Tobias Doerffel - - * src/lib/sample_buffer.cpp: - - first try to use libsndfile instead of SDL_sound for decoding sample - as SDL_sound sometimes doesn't handle samples (raw- and FLAC-files) - the correct way and returns unusable data while libsndfile seems to - work quite fine with these samples - - when using libsamplerate, use linear-interpolation per default - instead of zero-order-hold-resampling which results in MUCH higher - quality when resampling as it produces much less artifacts - - * src/core/file_browser.cpp: - classify files with extension "flac" as samples - - * src/widgets/tab_widget.cpp: - hide all other tabs when changing active tab - necessary for working - with Qt 4.1 - -2005-12-20 Danny McRae - - * resources/step_btn_on_100.png: - * resources/step_btn_yellow.png: - * include/pattern.h: - * src/tracks/pattern.cpp: - make it possible to change volume of steps in bb-editor using mouse - wheel and which changes color of step-button accordingly - -2005-12-20 Tobias Doerffel - - * src/lib/sample_buffer.cpp: - first implementation of FLAC-encoding/decoding for compressing buffers - before encoding them to base64 which results in smaller XML-files - - currently disabled as it's still buggy and unusable - - * src/lib/buffer_allocator.cpp: - in cleanup-method use list instead of vector for pool of buffers to be - removed - fixes crash with Qt4 - -2005-12-19 Tobias Doerffel - - * src/widgets/knob.cpp: - made knob ready for drag'n'drop of values - - * src/tracks/sample_track.cpp: - load and save/load sample-data which doesn't come from sample in/from - XML-node (base64-encoded) - -2005-12-18 Tobias Doerffel - - * src/tracks/pattern.cpp: - use Sint32 instead of Sint16 for determining central key, otherwise we - might get overflows when having a lot of notes - - * src/tracks/sample_track.cpp: - draw zero-line if sample is shorter than TCO - - * src/core/track.cpp: - display text-float with current position/size when moving/resizing TCO - - * src/core/song_editor.cpp: - do correct positioning for text-floats for master-volume/-pitch - - * include/envelope_and_lfo_widget.h: - * src/core/envelope_and_lfo_widget.cpp: - added support for user-defined wave-shapes - the user just has to drag - an audio-sample into envelope/lfo-widget and that's all ;-) - - * src/tracks/pattern.cpp: - * src/tracks/sample_track.cpp: - make sound-buffer of frozen pattern draggable to sample in - sample-track - - * include/sample_buffer.h: - * src/lib/sample_buffer.cpp: - support for base64-encoding of sample-data into a QString - - * src/core/track_container.cpp: - import MIDI-file to itself when getting according drag'n'drop-request - - * plugins/audio_file_processor/audio_file_processor.h: - * plugins/audio_file_processor/audio_file_processor.cpp: - receive drop-events (set dragged sample etc.) - - * plugins/vestige/fstclient.h: - * plugins/vestige/fstclient.cpp: - renamed removeVSTPlugin::write/readValue to write/readValueS for - compiling even with buggy GCC 3.x - - * include/file_browser.h: - * src/core/file_browser.cpp: - made up all that drag'n'drop-stuff, you're now able to drag samples - and presets directly to according channel, sample etc. - -2005-12-17 Tobias Doerffel - - * include/bb_editor.h: - * include/pattern.h: - * src/core/bb_editor.cpp: - * src/tracks/pattern.cpp: - always update according bb-tracks when changing pattern/it's length - - * include/track.h: - * src/core/track.cpp: - * src/core/track_container.cpp: - drag'n'drop everywhere - now you can drag every track-content-object - (e.g. a pattern) to every other track-content-object of the same type - or to a free place in an according track or just in another - track-container - - * include/mmp.h: - * src/lib/mmp.cpp: - allow additionally to load data from given string instead of file - - * include/timeline.h: - * src/core/timeline.cpp: - - disable magnetic loop-points when pressing control - - set start-point directly to given position when pressing middle - mouse-button, do the same for end-point of shift is pressed at the - same time - - * include/piano_roll.h: - * include/song_editor.h: - * src/core/piano_roll.cpp: - * src/core/song_editor.cpp: - use modifier-key-states from lmmsMainWin instead of monitoring them on - it's own - - * include/lmms_main_win.h: - * src/core/lmms_main_win.cpp: - capture key-events and save states of shift, control- and alt-key - everytime it changes - other widgets can use this for querying whether - one of these modifier-keys is pressed - -2005-12-16 Tobias Doerffel - - * configure.in: - added better LADSPA-check and fixed some other small things - - * src/core/mixer.cpp: - query attribute "mididev" instead of "midiclient" for determining - selected MIDI-device - fixes bug with apparently non-selectable - MIDI-device/-client - - * src/core/plugin.cpp: - * src/lib/ladspa_manager.cpp: - load plugins using QLibrary instead of platform-dependent dl-functions - -2005-12-15 Tobias Doerffel - - * include/audio_alsa.h: - do not include alsa-headers if they do not exist... - -2005-12-14 Tobias Doerffel - - * src/core/file_browser.cpp: - display text-float while loading sample for preview - - * plugins/audio_file_processor/audio_file_processor.cpp: - fixed bug which caused LMMS to crash when playing notes on - audio-file-processor, which was created out of preset containing link - to file which doesn't exist - - * src/core/song_editor.cpp: - use text-floats instead of status-bar - - * src/core/lmms_main_win.cpp: - removed status-bar - - * plugins/vestige/vestige.cpp: - show text-float while loading plugin - - * include/text_float.h: - * src/widgets/text_float.cpp: - heavy improvements on text-float-widget which is now also able to - display messages with title and pixmap and offers two static methods - for displaying a certain message - - * src/tracks/channel_track.cpp: - set project modified after accepting drops of presets/plugins - - * include/instrument_play_handle.h: - check for m_instrument being NULL because play-handle might be - invalidated and thus crash when referencing NULL-ptr - - * most files: - continued improving Qt4-support - -2005-12-13 Tobias Doerffel - - * most files: - made LMMS compatible with Qt4 again after heavy development under Qt3 - led to incompatibility with Qt4 - -2005-12-11 Tobias Doerffel - - * src/core/lmms_main_win.cpp: - * src/lib/mmp.cpp: - - default file-extension is now "mmp" (MultiMedia Project) instead of - "xml" for being able to associate mmp-files with LMMS in - file-managers etc. - futhermore LMMS-file-browser is much faster now - because it does not have to examine each file - - file-extension for song-templates is now "mpt" (MultiMedia Project - Template) - - * include/cpuload_widget.h: - * src/widgets/cpuload_widget.cpp: - added cool CPU-load-widget displaying LMMS's current CPU-usage - - * src/core/note_play_handle.cpp: - always check validity of sub-notes as they might not be known to mixer - and therefore not invalidated in certain situations which made LMMS - crashing (e.g. when deleting a channel-track which was current playing - some arpeggio-notes) - - * include/pattern.h: - * src/tracks/pattern.cpp: - start separate thread for freezing pattern as this doesn't block the - GUI-thread and user is now able to cancel pattern-freezing (which was - not possible after last rewrite a few days ago) - - * include/timeline.h: - * src/core/timeline.cpp: - use timer for periodically screen-updates - locking QApplication-mutex - isn't necessary anymore which makes LMMS not to hang when creating - new song while playing etc. - - * src/core/piano_roll.cpp: - when settings time-line-position, call setTact( 0 ) and - setTact64th( 0 )-members instead of pos() = 0 (the latter one leads - to crashes) - - * plugins/audio_file_processor/audio_file_processor.cpp: - update start- and end-frames of sample-buffer when loading settings - -2005-12-10 Tobias Doerffel - - * include/lmms_main_win.h: - * include/song_editor.h: - * src/core/lmms_main_win.cpp: - * src/core/song_editor.cpp: - * resources/toolbar_bg.png: - * resources/main_toolbar_bg.png: - heavy improvements on toolbars - - * include/nstate_button.h: - * src/widgets/nstate_button.cpp: - base-class is now toolButton instead of QPushButton - - * include/tool_button.h: - * src/widgets/tool_button.cpp: - - moved implemenation of toolButton into cpp-file - - added highlighting during mouse-over - - do not connect clicked()-signal if receiver and/or slot are NULL - -2005-12-09 Tobias Doerffel - - * include/channel_track.h: - * src/core/midi_tab_widget.cpp: - * src/core/preset_preview_play_handle.cpp: - added support for saving and restoring MIDI-connections of a channel - in ordinary channel-preset-data - - * include/channel_track.h: - * include/midi_tab_widget.h: - * src/core/midi_tab_widget.cpp: - * src/tracks/channel_track.cpp: - dropped support for switchable MIDI-event-routing as it is done per - default and actually makes no sense... - - * src/midi/midi_port.cpp: - do not process MIDI-out-event if channel = -1 - -2005-12-08 Tobias Doerffel - - * src/core/midi_tab_widget.cpp: - - always un-check items in port-menus when disabling receiving or - sending MIDI-events - - small GUI improvements - - * resources/midi_in.png: - * resources/midi_out.png: - added icons for MIDI-input- and MIDI-output-port-selection - -2005-12-07 Tobias Doerffel - - * include/midi_alsa_seq.h: - * include/midi_client.h: - * include/midi_tab_widget.h: - * src/core/midi_tab_widget.cpp: - * src/midi/midi_alsa_seq.cpp: - * src/midi/midi_client.cpp: - added support for easy MIDI-port-subscription inside LMMS by just - selecting according source-/destination-port from a menu in - MIDI-setup-tab in each channel-window - -2005-12-06 Tobias Doerffel - - * src/core/note_play_handle.cpp: - * src/core/piano_roll.cpp: - * src/core/piano_widget.cpp: - * src/tracks/channel_track.cpp: - moved output-MIDI-event-generation-code from channel-track to - note-play-handles for covering arpeggio/chords and having exactly - timed events - makes it now possible to control other MIDI-based - synths etc. from patterns (which was not possible before because - of a small bug) - will drop MIDI-out-plugin very soon as it isn't - needed anymore - -2005-12-05 Tobias Doerffel - - * include/piano_roll.h: - * src/core/piano_roll.cpp: - - when moving mouse draw a bar at current key - - re-enabled mouse-tracking for cursor-changes when mouse is over tail - of note etc. - - * resources/zoom.png: - * src/core/song_editor.cpp: - * src/core/piano_roll.cpp: - added small zoom-icon to zoom-combobox - -2005-12-04 Tobias Doerffel - - * include/midi_alsa_raw.h: - * include/midi_client.h: - * include/midi_dummy.h: - * include/midi_oss.h: - * src/midi/midi_alsa_raw.cpp: - * src/midi/midi_client.cpp: - * src/midi/midi_oss.cpp: - renamed class midiRawClient to midiClientRaw - - * include/pattern.h: - * src/core/song_editor.cpp: - * src/tracks/pattern.cpp: - do not hang in endless loop when rendering pattern with enabled - looping-points - - * src/core/time_line.cpp: - align looping-points on bars - - * include/bb_editor.h: - * include/piano_roll.h: - * include/song_editor.h: - * include/timeline.h: - * include/tool_button.h: - * src/core/bb_editor.cpp: - * src/core/piano_roll.cpp: - * src/core/song_editor.cpp: - * src/core/timeline.cpp: - redesigned toolbars of song-editor, bb-editor and piano-roll - now - they're looking really cool and especially time-line-features are much - more usable - - * include/song_editor.cpp: - * src/core/lmms_main_win.cpp: - * src/core/song_editor.cpp: - - added main-toolbar at bottom of screen and moved several widgets from - song-editor-toolbar into it - - added high-quality-button for switching to 88200/96000 Hz - - * src/widgets/tab_widget.cpp: - reversed scroll-wheel-direction for changing tab - -2005-12-03 Tobias Doerffel - - * src/core/main.cpp: - - better handling of command-line options - - added help switch - - fixed bugs concerning rendering from command-line - - * include/audio_alsa.h: - * include/audio_device.h: - * include/audio_dummy.h: - * include/audio_file_device.h: - * include/audio_file_ogg.h: - * include/audio_file_wave.h - * include/audio_jack.h: - * include/audio_oss.h: - * include/audio_sdl.h: - * include/export.h: - * include/export_project_dialog.h: - * include/mixer.h: - * include/pattern.h - * include/song_editor.h: - * src/audio/audio_alsa.cpp: - * src/audio/audio_device.cpp: - * src/audio/audio_file_device.cpp: - * src/audio/audio_file_ogg.cpp: - * src/audio/audio_file_wave.cpp: - * src/audio/audio_jack.cpp: - * src/audio/audio_oss.cpp: - * src/audio/audio_port.cpp: - * src/audio/audio_sdl.cpp: - * src/core/export_project_dialog.cpp: - * src/core/lmms_main_win.cpp: - * src/core/main.cpp: - * src/core/mixer.cpp: - * src/core/song_editor.cpp: - * src/track/pattern.cpp: - changed architecture of mixer-system from push- to pull-architecture - which makes almost all things (song-export, pattern-freezing etc.) much - easier and also results in a better performance (especially when using - JACK) - additionally LMMS doesn't take 100% CPU anymore - -2005-12-02 Tobias Doerffel - - * src/core/config_mgr.cpp: - do not try to re-run wizard in case of version mismatches - - * configure.in: - * plugins/Makefile.am: - * presets/Makefile.am: - dropped ladspa_sine_1063-plugin as it is only for experimental - purposes - -2005-11-29 Tobias Doerffel - - * plugins/vestige/vestige.h: - * plugins/vestige/vestige.cpp: - changes for working with new VST-framework - - * plugins/vestige/fstclient.h: - * plugins/vestige/fstserver.h: - * plugins/vestige/fstclient.cpp: - * plugins/vestige/fstserver.cpp: - * plugins/vestige/fstcore.c: - * plugins/vestige/communication.h: - added new VST-framework (client-server-architecture) based on XFST - - * include/qxembed.h - * src/widgets/qxembed.cpp: - added QXEmbed-widget which is necessary for embedding VST-plugin - -2005-11-27 Tobias Doerffel - - * src/core/mixer.cpp: - added usleep()-call for realizing usable threading and solve problems - with 100%-CPU-usage - -2005-11-08 Tobias Doerffel - - * include/channel_track.h: - * include/sample_play_handle.h: - * include/sample_track.h: - * src/core/sample_play_handle.cpp: - * src/tracks/channel_track.cpp: - * src/tracks/sample_track.cpp: - made things work with audio-ports - - * include/mixer.h: - * src/core/mixer.cpp: - completely revised internal mixing-engine make it working with - the new audio-ports, which results in a much cleaner, faster and more - powerful mixing-engine - - * include/audio_port.h: - * src/audio/audio_port.cpp: - added so called audio-ports which are important for transporting sound - from it's origin through the mixer and the effect-board (the latter - one isn't existing yet but coming quite soon) - another important - point is the ability of having output-ports for each channel/sample- - track with JACK - - * src/tracks/channel_track.cpp: - translate default-channel-name "Default" - - * src/audio/audio_jack.cpp: - - sync JACK's buffer-size with LMMS's one - - start JACK-transport if not already done - - * include/mixer.h: - * src/audio/audio_jack.cpp: - * src/core/mixer.cpp: - * src/lib/sample_buffer.cpp: - * src/widgets/visualization_widget.cpp: - use memset() for clearing buffers - obsoletes usage of silence-buffers - in mixer - -2005-11-07 Tobias Doerffel - - * src/midi/midi_alsa_seq.cpp: - use relative instead of absolute scheduling for events which makes - MIDI-out working - -2005-10-31 Tobias Doerffel - - * include/midi_alsa_seq.h: - * src/midi/midi_alsa_seq.cpp: - several bug-fixes - -2005-10-30 Tobias Doerffel - - * include/midi_alsa_seq.h: - * src/midi/midi_alsa_seq.cpp: - added first version of ALSA-sequencer - currently doesn't handle all - common events, but note-on/off and key-pressure work so far - - * include/midi_client.h: - - added method applyPortMode() for making MIDI-subsystem able to get - known of port-mode changes which is necessary if they have REAL - ports like ALSA-seq. has - - renamed validatePortName() to applyPortName() and made it non-pure - virtual - - * src/tracks/channel_track.cpp: - initialize m_midiEventRoutingEnabled with FALSE per default in ctor - - * src/core/mixer.cpp: - delete midi-dev on exit - - * src/midi/midi_midi_alsa_raw.cpp: - when reading/saving device-name via config-mgr, use "midialsaraw" - instead of "midialsa" as context-name - -2005-10-28 Tobias Doerffel - - * src/widgets/project_notes.cpp: - set initial text to bright gray, since black text on a very dark back- - ground isn't very readable... - - * include/lmms_main_win.h: - * include/setup_dialog.h: - * src/core/bb_editor.cpp: - * src/core/lmms_main_win.cpp: - * src/core/setup_dialog.cpp: - * src/core/song_editor.cpp: - * src/widgets/project_notes.cpp: - added support for GIMP-like usability, i.e. no MDI - - * src/core/song_editor.cpp: - * src/core/bb_editor.cpp: - reorder some code in constructor for not crashing if window is - shown while constructor is still running - -2005-10-23 Tobias Doerffel - - * src/widgets/led_checkbox.cpp: - also emit toggled()-signal if state actually wasn't changed - - * include/lcd_spinbox.h: - * src/widgets/lcd_spinbox.cpp: - - display special strings if value is a certain number - - support for disabled-state (gray/no input) - - * include/midi_tab_widget.h: - * src/core/midi_tab_widget.cpp: - * src/tracks/channel_track.cpp: - added new tab "MIDI" for being able to setup MIDI-related stuff for - each channel - - * include/channel_track.h: - * include/midi*: - * include/piano_widget.h: - * include/setup_dialog.h: - * src/core/mixer.cpp: - * src/core/piano_roll.cpp: - * src/core/piano_widget.cpp: - * src/core/setup_dialog.cpp: - * src/core/song_editor.cpp: - * src/midi/midi*: - * src/tracks/channel_track.cpp: - coded a completely new, powerful and clean MIDI-system which e.g. makes - it possible to mask MIDI-events for each channel and to receive and send - (timed!) MIDI-events on a separate MIDI-port for each channel, which - only makes sense if using non-raw (sequenced) MIDI-client - currently - none existing, but ALSA-sequencer-support is in progress - - * include/midi_device.h: - * src/midi/midi_device.cpp: - removed - -2005-10-21 Tobias Doerffel - - * src/widgets/tempo_sync_knob.cpp: - do not implement the same code as knob does in mouseMoveEvent() - call - knob::mouseMoveEvent() instead - - * include/knob.h: - * src/widgets/knob.cpp: - cleaned up a lot and fixed some bugs - -2005-10-20 Tobias Doerffel - - * include/song_editor.h: - decreased MAX_BPM to 999 since BPM-LCD-spinbox is intended to have - only three digits while 1000 has four of them... ;-) - - * include/track_container.h: - * src/core/track_container.cpp: - trackContainer::scrollArea-class has now m_trackContainer-member - for storing parent which makes cast of parent-widget to track-container - (which sometimes failed...) obsolete - - * configure.in: - check for libfst and present VST-SDK header-files - -2005-10-19 Tobias Doerffel - - * plugins/vestige/vestige.h: - * plugins/vestige/vestige.cpp: - added possibility of opening plugins instead of hardcoding them ;-) - - * include/track.h: - renamed createTrack() and cloneTrack() to create() and clone() - - * include/track_container.h: - * src/core/track_container.cpp: - receive drop-events -> add channel with instrument/preset - - * src/audio/audio_jack.cpp: - removed usleep() out of loop in audioJACK::writeBufferToDev() since it - caused LMMS to hang e.g when removing a track - - * src/core/plugin_browser.cpp: - show hand-cursor if over a plugin-description-widget - - * src/widgets/pixmap_button.cpp: - if pixmap-button is set non-checkable, draw active-graphic if pressed - down and inactive one in normal state - - * include/lmms_main_win.h: - * src/core/lmms_main_win.cpp: - own workspace for making wheelEvent(...) is now obsolete -> removed - - * include/track_container.h: - * src/core/song_editor.cpp: - * src/core/track_container.cpp: - added own scroll-area for capturing special wheel-events where a - modifier-key (shift, control etc.) is pressed - - * src/core/song_editor.cpp: - removed add-channel-button as it is obsolete after adding plugin-browser - - * resources/: - improved icons such as project_*.png and sample-track-related icons - -2005-10-18 Tobias Doerffel - - * include/channel_track.h: - * src/tracks/channel_track.cpp: - - moved channelButton-implementation to channel_track.src - - added support for receiving drop-events, which makes channel-track - to load either the given instrument or the given preset - - * src/core/plugin_browser.cpp: - * include/plugin_browser.h: - added cool plugin-browser, which displays all available instrument- - plugins which are draggable to a channel-window/button - - * include/string_pair_drag.h: - * src/lib/string_pair_drag.cpp: - added drag'n'drop-implementation for dragging string-pairs (key/value) - which provides a standard-interface, although drag'n'drop has changed a - lot in Qt 4 - - * src/widgets/crystal_button.cpp: - made mouseMoveEvent()-method much more effective - - * Makefile.am: - * buildtools/Makefile.am: - build buildtools in subdir instead of top-build-directory - solves - dependendy problems with bin2res - - * src/core/file_browser.cpp: - do not depend on typeinfo of audioFileProcessor anymore by using - new setParameter()-method - - * include/plugin.h: - added setParameter() and getParameter()-methods for making LMMS able to - set parameters of a specific plugin without knowing anything about it - -2005-10-17 Tobias Doerffel - - * buildtools/bin2res.cpp: - * include/embed.h: - * src/lib/embed.cpp: - - declaration of embedded-data-descriptor is now located in embed.h and - part of namespace embed - - added support for local embedded-resources which is important for - plugins containing their own images etc., so data and access-methods - are stored into namespace PLUGIN_NAME - - * include/plugin.h: - * src/core/plugin.cpp: - added logo-field to descriptor-structure and simplified method for - getting descriptors of all plugins - - * include/basic_filters.h: - removed Moog-2-filter as it is only very CPU-intensive without any - significant difference to sound of normal Moog-filter - -2005-10-16 Tobias Doerffel - - * src/lib/ladspa_manager.cpp: - skip not existing/unreadable directories when searching for plugins - - * include/vestige.h: - * src/plugins/vestige.cpp: - make use of new instrument-play-handle - - * include/channel_track.h: - * src/core/browser.cpp: - * src/core/song_editor.cpp: - * src/midi/midi_file.cpp: - * src/tracks/channel_track.cpp: - renamed loadPlugin() to loadInstrument() - - * include/config_mgr.h: - * src/core/config_mgr.cpp: - added pluginDir()-method - - * include/instrument_play_handle.h: - added another play-handle for playing instruments which do not - produce sound for each note - - * src/plugins/: - renamed directory soundgenerators to plugins and modified all plugins - for working with revised plugin-system - - * include/instrument.h: - * include/plugin.h: - * src/core/instrument.cpp: - * src/core/plugin.cpp: - splitted code from instrument up into class plugin and class instrument - and revised plugin-system - - * include/instrument.h: - * src/core/instrument.cpp: - renamed files soundgenerator.* to instrument.* as well as class-name - -2005-10-15 Tobias Doerffel - - * include/vestige.h: - * src/soundgenerators/vestige.cpp: - new plugin "VeSTige" for handling VST-plugins - VERY experimental, - but at least, we get some sound out of these strange dll-files ;-) - -2005-10-13 Tobias Doerffel - - * src/audio/audio_jack.cpp: - do not fill up buffers if JACK-transport is not rolling but at the same - time always handle frame-syncing-var in JACK-callback, even if JACK- - transport is not rolling - fixes several bugs like lockups when - removing tracks while JACK-server is pausing... - - * src/widgets/knob.cpp: - fixed bug which caused hidden mouse-cursor forever when pressing right - mouse-button while left one is pressed - - * src/lib/ladspa_manager.cpp: - use /usr/lib/ladspa as default-directory if env-var LADSPA_PATH is not - set - - * src/soundgenerators/*.cpp: - removed obsolete defaultSettings()-method from each soundgenerator - -2005-10-13 Danny McRae - - * include/ladspa_manager.h - * include/ladspa_sine_1063.h - * src/lib/ladspa_manager.cpp: - * src/soundgenerators/ladspa_sine_1063.cpp: - added LADSPA-support and a simple soundgenerator for testing-purposes - -2005-10-12 Danny McRae - - * Makefile.am: - * include/led_checkbox.h: - * src/core/envelope_and_lfo_widget.cpp: - * src/widgets/led_checkbox.cpp: - inherit ledCheckBox from QWidget instead of QCheckBox since it sometimes - caused graphic-errors when running on KDE with Baghira-style... - -2005-10-05 Danny McRae - - * resources/note_double_whole.png: - * resources/note_eighth.png: - * resources/note_half.png: - * resources/note_none.png: - * resources/note_quarter.png: - * resources/note_sixteenth.png: - * resources/note_thirtysecond.png: - * resources/note_whole.png: - * resources/xclock.png: - added icons for context-menu of tempoSyncKnob - - * src/widgets/lcd_spinbox.cpp: - emit valueChanged()-signal in wheelEvent()-method - - * include/song_editor.h: - * src/core/song_editor.cpp: - - added getBPM()-method - - emit signal if BPM is changed - - * include/arp_and_chords_tab_widget.h: - * include/envelope_and_lfo_widget.h: - * src/core/arp_and_chords_tab_widget.cpp: - * src/core/envelope_and_lfo_widget.cpp: - use new tempoSyncKnob-widget instead of traditional time-knob - - * include/tempo_sync_knob.h: - * src/widgets/tempo_sync_knob.cpp: - added tempo-sync-knob which automatically converts fixed note-length's - to a fixed time in ms everytime BPM is changed - -2005-10-03 Tobias Doerffel - - * include/basic_filters.h: - - added another moog-filter which sounds a bit better but needs MUCH - more CPU-time... - - cleaned up different filter-code-branches - -2005-10-02 Tobias Doerffel - - * include/oscillator.h: - cast to int instead of floor()ing value in oscillator::phase() which - makes the whole thing faster again... - -2005-09-29 Tobias Doerffel - - * src/widgets/tab_widget.cpp: - fixed bugs when adding widget with already existing index - - * Makefile.am: - * include/midi_out.h: - * include/plucked_string_synth.h: - * src/soundgenerators/midi_out.cpp: - * src/soundgenerators/plucked_string_synth.cpp: - classes midiOut and pluckedStringSynth do not have slots or signals, - so Q_OBJECT-macros were removed and MOC-code isn't compiled anymore - - * include/sgs: - * src/core/plugin_management.cpp: - removed because not needed anymore with new plugin-system - - * configure.in: - * Makefile.am: - * include/audio_file_processor.h: - * include/channel_track.h: - * include/midi_out.h: - * include/plucked_string_synth.h: - * include/sound_generator.h: - * include/triple_oscillator.h: - * src/core/browser.cpp: - * src/core/sound_generator.cpp: - * src/core/song_editor.cpp: - * src/midi/midi_file.cpp: - * src/soundgenerators/*: - * src/tracks/channel_track.cpp: - made all sound-generator-plugins shared libraries loaded at runtime, - which gives much more flexibility because you can load songs/presets - from people having other plugins just by adding according lib*.so file - to /usr/lib - no need to recompile! - - * inlude/empty_sg_plugin.h: - added empty sound-generator plugin - -2005-09-28 Tobias Doerffel - - * include/song_editor.h: - * src/core/song_editor.cpp: - added combo-box for selectinf zooming-factor - - * include/piano_roll.h: - * src/core/piano_roll.cpp: - added combo-box for selecting zooming-factor - - * include/led_checkbox.h: - * src/widgets/led_checkbox.cpp: - added methods for querying and setting state - - * src/core/arp_and_chords_tab_widget.cpp: - * src/core/envelope_tab_widget.cpp: - better alignment of widgets inside each of this tabs - - * src/tracks/channel_track.cpp: - finished improving GUI of channel-track-window by using tabWidget - instead of tabBar for plugin-, env/lfo- and arp-widgets - - * include/envelope_and_lfo_widget.h: - * src/core/envelope_and_lfo_widget.cpp: - use ledCheckBox'es instead of pixmapButton's with QLabel's - - * include/tab_widget.h: - * src/widgets/tab_widget.cpp: - made tabWidget more powerful: - - use indexed tabs - - different painting if no caption was defined - - switch tabs if wheel-events occurs - -2005-09-27 Tobias Doerffel - - * src/tracks/channel_track.cpp: - began improving GUI of channel-track-window - - * projects/cool_songs/TobyDox-TheFourthDimension.xml: - added another song... - - * include/qt3support.h: - Qt 3.1-support - - * include/audio_alsa.h: - define macro ALSA_PCM_NEW_HW_PARAMS_API for working with older ALSA- - versions which offer old and new HW-param-API - we're using the new one - -2005-09-26 Tobias Doerffel - - * many files: - make LMMS compile with Qt 3.0 and GCC 2.95 - -2005-09-25 Tobias Doerffel - - * src/audio/audio_jack.cpp: - - decreased wait-time from 0.5 ms to 0.2 ms in writeBufferToDev(...) - - clear part of buffers that could not be filled for avoiding bad - noise in case there's no data from sound-render-thread, because it is - locked or got no cpu-time for some reason - - * src/core/timeline.cpp: - do not call update() in updatePosition, call paintEvent() directly - instead - hopefully fixes the "unexspected Xlib async replies" - which occured in some seldom cases because there were paint-events - generated - something that must not be done in other threads... - - * resources/source/songeditor.svg: - * resources/songeditor.png: - created a new song-editor-icon - - * src/core/song_editor.cpp: - do not save play-pos from previous play-mode when beginning to play - in different play-mode - fixes bug in timeline behaviour "back to start" - -2005-09-24 Tobias Doerffel - - * configure.in: - * include/audio_oss.h: - * include/midi_oss.h: - * src/audio/audio_oss.cpp: - * src/midi/midi_oss.cpp: - made LMMS compiling and working without OSS - configure detects - whether soundcard.h is available - - * include/gui_templates.h: - made template pointSize(...) platform-independent by not using x11- - specific qt-classes/-functions - - * include/templates.h: - moved pointSize-function with all the headers it depends on into - gui_templates.h - - * src/core/mixer.cpp: - - do not initialize member m_surroundSilence if surround is disabled - - free silence-buffers in dtor - - * src/tracks/bb_track.cpp: - when drawing gradient skip first and last line as a rect is painted - over it afterwards - - * src/core/track_container.cpp: - set modified-state for song when removing track - -2005-09-21 Tobias Doerffel - - * configure.in: - made 0.1.1 release - -2005-09-20 Tobias Doerffel - - * include/about_dialog.h: - * src/core/about_dialog.cpp: - no need for passing parent when creating about-dialog - - * src/core/song_editor.cpp: - - different usage of question-box in songEditor::mayChangeProject() - because of bugs with several qt-versions... - - when exporting song, do use baseName( TRUE ) instead of baseName() - for determining base-name of rendered file - - * src/core/lmms_main_win.cpp: - - display filename before app-name in window-title - - only use basename of filename in window-title - - added message referring to LMMS-homepage when clicking on - Help/Help - - * src/core/export_song_dialog.cpp: - use lmmsMainWin::resetWindowTitle() for resetting window-title - after export is done - - * src/widgets/knob.cpp: - do not add tooltips to knobs - clicking on knob has quite the same - effect so tooltips are just annoying - - * src/core/browser.cpp: - when matching file-name, always convert them to lower case for also - handling files like foo.WAV - - * src/core/config_mgr.cpp: - added setValue(...)-call for saving working-directory after setting - up everything - fixes bug with empty browsers after fresh personal - installation of LMMS - -2005-09-19 Tobias Doerffel - - * configure.in: - made 0.1.0 release - -2005-09-18 Tobias Doerffel - - * src/tracks/bb_track.cpp: - revised paintEvent()-method -> bb-TCO's are now painted with a gradient! - - * src/core/song_editor.cpp: - - call bbEditor::stop before playing to make sure play-button in - bb-editor is properly reset - - call realignTracks() with parameter TRUE in wheelEvent(...) - - some hacks for making pause-button work... - - * src/core/track_container.cpp: - added parameter _complete_update to trackContainer::realignTracks() - to be able to hide and show all tracks which is necessary e.g. - after having changed pixels-per-tact-property -> zooming in song-editor - works now well - - * src/core/setup_dialog.cpp: - added message-box telling the user to restart LMMS - - * include/midi_alsa_raw.h: - * include/midi_device.h: - * include/midi_oss.h: - * include/midi_dummy.h: - * include/mixer.h: - * include/setup_dialog.h: - * src/core/mixer.cpp: - * src/core/setup_dialog.cpp: - * src/midi/midi_alsa_raw.cpp: - * src/midi/midi_device.cpp: - * src/midi/midi_oss.cpp: - made it possible to select and setup MIDI-device - - * include/knob.h: - * src/widgets/knob.cpp: - - many cleanups, coding style improvements etc. - - added new behaviour for controlling knob -> move cursor up/down for - changing value - - replaced usage of status-bar by text-float-widget - - * include/text_float.h: - * src/widgets/text_float.cpp: - took text-float from Rosegarden - - * include/config_mgr.h: - * src/core/config_mgr.cpp: - - fixed bug in configManager::setValue(): new value-pair was always - pushed back, even if it already existed, so result of value() didn't - change until restart - - moved widget-creation-code from ctor to new method createWidgets() - which fixes problems with unlocalized strings in wizard because - embed::loadTranslation() calls configManager::inst()->localeDir() - for determining path to localization files - this call created all - wizard-widgets before actual localization was loaded... - -2005-09-17 Tobias Doerffel - - * src/core/setup_dialog.cpp: - added switches for disabling tooltips and turning on classical knob- - behaviour - - * include/led_checkbox.h: - * src/widget/led_checkbox.cpp: - added LED-check-box - -2005-09-16 Tobias Doerffel - - * src/core/mixer.cpp: - clear output-buffers in ctor before using them -> avoids awful noises - at startup - - * src/core/mixer.cpp: - * src/lib/sample_buffer.cpp: - * src/tracks/channel_track.cpp: - * src/tracks/sample_track.cpp: - use given frame-parameter in methods playing sample-buffers instead - of mixer::framesPerAudioBuffer() -> no clicks at tact-border because - of odd sample-frame-count - - * src/core/lmms_main_win.cpp: - call presetPreviewPlayHandle::cleanUp() in dtor -> fixes segfault which - which occured at exit if you previewed a channel during session - - * include/preset_preview_play_handle.h: - * src/core/preset_preview_play_handle.cpp: - added cleanUp()-method which deletes blind track-container containing - preset-preview-channel - - * src/soundgenerators/triple_oscillator.cpp: - - unified much code by defining setChecked when compiling with Qt 3 - - also set file-name of user-defined-wave as tool-tip when loading - settings - - * most files in src/: - use new tooltip-system - removes qt3/qt4-compat-code - - * include/tooltip.h: - * src/widget/tooltip.cpp: - added tooltip-namespace with method "add(...)" for allowing transparent - usage of tooltips, so there's no difference to code using tooltips - whether it is compiled with Qt 3 or Qt 4 - -2005-09-14 Tobias Doerffel - - * include/mixer.h: - * include/note_play_handle.h: - * include/play_handle.h: - * src/core/mixer.cpp: - * src/core/note_play_handle.cpp: - * src/tracks/channel_track.cpp: - added play-handle-invalidating-feature making it possible to - invalidate notes of which the objects they depend on do not exist - anymore or things like that. for example channel-track-dtor - invalidates all note-play-handles linked with according channel - -> no segfault when deleting channel-track - - * src/core/track_container.cpp: - pause mixer before removing track -> no segfault - - * src/lib/mmp.cpp: - initialize m_type in mmp::multimediaProject( projectTypes ) - - * src/lib/buffer_allocator.cpp: - added mutex for better protection against parallel accesses from - several threads - fixes some segfaults - - * src/core/lmms_main_win.cpp: - improved ~lmmsMainWin() which now first instructs mixer to quit it's - thread for avoiding spurious usages of objects to be destroyed - afterwards -> no segfault at the end - - * src/core/export_song_dialog.cpp: - * src/tracks/pattern.cpp: - cleaned up exporting/freezing mechanisms by using mixer's new methods - play() and pause() - - * include/mixer.h: - * src/core/mixer.cpp: - cleaned up mixer-thread syncing stuff by reorganizing mutexes and - replacing m_waitMutex by m_safetySyncMutex as well as according methods - lockWaitMutex() and unlockWaitMutex() by play() and pause() - - * src/core/setup_dialog.cpp: - tell config-manager to save it's config-file when setupDialog is - destroyed - -2005-09-13 Stephane Thomas - - * locale/fr.ts: - added French translation - -2005-09-13 Tobias Doerffel - - * src/core/lmms_main_win.cpp: - - show setup-dialog if LMMS is started first time or mixer uses dummy- - audio-driver - - added setup-dialog-entry to settings-menu - - * src/lib/mmp.cpp: - if saving preset, check whether file-name contains suffix ".cs.xml" - and add it if necessary - - * include/midi_alsa_raw.h: - * src/midi/midi_alsa_raw.cpp: - * src/midi/midi_device.cpp: - - changed everything (including file-names) from midiAlsa to midiALSARaw - - added terminate()-call in dtor for terminating thread properly - - * include/tab_bar.h: - * src/widget/tab_bar.cpp: - - added flag for addTab(...)-method indicating whether to use given - text as caption or just as tooltip - - reduced #ifdef QT4-macros by defining some names when compiling - with Qt3 - - * include/setup_dialog.h: - * src/core/setup_dialog.cpp: - added help-button in audio-setup-tab and improved geometry-stuff - - * include/audio_alsa.h: - * include/audio_oss.h: - * src/audio/audio_alsa.cpp: - * src/audio/audio_oss.cpp: - added probeDevice()-method which eases determining device-name in - either actual audio-class as well as in it's setup-widget - -2005-09-11 Tobias Doerffel - - * src/core/mixer.cpp: - use new audio-settings-technology for opening audio-device - - * include/setup_dialog.h: - * src/core/setup_dialog.cpp: - added setup-dialog for general-, audio- and MIDI-settings - - * include/audio_alsa.h: - * include/audio_device.h: - * include/audio_dummy.h: - * include/audio_jack.h: - * include/audio_oss.h: - * include/audio_sdl.h: - * src/audio/audio_alsa.cpp: - * src/audio/audio_device.cpp: - * src/audio/audio_jack.cpp: - * src/audio/audio_oss.cpp: - * src/audio/audio_sdl.cpp: - added setup-widget-technology making it possible to have audio-device- - specific setup-widgets which can be used in setup-dialog etc. - - * include/lcd_spinbox.h: - * src/widgets/lcd_spinbox.cpp: - added stepping-functionality - - * include/tab_widget.h: - * src/widgets/tab_widget.cpp: - pass caption to constructor instead of using fixed text - - * include/tab_bar.h: - * src/widgets/tab_bar.cpp: - - added direction-parameter in constructor - - added exclusive-property - - addTab(...) returns now pointer to tab-button which gives caller - possibility to modify the button - - * src/core/mixer.cpp: - save frames-per-audio-buffer-value in ctor if not set yet instead - of saving it in dtor - - * src/lib/embed.cpp: - do not return null-pixmap if pixmap not found - -2005-09-10 Tobias Doerffel - - * resources/setup_audio.png: - * resources/setup_general.png: - * resources/setup_midi.png: - added icons to be used in setup-dialog - - * src/audio/audio_alsa.cpp: - * src/audio/audio_sample_recorder.cpp: - use auto-cleaning pointer in createSampleBuffer(...) (fixes memory-leak - in ALSA-driver) - - * include/buffer_allocator.h: - added simple class for auto-cleaning pointers - - * src/core/mixer.cpp: - - added delete-calls in mixer::tryAudioDevices() - - init s_instanceOfMe-member in dtor, otherwise LMMS hangs up - - * locale/: - * artwork/: - moved translations and some artwork-stuff into locale- and artwork- - directory which is going to be installed into - LMMS-data-dir (/usr/share/lmms etc.) and shrinks executable - - * src/lib/embed.cpp: - added possibility to have resources in external files instead of being - linked into executable - - * configure.in: - - use macro AS_HELP_STRING for formatting help-strings - - removed --with-latency option as it is not needed anymore - -2005-09-06 Alireza - - * resources/ir.ts: - added Persian translation - -2005-09-04 Tobias Doerffel - - * src/audio/audio_oss.cpp: - - read device-name from config-file before evaluating environment- - variables etc. - - fixed bugs with device-probing (after dev-file was searched, there - was no open(...)-call again so it always failed if the first open(...) - didn't work - - * src/audio/audio_alsa.cpp: - read device-name from config-file before evaluating environment- - variables or using "default" - - * src/core/lmms_main_win.cpp: - call bufferAllocator::cleanUp( 0 ) for destroying all allocated buffers - - * include/buffer_allocator.h: - * src/lib/buffer_allocator.cpp: - - added clean-up-technique which removes least used buffers if - buffer-size exceeds limits (which depends on mixer's buffer-size) - - added field to bufDesc indicating usage of this buf - used by - alloc-method for determining most used, free and matching buffer - - * include/lcd_spinbox.h: - * src/widgets/lcd_spinbox.cpp: - made lcdSpinBox controlable by scroll-wheel - - * src/widgets/knob.cpp: - do not center knob if width of label is greater than actual knob - - * src/audio/audio_sample_recorder.cpp: - use bufferAllocator instead of new[]/delete[] - - * src/core/mixer.cpp: - - read value for frames-per-audio-buffer out of config-file and save - it at exit - - free buffer at exit - - * include/config_mgr.h: - * src/core/config_mgr.cpp: - added value() and setValue()-method which offers all components of LMMS - an easy way for loading/saving their settings at startup/exit - -2005-09-02 Mario Izquierdo -2005-09-02 Johnny Saenz - - * resources/es.ts: - added Spanish translation - -2005-09-02 Tobias Doerffel - - * most files: - finished changes began on 2005-08-29 - - * include/buffer_allocator.h: - * src/lib/buffer_allocator.cpp: - - only return aligned pointers - - small changes in API - - * resources/de.ts: - completed German translation - -2005-08-29 Tobias Doerffel - - * most files: - begin to use new bufferAllocator instead of old buffer-types and - use mixer-method for determining current number of frames per - audio-buffer - - * include/mixer.h: - types audioBuffer and surroundAudioBuffer don't exist anymore as well - as the constant FRAMES_PER_AUDIO_BUFFER - use - mixer::inst()->framesPerAudioBuffer() instead - -2005-08-28 Tobias Doerffel - - * include/song_editor.h: - * src/core/song_editor.cpp: - replaced QSpinBox by lcdSpinBox for BPM-spinbox - - * include/tab_bar.h: - * src/widgets/tab_bar.cpp: - removed function-parameter _font_size for tabBar::addTab(...) - - * most files: - - replaced QFont::setPointSize()-calls by according pointSize()-calls - which makes LMMS usable at any DPI-resolution - - changes for Qt4-compatibility - - * include/misc.h: - * include/template.h: - moved misc.h to template.h and added template-function pointSize - which sets a DPI-independent size for a given font - - * src/tracks/channel_track.cpp: - use labeling-feature of LCD-spinbox and removed old QLabel and - layouting-stuff - - * include/lcd_spinbox.h: - * src/widgets/lcd_spinbox.cpp: - - fixed bug: when moving mouse up, value was not updated properly - - added labeling-feature - - added valueChanged()-signal - - * src/core/arp_and_chords_tab_widget.cpp: - set m_arpDirection correct when loading older settings - -2005-08-27 Tobias Doerffel - - * include/channel_track.h: - * src/tracks/channel_track.cpp: - use new LCD-spinbox for effect-spinbox - - * include/lcd_spinbox.h: - * src/widgets/lcd_spinbox.cpp: - added LCD-spinbox, an improved QLCDNumber with ability of user-input - - * src/core/main.cpp: - changed highlight- and text-color to dark white instead of glaring green - for many people didn't like it... - - * include/audio_jack.h: - * src/audio/audio_jack.cpp: - - read and observe buf-size from JACK, so that writeBufferToDev() can - wait accordingly to it - now JACK-transport also works if buf-sizes - of LMMS and JACK are different - - also free buffers in destructor and not just throw them out of list - -2005-08-26 Tobias Doerffel - - * include/audio_jack.h: - * src/audio/audio_jack.cpp: - - also work with older versions which do not have jack_client_open() - - fixed bugs - - use bufferAllocator instead of new[] and delete[] in time-critical - functions - - * include/buffer_allocator.h: - * src/lib/buffer_allocator.cpp: - added bufferAllocator which is an optimized internal memory-manager - -2005-08-24 Tobias Doerffel - - * include/audio_jack.h: - * src/audio/audio_jack.cpp: - beginning of support for JACK-transport - - * src/audio/audio_sdl.cpp: - fixed memory leak - m_outputBuffer was not deleted in destructor - - * src/core/arp_and_chords_tab_widget.cpp: - completed usage of switchable groupboxes by saving groupbox-states - and evaluating them in processNote() - -2005-08-22 Tobias Doerffel - - * resources/afp_artwork.png: - small improvements for better usability and internationalization - - * src/soundgenerators/audio_file_processor.cpp: - - cleanups and small improvements concerning painting - - added missing tooltips - - moved open-sample-button right to filename-display-bar - - * src/widgets/pixmap_button.cpp: - changed default-pixmaps to led_yellow.png and led_off.png - - * resources/pattern_bg.png: - resized from 2x43 to 2x25 - - * src/core/name_label.cpp: - decreased default-font - - * include/track.h: - decreased size of track-settings-widget from 256 to 224 - - * include/channel_track.h: - * src/tracks/channel_track.cpp: - - use labeling-feature of knob for labeling volume-knob - - use smaller surroundArea in track-settings-widget and smaller - channel-button with smaller font - - * src/core/surround_area.cpp: - made surroundArea working with different widget-sizes than default size - - * resources/background_artwork.png: - made bg-image more pale - - * include/bb_editor.h: - * src/core/bb_editor.cpp: - changed painting-behaviour and made button-bg-gfx's obsolete by using - specialBgHandlingWidget - - * include/groupbox.h: - * src/widgets/groupbox.cpp: - improved groupbox by adding animation and more - - * src/core/envelope_and_lfo_widget.cpp: - * src/core/envelope_tab_widget.cpp: - - use knobs new labeling-feature - - use new tab-widget for target-widgets - - * include/tab_widget.h: - * src/widgets/tab_widget.cpp: - added own tab-widget which looks much cooler than Qt's one - - * src/core/arp_and_chords_tab_widget.cpp: - - using now new groupbox-widget and reorganized knob/switch-positions - - revised arpeggio-direction-buttons - - use knobs new labeling-feature - - removed obsolete headers - - * include/knob.h: - * src/widgets/knob.cpp: - added labeling-feature for automatically labeling knobs with given - text - - -2005-08-21 Tobias Doerffel - - * src/widgets/side_bar_widget.cpp: - * src/tracks/channel_track.cpp: - * src/core/config_mgr.cpp: - * src/core/piano_roll.cpp: - * src/core/arp_and_chords_tab_widget.cpp: - * src/core/main.cpp: - * src/core/browser.cpp: - replaced painting-device-dependent method setPixelSize by setPointSize - - * src/core/envelope_and_lfo_widget.cpp: - now using new group-box which looks much cooler and is more usable - - * include/groupbox.h: - * src/widgets/groupbox.cpp: - added own groupbox-widget with state-LED - - * src/widgets/pixmap_button.cpp: - delete m_bgPixmap in destructor - - * include/spc_bg_hndl_widget.h: - - made member m_backgroundPixmap to normal QPixmap instead of pointer to - it which also fixes a memory leak as dtor didn't delete the pixmap - - also use erase-pixmap of widget if available - - * include/oscillator.h: - - made shape-functions using phase()-function for determining phase of - sample - - made oscillator::phase() using modff instead of floorf-math which - makes the whole thing up to 20% faster - - * src/core/about_dialog.cpp: - added URL of project-page of LMMS - - * src/core/song_editor.cpp: - create new project if file given in cmd-line is not read-/usable - - * include/export_project_dialog.h: - * include/song_editor.h: - * src/core/main.cpp: - * src/core/song_editor.cpp: - added --render command-line-switch to render file and quit as soon as - job is done - very good for benchmarks - - * src/core/main.cpp: - added --version command-line-switch - -2005-08-20 Tobias Doerffel - - * src/core/lmms_main_win.cpp: - - extended filter for sample-browser - - added home- and root-browser for being able to load songs, presets, - samples etc. from somewhere else than within lmms-working-directory - -2005-07-27 Tobias Doerffel - - * src/core/lmms_main_win.cpp: - * src/core/track_container.cpp: - * src/core/track.cpp: - by completing destructors and fixing some other small bugs there's - finally no seg-fault when quitting app! (the bug annoying for months...) - - * include/track_container.h: - all public-slots were made to normal public and FASTCALLed functions - since they aren't connected to a signal anywhere and it just blows up - qt-moc-code - - * include/sample_track.h: - made method sampleTCO::changeLength(...) FASTCALLed since it's virtual - and method in base-class is also FASTCALLed - eliminates crash when - resizing sample - - * include/track.h: - * src/core/track.cpp: - removed unsused method setTrackWidgetHeight( int ) - -2005-07-26 Pedro Lopez-Cabanillas - - * src/core/browser.cpp: - * src/core/config_mgr.cpp: - * src/core/lmms_main_win.cpp: - * src/core/main.cpp: - * src/core/song_editor.cpp: - * src/lib/mmp.cpp: - * src/tracks/pattern.cpp: - * src/widgets/project_notes.cpp: - small changes for compatibility with Qt 3.1 - - * src/midi/midi_alsa.cpp: - * src/midi/midi_oss.cpp: - added MIDIDEV-environment variable for being able to choose a MIDI - device different from the default one - -2005-07-24 Tobias Doerffel - - * include/midi_mapper.h: - * src/midi/midi_mapper.cpp: - added MIDI-mapper to be used in combination with midiDevice's and/or - MIDI-Out-Plugin which can read MIDI-maps added before - - * midi-maps/*map: - added MIDI-maps from KMid - - * include/midi_dummy.h: - * src/midi/midi_device.cpp: - added dummy MIDI-driver for not crashing if no MIDI-device is available - - * src/core/piano_roll.cpp: - - go to start of pattern when pressing home-key - - added support for zooming - - * src/core/song_editor.cpp: - - fixed bug with loop-points by setting current-frame-var to zero to - force reset of it - - added auto-scrolling ability - - fixed bug which caused horizontal scrollbar to have an undefined - max-value after starting up LMMS - - go to start of pattern when pressing home-key - -2005-07-23 Alexey Kouznetsov - - * resources/ru.ts: - added Russian translation - -2005-07-23 Tobias Doerffel - - * src/core/piano_roll.cpp: - scroll back when stopping and play-position changes to invisible area - - * include/time_line.h: - * src/core/song_editor.cpp: - * src/core/time_line.cpp: - added control-buttons to time-line making it possible to control - things like auto-scrolling, looping and play-position after stop - - * src/midi/midi_device.cpp: - limit volume between 0 and 127 when sending out note-on-event - -2005-07-21 Tobias Doerffel - - * include/nstate_button.h: - * src/widgets/nstate_button.cpp: - added widget nStateButton which is a button able to have n different - states with according pixmaps and tooltips - - * resources/back_to_zero.png: - * resources/keep_stop_position.png: - * resources/back_to_start.png: - * resources/loop_points_off.png: - * resources/loop_points_on.png: - * resources/autoscroll_off.png: - * resources/autoscroll_on.png: - added pixmaps for buttons to be used in time-line as soon as possible - - * lmms-0.1.0rc1.tar.bz2: - release of Release Candidate 1 of LMMS 0.1.0 - -2005-07-20 Tobias Doerffel - - * src/midi/midi_file.cpp: - - proper handling of note-on-events which velocity 0 -> treat like - note-off-events makes it now possible to import a much larger amount - of MIDI-files - - added progress-dialog when importing MIDI-file - - * src/core/song_editor.cpp: - horizontal scrollbar is now placed some pixels above lower edge so that - it doesn't take action when resizing song-editor-window at lower edge - - * src/core/track_container.cpp: - added progress-dialog for loading project and according - qApp->processEvents()-call -> LMMS now isn't blocked anymore while - loading project - - * include/knob.h: - * src/widgets/knob.cpp: - fixed bugs caused by changes made before for scroll-wheel-support - -2005-07-19 Tobias Doerffel - - * include/knob.h: - * src/widgets/knob.cpp: - added better scroll-wheel support which increases/decreases knob-value - by 20th of range (e.g 0.05 if knob is ranged between 0 and 1) - -2005-07-17 Tobias Doerffel - - * projects/: - added "covers"-dir and added "Preludium and Fuge A-Minor" by J.S.Bach - to it as first covered project ;-) - - * src/core/note_play_handle.cpp: - - fixed bad bug in notePlayHandle::play(): instead of directly being - deleted, sub-notes were given to mixer to be removed when they played - completely but since these sub-notes are not known to mixer, it - couldn't delete them - - always call channelTrack::deleteNotePluginData() in - noteplayhandle-dtor even if pointer to note-plugin-data is NULL so - that all plugins are notified when note is done (midiOut-plugin - needs that for sending note-off-events!) - - * include/midi_out.h: - * src/soundgenerators/midi_out.cpp: - new plugin midiOut which sends all notes on this channel out to - external midi-device this is especially cool for playing arpeggio for - key pressed on external midi-device!! - - * src/soundgenerators/plucked_string_synth.cpp: - removed unneccesary inclusion of qpainter-header - - * include/midi_file.h: - * src/midi/midi_file.cpp: - * src/core/lmms_main_win.cpp: - * src/core/song_editor.cpp: - added support for importing MIDI-file (very experimental!!) - - * include/midi.h: - * include/midi_device.h: - moved general MIDI-stuff from midi_device.h to midi.h - - * src/audio/audio_file_device.cpp: - added missing arg()-call to QMessageBox::critical()-call in - audioFileDevice-ctor - -2005-07-16 Tobias Doerffel - - * src/core/config_mgr.cpp: - added shortcuts to navigation-buttons - -2005-07-14 Tobias Doerffel - - * src/core/piano_roll.cpp: - only play notes while editing if we're not in play-mode - - * include/song_editor.h: - * src/core/song_editor.cpp: - when exporting always render one additional tact at the end so that - we don't cut off notes with delay etc. - -2005-07-12 Tobias Doerffel - - - successful compilation with GCC 4.0.1 ;-) - - * src/core/arp_and_chords_tab_widget.cpp: - fixed bug responsible for playing base-notes of chords all time - if any arpeggio selected was selected - -2005-07-11 Tobias Doerffel - - * resources/source/wizard_files.xcf: - * resources/wizard_files.png: - updated project-file-icon in image - - * src/core/config_mgr.cpp: - - ask user whether to re-run setup-wizard if config-file indicates - different version of LMMS - - removed redundant assignment in configManager::loadConfigFile() - - added additional layout for having space at the left and right side - - increased font-size of title - - * Makefile.am: - install LMMS-icon into LMMS-data-dir - - * lmms-0.1.0beta.tar.bz2: - made beta-release of 0.1.0 and announced it on kde-apps.org - -2005-07-10 Tobias Doerffel - - * presets/TripleOscillator/: - added cool Church Organ preset and improved Xylophon preset - - * resources/de.ts: - updated German translations and cleaned up all obsolete translations - and context which shrinks the file by 50K... - - * samples/instruments/: - removed vibraphone01.ogg because of poor quality - - * src/core/piano_roll.cpp: - - do not set what's-this-texts as tooltips for play/stop-button - - added tooltip and what's-this-text to record-button - - display message in piano-roll how to open a pattern if none is opened - - always set window-title, even if no pattern is opened - - * src/core/mixer.cpp: - using iterators in second loop in mixer::run() leads to crashes, so - an optimized version of the old code is used now again... - - * src/core/lmms_main_win.cpp: - added tool-buttons for new project, open/save project etc. and added - popup-menu to new-button containing projects in template-directory - - * include/song_editor.h: - * src/core/song_editor.cpp: - - changed remaining method-names containing "[Ss]ong" to "[Pp]roject" - - toggle channel-button after adding channel-track - - * include/export_project_dialog.h: - * src/core/export_project_dialog.cpp: - renamed from export_song_dialog.ext to export_project_dialog.ext - -2005-07-09 Tobias Doerffel - - * all files: - now all source-code-files but some single exceptions do not have more - than 80 characters per line and also were made to conform one - programming-style - - * include/sgs: - wrote sane soundgenerator-plugin-scanner using bash-scripting which - replaces old, dirty and exaggerated c++-program and is also fully - portable - - * include/lmms_main_win.h: - * include/song_editor.h: - * src/core/lmms_main_win.cpp: - * src/core/song_editor.cpp: - renamed methods newFile, openFile etc. to createNewProject, openProject - etc. - - * resources/source/: - - renamed filenew.png, fileopen.png etc. to project_new.png etc. - - replaced song_file.png by project_file.png which has a new file-icon - with LMMS-logo inside - - replaced preset_file.png by new graphic where the star is inside - of a file-icon - - * resources/source/lmms_logo.svg: - made logo Inkscape 0.41 compatible (had problems with gradients since - logo originally had been made with Inkscape 0.39) - - * src/widgets/project_notes.cpp: - removed unnecessary name-strings for QActions - - * resources/project_notes.png: - replaced 16x16-icon with 22x22-icon to provide big enough icon for - toolbar which needs 22x22-icons - - * src/core/bb_editor.cpp: - * src/core/song_editor.cpp: - * src/tracks/bb_track.cpp: - do not crash if either there're no bb-tracks but bb-editor has tracks - or there're bb-tracks but bb-editor contains no tracks - - * src/core/mixer.cpp: - * src/core/note_play_handle.cpp: - * src/core/track_container.cpp: - * src/tracks/pattern.cpp: - rewrote loops using vectors to use iterators instead of indices etc. - which makes it all a bit smaller and faster since we do not always have - to access the current element using the []-operator - -2005-07-08 Tobias Doerffel - - * src/core/envelope_tab_widget.cpp: - * src/lib/sample_buffer.cpp: - * src/widgets/knob.cpp: - small fixes for making compilable with qt4 - - * configure.in: - * projects/: - added directories "tutorials" and "recorded_loops" - -2005-07-07 Tobias Doerffel - - * include/bb_track.h: - added FASTCALL to moveLocation(...) and changeLength(...) which fixes - crash-bug - - * src/core/song_editor.cpp: - do not confirm overwriting file if new project was just saved - - * samples/: - added a lot of new samples from wikisource and others - -2005-07-06 Tobias Doerffel - - * include/project_notes.h: - * src/core/song_editor.cpp: - * src/widgets/project_notes.cpp: - clear project-notes when clearing song (new/open file etc.) - - * src/tracks/pattern.cpp: - ask user when he tries to freeze a pattern of a muted channel whether he - wants to continue since freezing a pattern of a muted channel makes no - sense (you're rendering silence!) - - * include/piano_roll: - * src/core/piano_roll.cpp: - - added possibility to edit the volume of notes - - removed all bool-variables indicating whether an action is being - performed at the moment and introduced m_action, indicating - one of the actions defined in (also new) enum editActions - - replaced m_startTone and m_startOctave with one variable m_startKey, - which makes a lot of code unnecessary - - rewrote loops using note-vectors to use iterators instead of - indices and vector::size() - - renamed m_evolutionHeight to m_notesEditHeight - - replaced QMouseEvent::pos().[xy]()-calls with QMouseEvent::[xy]() - - pianoRoll::getKey() does now take y-position (int) as parameter - instead of QPoint since it only needs y-position - - use new setKey()/key()-member of note everywhere where it is possible - - * include/note.h: - added setKey()- and key()-member which setting/getting absolute key - of note - -2005-07-05 Tobias Doerffel - - * configure.in: - * projects/: - categorized projects in "cool_songs", "demos", "misc" and "templates" - so that we don't annoy the user with a lot projects in his/her project- - root - have to fill up "templates" with project-templates, e.g. - basic drum-kit, accoustic drum-kit etc. - - * most files: - added FASTCALL-attributes to functions taking at least one parameter - - * include/audio_file_processor.h: - * include/plucked_string_synth.h: - * include/triple_oscillator.h: - moved deleteNotePluginData()-method into according cpp-files which - makes including note_play_handle.h obsolete - - * include/audio_file_processor.h: - * include/sample_buffer.h: - * src/lib/sample_buffer.cpp: - * src/soundgenerators/audio_file_processor.cpp: - added support for saving sample-rate-conversion-state in m_pluginData - of a note which fixes bug making clicks in sound when playing a sample - simultanously at different pitches - - * configure.in: - check whether compiler knows floorf and powf and if not, define them - to floor/pow - -2005-07-04 Tobias Doerffel - - * most files: - made LMMS compiling (and working) with Qt 3.0, GCC 2.95 and other old - libs (compiled it under Knoppix 3.1) - - * include/misc.h: - changed names of abs, min, max, limit to myAbs, myMin etc. for not - conflicting with functions of STL with the same name - - * configure.in: - * src/lib/sample_buffer.cpp: - added support for versions of libsndfile < 1.0.11 since API has changed - in libsndfile 1.0.11 - -2005-07-03 Tobias Doerffel - - * resources/control_env_amount_active.png: - * resources/control_env_amount_inactive.png: - * include/envelope_and_lfo_widget.h: - * src/core/envelope_and_lfo_widget.cpp: - it's now possible to control the amount of an envelope with the - according LFO by toggling new button (otherwise the level of the LFO is - added to the level of the envelope as it always has been) - - * src/core/envelope_and_lfo_widget.cpp: - now you can toggle the amount of an envelope/LFO between 0 and 1 by - clicking on according graph - - * all files: - updated mail-address in header - - * src/audio/audio_device.cpp: - always use SURROUND_CHANNELS as channel-count for libsrc since - resampling is done on surround-buffers - fixes bug which was - responsible for producing useless noise when exporting file in - high-quality-mode - - * src/core/export_song_dialog.cpp: - made "high-quality-mode"-switch working (disabled for some reason - in 0.0.9...) - - * src/core/mixer.cpp: - when restoring audio-device, also restore quality-level - - * include/bb_editor.h: - * src/core/bb_editor.cpp: - cleaned up a lot because there was still much code from times when - the track-technology didn't exist and which isn't now used any more - - * src/audio/audio_alsa.cpp: - added support for 48 KHz soundcards - -2005-07-02 Tobias Doerffel - - * configure.in: - * src/lib/sample_buffer.cpp: - made it possible to compile LMMS without SDL_sound, reorganized - sample-decoding and added libsndfile- and libvorbis-support - - * include/midi_time.h: - added operators "=", "+=", "-=" and implemented copy-ctor - - * include/piano_roll.h: - made currentPattern() a const method and added validPattern() - - * src/tracks/pattern.cpp: - optimized addNote() function which uses m_note.push_back() for notes - beyond last note - - * src/core/piano_roll.cpp: - * src/tracks/pattern.cpp: - when pattern is destroyed it checks whether it is currently opened in - piano-roll and if so pattern lets piano-roll set its pointer to current - pattern to NULL. piano-roll does now always check whether current - pattern is not NULL. in this case it denies any actions. fixes bug which - led to crash when having piano-roll open while deleting pattern (e.g. - creating new file, opening file etc.) - -2005-07-01 Tobias Doerffel - - * all files: - replaced "location" in names of functions/variables by "position" - for more clear and unified names - - * include/piano_roll.h: - * include/timeline.h: - * src/core/piano_roll.cpp: - * src/core/timeline.cpp: - added support for autoscroll in piano-roll when playing/recording - pattern - -2005-06-30 Tobias Doerffel - - * include/channel_track.h: - * include/midi_device.h - * include/mixer.h: - * include/pattern.h: - * src/core/piano_roll.cpp: - * src/midi/midi_device.cpp: - * src/tracks/channel_track.cpp: - added support for recording notes from MIDI-device (e.g. MIDI-keyboard - or virtual channel-piano) in a pattern using the piano-roll - - * include/pattern.h - * src/core/song_editor.cpp: - fixed bug which led to crash: when pattern was played in non-looping - mode song-editor always called pattern::finishFreeze() even if there - actually was no pattern-freezing-process -> added isFreezing() which - is called by song-editor for checking whether pattern is being freezed - before calling finishFreeze() - - * src/core/lmms_main_win.cpp: - * src/lib/sample_buffer.cpp: - when showing open-file-dialog, use QFileDialog::selectedFiles()[0] - instead of QFileDialog::selectedFile() because selectedFile() returns - incorrect file-name if user clicked on the file and then on - "Open"-button instead of double-clicking file - - * src/audio/audio_oss.cpp: - * src/soundgenerators/triple_oscillator.cpp: - * src/tracks/channel_track.cpp: - added #include for solving problems with undeclared - functions getenv() and rand() on some distributions (e.g Slackware) - - * src/core/track.cpp: - * src/soundgenerators/triple_oscillator.cpp: - * src/tracks/channel_track.cpp: - added missing #include "debug.h" for solving problems with undeclared - assert() because of not included assert.h - -2005-06-29 Tobias Doerffel - - * configure.in: - * include/audio_sdl.h: - * src/lib/sample_buffer.cpp: - if SDL/SDL.h does not exist, search for it in SDL10, SDL11 etc. and - include according headers in source-files (solves problems on FreeBSD) - - * README: - updated everything a bit... - -2005-06-28 Tobias Doerffel - - * include/envelope_tab_widget.h: - * src/core/envelope_tab_widget.cpp: - use button instead of knob for turning filter on/off - -2005-06-27 Tobias Doerffel - - * samples/effects/Makefile.am: - don't install effect-samples into directory of basses-samples - From 6650dd356dbdd08739ad69153b0c7020e39787b9 Mon Sep 17 00:00:00 2001 From: Tobias Doerffel Date: Wed, 26 Mar 2014 11:39:14 +0100 Subject: [PATCH 095/647] NotePlayHandle, InstrumentFunctions: reworked stacking and arpeggio handling Instead of having various flags for realizing the arpeggion functionality use a more generic approach here using the recently introduced "origin" property. --- include/NotePlayHandle.h | 31 ++++----- plugins/lb302/lb302.cpp | 2 +- src/core/InstrumentFunctions.cpp | 115 +++++++++++-------------------- src/core/NotePlayHandle.cpp | 52 ++++---------- src/tracks/InstrumentTrack.cpp | 13 ++-- 5 files changed, 74 insertions(+), 139 deletions(-) diff --git a/include/NotePlayHandle.h b/include/NotePlayHandle.h index a20aaa367..d2a5170b7 100644 --- a/include/NotePlayHandle.h +++ b/include/NotePlayHandle.h @@ -51,6 +51,8 @@ public: { OriginPattern, /*! playback of a note from a pattern */ OriginMidiInput, /*! playback of a MIDI note input event */ + OriginNoteStacking, /*! created by note stacking instrument function */ + OriginArpeggio, /*! created by arpeggio instrument function */ OriginCount }; typedef Origins Origin; @@ -60,7 +62,6 @@ public: const f_cnt_t frames, const note& noteToPlay, NotePlayHandle* parent = NULL, - const bool isPartOfArp = false, int midiEventChannel = -1, Origin origin = OriginPattern ); virtual ~NotePlayHandle(); @@ -160,27 +161,24 @@ public: return m_instrumentTrack; } - /*! Returns whether note is a top note, e.g. is not part of an arpeggio or a chord */ - bool isTopNote() const + /*! Returns whether note has a parent, e.g. is not part of an arpeggio or a chord */ + bool hasParent() const { - return m_topNote; + return m_hasParent; } - /*! Returns whether note is part of an arpeggio playback */ - bool isPartOfArpeggio() const + /*! Returns origin of note */ + Origin origin() const { - return m_partOfArpeggio; + return m_origin; } - /*! Sets whether note is part of an arpeggio playback */ - void setPartOfArpeggio( const bool _on ) + /*! Returns whether note has children */ + bool isMasterNote() const { - m_partOfArpeggio = _on; + return m_subNotes.size() > 0 || m_hadChildren; } - /*! Returns whether note is base note for arpeggio */ - bool isArpeggioBaseNote() const; - /*! Returns whether note is muted */ bool isMuted() const { @@ -268,11 +266,8 @@ private: // release of note NotePlayHandleList m_subNotes; // used for chords and arpeggios volatile bool m_released; // indicates whether note is released - bool m_topNote; // indicates whether note is a - // base-note (i.e. no sub-note) - bool m_partOfArpeggio; // indicates whether note is part of - // an arpeggio (either base-note or - // sub-note) + bool m_hasParent; + bool m_hadChildren; bool m_muted; // indicates whether note is muted track* m_bbTrack; // related BB track diff --git a/plugins/lb302/lb302.cpp b/plugins/lb302/lb302.cpp index 28628a27d..83b824d52 100644 --- a/plugins/lb302/lb302.cpp +++ b/plugins/lb302/lb302.cpp @@ -713,7 +713,7 @@ void lb302Synth::playNote( NotePlayHandle * _n, sampleFrame * _working_buffer ) { //fpp_t framesPerPeriod = engine::mixer()->framesPerPeriod(); - if( _n->isArpeggioBaseNote() ) + if( _n->isMasterNote() ) { return; } diff --git a/src/core/InstrumentFunctions.cpp b/src/core/InstrumentFunctions.cpp index abf6131af..70a94e6f1 100644 --- a/src/core/InstrumentFunctions.cpp +++ b/src/core/InstrumentFunctions.cpp @@ -231,30 +231,24 @@ void InstrumentFunctionNoteStacking::processNote( NotePlayHandle * _n ) // at the same time we only add sub-notes if nothing of the note was // played yet, because otherwise we would add chord-subnotes every // time an audio-buffer is rendered... - if( ( ( _n->isTopNote() && _n->instrumentTrack()->isArpeggioEnabled() == false ) || _n->isPartOfArpeggio() ) && - _n->totalFramesPlayed() == 0 && - m_chordsEnabledModel.value() == true ) + if( ( _n->origin() == NotePlayHandle::OriginArpeggio || ( _n->hasParent() == false && _n->instrumentTrack()->isArpeggioEnabled() == false ) ) && + _n->totalFramesPlayed() == 0 && + m_chordsEnabledModel.value() == true ) { // then insert sub-notes for chord const int selected_chord = m_chordsModel.value(); - for( int octave_cnt = 0; - octave_cnt < m_chordRangeModel.value(); ++octave_cnt ) + for( int octave_cnt = 0; octave_cnt < m_chordRangeModel.value(); ++octave_cnt ) { - const int sub_note_key_base = base_note_key + - octave_cnt * KeysPerOctave; + const int sub_note_key_base = base_note_key + octave_cnt * KeysPerOctave; // if octave_cnt == 1 we're in the first octave and // the base-note is already done, so we don't have to // create it in the following loop, then we loop until // there's a -1 in the interval-array - for( int i = ( octave_cnt == 0 ) ? 1 : 0; - i < chord_table[selected_chord].size(); - ++i ) + for( int i = ( octave_cnt == 0 ) ? 1 : 0; i < chord_table[selected_chord].size(); ++i ) { // add interval to sub-note-key - const int sub_note_key = sub_note_key_base + - (int) chord_table[ - selected_chord][i]; + const int sub_note_key = sub_note_key_base + (int) chord_table[selected_chord][i]; // maybe we're out of range -> let's get outta // here! if( sub_note_key > NumKeys ) @@ -262,16 +256,12 @@ void InstrumentFunctionNoteStacking::processNote( NotePlayHandle * _n ) break; } // create copy of base-note - note note_copy( _n->length(), 0, sub_note_key, - _n->getVolume(), - _n->getPanning(), - _n->detuning() ); + note note_copy( _n->length(), 0, sub_note_key, _n->getVolume(), _n->getPanning(), _n->detuning() ); + // create sub-note-play-handle, only note is // different - new NotePlayHandle( _n->instrumentTrack(), - _n->offset(), - _n->frames(), note_copy, - _n ); + new NotePlayHandle( _n->instrumentTrack(), _n->offset(), _n->frames(), note_copy, + _n, -1, NotePlayHandle::OriginNoteStacking ); } } } @@ -310,10 +300,8 @@ InstrumentFunctionArpeggio::InstrumentFunctionArpeggio( Model * _parent ) : m_arpEnabledModel( false ), m_arpModel( this, tr( "Arpeggio type" ) ), m_arpRangeModel( 1.0f, 1.0f, 9.0f, 1.0f, this, tr( "Arpeggio range" ) ), - m_arpTimeModel( 100.0f, 25.0f, 2000.0f, 1.0f, 2000, this, - tr( "Arpeggio time" ) ), - m_arpGateModel( 100.0f, 1.0f, 200.0f, 1.0f, this, - tr( "Arpeggio gate" ) ), + m_arpTimeModel( 100.0f, 25.0f, 2000.0f, 1.0f, 2000, this, tr( "Arpeggio time" ) ), + m_arpGateModel( 100.0f, 1.0f, 200.0f, 1.0f, this, tr( "Arpeggio gate" ) ), m_arpDirectionModel( this, tr( "Arpeggio direction" ) ), m_arpModeModel( this, tr( "Arpeggio mode" ) ) { @@ -325,10 +313,8 @@ InstrumentFunctionArpeggio::InstrumentFunctionArpeggio( Model * _parent ) : m_arpDirectionModel.addItem( tr( "Up" ), new PixmapLoader( "arp_up" ) ); m_arpDirectionModel.addItem( tr( "Down" ), new PixmapLoader( "arp_down" ) ); - m_arpDirectionModel.addItem( tr( "Up and down" ), - new PixmapLoader( "arp_up_and_down" ) ); - m_arpDirectionModel.addItem( tr( "Random" ), - new PixmapLoader( "arp_random" ) ); + m_arpDirectionModel.addItem( tr( "Up and down" ), new PixmapLoader( "arp_up_and_down" ) ); + m_arpDirectionModel.addItem( tr( "Random" ), new PixmapLoader( "arp_random" ) ); m_arpDirectionModel.setInitValue( ArpDirUp ); m_arpModeModel.addItem( tr( "Free" ), new PixmapLoader( "arp_free" ) ); @@ -349,9 +335,10 @@ InstrumentFunctionArpeggio::~InstrumentFunctionArpeggio() void InstrumentFunctionArpeggio::processNote( NotePlayHandle * _n ) { const int base_note_key = _n->key(); - if( _n->isTopNote() == false || - !m_arpEnabledModel.value() || - ( _n->isReleased() && _n->releaseFramesDone() >= _n->actualReleaseFramesToDo() ) ) + if( _n->origin() == NotePlayHandle::OriginArpeggio || + _n->origin() == NotePlayHandle::OriginNoteStacking || + !m_arpEnabledModel.value() || + ( _n->isReleased() && _n->releaseFramesDone() >= _n->actualReleaseFramesToDo() ) ) { return; } @@ -359,8 +346,8 @@ void InstrumentFunctionArpeggio::processNote( NotePlayHandle * _n ) const int selected_arp = m_arpModel.value(); - ConstNotePlayHandleList cnphv = NotePlayHandle::nphsOfInstrumentTrack( - _n->instrumentTrack() ); + ConstNotePlayHandleList cnphv = NotePlayHandle::nphsOfInstrumentTrack( _n->instrumentTrack() ); + if( m_arpModeModel.value() != FreeMode && cnphv.size() == 0 ) { // maybe we're playing only a preset-preview-note? @@ -379,27 +366,23 @@ void InstrumentFunctionArpeggio::processNote( NotePlayHandle * _n ) const int total_range = range * cnphv.size(); // number of frames that every note should be played - const f_cnt_t arp_frames = (f_cnt_t)( m_arpTimeModel.value() / 1000.0f * - engine::mixer()->processingSampleRate() ); - const f_cnt_t gated_frames = (f_cnt_t)( m_arpGateModel.value() * - arp_frames / 100.0f ); + const f_cnt_t arp_frames = (f_cnt_t)( m_arpTimeModel.value() / 1000.0f * engine::mixer()->processingSampleRate() ); + const f_cnt_t gated_frames = (f_cnt_t)( m_arpGateModel.value() * arp_frames / 100.0f ); // used for calculating remaining frames for arp-note, we have to add // arp_frames-1, otherwise the first arp-note will not be setup // correctly... -> arp_frames frames silence at the start of every note! int cur_frame = ( ( m_arpModeModel.value() != FreeMode ) ? - cnphv.first()->totalFramesPlayed() : - _n->totalFramesPlayed() ) + arp_frames - 1; + cnphv.first()->totalFramesPlayed() : + _n->totalFramesPlayed() ) + arp_frames - 1; // used for loop f_cnt_t frames_processed = 0; while( frames_processed < engine::mixer()->framesPerPeriod() ) { - const f_cnt_t remaining_frames_for_cur_arp = arp_frames - - ( cur_frame % arp_frames ); + const f_cnt_t remaining_frames_for_cur_arp = arp_frames - ( cur_frame % arp_frames ); // does current arp-note fill whole audio-buffer? - if( remaining_frames_for_cur_arp > - engine::mixer()->framesPerPeriod() ) + if( remaining_frames_for_cur_arp > engine::mixer()->framesPerPeriod() ) { // then we don't have to do something! break; @@ -413,8 +396,7 @@ void InstrumentFunctionArpeggio::processNote( NotePlayHandle * _n ) // in sorted mode: is it our turn or do we have to be quiet for // now? if( m_arpModeModel.value() == SortMode && - ( ( cur_frame / arp_frames ) % total_range ) / - range != (f_cnt_t) _n->index() ) + ( ( cur_frame / arp_frames ) % total_range ) / range != (f_cnt_t) _n->index() ) { // update counters frames_processed += arp_frames; @@ -439,33 +421,28 @@ void InstrumentFunctionArpeggio::processNote( NotePlayHandle * _n ) // once down -> makes 2 * range possible notes... // because we don't play the lower and upper notes // twice, we have to subtract 2 - cur_arp_idx = ( cur_frame / arp_frames ) % - ( range * 2 - 2 ); + cur_arp_idx = ( cur_frame / arp_frames ) % ( range * 2 - 2 ); // if greater than range, we have to play down... // looks like the code for arp_dir==DOWN... :) if( cur_arp_idx >= range ) { - cur_arp_idx = range - cur_arp_idx % - ( range - 1 ) - 1; + cur_arp_idx = range - cur_arp_idx % ( range - 1 ) - 1; } } else if( dir == ArpDirRandom ) { // just pick a random chord-index - cur_arp_idx = (int)( range * ( (float) rand() / - (float) RAND_MAX ) ); + cur_arp_idx = (int)( range * ( (float) rand() / (float) RAND_MAX ) ); } // now calculate final key for our arp-note - const int sub_note_key = base_note_key + (cur_arp_idx / - cur_chord_size ) * - KeysPerOctave + - chord_table[selected_arp][cur_arp_idx % cur_chord_size]; + const int sub_note_key = base_note_key + (cur_arp_idx / cur_chord_size ) * + KeysPerOctave + chord_table[selected_arp][cur_arp_idx % cur_chord_size]; // range-checking if( sub_note_key >= NumKeys || sub_note_key < 0 || - engine::mixer()->criticalXRuns() ) + engine::mixer()->criticalXRuns() ) { continue; } @@ -477,34 +454,20 @@ void InstrumentFunctionArpeggio::processNote( NotePlayHandle * _n ) } // create new arp-note - note new_note( MidiTime( 0 ), MidiTime( 0 ), - sub_note_key, - (volume_t) - qRound( _n->getVolume() * vol_level ), - _n->getPanning(), _n->detuning() ); // create sub-note-play-handle, only ptr to note is different // and is_arp_note=true new NotePlayHandle( _n->instrumentTrack(), - ( ( m_arpModeModel.value() != FreeMode ) ? - cnphv.first()->offset() : - _n->offset() ) + - frames_processed, - gated_frames, - new_note, - _n, true ); + ( ( m_arpModeModel.value() != FreeMode ) ? cnphv.first()->offset() : _n->offset() ) + frames_processed, + gated_frames, + note( MidiTime( 0 ), MidiTime( 0 ), sub_note_key, (volume_t) qRound( _n->getVolume() * vol_level ), + _n->getPanning(), _n->detuning() ), + _n, -1, NotePlayHandle::OriginArpeggio ); // update counters frames_processed += arp_frames; cur_frame += arp_frames; } - - // make sure, note is handled as arp-base-note, even if we didn't add a - // sub-note so far - if( m_arpModeModel.value() != FreeMode ) - { - _n->setPartOfArpeggio( true ); - } } diff --git a/src/core/NotePlayHandle.cpp b/src/core/NotePlayHandle.cpp index fa5f30974..9ad49de41 100644 --- a/src/core/NotePlayHandle.cpp +++ b/src/core/NotePlayHandle.cpp @@ -49,7 +49,6 @@ NotePlayHandle::NotePlayHandle( InstrumentTrack* instrumentTrack, const f_cnt_t _frames, const note& n, NotePlayHandle *parent, - const bool _part_of_arp, int midiEventChannel, Origin origin ) : PlayHandle( TypeNotePlayHandle, _offset ), @@ -63,8 +62,8 @@ NotePlayHandle::NotePlayHandle( InstrumentTrack* instrumentTrack, m_releaseFramesToDo( 0 ), m_releaseFramesDone( 0 ), m_released( false ), - m_topNote( parent == NULL ), - m_partOfArpeggio( _part_of_arp ), + m_hasParent( parent != NULL ), + m_hadChildren( false ), m_muted( false ), m_bbTrack( NULL ), m_origTempo( engine::getSong()->getTempo() ), @@ -76,7 +75,7 @@ NotePlayHandle::NotePlayHandle( InstrumentTrack* instrumentTrack, m_midiChannel( midiEventChannel >= 0 ? midiEventChannel : instrumentTrack->midiPort()->realOutputChannel() ), m_origin( origin ) { - if( isTopNote() ) + if( hasParent() == false ) { m_baseDetuning = new BaseDetuning( detuning() ); m_instrumentTrack->m_processHandles.push_back( this ); @@ -86,10 +85,7 @@ NotePlayHandle::NotePlayHandle( InstrumentTrack* instrumentTrack, m_baseDetuning = parent->m_baseDetuning; parent->m_subNotes.push_back( this ); - // if there was an arp-note added and parent is a base-note - // we set arp-note-flag for indicating that parent is an - // arpeggio-base-note - parent->m_partOfArpeggio = isPartOfArpeggio() && parent->isTopNote(); + parent->m_hadChildren = true; m_bbTrack = parent->m_bbTrack; } @@ -104,7 +100,7 @@ NotePlayHandle::NotePlayHandle( InstrumentTrack* instrumentTrack, m_instrumentTrack->midiNoteOn( *this ); } - if( !isTopNote() || !instrumentTrack->isArpeggioEnabled() ) + if( !isMasterNote() || !instrumentTrack->isArpeggioEnabled() ) { const int baseVelocity = m_instrumentTrack->midiPort()->baseVelocity(); @@ -122,7 +118,7 @@ NotePlayHandle::~NotePlayHandle() { noteOff( 0 ); - if( isTopNote() ) + if( hasParent() == false ) { delete m_baseDetuning; m_instrumentTrack->m_processHandles.removeAll( this ); @@ -209,12 +205,13 @@ void NotePlayHandle::play( sampleFrame * _working_buffer ) if( m_released ) { f_cnt_t todo = engine::mixer()->framesPerPeriod(); + // if this note is base-note for arpeggio, always set // m_releaseFramesToDo to bigger value than m_releaseFramesDone // because we do not allow NotePlayHandle::isFinished() to be true // until all sub-notes are completely played and no new ones // are inserted by arpAndChordsTabWidget::processNote() - if( isArpeggioBaseNote() ) + if( isMasterNote() ) { m_releaseFramesToDo = m_releaseFramesDone + 2 * engine::mixer()->framesPerPeriod(); } @@ -274,16 +271,6 @@ void NotePlayHandle::play( sampleFrame * _working_buffer ) } } - // if this note is a base-note and there're no more sub-notes left we - // can set m_releaseFramesDone to m_releaseFramesToDo so that - // NotePlayHandle::isFinished() returns true and also this base-note is - // removed from mixer's active note vector - if( m_released && isArpeggioBaseNote() && m_subNotes.size() == 0 ) - { - m_releaseFramesDone = m_releaseFramesToDo; - m_frames = 0; - } - // update internal data m_totalFramesPlayed += engine::mixer()->framesPerPeriod(); } @@ -344,7 +331,7 @@ void NotePlayHandle::noteOff( const f_cnt_t _s ) m_framesBeforeRelease = _s; m_releaseFramesToDo = qMax( 0, m_instrumentTrack->m_soundShaping.releaseFrames() ); - if( !isTopNote() || !instrumentTrack()->isArpeggioEnabled() ) + if( hasParent() || !instrumentTrack()->isArpeggioEnabled() ) { // send MidiNoteOff event m_instrumentTrack->processOutEvent( @@ -367,8 +354,7 @@ void NotePlayHandle::noteOff( const f_cnt_t _s ) f_cnt_t NotePlayHandle::actualReleaseFramesToDo() const { - return m_instrumentTrack->m_soundShaping.releaseFrames(/* - isArpeggioBaseNote()*/ ); + return m_instrumentTrack->m_soundShaping.releaseFrames(); } @@ -395,19 +381,10 @@ float NotePlayHandle::volumeLevel( const f_cnt_t _frame ) -bool NotePlayHandle::isArpeggioBaseNote() const -{ - return isTopNote() && ( m_partOfArpeggio || m_instrumentTrack->isArpeggioEnabled() ); -} - - - - void NotePlayHandle::mute() { // mute all sub-notes - for( NotePlayHandleList::Iterator it = m_subNotes.begin(); - it != m_subNotes.end(); ++it ) + for( NotePlayHandleList::Iterator it = m_subNotes.begin(); it != m_subNotes.end(); ++it ) { ( *it )->mute(); } @@ -471,10 +448,11 @@ bool NotePlayHandle::operator==( const NotePlayHandle & _nph ) const offset() == _nph.offset() && m_totalFramesPlayed == _nph.m_totalFramesPlayed && m_released == _nph.m_released && - m_topNote == _nph.m_topNote && - m_partOfArpeggio == _nph.m_partOfArpeggio && + m_hasParent == _nph.m_hasParent && m_origBaseNote == _nph.m_origBaseNote && - m_muted == _nph.m_muted; + m_muted == _nph.m_muted && + m_midiChannel == _nph.m_midiChannel && + m_origin == _nph.m_origin; } diff --git a/src/tracks/InstrumentTrack.cpp b/src/tracks/InstrumentTrack.cpp index d6f011e94..2a08515b7 100644 --- a/src/tracks/InstrumentTrack.cpp +++ b/src/tracks/InstrumentTrack.cpp @@ -252,7 +252,7 @@ void InstrumentTrack::processInEvent( const MidiEvent& event, const MidiTime& ti NotePlayHandle* nph = new NotePlayHandle( this, time.frames( engine::framesPerTick() ), typeInfo::max() / 2, note( MidiTime(), MidiTime(), event.key(), event.volume( midiPort()->baseVelocity() ) ), - NULL, false, event.channel(), + NULL, event.channel(), NotePlayHandle::OriginMidiInput ); if( engine::mixer()->addPlayHandle( nph ) ) { @@ -431,18 +431,17 @@ f_cnt_t InstrumentTrack::beatLen( NotePlayHandle * _n ) const -void InstrumentTrack::playNote( NotePlayHandle * _n, - sampleFrame * _working_buffer ) +void InstrumentTrack::playNote( NotePlayHandle* n, sampleFrame* workingBuffer ) { // arpeggio- and chord-widget has to do its work -> adding sub-notes // for chords/arpeggios - m_noteStacking.processNote( _n ); - m_arpeggio.processNote( _n ); + m_noteStacking.processNote( n ); + m_arpeggio.processNote( n ); - if( !_n->isArpeggioBaseNote() && m_instrument != NULL ) + if( n->isMasterNote() == false && m_instrument != NULL ) { // all is done, so now lets play the note! - m_instrument->playNote( _n, _working_buffer ); + m_instrument->playNote( n, workingBuffer ); } } From 1d30222b909dca0a91d52f42bed783a14ac19697 Mon Sep 17 00:00:00 2001 From: Vesa Date: Wed, 26 Mar 2014 13:25:14 +0200 Subject: [PATCH 096/647] Watsyn: further optimizations, add two presets --- data/presets/Watsyn/Epic_lead.xpf | 48 ++++++++++++++++++++++++++++++ data/presets/Watsyn/Phase_bass.xpf | 21 +++++++++++++ plugins/watsyn/Watsyn.cpp | 34 ++++++++++++--------- plugins/watsyn/Watsyn.h | 34 ++------------------- 4 files changed, 92 insertions(+), 45 deletions(-) create mode 100644 data/presets/Watsyn/Epic_lead.xpf create mode 100644 data/presets/Watsyn/Phase_bass.xpf diff --git a/data/presets/Watsyn/Epic_lead.xpf b/data/presets/Watsyn/Epic_lead.xpf new file mode 100644 index 000000000..6fd4682a9 --- /dev/null +++ b/data/presets/Watsyn/Epic_lead.xpf @@ -0,0 +1,48 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/data/presets/Watsyn/Phase_bass.xpf b/data/presets/Watsyn/Phase_bass.xpf new file mode 100644 index 000000000..a6d3f0475 --- /dev/null +++ b/data/presets/Watsyn/Phase_bass.xpf @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/plugins/watsyn/Watsyn.cpp b/plugins/watsyn/Watsyn.cpp index 747141304..9fe2689e9 100644 --- a/plugins/watsyn/Watsyn.cpp +++ b/plugins/watsyn/Watsyn.cpp @@ -115,37 +115,41 @@ void WatsynObject::renderOutput( fpp_t _frames ) ///////////// A-series ///////////////// // A2 - sample_t A2_L = interpolate( m_A2wave[ static_cast( m_lphase[A2_OSC] ) % WAVELEN ], + sample_t A2_L = m_A2wave[ static_cast( m_lphase[A2_OSC] ) ] * m_parent->m_lvol[A2_OSC]; + /*interpolate( m_A2wave[ static_cast( m_lphase[A2_OSC] ) % WAVELEN ], m_A2wave[ static_cast( m_lphase[A2_OSC] + 1 ) % WAVELEN ], - fraction( m_lphase[A2_OSC] ) ) * m_parent->m_lvol[A2_OSC]; - sample_t A2_R = interpolate( m_A2wave[ static_cast( m_rphase[A2_OSC] ) % WAVELEN ], + fraction( m_lphase[A2_OSC] ) ) * m_parent->m_lvol[A2_OSC];*/ + sample_t A2_R = m_A2wave[ static_cast( m_rphase[A2_OSC] ) ] * m_parent->m_rvol[A2_OSC]; + /*interpolate( m_A2wave[ static_cast( m_rphase[A2_OSC] ) % WAVELEN ], m_A2wave[ static_cast( m_rphase[A2_OSC] + 1 ) % WAVELEN ], - fraction( m_rphase[A2_OSC] ) ) * m_parent->m_rvol[A2_OSC]; + fraction( m_rphase[A2_OSC] ) ) * m_parent->m_rvol[A2_OSC];*/ // if phase mod, add to phases if( m_amod == MOD_PM ) { A1_lphase = fmodf( A1_lphase + A2_L * PMOD_AMT, WAVELEN ); - while( A1_lphase < 0 ) A1_lphase += WAVELEN; + if( A1_lphase < 0 ) A1_lphase += WAVELEN; A1_rphase = fmodf( A1_rphase + A2_R * PMOD_AMT, WAVELEN ); - while( A1_rphase < 0 ) A1_rphase += WAVELEN; + if( A1_rphase < 0 ) A1_rphase += WAVELEN; } // A1 - sample_t A1_L = interpolate( m_A1wave[ static_cast( A1_lphase ) % WAVELEN ], + sample_t A1_L = interpolate( m_A1wave[ static_cast( A1_lphase ) ], m_A1wave[ static_cast( A1_lphase + 1 ) % WAVELEN ], fraction( A1_lphase ) ) * m_parent->m_lvol[A1_OSC]; - sample_t A1_R = interpolate( m_A1wave[ static_cast( A1_rphase ) % WAVELEN ], + sample_t A1_R = interpolate( m_A1wave[ static_cast( A1_rphase ) ], m_A1wave[ static_cast( A1_rphase + 1 ) % WAVELEN ], fraction( A1_rphase ) ) * m_parent->m_rvol[A1_OSC]; ///////////// B-series ///////////////// // B2 - sample_t B2_L = interpolate( m_B2wave[ static_cast( m_lphase[B2_OSC] ) % WAVELEN ], + sample_t B2_L = m_B2wave[ static_cast( m_lphase[B2_OSC] ) ] * m_parent->m_lvol[B2_OSC]; + /*interpolate( m_B2wave[ static_cast( m_lphase[B2_OSC] ) % WAVELEN ], m_B2wave[ static_cast( m_lphase[B2_OSC] + 1 ) % WAVELEN ], - fraction( m_lphase[B2_OSC] ) ) * m_parent->m_lvol[B2_OSC]; - sample_t B2_R = interpolate( m_B2wave[ static_cast( m_rphase[B2_OSC] ) % WAVELEN ], + fraction( m_lphase[B2_OSC] ) ) * m_parent->m_lvol[B2_OSC];*/ + sample_t B2_R = m_B2wave[ static_cast( m_rphase[B2_OSC] ) ] * m_parent->m_rvol[B2_OSC]; + /*interpolate( m_B2wave[ static_cast( m_rphase[B2_OSC] ) % WAVELEN ], m_B2wave[ static_cast( m_rphase[B2_OSC] + 1 ) % WAVELEN ], - fraction( m_rphase[B2_OSC] ) ) * m_parent->m_rvol[B2_OSC]; + fraction( m_rphase[B2_OSC] ) ) * m_parent->m_rvol[B2_OSC];*/ // if crosstalk active, add a1 const float xt = m_parent->m_xtalk.value(); @@ -159,9 +163,9 @@ void WatsynObject::renderOutput( fpp_t _frames ) if( m_bmod == MOD_PM ) { B1_lphase = fmodf( B1_lphase + B2_L * PMOD_AMT, WAVELEN ); - while( B1_lphase < 0 ) B1_lphase += WAVELEN; + if( B1_lphase < 0 ) B1_lphase += WAVELEN; B1_rphase = fmodf( B1_rphase + B2_R * PMOD_AMT, WAVELEN ); - while( B1_rphase < 0 ) B1_rphase += WAVELEN; + if( B1_rphase < 0 ) B1_rphase += WAVELEN; } // B1 sample_t B1_L = interpolate( m_B1wave[ static_cast( B1_lphase ) % WAVELEN ], @@ -215,8 +219,10 @@ void WatsynObject::renderOutput( fpp_t _frames ) { m_lphase[i] += ( static_cast( WAVELEN ) / ( m_samplerate / ( m_nph->frequency() * m_parent->m_lfreq[i] ) ) ); m_lphase[i] = fmodf( m_lphase[i], WAVELEN ); + if( m_lphase[i] < 0 ) m_lphase[i] += WAVELEN; m_rphase[i] += ( static_cast( WAVELEN ) / ( m_samplerate / ( m_nph->frequency() * m_parent->m_rfreq[i] ) ) ); m_rphase[i] = fmodf( m_rphase[i], WAVELEN ); + if( m_rphase[i] < 0 ) m_rphase[i] += WAVELEN; } } diff --git a/plugins/watsyn/Watsyn.h b/plugins/watsyn/Watsyn.h index 5b4072202..66a2b4757 100644 --- a/plugins/watsyn/Watsyn.h +++ b/plugins/watsyn/Watsyn.h @@ -56,11 +56,11 @@ #define B2ROW 95 -const int GRAPHLEN = 220; -const int WAVELEN = 4400; +const int GRAPHLEN = 220; // don't change - must be same as the size of the widget -const int WAVERATIO = WAVELEN / GRAPHLEN; +const int WAVERATIO = 25; // oversampling ratio +const int WAVELEN = GRAPHLEN * WAVERATIO; const int PMOD_AMT = WAVELEN / 2; const int MOD_MIX = 0; @@ -107,34 +107,6 @@ private: { return s1 + ( s2 - s1 ) * x; } -/* - // quick and dirty approximation of cubic interpolation - inline sample_t interpolate( sample_t s1, sample_t s2, float x ) - { - const float x2 = powf( x, 2 ); - const float x3 = powf( x, 3 ); - const float m = s2 - s1; - - return ( ( x3 * 2.0 - x2 * 3.0 + 1.0 ) * s1 ) + - ( ( x3 * -2.0 + x2 * 3.0 ) * s2 ); + - ( ( x + x3 * 2.0 - x2 * 3.0 ) * m ); - } -*/ - // more accurate cubic interpolation... - // consumes more cpu than ^ but doesn't bring a marked increase in sound quality IMO -/* inline sample_t interpolate( sample_t s0, sample_t s1, sample_t s2, sample_t s3, float x ) - { - const float x2 = powf( x, 2 ); - const float x3 = powf( x, 3 ); - const float m1 = ( s2 - s0 ) / 2; - const float m2 = ( s3 - s1 ) / 2; - - return ( ( x3 * 2.0 - x2 * 3.0 + 1.0 ) * s1 ) + - ( ( x3 * -2.0 + x2 * 3.0 ) * s2 ) + - ( ( x3 - x2 * 2 + x ) * m1 ) + - ( ( x3 - x2 ) * m2 ); - }*/ - int m_amod; int m_bmod; From b2725816328136b5fe001c58add2fb52650d2a07 Mon Sep 17 00:00:00 2001 From: Vesa Date: Wed, 26 Mar 2014 13:38:07 +0200 Subject: [PATCH 097/647] Remove unnecessary if clauses --- plugins/watsyn/Watsyn.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/plugins/watsyn/Watsyn.cpp b/plugins/watsyn/Watsyn.cpp index 9fe2689e9..3b7c93265 100644 --- a/plugins/watsyn/Watsyn.cpp +++ b/plugins/watsyn/Watsyn.cpp @@ -219,10 +219,8 @@ void WatsynObject::renderOutput( fpp_t _frames ) { m_lphase[i] += ( static_cast( WAVELEN ) / ( m_samplerate / ( m_nph->frequency() * m_parent->m_lfreq[i] ) ) ); m_lphase[i] = fmodf( m_lphase[i], WAVELEN ); - if( m_lphase[i] < 0 ) m_lphase[i] += WAVELEN; m_rphase[i] += ( static_cast( WAVELEN ) / ( m_samplerate / ( m_nph->frequency() * m_parent->m_rfreq[i] ) ) ); m_rphase[i] = fmodf( m_rphase[i], WAVELEN ); - if( m_rphase[i] < 0 ) m_rphase[i] += WAVELEN; } } From 78337e5ac67bcb1465b1d1f2e6888be184ee68f9 Mon Sep 17 00:00:00 2001 From: Tobias Doerffel Date: Thu, 27 Mar 2014 20:39:57 +0100 Subject: [PATCH 098/647] ZynAddSubFX: integrated latest version --- plugins/zynaddsubfx/LocalZynAddSubFx.cpp | 2 +- plugins/zynaddsubfx/zynaddsubfx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/zynaddsubfx/LocalZynAddSubFx.cpp b/plugins/zynaddsubfx/LocalZynAddSubFx.cpp index 36312d651..1fb3a74c6 100644 --- a/plugins/zynaddsubfx/LocalZynAddSubFx.cpp +++ b/plugins/zynaddsubfx/LocalZynAddSubFx.cpp @@ -260,7 +260,7 @@ void LocalZynAddSubFx::processAudio( sampleFrame * _out ) float outputl[synth->buffersize]; float outputr[synth->buffersize]; - m_master->GetAudioOutSamples( SOUND_BUFFER_SIZE, SAMPLE_RATE, outputl, outputr ); + m_master->GetAudioOutSamples( synth->buffersize, synth->samplerate, outputl, outputr ); // TODO: move to MixHelpers for( int f = 0; f < synth->buffersize; ++f ) diff --git a/plugins/zynaddsubfx/zynaddsubfx b/plugins/zynaddsubfx/zynaddsubfx index 2ffc12005..e97ff9076 160000 --- a/plugins/zynaddsubfx/zynaddsubfx +++ b/plugins/zynaddsubfx/zynaddsubfx @@ -1 +1 @@ -Subproject commit 2ffc12005865855add8fa7f3129e563e34215c06 +Subproject commit e97ff9076c7b3fdf7ba8410c2e94970d9418f48c From 166a493eef769be7d9454999326834234ea9a302 Mon Sep 17 00:00:00 2001 From: "Raine M. Ekman" Date: Fri, 28 Mar 2014 19:14:53 +0200 Subject: [PATCH 099/647] Removed an unnecessary QDebug include --- src/gui/AutomationEditor.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/gui/AutomationEditor.cpp b/src/gui/AutomationEditor.cpp index 29b1a59d1..59b438d1a 100644 --- a/src/gui/AutomationEditor.cpp +++ b/src/gui/AutomationEditor.cpp @@ -39,7 +39,6 @@ #include #include -#include #ifndef __USE_XOPEN #define __USE_XOPEN From 5c142cb2a4b9104b8f2275aa6046b395fbf4ef0d Mon Sep 17 00:00:00 2001 From: Vesa Date: Fri, 28 Mar 2014 02:24:52 +0200 Subject: [PATCH 100/647] AFP: add a separate loopback point, and knob to control it. --- include/SampleBuffer.h | 16 +- .../audio_file_processor.cpp | 221 +++++++++++------- .../audio_file_processor.h | 23 +- src/core/SampleBuffer.cpp | 6 +- 4 files changed, 175 insertions(+), 91 deletions(-) diff --git a/include/SampleBuffer.h b/include/SampleBuffer.h index 54c444fc5..181956ea9 100644 --- a/include/SampleBuffer.h +++ b/include/SampleBuffer.h @@ -23,8 +23,8 @@ */ -#ifndef _SAMPLE_BUFFER_H -#define _SAMPLE_BUFFER_H +#ifndef SAMPLE_BUFFER_H +#define SAMPLE_BUFFER_H #include #include @@ -108,6 +108,16 @@ public: { return m_endFrame; } + + inline f_cnt_t loopStartFrame() const + { + return m_loopStartFrame; + } + + inline f_cnt_t loopEndFrame() const + { + return m_loopEndFrame; + } void setLoopStartFrame( f_cnt_t _start ) { @@ -175,7 +185,7 @@ public: QString openAudioFile() const; QString openAndSetAudioFile(); QString openAndSetWaveformFile(); - + QString & toBase64( QString & _dst ) const; diff --git a/plugins/audio_file_processor/audio_file_processor.cpp b/plugins/audio_file_processor/audio_file_processor.cpp index ff8ffdd0b..a114514c3 100644 --- a/plugins/audio_file_processor/audio_file_processor.cpp +++ b/plugins/audio_file_processor/audio_file_processor.cpp @@ -72,10 +72,11 @@ audioFileProcessor::audioFileProcessor( InstrumentTrack * _instrument_track ) : Instrument( _instrument_track, &audiofileprocessor_plugin_descriptor ), m_sampleBuffer(), m_ampModel( 100, 0, 500, 1, this, tr( "Amplify" ) ), - m_startPointModel( 0, 0, 1, 0.0000001f, this, tr( "Start of sample") ), + m_startPointModel( 0, 0, 1, 0.0000001f, this, tr( "Start of sample" ) ), m_endPointModel( 1, 0, 1, 0.0000001f, this, tr( "End of sample" ) ), + m_loopPointModel( 0, 0, 1, 0.0000001f, this, tr( "Loopback point" ) ), m_reverseModel( false, this, tr( "Reverse sample" ) ), - m_loopModel( false, this, tr( "Loop") ), + m_loopModel( false, this, tr( "Loop enabled" ) ), m_stutterModel( false, this, tr( "Stutter" ) ), m_nextPlayStartPoint( 0 ) { @@ -87,8 +88,11 @@ audioFileProcessor::audioFileProcessor( InstrumentTrack * _instrument_track ) : this, SLOT( loopPointChanged() ) ); connect( &m_endPointModel, SIGNAL( dataChanged() ), this, SLOT( loopPointChanged() ) ); + connect( &m_loopPointModel, SIGNAL( dataChanged() ), + this, SLOT( loopPointChanged() ) ); connect( &m_stutterModel, SIGNAL( dataChanged() ), this, SLOT( stutterModelChanged() ) ); + loopPointChanged(); } @@ -124,27 +128,31 @@ void audioFileProcessor::playNote( NotePlayHandle * _n, m_nextPlayStartPoint = m_sampleBuffer.startFrame(); } _n->m_pluginData = new handleState( _n->hasDetuningInfo() ); - ((handleState *)_n->m_pluginData)->setFrameIndex(m_nextPlayStartPoint); + ((handleState *)_n->m_pluginData)->setFrameIndex( m_nextPlayStartPoint ); + +// debug code + qDebug( "frames %d", m_sampleBuffer.frames() ); + qDebug( "startframe %d", m_sampleBuffer.startFrame() ); + qDebug( "nextPlayStartPoint %d", m_nextPlayStartPoint ); } - if( m_sampleBuffer.play( _working_buffer, - (handleState *)_n->m_pluginData, - frames, _n->frequency(), - m_loopModel.value() ) == TRUE ) + if( ! _n->isFinished() ) { - applyRelease( _working_buffer, _n ); - instrumentTrack()->processAudioBuffer( _working_buffer, - frames,_n ); - int framesPosition; - if( m_stutterModel.value() == true ) + if( m_sampleBuffer.play( _working_buffer, + (handleState *)_n->m_pluginData, + frames, _n->frequency(), + m_loopModel.value() ) ) { - framesPosition = m_nextPlayStartPoint; + applyRelease( _working_buffer, _n ); + instrumentTrack()->processAudioBuffer( _working_buffer, + frames,_n ); + + emit isPlaying( ((handleState *)_n->m_pluginData)->frameIndex() ); } else { - framesPosition = _n->totalFramesPlayed() * _n->frequency() / m_sampleBuffer.frequency(); + emit isPlaying( 0 ); } - emit isPlaying( framesPosition ); } else { @@ -182,6 +190,7 @@ void audioFileProcessor::saveSettings( QDomDocument & _doc, m_ampModel.saveSettings( _doc, _this, "amp" ); m_startPointModel.saveSettings( _doc, _this, "sframe" ); m_endPointModel.saveSettings( _doc, _this, "eframe" ); + m_loopPointModel.saveSettings( _doc, _this, "lframe" ); m_stutterModel.saveSettings( _doc, _this, "stutter" ); } @@ -199,11 +208,23 @@ void audioFileProcessor::loadSettings( const QDomElement & _this ) { m_sampleBuffer.loadFromBase64( _this.attribute( "srcdata" ) ); } + m_reverseModel.loadSettings( _this, "reversed" ); m_loopModel.loadSettings( _this, "looped" ); m_ampModel.loadSettings( _this, "amp" ); m_startPointModel.loadSettings( _this, "sframe" ); m_endPointModel.loadSettings( _this, "eframe" ); + + // compat code for not having a separate loopback point + if( _this.hasAttribute( "lframe" ) ) + { + m_loopPointModel.loadSettings( _this, "lframe" ); + } + else + { + m_loopPointModel.setValue( m_startPointModel.value() ); + } + m_stutterModel.loadSettings( _this, "stutter" ); loopPointChanged(); @@ -239,6 +260,7 @@ int audioFileProcessor::getBeatLen( NotePlayHandle * _n ) const + PluginView * audioFileProcessor::instantiateView( QWidget * _parent ) { return new AudioFileProcessorView( this, _parent ); @@ -292,7 +314,7 @@ void audioFileProcessor::stutterModelChanged() void audioFileProcessor::loopPointChanged( void ) { - //check if start is over end and swap values if so + // check if start is over end and swap values if so if( m_startPointModel.value() > m_endPointModel.value() ) { float tmp = m_endPointModel.value(); @@ -300,7 +322,7 @@ void audioFileProcessor::loopPointChanged( void ) m_startPointModel.setValue( tmp ); } - //check if start & end overlap and nudge end up if so + // check if start & end overlap and nudge end up if so if( m_startPointModel.value() == m_endPointModel.value() ) { m_endPointModel.setValue( qMin( m_endPointModel.value() + 0.001f, 1.0f ) ); @@ -311,8 +333,17 @@ void audioFileProcessor::loopPointChanged( void ) const f_cnt_t f_end = static_cast( m_endPointModel.value() * ( m_sampleBuffer.frames()-1 ) ); m_nextPlayStartPoint = f_start; + + // check that loop point is between start-end points + if( m_loopPointModel.value() < m_startPointModel.value() ) + m_loopPointModel.setValue( m_startPointModel.value() ); + if( m_loopPointModel.value() > m_endPointModel.value() ) + m_loopPointModel.setValue( m_endPointModel.value() ); + m_sampleBuffer.setStartFrame( f_start ); m_sampleBuffer.setEndFrame( f_end ); + m_sampleBuffer.setLoopStartFrame( static_cast( m_loopPointModel.value() * ( m_sampleBuffer.frames()-1 ) ) ); + m_sampleBuffer.setLoopEndFrame( f_end ); emit dataChanged(); } @@ -367,18 +398,14 @@ AudioFileProcessorView::AudioFileProcessorView( Instrument * _instrument, m_loopButton->setCheckable( TRUE ); m_loopButton->move( 200, 124 ); m_loopButton->setActiveGraphic( PLUGIN_NAME::getIconPixmap( - "loop_on" ) ); + "loop_on" ) ); m_loopButton->setInactiveGraphic( PLUGIN_NAME::getIconPixmap( - "loop_off" ) ); - toolTip::add( m_loopButton, - tr( "Loop sample at start- and end-point" ) ); + "loop_off" ) ); + toolTip::add( m_loopButton, tr( "Enable loop" ) ); m_loopButton->setWhatsThis( - tr( "Here you can set, whether looping-mode is enabled. If " - "enabled, AudioFileProcessor loops between start and " - "end-points of a sample until the whole note is played. " - "This is useful for things like string and choir " - "samples." ) ); - + tr( "This button enables looping. " + "The sample loops between the end point and the loop point." ) ); + m_stutterButton = new pixmapButton( this ); m_stutterButton->setCheckable( true ); m_stutterButton->move( 226, 124 ); @@ -412,26 +439,29 @@ AudioFileProcessorView::AudioFileProcessorView( Instrument * _instrument, m_startKnob->setHintText( tr( "Startpoint:" )+" ", "" ); m_startKnob->setWhatsThis( tr( "With this knob you can set the point where " - "AudioFileProcessor should begin playing your sample. " - "If you enable looping-mode, this is the point to " - "which AudioFileProcessor returns if a note is longer " - "than the sample between the start and end-points." ) ); + "AudioFileProcessor should begin playing your sample. " ) ); m_endKnob = new AudioFileProcessorWaveView::knob( this ); m_endKnob->move( 119, 108 ); m_endKnob->setHintText( tr( "Endpoint:" )+" ", "" ); m_endKnob->setWhatsThis( tr( "With this knob you can set the point where " - "AudioFileProcessor should stop playing your sample. " - "If you enable looping-mode, this is the point where " - "AudioFileProcessor returns if a note is longer than " - "the sample between the start and end-points." ) ); + "AudioFileProcessor should stop playing your sample. " ) ); + + m_loopKnob = new AudioFileProcessorWaveView::knob( this ); + m_loopKnob->move( 68, 58 ); + m_loopKnob->setHintText( tr( "Loopback point:" )+" ", "" ); + m_loopKnob->setWhatsThis( + tr( "With this knob you can set the point where " + "the loop starts. " ) ); + m_waveView = new AudioFileProcessorWaveView( this, 245, 75, castModel()->m_sampleBuffer ); m_waveView->move( 2, 172 ); m_waveView->setKnobs( dynamic_cast( m_startKnob ), - dynamic_cast( m_endKnob ) + dynamic_cast( m_endKnob ), + dynamic_cast( m_loopKnob ) ); connect( castModel(), SIGNAL( isPlaying( f_cnt_t ) ), @@ -572,6 +602,7 @@ void AudioFileProcessorView::modelChanged( void ) m_ampKnob->setModel( &a->m_ampModel ); m_startKnob->setModel( &a->m_startPointModel ); m_endKnob->setModel( &a->m_endPointModel ); + m_loopKnob->setModel( &a->m_loopPointModel ); m_reverseButton->setModel( &a->m_reverseModel ); m_loopButton->setModel( &a->m_loopModel ); m_stutterButton->setModel( &a->m_stutterModel ); @@ -612,17 +643,9 @@ AudioFileProcessorWaveView::AudioFileProcessorWaveView( QWidget * _parent, int _ -void AudioFileProcessorWaveView::isPlaying( f_cnt_t _frames_played ) +void AudioFileProcessorWaveView::isPlaying( f_cnt_t _current_frame ) { - const f_cnt_t nb_frames = m_sampleBuffer.endFrame() - m_sampleBuffer.startFrame(); - if( nb_frames < 1 ) - { - m_framesPlayed = 0; - } - else - { - m_framesPlayed = _frames_played % nb_frames; - } + m_framesPlayed = _current_frame; update(); } @@ -652,14 +675,18 @@ void AudioFileProcessorWaveView::mousePressEvent( QMouseEvent * _me ) { m_isDragging = true; m_draggingLastPoint = _me->pos(); - - if( isCloseTo( _me->x(), m_startFrameX ) ) + + const int start_dist = qAbs( m_startFrameX - _me->x() ); + const int end_dist = qAbs( m_endFrameX - _me->x() ); + const int loop_dist = qAbs( m_loopFrameX - _me->x() ); + + draggingType dt = sample_loop; int md = loop_dist; + if( start_dist < loop_dist ) { dt = sample_start; md = start_dist; } + if( end_dist < start_dist ) { dt = sample_end; md = end_dist; } + + if( md < 3 ) { - m_draggingType = sample_start; - } - else if( isCloseTo( _me->x(), m_endFrameX ) ) - { - m_draggingType = sample_end; + m_draggingType = dt; } else { @@ -691,7 +718,8 @@ void AudioFileProcessorWaveView::mouseMoveEvent( QMouseEvent * _me ) QApplication::overrideCursor()->shape() == Qt::SizeHorCursor; if( isCloseTo( _me->x(), m_startFrameX ) || - isCloseTo( _me->x(), m_endFrameX ) ) + isCloseTo( _me->x(), m_endFrameX ) || + isCloseTo( _me->x(), m_loopFrameX ) ) { if( ! is_size_cursor ) { @@ -714,6 +742,10 @@ void AudioFileProcessorWaveView::mouseMoveEvent( QMouseEvent * _me ) case sample_end: slideSamplePointByPx( end, step ); break; + case sample_loop: + slideSamplePointByPx( loop, step ); + break; + case wave: default: if( qAbs( _me->y() - m_draggingLastPoint.y() ) < 2 * qAbs( _me->x() - m_draggingLastPoint.x() ) ) @@ -748,13 +780,17 @@ void AudioFileProcessorWaveView::paintEvent( QPaintEvent * _pe ) p.drawPixmap( s_padding, s_padding, m_graph ); - p.setPen( QColor( 0xFF, 0xFF, 0xFF ) ); + p.setPen( QColor( 0xFF, 0xFF, 0xFF ) ); //TODO: put into a qproperty const QRect graph_rect( s_padding, s_padding, width() - 2 * s_padding, height() - 2 * s_padding ); const f_cnt_t frames = m_to - m_from; m_startFrameX = graph_rect.x() + ( m_sampleBuffer.startFrame() - m_from ) * double( graph_rect.width() ) / frames; m_endFrameX = graph_rect.x() + ( m_sampleBuffer.endFrame() - m_from ) * double( graph_rect.width() ) / frames; + m_loopFrameX = graph_rect.x() + ( m_sampleBuffer.loopStartFrame() - m_from ) * + double( graph_rect.width() ) / frames; + const int played_width_px = ( m_framesPlayed - m_from ) * + double( graph_rect.width() ) / frames; p.drawLine( m_startFrameX, graph_rect.y(), m_startFrameX, @@ -762,6 +798,11 @@ void AudioFileProcessorWaveView::paintEvent( QPaintEvent * _pe ) p.drawLine( m_endFrameX, graph_rect.y(), m_endFrameX, graph_rect.height() + graph_rect.y() ); + + p.setPen( QColor( 0x7F, 0xFF, 0xFF ) ); //TODO: put into a qproperty + p.drawLine( m_loopFrameX, graph_rect.y(), + m_loopFrameX, + graph_rect.height() + graph_rect.y() ); if( m_endFrameX - m_startFrameX > 2 ) { @@ -770,31 +811,36 @@ void AudioFileProcessorWaveView::paintEvent( QPaintEvent * _pe ) graph_rect.y(), m_endFrameX - m_startFrameX - 1, graph_rect.height() + graph_rect.y(), - QColor( 95, 195, 255, 70 ) + QColor( 95, 175, 255, 50 ) //TODO: put into a qproperty + ); + if( m_endFrameX - m_loopFrameX > 2 ) + p.fillRect( + m_loopFrameX + 1, + graph_rect.y(), + m_endFrameX - m_loopFrameX - 1, + graph_rect.height() + graph_rect.y(), + QColor( 95, 205, 255, 65 ) //TODO: put into a qproperty ); if( m_framesPlayed && m_animation) { - const int played_width_px = m_framesPlayed - / double( m_sampleBuffer.endFrame() - m_sampleBuffer.startFrame() ) - * ( m_endFrameX - m_startFrameX ); - QLinearGradient g( m_startFrameX + 1, 0, m_startFrameX + 1 + played_width_px, 0 ); - const QColor c( 0, 120, 255, 180 ); + QLinearGradient g( m_startFrameX, 0, played_width_px, 0 ); + const QColor c( 0, 120, 255, 180 ); //TODO: put into a qproperty g.setColorAt( 0, Qt::transparent ); g.setColorAt( 0.8, c ); g.setColorAt( 1, c ); p.fillRect( m_startFrameX + 1, graph_rect.y(), - played_width_px, + played_width_px - ( m_startFrameX + 1 ), graph_rect.height() + graph_rect.y(), g ); - p.setPen( QColor( 255, 255, 255 ) ); + p.setPen( QColor( 255, 255, 255 ) ); //TODO: put into a qproperty p.drawLine( - m_startFrameX + 1 + played_width_px, + played_width_px, graph_rect.y(), - m_startFrameX + 1 + played_width_px, + played_width_px, graph_rect.height() + graph_rect.y() ); m_framesPlayed = 0; @@ -949,16 +995,19 @@ void AudioFileProcessorWaveView::slide( int _px ) -void AudioFileProcessorWaveView::setKnobs( knob * _start, knob * _end ) +void AudioFileProcessorWaveView::setKnobs( knob * _start, knob * _end, knob * _loop ) { m_startKnob = _start; m_endKnob = _end; + m_loopKnob = _loop; m_startKnob->setWaveView( this ); m_startKnob->setRelatedKnob( m_endKnob ); m_endKnob->setWaveView( this ); m_endKnob->setRelatedKnob( m_startKnob ); + + m_loopKnob->setWaveView( this ); } @@ -977,20 +1026,33 @@ void AudioFileProcessorWaveView::slideSamplePointByPx( knobType _point, int _px void AudioFileProcessorWaveView::slideSamplePointByFrames( knobType _point, f_cnt_t _frames, bool _slide_to ) { - knob * a_knob = _point == start ? m_startKnob : m_endKnob; - if( ! a_knob ) + knob * a_knob = m_startKnob; + switch( _point ) + { + case end: + a_knob = m_endKnob; + break; + case loop: + a_knob = m_loopKnob; + break; + case start: + break; + } + if( a_knob == NULL ) { return; } - - const double v = double( _frames ) / m_sampleBuffer.frames(); - if( _slide_to ) - { - a_knob->slideTo( v ); - } else { - a_knob->slideBy( v ); + const double v = static_cast( _frames ) / m_sampleBuffer.frames(); + if( _slide_to ) + { + a_knob->slideTo( v ); + } + else + { + a_knob->slideBy( v ); + } } } @@ -1003,13 +1065,16 @@ void AudioFileProcessorWaveView::slideSampleByFrames( f_cnt_t _frames ) { return; } - const double v = double( _frames ) / m_sampleBuffer.frames(); - if(m_startKnob) { + const double v = static_cast( _frames ) / m_sampleBuffer.frames(); + if( m_startKnob ) { m_startKnob->slideBy( v, false ); } - if(m_endKnob) { + if( m_endKnob ) { m_endKnob->slideBy( v, false ); } + if( m_loopKnob ) { + m_loopKnob->slideBy( v, false ); + } } diff --git a/plugins/audio_file_processor/audio_file_processor.h b/plugins/audio_file_processor/audio_file_processor.h index b1d21c23b..0fd0f97f3 100644 --- a/plugins/audio_file_processor/audio_file_processor.h +++ b/plugins/audio_file_processor/audio_file_processor.h @@ -3,7 +3,7 @@ * (instrument-plugin for using audio-files) * * Copyright (c) 2004-2014 Tobias Doerffel - * + * * This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net * * This program is free software; you can redistribute it and/or @@ -24,8 +24,8 @@ */ -#ifndef _AUDIO_FILE_PROCESSOR_H -#define _AUDIO_FILE_PROCESSOR_H +#ifndef AUDIO_FILE_PROCESSOR_H +#define AUDIO_FILE_PROCESSOR_H #include @@ -44,7 +44,7 @@ public: audioFileProcessor( InstrumentTrack * _instrument_track ); virtual ~audioFileProcessor(); - virtual void playNote( NotePlayHandle * _n, + virtual void playNote( NotePlayHandle * _n, sampleFrame * _working_buffer ); virtual void deleteNotePluginData( NotePlayHandle * _n ); @@ -78,17 +78,18 @@ private slots: signals: - void isPlaying( f_cnt_t _frames_played ); + void isPlaying( f_cnt_t _current_frame ); private: typedef SampleBuffer::handleState handleState; SampleBuffer m_sampleBuffer; - + FloatModel m_ampModel; FloatModel m_startPointModel; FloatModel m_endPointModel; + FloatModel m_loopPointModel; BoolModel m_reverseModel; BoolModel m_loopModel; BoolModel m_stutterModel; @@ -132,6 +133,8 @@ private: knob * m_ampKnob; knob * m_startKnob; knob * m_endKnob; + knob * m_loopKnob; + pixmapButton * m_openAudioFileButton; pixmapButton * m_reverseButton; pixmapButton * m_loopButton; @@ -159,6 +162,7 @@ public: { start, end, + loop } ; class knob : public ::knob @@ -211,7 +215,7 @@ public slots: QWidget::update(); } - void isPlaying( f_cnt_t _frames_played ); + void isPlaying( f_cnt_t _current_frame ); private: @@ -222,6 +226,7 @@ private: wave, sample_start, sample_end, + sample_loop } ; SampleBuffer& m_sampleBuffer; @@ -232,8 +237,10 @@ private: f_cnt_t m_last_to; knob * m_startKnob; knob * m_endKnob; + knob * m_loopKnob; f_cnt_t m_startFrameX; f_cnt_t m_endFrameX; + f_cnt_t m_loopFrameX; bool m_isDragging; QPoint m_draggingLastPoint; draggingType m_draggingType; @@ -243,7 +250,7 @@ private: public: AudioFileProcessorWaveView( QWidget * _parent, int _w, int _h, SampleBuffer& buf ); - void setKnobs( knob * _start, knob * _end ); + void setKnobs( knob * _start, knob * _end, knob * _loop ); private: diff --git a/src/core/SampleBuffer.cpp b/src/core/SampleBuffer.cpp index 2a7639a05..148c2fe71 100644 --- a/src/core/SampleBuffer.cpp +++ b/src/core/SampleBuffer.cpp @@ -628,6 +628,7 @@ bool SampleBuffer::play( sampleFrame * _ab, handleState * _state, const f_cnt_t total_frames_for_current_pitch = static_cast( ( m_endFrame - m_startFrame ) / freq_factor ); + qDebug( "total pitched frames %d", total_frames_for_current_pitch ); if( total_frames_for_current_pitch == 0 ) { return false; @@ -663,6 +664,7 @@ bool SampleBuffer::play( sampleFrame * _ab, handleState * _state, return false; } } + qDebug( "frames for loop %d", frames_for_loop ); sampleFrame * tmp = NULL; @@ -1243,7 +1245,7 @@ void SampleBuffer::loadFromBase64( const QString & _data ) void SampleBuffer::setStartFrame( const f_cnt_t _s ) { m_varLock.lock(); - m_loopStartFrame = m_startFrame = _s; + m_startFrame = _s; m_varLock.unlock(); } @@ -1253,7 +1255,7 @@ void SampleBuffer::setStartFrame( const f_cnt_t _s ) void SampleBuffer::setEndFrame( const f_cnt_t _e ) { m_varLock.lock(); - m_loopEndFrame = m_endFrame = _e; + m_endFrame = _e; m_varLock.unlock(); } From 8c0b22eca8bf3baef1cfb960fc38dc2eb159e07c Mon Sep 17 00:00:00 2001 From: Vesa Date: Fri, 28 Mar 2014 02:28:51 +0200 Subject: [PATCH 101/647] Forgot to clean some debug code... --- plugins/audio_file_processor/audio_file_processor.cpp | 4 ++-- src/core/SampleBuffer.cpp | 3 +-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/plugins/audio_file_processor/audio_file_processor.cpp b/plugins/audio_file_processor/audio_file_processor.cpp index a114514c3..a70fe52a4 100644 --- a/plugins/audio_file_processor/audio_file_processor.cpp +++ b/plugins/audio_file_processor/audio_file_processor.cpp @@ -131,9 +131,9 @@ void audioFileProcessor::playNote( NotePlayHandle * _n, ((handleState *)_n->m_pluginData)->setFrameIndex( m_nextPlayStartPoint ); // debug code - qDebug( "frames %d", m_sampleBuffer.frames() ); +/* qDebug( "frames %d", m_sampleBuffer.frames() ); qDebug( "startframe %d", m_sampleBuffer.startFrame() ); - qDebug( "nextPlayStartPoint %d", m_nextPlayStartPoint ); + qDebug( "nextPlayStartPoint %d", m_nextPlayStartPoint );*/ } if( ! _n->isFinished() ) diff --git a/src/core/SampleBuffer.cpp b/src/core/SampleBuffer.cpp index 148c2fe71..2b656cb7a 100644 --- a/src/core/SampleBuffer.cpp +++ b/src/core/SampleBuffer.cpp @@ -628,7 +628,7 @@ bool SampleBuffer::play( sampleFrame * _ab, handleState * _state, const f_cnt_t total_frames_for_current_pitch = static_cast( ( m_endFrame - m_startFrame ) / freq_factor ); - qDebug( "total pitched frames %d", total_frames_for_current_pitch ); + if( total_frames_for_current_pitch == 0 ) { return false; @@ -664,7 +664,6 @@ bool SampleBuffer::play( sampleFrame * _ab, handleState * _state, return false; } } - qDebug( "frames for loop %d", frames_for_loop ); sampleFrame * tmp = NULL; From ebc11f8558a7445b047eb23d741b20bae6e0c9bf Mon Sep 17 00:00:00 2001 From: Tobias Doerffel Date: Sat, 29 Mar 2014 10:08:53 +0100 Subject: [PATCH 102/647] ZynAddSubFX: update --- plugins/zynaddsubfx/zynaddsubfx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/zynaddsubfx/zynaddsubfx b/plugins/zynaddsubfx/zynaddsubfx index e97ff9076..10a2e2a08 160000 --- a/plugins/zynaddsubfx/zynaddsubfx +++ b/plugins/zynaddsubfx/zynaddsubfx @@ -1 +1 @@ -Subproject commit e97ff9076c7b3fdf7ba8410c2e94970d9418f48c +Subproject commit 10a2e2a0864274eaf53826422af4a91822df44aa From a4f070793976c1ce0868ac0dafe36c67083ced69 Mon Sep 17 00:00:00 2001 From: Hannu Haahti Date: Fri, 28 Mar 2014 03:46:28 +0200 Subject: [PATCH 103/647] slope param for kicker --- plugins/kicker/KickerOsc.h | 88 ++++++++++++++++++++++++++++++++++++++ plugins/kicker/kicker.cpp | 31 ++++++++++---- plugins/kicker/kicker.h | 2 + 3 files changed, 113 insertions(+), 8 deletions(-) create mode 100644 plugins/kicker/KickerOsc.h diff --git a/plugins/kicker/KickerOsc.h b/plugins/kicker/KickerOsc.h new file mode 100644 index 000000000..4069b940c --- /dev/null +++ b/plugins/kicker/KickerOsc.h @@ -0,0 +1,88 @@ +/* + * KickerOsc.h - alternative sweeping oscillator + * + * Copyright (c) 2006-2014 Tobias Doerffel + * Copyright (c) 2014 Hannu Haahti + * + * This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net + * + * 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 KICKER_OSC_H +#define KICKER_OSC_H + +#include "DspEffectLibrary.h" +#include "Oscillator.h" + + +template +class KickerOsc +{ +public: + KickerOsc( const FX & fx, const float start, const float end, const float slope, const float length ) : + m_phase( 0.25f ), + m_startFreq( start ), + m_endFreq( end ), + m_slope( slope ), + m_length( length ), + m_FX( fx ), + m_counter( 0 ), + m_freq( start ) + { + } + + virtual ~KickerOsc() + { + } + + void update( sampleFrame* buf, const fpp_t frames, const float sampleRate ) + { + for( fpp_t frame = 0; frame < frames; ++frame ) + { + //~ if( m_counter > m_length ) + //~ { + //~ buf[frame][0] = 0.0f; + //~ buf[frame][1] = 0.0f; + //~ continue; + //~ } + const sample_t s = Oscillator::sinSample( m_phase ); + buf[frame][0] = s; + buf[frame][1] = s; + m_FX.nextSample( buf[frame][0], buf[frame][1] ); + m_phase += m_freq / sampleRate; + m_freq = m_endFreq + ( ( m_startFreq - m_endFreq ) * ( 1 - powf( m_counter / m_length, m_slope ) ) ); + ++m_counter; + } + } + + +private: + float m_phase; + const float m_startFreq; + const float m_endFreq; + const float m_slope; + const float m_length; + FX m_FX; + + fpp_t m_counter; + float m_freq; + +}; + + +#endif diff --git a/plugins/kicker/kicker.cpp b/plugins/kicker/kicker.cpp index c04f69edb..68c32ae7c 100644 --- a/plugins/kicker/kicker.cpp +++ b/plugins/kicker/kicker.cpp @@ -31,7 +31,7 @@ #include "InstrumentTrack.h" #include "knob.h" #include "NotePlayHandle.h" -#include "SweepOscillator.h" +#include "KickerOsc.h" #include "embed.cpp" @@ -62,7 +62,8 @@ kickerInstrument::kickerInstrument( InstrumentTrack * _instrument_track ) : m_endFreqModel( 40.0f, 5.0f, 1000.0f, 1.0f, this, tr( "End frequency" ) ), m_decayModel( 120.0f, 5.0f, 1000.0f, 1.0f, this, tr( "Decay" ) ), m_distModel( 0.8f, 0.0f, 100.0f, 0.1f, this, tr( "Distortion" ) ), - m_gainModel( 1.0f, 0.1f, 5.0f, 0.05f, this, tr( "Gain" ) ) + m_gainModel( 1.0f, 0.1f, 5.0f, 0.05f, this, tr( "Gain" ) ), + m_slopeModel( 0.5f, 0.001f, 1.0f, 0.001f, this, tr( "Slope" ) ) { } @@ -84,6 +85,7 @@ void kickerInstrument::saveSettings( QDomDocument & _doc, m_decayModel.saveSettings( _doc, _this, "decay" ); m_distModel.saveSettings( _doc, _this, "dist" ); m_gainModel.saveSettings( _doc, _this, "gain" ); + m_slopeModel.saveSettings( _doc, _this, "slope" ); } @@ -96,6 +98,7 @@ void kickerInstrument::loadSettings( const QDomElement & _this ) m_decayModel.loadSettings( _this, "decay" ); m_distModel.loadSettings( _this, "dist" ); m_gainModel.loadSettings( _this, "gain" ); + m_slopeModel.loadSettings( _this, "slope" ); } @@ -110,7 +113,7 @@ QString kickerInstrument::nodeName() const //typedef DspEffectLibrary::foldbackDistortion<> DistFX; typedef DspEffectLibrary::Distortion DistFX; -typedef SweepOscillator > SweepOsc; +typedef KickerOsc > SweepOsc; void kickerInstrument::playNote( NotePlayHandle * _n, @@ -124,7 +127,11 @@ void kickerInstrument::playNote( NotePlayHandle * _n, { _n->m_pluginData = new SweepOsc( DistFX( m_distModel.value(), - m_gainModel.value() ) ); + m_gainModel.value() ), + m_startFreqModel.value(), + m_endFreqModel.value(), + m_slopeModel.value(), + decfr ); } else if( tfp > decfr && !_n->isReleased() ) { @@ -132,7 +139,7 @@ void kickerInstrument::playNote( NotePlayHandle * _n, } //const float freq = instrumentTrack()->frequency( _n ) / 2; - const float fdiff = m_endFreqModel.value() - m_startFreqModel.value(); + //~ const float fdiff = m_endFreqModel.value() - m_startFreqModel.value(); /* const fpp_t frames = _n->isReleased() ? tMax( tMin( desiredReleaseFrames() - _n->releaseFramesDone(), @@ -140,12 +147,15 @@ void kickerInstrument::playNote( NotePlayHandle * _n, : engine::mixer()->framesPerAudioBuffer();*/ const fpp_t frames = _n->framesLeftForCurrentPeriod(); - const float f1 = m_startFreqModel.value() + tfp * fdiff / decfr; - const float f2 = m_startFreqModel.value() + (frames+tfp-1)*fdiff/decfr; + //~ const float slopePoint = powf( fdiff / decfr, 1 + m_slopeModel.value() * 6 ); + + //~ const float f1 = m_startFreqModel.value() + tfp * ((fdiff/decfr) * slopePoint); + //~ const float f2 = m_startFreqModel.value() + (frames+tfp-1) * ((fdiff/decfr) * slopePoint); + SweepOsc * so = static_cast( _n->m_pluginData ); - so->update( _working_buffer, frames, f1, f2, + so->update( _working_buffer, frames, engine::mixer()->processingSampleRate() ); if( _n->isReleased() ) @@ -219,6 +229,10 @@ kickerInstrumentView::kickerInstrumentView( Instrument * _instrument, m_gainKnob->setHintText( tr( "Gain:" ) + " ", "" ); m_gainKnob->move( 203, 124 ); + m_slopeKnob = new kickerKnob( this ); + m_slopeKnob->setHintText( tr( "Slope:" ) + " ", "" ); + m_slopeKnob->move( 203, 164 ); + setAutoFillBackground( true ); QPalette pal; pal.setBrush( backgroundRole(), PLUGIN_NAME::getIconPixmap( @@ -244,6 +258,7 @@ void kickerInstrumentView::modelChanged() m_decayKnob->setModel( &k->m_decayModel ); m_distKnob->setModel( &k->m_distModel ); m_gainKnob->setModel( &k->m_gainModel ); + m_slopeKnob->setModel( &k->m_slopeModel ); } diff --git a/plugins/kicker/kicker.h b/plugins/kicker/kicker.h index f6633b07e..b1b5e2403 100644 --- a/plugins/kicker/kicker.h +++ b/plugins/kicker/kicker.h @@ -66,6 +66,7 @@ private: FloatModel m_decayModel; FloatModel m_distModel; FloatModel m_gainModel; + FloatModel m_slopeModel; friend class kickerInstrumentView; @@ -88,6 +89,7 @@ private: knob * m_decayKnob; knob * m_distKnob; knob * m_gainKnob; + knob * m_slopeKnob; } ; From f53ecdf023201659219afbd454d5fa695e476bfe Mon Sep 17 00:00:00 2001 From: Hannu Haahti Date: Fri, 28 Mar 2014 16:03:48 +0200 Subject: [PATCH 104/647] kicker: click param --- plugins/kicker/KickerOsc.h | 13 ++++++++----- plugins/kicker/kicker.cpp | 17 +++++++++++++---- plugins/kicker/kicker.h | 2 ++ 3 files changed, 23 insertions(+), 9 deletions(-) diff --git a/plugins/kicker/KickerOsc.h b/plugins/kicker/KickerOsc.h index 4069b940c..d559ee6f4 100644 --- a/plugins/kicker/KickerOsc.h +++ b/plugins/kicker/KickerOsc.h @@ -34,8 +34,8 @@ template class KickerOsc { public: - KickerOsc( const FX & fx, const float start, const float end, const float slope, const float length ) : - m_phase( 0.25f ), + KickerOsc( const FX & fx, const float start, const float end, const float offset, const float slope, const float length ) : + m_phase( offset ), m_startFreq( start ), m_endFreq( end ), m_slope( slope ), @@ -65,7 +65,10 @@ public: buf[frame][1] = s; m_FX.nextSample( buf[frame][0], buf[frame][1] ); m_phase += m_freq / sampleRate; - m_freq = m_endFreq + ( ( m_startFreq - m_endFreq ) * ( 1 - powf( m_counter / m_length, m_slope ) ) ); + + const double change = ( m_counter < m_length ) ? ( ( m_startFreq - m_endFreq ) * ( 1 - powf( m_counter / m_length, m_slope ) ) ) : 0; + //~ qDebug( "%f (%f) [%lu, %f]", change, powf( m_counter / m_length, m_slope ), m_counter, m_length ); + m_freq = m_endFreq + change; ++m_counter; } } @@ -79,8 +82,8 @@ private: const float m_length; FX m_FX; - fpp_t m_counter; - float m_freq; + unsigned long m_counter; + double m_freq; }; diff --git a/plugins/kicker/kicker.cpp b/plugins/kicker/kicker.cpp index 68c32ae7c..76027f8ef 100644 --- a/plugins/kicker/kicker.cpp +++ b/plugins/kicker/kicker.cpp @@ -63,6 +63,7 @@ kickerInstrument::kickerInstrument( InstrumentTrack * _instrument_track ) : m_decayModel( 120.0f, 5.0f, 1000.0f, 1.0f, this, tr( "Decay" ) ), m_distModel( 0.8f, 0.0f, 100.0f, 0.1f, this, tr( "Distortion" ) ), m_gainModel( 1.0f, 0.1f, 5.0f, 0.05f, this, tr( "Gain" ) ), + m_clickModel( 1.0f, 0.0f, 1.0f, 0.1f, this, tr( "Click" ) ), m_slopeModel( 0.5f, 0.001f, 1.0f, 0.001f, this, tr( "Slope" ) ) { } @@ -85,6 +86,7 @@ void kickerInstrument::saveSettings( QDomDocument & _doc, m_decayModel.saveSettings( _doc, _this, "decay" ); m_distModel.saveSettings( _doc, _this, "dist" ); m_gainModel.saveSettings( _doc, _this, "gain" ); + m_clickModel.saveSettings( _doc, _this, "click" ); m_slopeModel.saveSettings( _doc, _this, "slope" ); } @@ -98,6 +100,7 @@ void kickerInstrument::loadSettings( const QDomElement & _this ) m_decayModel.loadSettings( _this, "decay" ); m_distModel.loadSettings( _this, "dist" ); m_gainModel.loadSettings( _this, "gain" ); + m_clickModel.loadSettings( _this, "gain" ); m_slopeModel.loadSettings( _this, "slope" ); } @@ -130,6 +133,7 @@ void kickerInstrument::playNote( NotePlayHandle * _n, m_gainModel.value() ), m_startFreqModel.value(), m_endFreqModel.value(), + m_clickModel.value() * 0.25f, m_slopeModel.value(), decfr ); } @@ -160,11 +164,11 @@ void kickerInstrument::playNote( NotePlayHandle * _n, if( _n->isReleased() ) { - const float rfd = _n->releaseFramesDone(); - const float drf = desiredReleaseFrames(); + const float done = _n->releaseFramesDone(); + const float desired = desiredReleaseFrames(); for( fpp_t f = 0; f < frames; ++f ) { - const float fac = 1.0f - ( rfd+f ) / drf; + const float fac = ( done+f < desired ) ? ( 1.0f - ( ( done+f ) / desired ) ) : 0; _working_buffer[f][0] *= fac; _working_buffer[f][1] *= fac; } @@ -229,9 +233,13 @@ kickerInstrumentView::kickerInstrumentView( Instrument * _instrument, m_gainKnob->setHintText( tr( "Gain:" ) + " ", "" ); m_gainKnob->move( 203, 124 ); + m_clickKnob = new kickerKnob( this ); + m_clickKnob->setHintText( tr( "Click:" ) + " ", "" ); + m_clickKnob->move( 203, 164 ); + m_slopeKnob = new kickerKnob( this ); m_slopeKnob->setHintText( tr( "Slope:" ) + " ", "" ); - m_slopeKnob->move( 203, 164 ); + m_slopeKnob->move( 203, 204 ); setAutoFillBackground( true ); QPalette pal; @@ -258,6 +266,7 @@ void kickerInstrumentView::modelChanged() m_decayKnob->setModel( &k->m_decayModel ); m_distKnob->setModel( &k->m_distModel ); m_gainKnob->setModel( &k->m_gainModel ); + m_clickKnob->setModel( &k->m_clickModel ); m_slopeKnob->setModel( &k->m_slopeModel ); } diff --git a/plugins/kicker/kicker.h b/plugins/kicker/kicker.h index b1b5e2403..02007e22a 100644 --- a/plugins/kicker/kicker.h +++ b/plugins/kicker/kicker.h @@ -66,6 +66,7 @@ private: FloatModel m_decayModel; FloatModel m_distModel; FloatModel m_gainModel; + FloatModel m_clickModel; FloatModel m_slopeModel; friend class kickerInstrumentView; @@ -89,6 +90,7 @@ private: knob * m_decayKnob; knob * m_distKnob; knob * m_gainKnob; + knob * m_clickKnob; knob * m_slopeKnob; } ; From 172cffa3c5dfdbf0876b7739d32b0eed6f7e40e1 Mon Sep 17 00:00:00 2001 From: Hannu Haahti Date: Fri, 28 Mar 2014 17:26:06 +0200 Subject: [PATCH 105/647] kicker: envelope slope --- plugins/kicker/KickerOsc.h | 20 ++++++++++---------- plugins/kicker/fastpow.h | 20 ++++++++++++++++++++ plugins/kicker/kicker.cpp | 21 +++++++++++++++------ plugins/kicker/kicker.h | 2 ++ 4 files changed, 47 insertions(+), 16 deletions(-) create mode 100644 plugins/kicker/fastpow.h diff --git a/plugins/kicker/KickerOsc.h b/plugins/kicker/KickerOsc.h index d559ee6f4..2dbfd19f6 100644 --- a/plugins/kicker/KickerOsc.h +++ b/plugins/kicker/KickerOsc.h @@ -29,16 +29,19 @@ #include "DspEffectLibrary.h" #include "Oscillator.h" +#include "fastpow.h" + template class KickerOsc { public: - KickerOsc( const FX & fx, const float start, const float end, const float offset, const float slope, const float length ) : + KickerOsc( const FX & fx, const float start, const float end, const float offset, const float slope, const float env, const float length ) : m_phase( offset ), m_startFreq( start ), m_endFreq( end ), m_slope( slope ), + m_env( env ), m_length( length ), m_FX( fx ), m_counter( 0 ), @@ -54,19 +57,15 @@ public: { for( fpp_t frame = 0; frame < frames; ++frame ) { - //~ if( m_counter > m_length ) - //~ { - //~ buf[frame][0] = 0.0f; - //~ buf[frame][1] = 0.0f; - //~ continue; - //~ } + const double gain = ( 1 - fastPow( ( m_counter < m_length ) ? m_counter / m_length : 1, m_env ) ); + //~ qDebug( "%f", gain ); const sample_t s = Oscillator::sinSample( m_phase ); - buf[frame][0] = s; - buf[frame][1] = s; + buf[frame][0] = s * gain; + buf[frame][1] = s * gain; m_FX.nextSample( buf[frame][0], buf[frame][1] ); m_phase += m_freq / sampleRate; - const double change = ( m_counter < m_length ) ? ( ( m_startFreq - m_endFreq ) * ( 1 - powf( m_counter / m_length, m_slope ) ) ) : 0; + const double change = ( m_counter < m_length ) ? ( ( m_startFreq - m_endFreq ) * ( 1 - fastPow( m_counter / m_length, m_slope ) ) ) : 0; //~ qDebug( "%f (%f) [%lu, %f]", change, powf( m_counter / m_length, m_slope ), m_counter, m_length ); m_freq = m_endFreq + change; ++m_counter; @@ -79,6 +78,7 @@ private: const float m_startFreq; const float m_endFreq; const float m_slope; + const float m_env; const float m_length; FX m_FX; diff --git a/plugins/kicker/fastpow.h b/plugins/kicker/fastpow.h new file mode 100644 index 000000000..145388d3f --- /dev/null +++ b/plugins/kicker/fastpow.h @@ -0,0 +1,20 @@ + +#ifndef FASTPOW_H +#define FASTPOW_H + +/* + * source: + * http://martin.ankerl.com/2007/10/04/optimized-pow-approximation-for-java-and-c-c/ + */ + +double fastPow(double a, double b) { + union { + double d; + int x[2]; + } u = { a }; + u.x[1] = (int)(b * (u.x[1] - 1072632447) + 1072632447); + u.x[0] = 0; + return u.d; +} + +#endif diff --git a/plugins/kicker/kicker.cpp b/plugins/kicker/kicker.cpp index 76027f8ef..7f0948059 100644 --- a/plugins/kicker/kicker.cpp +++ b/plugins/kicker/kicker.cpp @@ -60,11 +60,12 @@ kickerInstrument::kickerInstrument( InstrumentTrack * _instrument_track ) : Instrument( _instrument_track, &kicker_plugin_descriptor ), m_startFreqModel( 150.0f, 5.0f, 1000.0f, 1.0f, this, tr( "Start frequency" ) ), m_endFreqModel( 40.0f, 5.0f, 1000.0f, 1.0f, this, tr( "End frequency" ) ), - m_decayModel( 120.0f, 5.0f, 1000.0f, 1.0f, this, tr( "Decay" ) ), + m_decayModel( 440.0f, 5.0f, 2000.0f, 1.0f, this, tr( "Decay" ) ), m_distModel( 0.8f, 0.0f, 100.0f, 0.1f, this, tr( "Distortion" ) ), m_gainModel( 1.0f, 0.1f, 5.0f, 0.05f, this, tr( "Gain" ) ), - m_clickModel( 1.0f, 0.0f, 1.0f, 0.1f, this, tr( "Click" ) ), - m_slopeModel( 0.5f, 0.001f, 1.0f, 0.001f, this, tr( "Slope" ) ) + m_envModel( 0.163f, 0.01f, 1.0f, 0.001f, this, tr( "Env" ) ), + m_clickModel( 0.4f, 0.0f, 1.0f, 0.05f, this, tr( "Click" ) ), + m_slopeModel( 0.06f, 0.001f, 1.0f, 0.001f, this, tr( "Slope" ) ) { } @@ -86,6 +87,7 @@ void kickerInstrument::saveSettings( QDomDocument & _doc, m_decayModel.saveSettings( _doc, _this, "decay" ); m_distModel.saveSettings( _doc, _this, "dist" ); m_gainModel.saveSettings( _doc, _this, "gain" ); + m_envModel.saveSettings( _doc, _this, "env" ); m_clickModel.saveSettings( _doc, _this, "click" ); m_slopeModel.saveSettings( _doc, _this, "slope" ); } @@ -100,7 +102,8 @@ void kickerInstrument::loadSettings( const QDomElement & _this ) m_decayModel.loadSettings( _this, "decay" ); m_distModel.loadSettings( _this, "dist" ); m_gainModel.loadSettings( _this, "gain" ); - m_clickModel.loadSettings( _this, "gain" ); + m_envModel.loadSettings( _this, "env" ); + m_clickModel.loadSettings( _this, "click" ); m_slopeModel.loadSettings( _this, "slope" ); } @@ -135,6 +138,7 @@ void kickerInstrument::playNote( NotePlayHandle * _n, m_endFreqModel.value(), m_clickModel.value() * 0.25f, m_slopeModel.value(), + m_envModel.value(), decfr ); } else if( tfp > decfr && !_n->isReleased() ) @@ -233,13 +237,17 @@ kickerInstrumentView::kickerInstrumentView( Instrument * _instrument, m_gainKnob->setHintText( tr( "Gain:" ) + " ", "" ); m_gainKnob->move( 203, 124 ); + m_envKnob = new kickerKnob( this ); + m_envKnob->setHintText( tr( "Env:" ) + " ", "" ); + m_envKnob->move( 203, 204 ); + m_clickKnob = new kickerKnob( this ); m_clickKnob->setHintText( tr( "Click:" ) + " ", "" ); - m_clickKnob->move( 203, 164 ); + m_clickKnob->move( 12, 204 ); m_slopeKnob = new kickerKnob( this ); m_slopeKnob->setHintText( tr( "Slope:" ) + " ", "" ); - m_slopeKnob->move( 203, 204 ); + m_slopeKnob->move( 59, 204 ); setAutoFillBackground( true ); QPalette pal; @@ -266,6 +274,7 @@ void kickerInstrumentView::modelChanged() m_decayKnob->setModel( &k->m_decayModel ); m_distKnob->setModel( &k->m_distModel ); m_gainKnob->setModel( &k->m_gainModel ); + m_envKnob->setModel( &k->m_envModel ); m_clickKnob->setModel( &k->m_clickModel ); m_slopeKnob->setModel( &k->m_slopeModel ); } diff --git a/plugins/kicker/kicker.h b/plugins/kicker/kicker.h index 02007e22a..78944da47 100644 --- a/plugins/kicker/kicker.h +++ b/plugins/kicker/kicker.h @@ -66,6 +66,7 @@ private: FloatModel m_decayModel; FloatModel m_distModel; FloatModel m_gainModel; + FloatModel m_envModel; FloatModel m_clickModel; FloatModel m_slopeModel; @@ -90,6 +91,7 @@ private: knob * m_decayKnob; knob * m_distKnob; knob * m_gainKnob; + knob * m_envKnob; knob * m_clickKnob; knob * m_slopeKnob; From f1f6c71aa1000de5554eca9721f0ef75243adeb4 Mon Sep 17 00:00:00 2001 From: Hannu Haahti Date: Fri, 28 Mar 2014 20:36:11 +0200 Subject: [PATCH 106/647] kicker: noise option + artwork --- plugins/kicker/KickerOsc.h | 6 ++-- plugins/kicker/artwork.png | Bin 40329 -> 8769 bytes plugins/kicker/kicker.cpp | 58 ++++++++++++++++++++++--------------- plugins/kicker/kicker.h | 2 ++ 4 files changed, 40 insertions(+), 26 deletions(-) diff --git a/plugins/kicker/KickerOsc.h b/plugins/kicker/KickerOsc.h index 2dbfd19f6..440fa5837 100644 --- a/plugins/kicker/KickerOsc.h +++ b/plugins/kicker/KickerOsc.h @@ -36,10 +36,11 @@ template class KickerOsc { public: - KickerOsc( const FX & fx, const float start, const float end, const float offset, const float slope, const float env, const float length ) : + KickerOsc( const FX & fx, const float start, const float end, const float noise, const float offset, const float slope, const float env, const float length ) : m_phase( offset ), m_startFreq( start ), m_endFreq( end ), + m_noise( noise ), m_slope( slope ), m_env( env ), m_length( length ), @@ -59,7 +60,7 @@ public: { const double gain = ( 1 - fastPow( ( m_counter < m_length ) ? m_counter / m_length : 1, m_env ) ); //~ qDebug( "%f", gain ); - const sample_t s = Oscillator::sinSample( m_phase ); + const sample_t s = Oscillator::sinSample( m_phase ) + ( Oscillator::noiseSample( 0 ) * gain * gain * m_noise ); buf[frame][0] = s * gain; buf[frame][1] = s * gain; m_FX.nextSample( buf[frame][0], buf[frame][1] ); @@ -77,6 +78,7 @@ private: float m_phase; const float m_startFreq; const float m_endFreq; + const float m_noise; const float m_slope; const float m_env; const float m_length; diff --git a/plugins/kicker/artwork.png b/plugins/kicker/artwork.png index 12a56504448b60f544dbc854a9b846b6b727e2ee..4d583bb4fd03f3c3296ba49cca6b65d68a8f6b12 100644 GIT binary patch literal 8769 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 INbBo=0K-ICxBvhE literal 40329 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 tr( "Start frequency:" ) + " ", "Hz" ); - m_startFreqKnob->move( 12, 124 ); + m_startFreqKnob->move( 15, 100 ); m_endFreqKnob = new kickerKnob( this ); m_endFreqKnob->setHintText( tr( "End frequency:" ) + " ", "Hz" ); - m_endFreqKnob->move( 59, 124 ); - - m_decayKnob = new kickerKnob( this ); - m_decayKnob->setHintText( tr( "Decay:" ) + " ", "ms" ); - m_decayKnob->move( 107, 124 ); - - m_distKnob = new kickerKnob( this ); - m_distKnob->setHintText( tr( "Distortion:" ) + " ", "" ); - m_distKnob->move( 155, 124 ); - - m_gainKnob = new kickerKnob( this ); - m_gainKnob->setHintText( tr( "Gain:" ) + " ", "" ); - m_gainKnob->move( 203, 124 ); - - m_envKnob = new kickerKnob( this ); - m_envKnob->setHintText( tr( "Env:" ) + " ", "" ); - m_envKnob->move( 203, 204 ); - - m_clickKnob = new kickerKnob( this ); - m_clickKnob->setHintText( tr( "Click:" ) + " ", "" ); - m_clickKnob->move( 12, 204 ); + m_endFreqKnob->move( 60, 100 ); m_slopeKnob = new kickerKnob( this ); m_slopeKnob->setHintText( tr( "Slope:" ) + " ", "" ); - m_slopeKnob->move( 59, 204 ); + m_slopeKnob->move( 105, 100 ); + + m_gainKnob = new kickerKnob( this ); + m_gainKnob->setHintText( tr( "Gain:" ) + " ", "" ); + m_gainKnob->move( 15, 155 ); + + m_decayKnob = new kickerKnob( this ); + m_decayKnob->setHintText( tr( "Length:" ) + " ", "ms" ); + m_decayKnob->move( 60, 155 ); + + m_envKnob = new kickerKnob( this ); + m_envKnob->setHintText( tr( "Env:" ) + " ", "" ); + m_envKnob->move( 105, 155 ); + + m_noiseKnob = new kickerKnob( this ); + m_noiseKnob->setHintText( tr( "Noise:" ) + " ", "" ); + m_noiseKnob->move( 200, 45 ); + + m_distKnob = new kickerKnob( this ); + m_distKnob->setHintText( tr( "Distortion:" ) + " ", "" ); + m_distKnob->move( 200, 100 ); + + m_clickKnob = new kickerKnob( this ); + m_clickKnob->setHintText( tr( "Click:" ) + " ", "" ); + m_clickKnob->move( 200, 155 ); + setAutoFillBackground( true ); QPalette pal; @@ -275,6 +284,7 @@ void kickerInstrumentView::modelChanged() m_distKnob->setModel( &k->m_distModel ); m_gainKnob->setModel( &k->m_gainModel ); m_envKnob->setModel( &k->m_envModel ); + m_noiseKnob->setModel( &k->m_noiseModel ); m_clickKnob->setModel( &k->m_clickModel ); m_slopeKnob->setModel( &k->m_slopeModel ); } diff --git a/plugins/kicker/kicker.h b/plugins/kicker/kicker.h index 78944da47..db17e642c 100644 --- a/plugins/kicker/kicker.h +++ b/plugins/kicker/kicker.h @@ -67,6 +67,7 @@ private: FloatModel m_distModel; FloatModel m_gainModel; FloatModel m_envModel; + FloatModel m_noiseModel; FloatModel m_clickModel; FloatModel m_slopeModel; @@ -92,6 +93,7 @@ private: knob * m_distKnob; knob * m_gainKnob; knob * m_envKnob; + knob * m_noiseKnob; knob * m_clickKnob; knob * m_slopeKnob; From 8d987aabd466459ddc0dc07770dfb7a04e5ff09b Mon Sep 17 00:00:00 2001 From: Hannu Haahti Date: Fri, 28 Mar 2014 21:04:22 +0200 Subject: [PATCH 107/647] kicker: noise improvements, decay -> length --- plugins/kicker/KickerOsc.h | 2 +- plugins/kicker/kicker.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/plugins/kicker/KickerOsc.h b/plugins/kicker/KickerOsc.h index 440fa5837..fe370c6b5 100644 --- a/plugins/kicker/KickerOsc.h +++ b/plugins/kicker/KickerOsc.h @@ -60,7 +60,7 @@ public: { const double gain = ( 1 - fastPow( ( m_counter < m_length ) ? m_counter / m_length : 1, m_env ) ); //~ qDebug( "%f", gain ); - const sample_t s = Oscillator::sinSample( m_phase ) + ( Oscillator::noiseSample( 0 ) * gain * gain * m_noise ); + const sample_t s = ( Oscillator::sinSample( m_phase ) * ( 1 - m_noise ) ) + ( Oscillator::noiseSample( 0 ) * gain * gain * m_noise ); buf[frame][0] = s * gain; buf[frame][1] = s * gain; m_FX.nextSample( buf[frame][0], buf[frame][1] ); diff --git a/plugins/kicker/kicker.cpp b/plugins/kicker/kicker.cpp index ab2459b72..4b9078aa0 100644 --- a/plugins/kicker/kicker.cpp +++ b/plugins/kicker/kicker.cpp @@ -60,7 +60,7 @@ kickerInstrument::kickerInstrument( InstrumentTrack * _instrument_track ) : Instrument( _instrument_track, &kicker_plugin_descriptor ), m_startFreqModel( 150.0f, 5.0f, 1000.0f, 1.0f, this, tr( "Start frequency" ) ), m_endFreqModel( 40.0f, 5.0f, 1000.0f, 1.0f, this, tr( "End frequency" ) ), - m_decayModel( 440.0f, 5.0f, 2000.0f, 1.0f, this, tr( "Decay" ) ), + m_decayModel( 440.0f, 5.0f, 2000.0f, 1.0f, this, tr( "Length" ) ), m_distModel( 0.8f, 0.0f, 100.0f, 0.1f, this, tr( "Distortion" ) ), m_gainModel( 1.0f, 0.1f, 5.0f, 0.05f, this, tr( "Gain" ) ), m_envModel( 0.163f, 0.01f, 1.0f, 0.001f, this, tr( "Env" ) ), @@ -139,7 +139,7 @@ void kickerInstrument::playNote( NotePlayHandle * _n, m_gainModel.value() ), m_startFreqModel.value(), m_endFreqModel.value(), - m_noiseModel.value(), + m_noiseModel.value() * m_noiseModel.value(), m_clickModel.value() * 0.25f, m_slopeModel.value(), m_envModel.value(), From 0967d91f44374738c88236e36b26c253a5ea0b09 Mon Sep 17 00:00:00 2001 From: Hannu Haahti Date: Sat, 29 Mar 2014 00:01:56 +0200 Subject: [PATCH 108/647] paranoid --- plugins/kicker/fastpow.h | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/plugins/kicker/fastpow.h b/plugins/kicker/fastpow.h index 145388d3f..48fd83c03 100644 --- a/plugins/kicker/fastpow.h +++ b/plugins/kicker/fastpow.h @@ -2,6 +2,8 @@ #ifndef FASTPOW_H #define FASTPOW_H +#include + /* * source: * http://martin.ankerl.com/2007/10/04/optimized-pow-approximation-for-java-and-c-c/ @@ -10,9 +12,9 @@ double fastPow(double a, double b) { union { double d; - int x[2]; + int32_t x[2]; } u = { a }; - u.x[1] = (int)(b * (u.x[1] - 1072632447) + 1072632447); + u.x[1] = (int32_t)(b * (u.x[1] - 1072632447) + 1072632447); u.x[0] = 0; return u.d; } From 29c2d3fb1a54f4e65a9f657f76239070bd363281 Mon Sep 17 00:00:00 2001 From: Hannu Haahti Date: Sat, 29 Mar 2014 00:48:34 +0200 Subject: [PATCH 109/647] kicker: possible to play notes too --- plugins/kicker/artwork.png | Bin 8769 -> 9016 bytes plugins/kicker/kicker.cpp | 19 ++++++++++++++++--- plugins/kicker/kicker.h | 13 ++++++++++++- 3 files changed, 28 insertions(+), 4 deletions(-) diff --git a/plugins/kicker/artwork.png b/plugins/kicker/artwork.png index 4d583bb4fd03f3c3296ba49cca6b65d68a8f6b12..463ea0efe6deff2d9784f9a94ec2a1d3d5305318 100644 GIT binary patch literal 9016 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 B`D6e9 literal 8769 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 INbBo=0K-ICxBvhE diff --git a/plugins/kicker/kicker.cpp b/plugins/kicker/kicker.cpp index 4b9078aa0..feecc34e5 100644 --- a/plugins/kicker/kicker.cpp +++ b/plugins/kicker/kicker.cpp @@ -66,7 +66,9 @@ kickerInstrument::kickerInstrument( InstrumentTrack * _instrument_track ) : m_envModel( 0.163f, 0.01f, 1.0f, 0.001f, this, tr( "Env" ) ), m_noiseModel( 0.0f, 0.0f, 1.0f, 0.01f, this, tr( "Noise" ) ), m_clickModel( 0.4f, 0.0f, 1.0f, 0.05f, this, tr( "Click" ) ), - m_slopeModel( 0.06f, 0.001f, 1.0f, 0.001f, this, tr( "Slope" ) ) + m_slopeModel( 0.06f, 0.001f, 1.0f, 0.001f, this, tr( "Slope" ) ), + m_startNoteModel( false, this, tr( "Start from note" ) ), + m_endNoteModel( false, this, tr( "End to note" ) ) { } @@ -92,6 +94,8 @@ void kickerInstrument::saveSettings( QDomDocument & _doc, m_noiseModel.saveSettings( _doc, _this, "noise" ); m_clickModel.saveSettings( _doc, _this, "click" ); m_slopeModel.saveSettings( _doc, _this, "slope" ); + m_startNoteModel.saveSettings( _doc, _this, "startnote" ); + m_endNoteModel.saveSettings( _doc, _this, "endnote" ); } @@ -108,6 +112,8 @@ void kickerInstrument::loadSettings( const QDomElement & _this ) m_noiseModel.loadSettings( _this, "noise" ); m_clickModel.loadSettings( _this, "click" ); m_slopeModel.loadSettings( _this, "slope" ); + m_startNoteModel.loadSettings( _this, "startnote" ); + m_endNoteModel.loadSettings( _this, "endnote" ); } @@ -137,8 +143,8 @@ void kickerInstrument::playNote( NotePlayHandle * _n, _n->m_pluginData = new SweepOsc( DistFX( m_distModel.value(), m_gainModel.value() ), - m_startFreqModel.value(), - m_endFreqModel.value(), + m_startNoteModel.value() ? _n->frequency() : m_startFreqModel.value(), + m_endNoteModel.value() ? _n->frequency() : m_endFreqModel.value(), m_noiseModel.value() * m_noiseModel.value(), m_clickModel.value() * 0.25f, m_slopeModel.value(), @@ -257,6 +263,11 @@ kickerInstrumentView::kickerInstrumentView( Instrument * _instrument, m_clickKnob->setHintText( tr( "Click:" ) + " ", "" ); m_clickKnob->move( 200, 155 ); + m_startNoteToggle = new ledCheckBox( "", this ); + m_startNoteToggle->move( 24, 79 ); + + m_endNoteToggle = new ledCheckBox( "", this ); + m_endNoteToggle->move( 69, 79 ); setAutoFillBackground( true ); QPalette pal; @@ -287,6 +298,8 @@ void kickerInstrumentView::modelChanged() m_noiseKnob->setModel( &k->m_noiseModel ); m_clickKnob->setModel( &k->m_clickModel ); m_slopeKnob->setModel( &k->m_slopeModel ); + m_startNoteToggle->setModel( &k->m_startNoteModel ); + m_endNoteToggle->setModel( &k->m_endNoteModel ); } diff --git a/plugins/kicker/kicker.h b/plugins/kicker/kicker.h index db17e642c..ca126c7e6 100644 --- a/plugins/kicker/kicker.h +++ b/plugins/kicker/kicker.h @@ -30,6 +30,7 @@ #include "Instrument.h" #include "InstrumentView.h" #include "knob.h" +#include "led_checkbox.h" class kickerInstrumentView; @@ -46,12 +47,16 @@ public: sampleFrame * _working_buffer ); virtual void deleteNotePluginData( NotePlayHandle * _n ); - virtual void saveSettings( QDomDocument & _doc, QDomElement & _parent ); virtual void loadSettings( const QDomElement & _this ); virtual QString nodeName() const; + virtual Flags flags() const + { + return IsNotBendable; + } + virtual f_cnt_t desiredReleaseFrames() const { return( 512 ); @@ -71,6 +76,9 @@ private: FloatModel m_clickModel; FloatModel m_slopeModel; + BoolModel m_startNoteModel; + BoolModel m_endNoteModel; + friend class kickerInstrumentView; } ; @@ -97,6 +105,9 @@ private: knob * m_clickKnob; knob * m_slopeKnob; + ledCheckBox * m_startNoteToggle; + ledCheckBox * m_endNoteToggle; + } ; From b4421700fac3c7248864ec6675a7c93416c14eb0 Mon Sep 17 00:00:00 2001 From: Hannu Haahti Date: Sat, 29 Mar 2014 01:21:44 +0200 Subject: [PATCH 110/647] kicker: some cleanup --- plugins/kicker/KickerOsc.h | 2 -- plugins/kicker/kicker.cpp | 23 ++++------------------- plugins/kicker/kicker.h | 3 ++- 3 files changed, 6 insertions(+), 22 deletions(-) diff --git a/plugins/kicker/KickerOsc.h b/plugins/kicker/KickerOsc.h index fe370c6b5..edcdcf5e5 100644 --- a/plugins/kicker/KickerOsc.h +++ b/plugins/kicker/KickerOsc.h @@ -59,7 +59,6 @@ public: for( fpp_t frame = 0; frame < frames; ++frame ) { const double gain = ( 1 - fastPow( ( m_counter < m_length ) ? m_counter / m_length : 1, m_env ) ); - //~ qDebug( "%f", gain ); const sample_t s = ( Oscillator::sinSample( m_phase ) * ( 1 - m_noise ) ) + ( Oscillator::noiseSample( 0 ) * gain * gain * m_noise ); buf[frame][0] = s * gain; buf[frame][1] = s * gain; @@ -67,7 +66,6 @@ public: m_phase += m_freq / sampleRate; const double change = ( m_counter < m_length ) ? ( ( m_startFreq - m_endFreq ) * ( 1 - fastPow( m_counter / m_length, m_slope ) ) ) : 0; - //~ qDebug( "%f (%f) [%lu, %f]", change, powf( m_counter / m_length, m_slope ), m_counter, m_length ); m_freq = m_endFreq + change; ++m_counter; } diff --git a/plugins/kicker/kicker.cpp b/plugins/kicker/kicker.cpp index feecc34e5..655d41dd1 100644 --- a/plugins/kicker/kicker.cpp +++ b/plugins/kicker/kicker.cpp @@ -1,7 +1,8 @@ /* - * kicker.cpp - bassdrum-synthesizer + * kicker.cpp - drum synthesizer * * Copyright (c) 2006-2009 Tobias Doerffel + * Copyright (c) 2014 Hannu Haahti * * This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net * @@ -44,7 +45,7 @@ Plugin::Descriptor PLUGIN_EXPORT kicker_plugin_descriptor = STRINGIFY( PLUGIN_NAME ), "Kicker", QT_TRANSLATE_NOOP( "pluginBrowser", - "Versatile kick- & bassdrum-synthesizer" ), + "Versatile drum synthesizer" ), "Tobias Doerffel ", 0x0100, Plugin::Instrument, @@ -126,7 +127,6 @@ QString kickerInstrument::nodeName() const -//typedef DspEffectLibrary::foldbackDistortion<> DistFX; typedef DspEffectLibrary::Distortion DistFX; typedef KickerOsc > SweepOsc; @@ -156,25 +156,10 @@ void kickerInstrument::playNote( NotePlayHandle * _n, _n->noteOff(); } - //const float freq = instrumentTrack()->frequency( _n ) / 2; - //~ const float fdiff = m_endFreqModel.value() - m_startFreqModel.value(); -/* const fpp_t frames = _n->isReleased() ? - tMax( tMin( desiredReleaseFrames() - - _n->releaseFramesDone(), - engine::mixer()->framesPerAudioBuffer() ), 0 ) - : - engine::mixer()->framesPerAudioBuffer();*/ const fpp_t frames = _n->framesLeftForCurrentPeriod(); - //~ const float slopePoint = powf( fdiff / decfr, 1 + m_slopeModel.value() * 6 ); - - //~ const float f1 = m_startFreqModel.value() + tfp * ((fdiff/decfr) * slopePoint); - //~ const float f2 = m_startFreqModel.value() + (frames+tfp-1) * ((fdiff/decfr) * slopePoint); - - SweepOsc * so = static_cast( _n->m_pluginData ); - so->update( _working_buffer, frames, - engine::mixer()->processingSampleRate() ); + so->update( _working_buffer, frames, engine::mixer()->processingSampleRate() ); if( _n->isReleased() ) { diff --git a/plugins/kicker/kicker.h b/plugins/kicker/kicker.h index ca126c7e6..8253becf8 100644 --- a/plugins/kicker/kicker.h +++ b/plugins/kicker/kicker.h @@ -1,5 +1,6 @@ /* - * kicker.h - bassdrum-synthesizer + * kicker.h - drum synthesizer + * Copyright (c) 2014 Hannu Haahti * * Copyright (c) 2006-2008 Tobias Doerffel * From 09630f1d56bad555b6467403e37f716bd0d1b4a3 Mon Sep 17 00:00:00 2001 From: Hannu Haahti Date: Sat, 29 Mar 2014 21:18:01 +0200 Subject: [PATCH 111/647] kicker: reordered knobs --- plugins/kicker/artwork.png | Bin 9016 -> 9021 bytes plugins/kicker/kicker.cpp | 18 +++++++++--------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/plugins/kicker/artwork.png b/plugins/kicker/artwork.png index 463ea0efe6deff2d9784f9a94ec2a1d3d5305318..59c0e19416b1dbc84eef7b6cd9a981c0350919be 100644 GIT binary patch literal 9021 zcmdtIWmr^Q7%n^rg0zSXh=hoONF$v}Nr!YxcXuNaQlcUv4Bd^iv`FXB9g;(jFw~G| z@xJf(=R1GSIls{uHv%lcfg`2jw?8S@@B&je+KgcUp{b?(somGv~cq@b}@%|dU~>1 zJJ`CK8atV@Il5TF_Jk=RkVg<%$ye%L$-DF3Ug}5lC;KO6TrZ|QEAHNk_;g$1*Inpm zDGYNQlA=s#2^sUk%#3bA!`Y!Ga=UdQHnVBVB}!{v7pp+!rHAU>kZ0ZZWF=*Oe-Vij zNql0K(vN!GEkl4S%g?y))Lgc`9IG(shkzN2x=t)2DZ&UTS6|+7)^OcKVu#$_ic81O zz`W;1=k_v~ErdvBD0Bz|xBjl+qgUkOI8QdjH-fMX?ofaFzy743$DWwt`ilCBrIMWl zbPRM!pI&8np}m&(HkAzQsd;L2BM*wrvdzE5e^zu=b4@!kr{J~vlm$0b{7|H=Zui7> zFEu7M4Q`%LtuZrowNEsdV_C3B0o+phecHrgCKx7@{C#Q#k^3a?hb798@*$D2|MwwQEn(%6@CP+tbQV=hI`yY2@6E0fy^#-_3I9_2aou ze8w{PV3<_%CzqMX`(evVqg>XXvY&Mm9={^bB+oRV_pMf5h;NUGknE6tu3H%cPNs3; zspCTIO&5-(x}MnSEB2-xeM`q5miWvmQSXjd!smD4_aXX0rk4SToXGvSyCrpJz&4*} zW-9sXTk=Dp8+7cn$^+vGH`nZ??j;qmgGYsL*=%!b83nUR5|2;W@ces3wx;vnk$JYc zO=XQ zPG3%2u9}$-kBp2g?z%-meW6>{c2;JHdV}mdiwir;ce^L)wM-Sd<<@pDw4+4ukCNr# z%PDJt*E)mSSCzQ+P|U23)X@4QSdxJMGC`hl@+MMqX7eO#PyEi2EGVCM0n=`=A7j?` z&iAq^GK1?;i1Vyano(d`)n)=u{j^Ez=xE%JzfK>i1x9FD55EHgG8J3qzx2H2__Mqm zJnw*vO+b>d9ETql-D2Yda&mI$ygNCGM3{<(PET0iWmIouq(>k7&r1)b6#iG81!|Ee%z2X`8=>e0oU=ePdH{IJyS@g>2wt4#K zS$^9J8yj2k^{MH{yljrm&WB{kQM6#826XxPw*;8HpZG25ERvwllLlR^uIp~~7n{)p z($Q47FW;)%#dm0-4$94Ch%DA5+L?WA^5!0Jdf_4SIjE1{=o#JSvjce=?+a&2N=hpS z8S;cdgapD-`)x!g2n{Qtx5J(RaH%nE(6!pO*F z--#6#OVJth>80PLe}3T))i>&$JxJwB%Sk?}nKW?;2~(q*2`1KKJ6_lW5w?hkIL3RV zq>6un9{KtC|InCz#?17To<45%vWM#Y_*qPhSZrz;w6qkoV(EJ+9MMC6?>723IiuY2 znrl9871|V|rOa|u7??$(*4LXG>|N4gUZ-(*bF-Iv1rNQ$WNRp{P7gt(`NcRM({8^X z6wK>Ljq7CCA9GbErE)=|`y-vHDG%?xAH8XU$o4Gpf?5VqUu8^x}=JJa)RDdw?krdOG_MFRG| z5yEuP6LMRFC-!hH{J4((!`pnH`8mtG;EJ+J#wY7d+y#w1`8Gr0jFPAsq3iI!ABGGk zyW!Ob?QPcyan^}=9uoqr$5hnhZBgt^GFIA1-x{c{_ti9_M>sy?t)*7W&<7Q$$d9{= zkVV7E{O4sRZ8)$W>$+q+#UkUudrO;xEn-IAQtzze(rnj`^}ZD}e;YG_@6qfvo(!LB z-9O-+5N9U7I+(1mKr#U1B;Xfkk>U%vg^iId*DWU+dX+^UW0$dTR*fedkR_6go1Yyy zwiOBWH9X$nk`gDnO9}0*c%8uXMxHpA9n3eMFi){hx%^udBgg9RYXplLA8Z)zE_$qe ze2V(c;a!!d~8ZjRx&NUpRUJZ zVW__!GGdP5<=jE4&0^89ZBuSpIo+=Y7b)>F2+B+KrL5FJ|C<#32EuyrGp^+D&T$QN z%o;-hwZVs zKWm?YnrBD4w13C@0INW}iQs!VeYZ+Xn~8UoRU1p8zM{vws-O(W%J558#$x@MO~-`d z;!{Hvb5;av@L=ljitO?wQ*q?TVR4;DE0^f zq3i9AZul=JL7^3g_8!`?R#hC7#7B;eyq|}iywNbsktr!Wc<$l2P$W|#uWBAcG&DBW zU+$>v)b@4w^wj4D1K6>KdT-HeV%ZW1OMEW|wjC1ozxSP2cc-qg zDtcG1W@Tk}zG&c-^&v0HDDbQ@q>pfFgUpk-*3iB)4`9Hn%b3D2Dl_O5n{~Nm z;_aI24Ik)Kl(q9mH!yFb>Q89r;oEE>8)7c<4F7*%oh~=j)YSCg?%dVk;26x&VxrL- z3+vcHH^-Tjfx~t|7@Lr$STZW*;NZBkt1E9_j67klMKRUTus?|}HqjMPIAzYv?&vr- zKMR+3xs*&CQ&rsC+oK=|^N98K@;O%Ho6p<88excwI8R_R_wo~FlcvAz?cIo;u^k&9 z=d|x6Xl!iiQBclnEJl!WMyK(Awhbf70WhU8nd<4R10qrE`T;xg*wy25EtLEj+txzI z6Y%W8Pk}Y|u;oh(3IgnJ!l#e0e+|s16!ywZl4OpE??eh z#2|^EF~0F!2<}f`ufJ=EH0Eg^99~$=dM-n{d(|5~W#5+5V3;Mm(~hg$bX)Vl)fMBr zu={g*>5thQVn*Z5kg%>UHC_Gw;{h1PcV1I$%(gbBjrWsK4)YoAkJO?HqoMGwwW_Jz zo#|@%wbJ@rtD*3YDnl-x$2{>d+Y_7?7hYdZc1?#3JdL>$gC>Zry>%V{C?$Njku`{5 zV0cFiv1e4D?8d)DokuHJltMOxpJnhhIsd$RQD`JBLG zY+?pB(Nuu6u&{6M@3y}8tF|PDw9?VB7*=2f&F$FnmKeph(Ix0ysDt<@)bC3-Uo1xv zwZJ&6?~yVncXqsed;X2};?uXV9y62uFHehouKgkFEZQ$+v?)rZ>CcaM=vKy<02*i3oFjY`|ky!XVC-E>u)Ul&pXsMZ^3cLde6Zxds|kU8K3+ zF_@B_CMTtXi=vPf0@y zpV}_7v~t_NSpWD93L&E5|0U1f7}U1(NcizBVq)S_YR+3hZ8*dg<}1?UzVeE)z_IUe z;~17qxD8zr(=jkVQ1V9CUY%))p8dhJ=ugCasi;U;+n+k{E#{&3c3GhLs{7>9(h|n6 zVl+zUdcUi2f2-&xMa*D}K~+MdBduv^OLN;kNoB|HpSYyj=(Fv{^W#~ChBYXJfQ{`G z2MbcdED_c58wc6g79MylB-&iUXH9jVw3pBN${|9-?Yoh&MLjzrsFNgTdqV73WEEqYpTEs0|RQt zkr9e}WTCBZe+>-81Yh`35#batF-hk8{ZT7QN=ll#UQ19&;mn#}`K+p%EbJVNs;*Yo zR9Df|omu+h3KG7}#PkNQ10ej7N)W3m00SVi@6d*nkuUcMMED_d)R7MLLR3UG4l|M# zK7vsREUoaxG??Y!DlO83DuLQ_x0>ZL_WG9<_ZvMm%qp6xpW6Ng*YkPjQ%h~?UlWWx zP(4=M%K^qQQwfu7e7xL0yxXvE9q*b>I|la6mbEBJdDo#%-h&!g>n1_K*UZgB2&rU1 zz{khM2Dx-Kb>+Myv7|Ja=`u1{y#Ky}=*M)5qQ%Dx9b3?0V!|kb#hpc@AB#!%Cl4HZ zd3iaC`y{Oeaf~Uk@d@$!JzL{*XHiB&CbgCRC<_4dA3vtAV-QT*=bM8B<>fIhEG+C^ zm6e8MzT(qk>HjVQn@gth*qv%k0j;q86Wy;^x*ysskU3#nsC3q6#qCK`)@N_0kpYwD z_P(>Ic^|R8TE^yumX>)@A4^?b-R`~~I-3oZFzMGPJ*_{ZfC1&UT|}kwayFiGnfX6H z{Yrl{m?D4~)Y2l>AtmMI=AmY?jsuSr#C*{GD^K+8r<*&pB7PxovHz!{7y4p=D!0 zqmMpTY>?Tpu@!8?#tF-L6_pi`pDTL}=-9<;!=r`uIUnZows4_9B3!~|)o+iy}w&(RFqFR79GAry0vlM)sn!H3Q!B?SNjoR8*o@ zD&ZzviBql-FC@I{>OjK}SzosRt@?&#c6Le+rik=qKXhF6R2G#54hFeiw()>iBdj2a z6&lUPmT>V22Mha+edX}jSO{>BMdfr|?k16um>8IwLBCL`SYx)}p!kbAajZ=%=8fwK zY03$OHZ+Zzvp6_#^Y98z3Szu_H|K#!xk)JyI(IK5AvUH(RA?B@McRjB@KZb*sC~(= z*}+%2ot;F+H9zZyr-sr`trevvH|*>2mO8XLs;jCFpRGbP;^Uk4%>+_r;b zN^kiVoGdIk$#j>gcru_iSmx8Sd%IIo`U( zjjNg-Q`6T6J57Cej*07cDmut=8moMshL4V?S(P*E?g&`h-BT7h;clfffJb7g=&ScL z_Zh8kEM@r*O^>s4@qVd`vRqj~x=x$hlkwJ+%)ip~`F0jFjPuH~_UHc8Z=(vQk?215 z3sM--&hmgFt?J}Z?MfEUbY-|uAB{ohg%rNe#Tj!6r65~+_^bQPI9~uB_e4oy zXWv!ri`rC^H@hO?mV-_K<>Ax^TkWeqq#?Hr19nFee^;2K`XYHoT;b2BbP!cju5S7S z?9GRdGmJBuN{v~o4lXL;ao*2Y4)F2w{y(-FB(MB#f?8uu!|wDg>4bh!a7uOFOe?=< z)GQee_9GUK?`y=O?;4~or;TomJSPjMdc@80mE6dO#FO}>kDVoGf(IQRM)iyDSArBV zOS>5-^O(--!rPbSp)HNezp8NY3D&`(dbXxk)f5U4R0HSk*^sc%ik)He8(Of5?@+(| zsdk_6ulZRp?0$heQz4eW-A?xnS2bVCeh?i)U0^j3WnGTQE|2@>e4Xn{veP%9npM z*kFm^2O>%nTPYFIF*_4XRSSRjPgKoIO1*~io<#r0?@;YMq-15&2}ji|g2vzfA%EXL zJj;B{$&H?7{b)v@yW@XyerMaVxxQ6e}*DwbMVWm~q1wPm$8V{RZ({~J3$ zEv$^4(mJZ{A5fdOB^=8K?6=6q_Upe4*RH67$*__g+||FNJ^`;t)o4FGL9@X3nv-YC zwj5FM<;}l*v#7LiLLacr)X%<3|BzTS_=CiMIjqG1d;NvDSmh0kEvllIOHgkDv|4E) zt=MazxwyT`y#pW+IDO(4@AM)eVdLVy>+g?vs7*}TU)Y?t4ycl$o z(DZ>a^)N+FD99?Q+IKz}4=ZS{+oZ?q`#N34!os``3XJJZ5vW@4H9h8X=<^rG@2ZD- zduzw0E9xkB7a9`)8I`iph}SCjMHx!j7({aZ>O$P+!Q-2S2?VU)Us;x3-d&pB7PPOd z*6x$Pzq2>OJq?8Mg04{tp#T=cg{BscJo~W3OmX+vXGV&;J033Zb!SEW`wn|eX=d5> zVGm&9MwAJex$B0cr>jjWrbSB)?+bqV{v_e$FYbaX1F`Dz{GkS+KsU<|gAo%r7rx!~ z@Da-o^3heQP2C-xb$29RecGhKo#DXMZwmj@0?$!H!5RA8_3FYKta6M66gZ&%9uNrO27w)P04hYzzaCPMZsGC+? z1Wo|z;nw!n-@}8)?0g9&5BWUM$?cq`-F*W&*)mP|eERzO+GpMLjm;*ZHf1DK_kt5@ z`7D)diTJ1}Xg-FAhZnwTK`r=lCMt0AR;MmkLht{uJ@*(lRIZAQh%#OH9s2b?`O4bv zz|wmhf$wvI?Vi80Wx-@FS6zbo?2vVjw1?k4vR=^LvP6}2gHItz(nbz1y!nbU=mtw? z3=b#w?D&blM}DN~SQ@&TZvOM>t~d^n8+KFK#ktXSW~To9w2S2HMQV}WQfeV5XXm9! zVljmP2R0x>13A8V2jOjI@)%6JGlXZK@}Keg9YmlI%GZ~UJ03zq^@-kyrjzBRO<8Ma z&WECCEI^CC7O3^~4Xi0xFq~X%Y283+03?IL!*PnlF7DbIXXx%OFE9W8EwuN@ z6I-p4%&P1Vz-(02)Y?vQNx?+S2vDvE(uR7Cms>Dt7Fi#KLcm>jx=DnEh4}+^DEQz> zp|A!aiO2NljrYWmzX!+blYQTo0y8>O;bL05j&)PO2qt!BQ{br6Gqm&R5FOyB14pEc z0DMc#?5{u+QU&9`WIk59{40@m=+0wfZN2o?g=gTqIe@H4I*3uU5i0PSlA$L#yhcRG4nR1%hy5>fcLFpVDAa4dFNtz!F_82UP${8yb4) zphQGMLIO}N0C_hcGAW7w^S6mLiQ zZIbMUH8nL8XsOKXL)w5}9!tOA9k1tR7hWT5eQStX2NaYoH+~p{rJnWku`B9m*J@A^ zK*}m^TS+U{X#=T^zI*}yJ8*S5KNG0+#b!1Z&_NI~;JeSTl!0G=o$y>-F@6SazPW1h zU0Agm_aDnhPguK)<;>V{ZSUwv$5P{0 zIrPQ?asbF70*PX`tM7`X!X>v~KS>zf+-%45ss`^1+$z0!7l82zq$Cd;*?6+Rmf&b@ zol#!?`7{LU;^I=4f~ObVFq1^t*f`!~AA9eHWZ>erS#j6QF5hih0ZK}UY#e_|>cXBg zkS$_Hb1_OL`I2Si>8*Z2(%tckidbKD_^1{A%_wWJ01A)r#q8oTxag!SR*28KS->d> zhbDj`u169y0D_iw(fXv{zuUZbA{dj!0_y`rHW`(2|gF4`4#84N|6@mP;xOM>2=5bMcVQ+7< z6|#^gU|BMAWf`nO?kqMWJhnYAXachhM}7Ul2JO|$>VYsA?BPvQv=ZU*oTc_u(bMY# za?6VFiyZFp@PecP3qYP`cPlYVUZ+qKjbHs(aB+3bYHn`U>!SoU7cc=bp`fsM)vGs_ z6g!FaTiQ6;yUf4`1lavhd_pm_-;oqly=9`Qyu4hZJL3p43uj$@St~(QqLtOr-m!#0 z!t;l-WW~HI=8;cVmrVd80jD`uJR()r#{k-^#X!nUUG^CHk0Z2x;|?4Av;G!VfcO8x hdldgmFMwPG@;za3=+CUg2dN8@l~R%{6@MH2KLBxa?8X29 literal 9016 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 B`D6e9 diff --git a/plugins/kicker/kicker.cpp b/plugins/kicker/kicker.cpp index 655d41dd1..5bbd35a10 100644 --- a/plugins/kicker/kicker.cpp +++ b/plugins/kicker/kicker.cpp @@ -236,17 +236,17 @@ kickerInstrumentView::kickerInstrumentView( Instrument * _instrument, m_envKnob->setHintText( tr( "Env:" ) + " ", "" ); m_envKnob->move( 105, 155 ); - m_noiseKnob = new kickerKnob( this ); - m_noiseKnob->setHintText( tr( "Noise:" ) + " ", "" ); - m_noiseKnob->move( 200, 45 ); - - m_distKnob = new kickerKnob( this ); - m_distKnob->setHintText( tr( "Distortion:" ) + " ", "" ); - m_distKnob->move( 200, 100 ); - m_clickKnob = new kickerKnob( this ); m_clickKnob->setHintText( tr( "Click:" ) + " ", "" ); - m_clickKnob->move( 200, 155 ); + m_clickKnob->move( 200, 45 ); + + m_noiseKnob = new kickerKnob( this ); + m_noiseKnob->setHintText( tr( "Noise:" ) + " ", "" ); + m_noiseKnob->move( 200, 100 ); + + m_distKnob = new kickerKnob( this ); + m_distKnob->setHintText( tr( "Dist:" ) + " ", "" ); + m_distKnob->move( 200, 155 ); m_startNoteToggle = new ledCheckBox( "", this ); m_startNoteToggle->move( 24, 79 ); From 78bcb8423f535956d5c6b067658b52cba91f168c Mon Sep 17 00:00:00 2001 From: Vesa Date: Sat, 29 Mar 2014 23:01:44 +0200 Subject: [PATCH 112/647] New instrument... Codename: Monstro. May be subject to a rename later. --- data/themes/default/style.css | 10 + plugins/CMakeLists.txt | 1 + plugins/monstro/CMakeLists.txt | 3 + plugins/monstro/Monstro.cpp | 1594 ++++++++++++++++++++++++++ plugins/monstro/Monstro.h | 593 ++++++++++ plugins/monstro/am_active.png | Bin 0 -> 730 bytes plugins/monstro/am_inactive.png | Bin 0 -> 525 bytes plugins/monstro/artwork_mat.png | Bin 0 -> 61598 bytes plugins/monstro/artwork_op.png | Bin 0 -> 58075 bytes plugins/monstro/exp.png | Bin 0 -> 367 bytes plugins/monstro/fm_active.png | Bin 0 -> 678 bytes plugins/monstro/fm_inactive.png | Bin 0 -> 484 bytes plugins/monstro/logo.png | Bin 0 -> 3335 bytes plugins/monstro/matview_active.png | Bin 0 -> 1992 bytes plugins/monstro/matview_inactive.png | Bin 0 -> 1501 bytes plugins/monstro/mix_active.png | Bin 0 -> 776 bytes plugins/monstro/mix_inactive.png | Bin 0 -> 510 bytes plugins/monstro/moog.png | Bin 0 -> 402 bytes plugins/monstro/noise.png | Bin 0 -> 478 bytes plugins/monstro/opview_active.png | Bin 0 -> 2129 bytes plugins/monstro/opview_inactive.png | Bin 0 -> 1519 bytes plugins/monstro/pm_active.png | Bin 0 -> 724 bytes plugins/monstro/pm_inactive.png | Bin 0 -> 481 bytes plugins/monstro/ramp.png | Bin 0 -> 333 bytes plugins/monstro/saw.png | Bin 0 -> 365 bytes plugins/monstro/sin.png | Bin 0 -> 398 bytes plugins/monstro/sqr.png | Bin 0 -> 342 bytes plugins/monstro/tri.png | Bin 0 -> 380 bytes 28 files changed, 2201 insertions(+) create mode 100644 plugins/monstro/CMakeLists.txt create mode 100644 plugins/monstro/Monstro.cpp create mode 100644 plugins/monstro/Monstro.h create mode 100644 plugins/monstro/am_active.png create mode 100644 plugins/monstro/am_inactive.png create mode 100644 plugins/monstro/artwork_mat.png create mode 100644 plugins/monstro/artwork_op.png create mode 100644 plugins/monstro/exp.png create mode 100644 plugins/monstro/fm_active.png create mode 100644 plugins/monstro/fm_inactive.png create mode 100644 plugins/monstro/logo.png create mode 100644 plugins/monstro/matview_active.png create mode 100644 plugins/monstro/matview_inactive.png create mode 100644 plugins/monstro/mix_active.png create mode 100644 plugins/monstro/mix_inactive.png create mode 100644 plugins/monstro/moog.png create mode 100644 plugins/monstro/noise.png create mode 100644 plugins/monstro/opview_active.png create mode 100644 plugins/monstro/opview_inactive.png create mode 100644 plugins/monstro/pm_active.png create mode 100644 plugins/monstro/pm_inactive.png create mode 100644 plugins/monstro/ramp.png create mode 100644 plugins/monstro/saw.png create mode 100644 plugins/monstro/sin.png create mode 100644 plugins/monstro/sqr.png create mode 100644 plugins/monstro/tri.png diff --git a/data/themes/default/style.css b/data/themes/default/style.css index b68ef0658..bab240bf3 100644 --- a/data/themes/default/style.css +++ b/data/themes/default/style.css @@ -644,6 +644,16 @@ WatsynView knob#xtalkKnob { qproperty-outerColor: #fb50fb; } +MonstroView knob { + color: #ffffff; + qproperty-outerColor: #aaaaaa; + qproperty-outerRadius: 9; + qproperty-innerRadius: 6; + qproperty-centerPointX: 10; + qproperty-centerPointY: 10; + qproperty-lineWidth: 2.5; +} + /* palette information - each colour definition must be on a single line, and the line must begin with "palette:", with no leading whitespace * colour codes MUST be of the form #RRGGBB */ diff --git a/plugins/CMakeLists.txt b/plugins/CMakeLists.txt index b1247ce18..c5bf9175f 100644 --- a/plugins/CMakeLists.txt +++ b/plugins/CMakeLists.txt @@ -12,6 +12,7 @@ ADD_SUBDIRECTORY(LadspaEffect) ADD_SUBDIRECTORY(lb302) #ADD_SUBDIRECTORY(lb303) ADD_SUBDIRECTORY(midi_import) +ADD_SUBDIRECTORY(monstro) ADD_SUBDIRECTORY(organic) ADD_SUBDIRECTORY(opl2) ADD_SUBDIRECTORY(papu) diff --git a/plugins/monstro/CMakeLists.txt b/plugins/monstro/CMakeLists.txt new file mode 100644 index 000000000..6a9195b75 --- /dev/null +++ b/plugins/monstro/CMakeLists.txt @@ -0,0 +1,3 @@ +INCLUDE(BuildPlugin) + +BUILD_PLUGIN(monstro Monstro.cpp Monstro.h MOCFILES Monstro.h EMBEDDED_RESOURCES "${CMAKE_CURRENT_SOURCE_DIR}/*.png") diff --git a/plugins/monstro/Monstro.cpp b/plugins/monstro/Monstro.cpp new file mode 100644 index 000000000..e3b843891 --- /dev/null +++ b/plugins/monstro/Monstro.cpp @@ -0,0 +1,1594 @@ +/* + * Monstro.cpp - a monstrous semi-modular 3-osc synth with modulation matrix + * + * Copyright (c) 2014 Vesa Kivimäki + * + * This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net + * + * 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 "Monstro.h" +#include "engine.h" +#include "InstrumentTrack.h" +#include "templates.h" +#include "gui_templates.h" +#include "tooltip.h" +#include "song.h" +#include "lmms_math.h" + +#include "embed.cpp" + + +extern "C" +{ + +Plugin::Descriptor PLUGIN_EXPORT monstro_plugin_descriptor = +{ + STRINGIFY( PLUGIN_NAME ), + "Monstro", + QT_TRANSLATE_NOOP( "pluginBrowser", + "Monstrous 3-oscillator synth with modulation matrix" ), + "Vesa Kivimäki ", + 0x0100, + Plugin::Instrument, + new PluginPixmapLoader( "logo" ), + NULL, + NULL +} ; + +} + + + + +MonstroSynth::MonstroSynth( MonstroInstrument * _i, NotePlayHandle * _nph, + const sample_rate_t _samplerate, fpp_t _frames ) : + m_parent( _i ), + m_nph( _nph ), + m_samplerate( _samplerate ), + m_fpp( _frames ) +{ + m_env1_buf = new sample_t[_frames]; + m_env2_buf = new sample_t[_frames]; + m_lfo1_buf = new sample_t[_frames]; + m_lfo2_buf = new sample_t[_frames]; + + m_osc1l_phase = 0.0; + m_osc1r_phase = 0.0; + m_osc2l_phase = 0.0; + m_osc2r_phase = 0.0; + m_osc3l_phase = 0.0; + m_osc3r_phase = 0.0; + + m_env1_phase = 0.0; + m_env2_phase = 0.0; +} + + +MonstroSynth::~MonstroSynth() +{ + delete[] m_env1_buf; + delete[] m_env2_buf; + delete[] m_lfo1_buf; + delete[] m_lfo2_buf; + +} + + +void MonstroSynth::renderOutput( fpp_t _frames, sampleFrame * _buf ) +{ +// macros for modulating with env/lfos +#define modulatefreq( car, mod, min, max ) \ + if( mod##_e1 != 0.0 ) car = qBound( min, car * static_cast( fastPow( 2, m_env1_buf[f] * mod##_e1 ) ), max ); \ + if( mod##_e2 != 0.0 ) car = qBound( min, car * static_cast( fastPow( 2, m_env2_buf[f] * mod##_e2 ) ), max ); \ + if( mod##_l1 != 0.0 ) car = qBound( min, car * static_cast( fastPow( 2, m_lfo1_buf[f] * mod##_l1 ) ), max ); \ + if( mod##_l2 != 0.0 ) car = qBound( min, car * static_cast( fastPow( 2, m_lfo2_buf[f] * mod##_l2 ) ), max ); + +#define modulateabs( car, mod, min, max ) \ + if( mod##_e1 != 0.0 ) car = qBound( min, car + mod##_e1 / 2 * m_env1_buf[f], max ); \ + if( mod##_e2 != 0.0 ) car = qBound( min, car + mod##_e2 / 2 * m_env2_buf[f], max ); \ + if( mod##_l1 != 0.0 ) car = qBound( min, car + mod##_l1 / 2 * m_lfo1_buf[f], max ); \ + if( mod##_l2 != 0.0 ) car = qBound( min, car + mod##_l2 / 2 * m_lfo2_buf[f], max ); + +#define modulatevol( car, mod ) \ + if( mod##_e1 > 0.0 ) car = qBound( 0.0f, car * ( 1.0f - mod##_e1 + mod##_e1 * m_env1_buf[f] ), MODCLIP ); \ + if( mod##_e1 < 0.0 ) car = qBound( 0.0f, car * ( 0.0f - mod##_e1 + mod##_e1 * m_env1_buf[f] ), MODCLIP ); \ + if( mod##_e2 > 0.0 ) car = qBound( 0.0f, car * ( 1.0f - mod##_e2 + mod##_e2 * m_env2_buf[f] ), MODCLIP ); \ + if( mod##_e2 < 0.0 ) car = qBound( 0.0f, car * ( 0.0f - mod##_e2 + mod##_e2 * m_env2_buf[f] ), MODCLIP ); \ + if( mod##_l1 != 0.0 ) car = qBound( 0.0f, car * ( 1.0f + mod##_l1 * m_lfo1_buf[f] ), MODCLIP ); \ + if( mod##_l2 != 0.0 ) car = qBound( 0.0f, car * ( 1.0f + mod##_l2 * m_lfo2_buf[f] ), MODCLIP ); + + // pre-render env's and lfo's + renderModulators( _frames ); + + // get updated osc1 values + // get pulse width + const float pw = ( m_parent->m_osc1Pw.value() / 100.0 ); + const float o1pw_e1 = ( m_parent->m_pw1env1.value() ); + const float o1pw_e2 = ( m_parent->m_pw1env2.value() ); + const float o1pw_l1 = ( m_parent->m_pw1lfo1.value() ); + const float o1pw_l2 = ( m_parent->m_pw1lfo2.value() ); + + // get phases + const float o1lpo = m_parent->m_osc1l_po; + const float o1rpo = m_parent->m_osc1r_po; + const float o1p_e1 = ( m_parent->m_phs1env1.value() ); + const float o1p_e2 = ( m_parent->m_phs1env2.value() ); + const float o1p_l1 = ( m_parent->m_phs1lfo1.value() ); + const float o1p_l2 = ( m_parent->m_phs1lfo2.value() ); + + // get pitch + const float o1lfb = ( m_parent->m_osc1l_freq * m_nph->frequency() ); + const float o1rfb = ( m_parent->m_osc1r_freq * m_nph->frequency() ); + const float o1f_e1 = ( m_parent->m_pit1env1.value() ); + const float o1f_e2 = ( m_parent->m_pit1env2.value() ); + const float o1f_l1 = ( m_parent->m_pit1lfo1.value() ); + const float o1f_l2 = ( m_parent->m_pit1lfo2.value() ); + + // get volumes + const float o1lv = m_parent->m_osc1l_vol; + const float o1rv = m_parent->m_osc1r_vol; + const float o1v_e1 = ( m_parent->m_vol1env1.value() ); + const float o1v_e2 = ( m_parent->m_vol1env2.value() ); + const float o1v_l1 = ( m_parent->m_vol1lfo1.value() ); + const float o1v_l2 = ( m_parent->m_vol1lfo2.value() ); + + + // update osc2 + // get waveform + const int o2w = m_parent->m_osc2Wave.value(); + + // get phases + const float o2lpo = m_parent->m_osc2l_po; + const float o2rpo = m_parent->m_osc2r_po; + const float o2p_e1 = ( m_parent->m_phs2env1.value() ); + const float o2p_e2 = ( m_parent->m_phs2env2.value() ); + const float o2p_l1 = ( m_parent->m_phs2lfo1.value() ); + const float o2p_l2 = ( m_parent->m_phs2lfo2.value() ); + + // get pitch + const float o2lfb = ( m_parent->m_osc2l_freq * m_nph->frequency() ); + const float o2rfb = ( m_parent->m_osc2r_freq * m_nph->frequency() ); + const float o2f_e1 = ( m_parent->m_pit2env1.value() ); + const float o2f_e2 = ( m_parent->m_pit2env2.value() ); + const float o2f_l1 = ( m_parent->m_pit2lfo2.value() ); + const float o2f_l2 = ( m_parent->m_pit2lfo2.value() ); + + // get volumes + const float o2lv = m_parent->m_osc2l_vol; + const float o2rv = m_parent->m_osc2r_vol; + const float o2v_e1 = ( m_parent->m_vol2env1.value() ); + const float o2v_e2 = ( m_parent->m_vol2env2.value() ); + const float o2v_l1 = ( m_parent->m_vol2lfo2.value() ); + const float o2v_l2 = ( m_parent->m_vol2lfo2.value() ); + + + + // update osc3 + // get waveforms + const int o3w1 = m_parent->m_osc3Wave1.value(); + const int o3w2 = m_parent->m_osc3Wave2.value(); + + // get phases + const float o3lpo = m_parent->m_osc3l_po; + const float o3rpo = m_parent->m_osc3r_po; + const float o3p_e1 = ( m_parent->m_phs3env1.value() ); + const float o3p_e2 = ( m_parent->m_phs3env2.value() ); + const float o3p_l1 = ( m_parent->m_phs3lfo1.value() ); + const float o3p_l2 = ( m_parent->m_phs3lfo2.value() ); + + // get pitch modulators + const float o3fb = ( m_parent->m_osc3_freq * m_nph->frequency() ); + const float o3f_e1 = ( m_parent->m_pit3env1.value() ); + const float o3f_e2 = ( m_parent->m_pit3env2.value() ); + const float o3f_l1 = ( m_parent->m_pit3lfo1.value() ); + const float o3f_l2 = ( m_parent->m_pit3lfo2.value() ); + + // get volumes + const float o3lv = m_parent->m_osc3l_vol; + const float o3rv = m_parent->m_osc3r_vol; + const float o3v_e1 = ( m_parent->m_vol3env1.value() ); + const float o3v_e2 = ( m_parent->m_vol3env2.value() ); + const float o3v_l1 = ( m_parent->m_vol3lfo1.value() ); + const float o3v_l2 = ( m_parent->m_vol3lfo2.value() ); + + // get sub + const float o3sub = ( m_parent->m_osc3Sub.value() + 100.0 ) / 200.0; + const float o3s_e1 = ( m_parent->m_sub3env1.value() ); + const float o3s_e2 = ( m_parent->m_sub3env2.value() ); + const float o3s_l1 = ( m_parent->m_sub3lfo1.value() ); + const float o3s_l2 = ( m_parent->m_sub3lfo2.value() ); + + + //o2-o3 modulation + + const int omod = m_parent->m_o23Mod.value(); + + /////////////////////////// + // // + // start buffer loop // + // // + /////////////////////////// + + + + for( f_cnt_t f = 0; f < _frames; f++ ) + { + +/* + // debug code + if( f % 10 == 0 ) { + qDebug( "env1 %f -- env1 phase %f", m_env1_buf[f], m_env1_phase ); + qDebug( "env1 pre %f att %f dec %f rel %f ", m_parent->m_env1_pre, m_parent->m_env1_att, + m_parent->m_env1_dec, m_parent->m_env1_rel ); + } +*/ + + ///////////////////////////// + // // + // OSC 1 // + // // + ///////////////////////////// + + // calc and mod frequencies + float o1l_f = o1lfb; + float o1r_f = o1rfb; + modulatefreq( o1l_f, o1f, 20.0f, 20000.0f ) + modulatefreq( o1r_f, o1f, 20.0f, 20000.0f ) + + // calc and modulate phase + float o1l_p = m_osc1l_phase + o1lpo; + float o1r_p = m_osc1r_phase + o1rpo; + modulateabs( o1l_p, o1p, 0.0f, 1.0f ) + modulateabs( o1r_p, o1p, 0.0f, 1.0f ) + + // calc and modulate pulse + float o1_pw = pw; + modulateabs( o1_pw, o1pw, -1.0f, 1.0f ) + + // pulse wave osc + sample_t O1L = ( o1l_p < o1_pw ) ? 1.0f : -1.0f; + sample_t O1R = ( o1r_p < o1_pw ) ? 1.0f : -1.0f; + + // modulate volume + O1L *= o1lv; + O1R *= o1rv; + modulatevol( O1L, o1v ) + modulatevol( O1R, o1v ) + + // update osc1 phases + m_osc1l_phase = fraction( m_osc1l_phase + ( 1.0 / ( static_cast( m_samplerate ) / o1l_f ) ) ); + m_osc1r_phase = fraction( m_osc1r_phase + ( 1.0 / ( static_cast( m_samplerate ) / o1r_f ) ) ); + + ///////////////////////////// + // // + // OSC 2 // + // // + ///////////////////////////// + + // calc and mod frequencies + float o2l_f = o2lfb; + float o2r_f = o2rfb; + modulatefreq( o2l_f, o2f, 20.0f, 20000.0f ) + modulatefreq( o2r_f, o2f, 20.0f, 20000.0f ) + + // calc and modulate phase + float o2l_p = m_osc2l_phase + o2lpo; + float o2r_p = m_osc2r_phase + o2rpo; + modulateabs( o2l_p, o2p, 0.0f, 1.0f ) + modulateabs( o2r_p, o2p, 0.0f, 1.0f ) + + // multi-wave DC Oscillator + sample_t O2L = oscillate( o2w, o2l_p ); + sample_t O2R = oscillate( o2w, o2r_p ); + + // modulate volume + O2L *= o2lv; + O2R *= o2rv; + modulatevol( O2L, o2v ) + modulatevol( O2R, o2v ) + + // update osc2 phases + m_osc2l_phase = fraction( m_osc2l_phase + ( 1.0 / ( static_cast( m_samplerate ) / o2l_f ) ) ); + m_osc2r_phase = fraction( m_osc2r_phase + ( 1.0 / ( static_cast( m_samplerate ) / o2r_f ) ) ); + + ///////////////////////////// + // // + // OSC 3 // + // // + ///////////////////////////// + + // calc and mod frequencies + float o3l_f = o3fb; + float o3r_f = o3fb; + modulatefreq( o3l_f, o3f, 20.0f, 20000.0f ) + modulatefreq( o3r_f, o3f, 20.0f, 20000.0f ) + // o2 modulation? + if( omod == MOD_FM ) + { + o3l_f = qBound( 20.0f, o3l_f * static_cast( fastPow( 2, O2L ) ), 20000.0f ); + o3r_f = qBound( 20.0f, o3r_f * static_cast( fastPow( 2, O2R ) ), 20000.0f ); + } + + // calc and modulate phase + float o3l_p = m_osc3l_phase + o3lpo; + float o3r_p = m_osc3r_phase + o3rpo; + modulateabs( o3l_p, o3p, 0.0f, 1.0f ) + modulateabs( o3r_p, o3p, 0.0f, 1.0f ) + // o2 modulation? + if( omod == MOD_PM ) + { + o3l_p = qBound( 0.0f, o3l_p + O2L/2, 1.0f ); + o3r_p = qBound( 0.0f, o3r_p + O2R/2, 1.0f ); + } + + // multi-wave DC Oscillator, sub-osc 1 + sample_t O3AL = oscillate( o3w1, o3l_p ); + sample_t O3AR = oscillate( o3w1, o3r_p ); + + // multi-wave DC Oscillator, sub-osc 2 + sample_t O3BL = oscillate( o3w2, o3l_p ); + sample_t O3BR = oscillate( o3w2, o3r_p ); + + // calc and modulate sub + float sub = o3sub; + modulateabs( sub, o3s, 0.0f, 1.0f ) + + sample_t O3L = interpolate( O3AL, O3BL, sub ); + sample_t O3R = interpolate( O3AR, O3BR, sub ); + + // modulate volume + O3L *= o3lv; + O3R *= o3rv; + modulatevol( O3L, o3v ) + modulatevol( O3R, o3v ) + // o2 modulation? + if( omod == MOD_AM ) + { + O3L = qBound( -MODCLIP, O3L * qMax( 0.0f, 1.0f + O2L ), MODCLIP ); + O3R = qBound( -MODCLIP, O3R * qMax( 0.0f, 1.0f + O2R ), MODCLIP ); + } + + // update osc3 phases + m_osc3l_phase = fraction( m_osc3l_phase + ( 1.0f / ( static_cast( m_samplerate ) / o3l_f ) ) ); + m_osc3r_phase = fraction( m_osc3r_phase + ( 1.0f / ( static_cast( m_samplerate ) / o3r_f ) ) ); + + _buf[f][0] = O1L + O3L + ( omod == MOD_MIX ? O2L : 0.0f ); + _buf[f][1] = O1R + O3R + ( omod == MOD_MIX ? O2R : 0.0f ); + } +} + + +void MonstroSynth::renderModulators( fpp_t _frames ) +{ + // LFO phase offsets + const float lfo1_p = m_parent->m_lfo1Phs.value() / 360.0f; + const float lfo2_p = m_parent->m_lfo2Phs.value() / 360.0f; + + // LFO rates + const float lfo1_r = m_parent->m_lfo1Rate.value() / 1000.0f * m_samplerate; + const float lfo2_r = m_parent->m_lfo2Rate.value() / 1000.0f * m_samplerate; + + // LFOs + + sample_t lfo1_s; + sample_t lfo2_s; + + // LFO 1 + + switch( m_parent->m_lfo1Wave.value() ) + { + case WAVE_SINE: + for( f_cnt_t f = 0; f < _frames; f++ ) + { + const f_cnt_t t = f + m_nph->totalFramesPlayed(); + lfo1_s = Oscillator::sinSample( lfo1_p + static_cast( t ) / lfo1_r ); + if( t < m_parent->m_lfo1_att ) lfo1_s *= ( static_cast( t ) / m_parent-> m_lfo1_att ); + m_lfo1_buf[f] = lfo1_s; + } + break; + case WAVE_TRI: + for( f_cnt_t f = 0; f < _frames; f++ ) + { + const f_cnt_t t = f + m_nph->totalFramesPlayed(); + lfo1_s = Oscillator::triangleSample( lfo1_p + static_cast( t ) / lfo1_r ); + if( t < m_parent->m_lfo1_att ) lfo1_s *= ( static_cast( t ) / m_parent->m_lfo1_att ); + m_lfo1_buf[f] = lfo1_s; + } + break; + case WAVE_SAW: + for( f_cnt_t f = 0; f < _frames; f++ ) + { + const f_cnt_t t = f + m_nph->totalFramesPlayed(); + lfo1_s = Oscillator::sawSample( lfo1_p + static_cast( t ) / lfo1_r ); + if( t < m_parent->m_lfo1_att ) lfo1_s *= ( static_cast( t ) / m_parent->m_lfo1_att ); + m_lfo1_buf[f] = lfo1_s; + } + break; + case WAVE_RAMP: + for( f_cnt_t f = 0; f < _frames; f++ ) + { + const f_cnt_t t = f + m_nph->totalFramesPlayed(); + lfo1_s = Oscillator::sawSample( lfo1_p + static_cast( t ) / lfo1_r ) * -1.0f; + if( t < m_parent->m_lfo1_att ) lfo1_s *= ( static_cast( t ) / m_parent->m_lfo1_att ); + m_lfo1_buf[f] = lfo1_s; + } + break; + case WAVE_SQR: + for( f_cnt_t f = 0; f < _frames; f++ ) + { + const f_cnt_t t = f + m_nph->totalFramesPlayed(); + lfo1_s = Oscillator::squareSample( lfo1_p + static_cast( t ) / lfo1_r ); + if( t < m_parent->m_lfo1_att ) lfo1_s *= ( static_cast( t ) / m_parent->m_lfo1_att ); + m_lfo1_buf[f] = lfo1_s; + } + break; + case WAVE_MOOG: + for( f_cnt_t f = 0; f < _frames; f++ ) + { + const f_cnt_t t = f + m_nph->totalFramesPlayed(); + lfo1_s = Oscillator::moogSawSample( lfo1_p + static_cast( t ) / lfo1_r ); + if( t < m_parent->m_lfo1_att ) lfo1_s *= ( static_cast( t ) / m_parent->m_lfo1_att ); + m_lfo1_buf[f] = lfo1_s; + } + break; + case WAVE_EXP: + for( f_cnt_t f = 0; f < _frames; f++ ) + { + const f_cnt_t t = f + m_nph->totalFramesPlayed(); + lfo1_s = Oscillator::expSample( lfo1_p + static_cast( t ) / lfo1_r ); + if( t < m_parent->m_lfo1_att ) lfo1_s *= ( static_cast( t ) / m_parent-> m_lfo1_att ); + m_lfo1_buf[f] = lfo1_s; + } + break; + case WAVE_NOISE: + default: + for( f_cnt_t f = 0; f < _frames; f++ ) + { + const f_cnt_t t = f + m_nph->totalFramesPlayed(); + if( t % static_cast( lfo1_r ) == 0 ) m_lfo1_last = Oscillator::noiseSample( 0.0f ); + lfo1_s = m_lfo1_last; + if( t < m_parent->m_lfo1_att ) lfo1_s *= ( static_cast( t ) / m_parent->m_lfo1_att ); + m_lfo1_buf[f] = lfo1_s; + } + break; + } + + // LFO 2 + + switch( m_parent->m_lfo2Wave.value() ) + { + case WAVE_SINE: + for( f_cnt_t f = 0; f < _frames; f++ ) + { + const f_cnt_t t = f + m_nph->totalFramesPlayed(); + lfo2_s = Oscillator::sinSample( lfo2_p + static_cast( t ) / lfo2_r ); + if( t < m_parent->m_lfo2_att ) lfo2_s *= ( static_cast( t ) / m_parent->m_lfo2_att ); + m_lfo2_buf[f] = lfo2_s; + } + break; + case WAVE_TRI: + for( f_cnt_t f = 0; f < _frames; f++ ) + { + const f_cnt_t t = f + m_nph->totalFramesPlayed(); + lfo2_s = Oscillator::triangleSample( lfo2_p + static_cast( t ) / lfo2_r ); + if( t < m_parent->m_lfo2_att ) lfo2_s *= ( static_cast( t ) / m_parent->m_lfo2_att ); + m_lfo2_buf[f] = lfo2_s; + } + break; + case WAVE_SAW: + for( f_cnt_t f = 0; f < _frames; f++ ) + { + const f_cnt_t t = f + m_nph->totalFramesPlayed(); + lfo2_s = Oscillator::sawSample( lfo2_p + static_cast( t ) / lfo2_r ); + if( t < m_parent->m_lfo2_att ) lfo2_s *= ( static_cast( t ) / m_parent->m_lfo2_att ); + m_lfo2_buf[f] = lfo2_s; + } + break; + case WAVE_RAMP: + for( f_cnt_t f = 0; f < _frames; f++ ) + { + const f_cnt_t t = f + m_nph->totalFramesPlayed(); + lfo2_s = Oscillator::sawSample( lfo2_p + static_cast( t ) / lfo2_r ) * -1.0f; + if( t < m_parent->m_lfo2_att ) lfo2_s *= ( static_cast( t ) / m_parent->m_lfo2_att ); + m_lfo2_buf[f] = lfo2_s; + } + break; + case WAVE_SQR: + for( f_cnt_t f = 0; f < _frames; f++ ) + { + const f_cnt_t t = f + m_nph->totalFramesPlayed(); + lfo2_s = Oscillator::squareSample( lfo2_p + static_cast( t ) / lfo2_r ); + if( t < m_parent->m_lfo2_att ) lfo2_s *= ( static_cast( t ) / m_parent->m_lfo2_att ); + m_lfo2_buf[f] = lfo2_s; + } + break; + case WAVE_MOOG: + for( f_cnt_t f = 0; f < _frames; f++ ) + { + const f_cnt_t t = f + m_nph->totalFramesPlayed(); + lfo2_s = Oscillator::moogSawSample( lfo2_p + static_cast( t ) / lfo2_r ); + if( t < m_parent->m_lfo2_att ) lfo2_s *= ( static_cast( t ) / m_parent->m_lfo2_att ); + m_lfo2_buf[f] = lfo2_s; + } + break; + case WAVE_EXP: + for( f_cnt_t f = 0; f < _frames; f++ ) + { + const f_cnt_t t = f + m_nph->totalFramesPlayed(); + lfo2_s = Oscillator::expSample( lfo2_p + static_cast( t ) / lfo2_r ); + if( t < m_parent->m_lfo2_att ) lfo2_s *= ( static_cast( t ) / m_parent->m_lfo2_att ); + m_lfo2_buf[f] = lfo2_s; + } + break; + case WAVE_NOISE: + default: + for( f_cnt_t f = 0; f < _frames; f++ ) + { + const f_cnt_t t = f + m_nph->totalFramesPlayed(); + if( t % static_cast( lfo2_r ) == 0 ) m_lfo2_last = Oscillator::noiseSample( 0.0f ); + lfo2_s = m_lfo2_last; + if( t < m_parent->m_lfo2_att ) lfo2_s *= ( static_cast( t ) / m_parent->m_lfo2_att ); + m_lfo2_buf[f] = lfo2_s; + } + break; + } + + ///////////////////////////////////////////// + // + // + // envelopes + // + // + ///////////////////////////////////////////// + + const float env1_s = m_parent-> m_env1Slope.value(); + const float env2_s = m_parent-> m_env2Slope.value(); + + const float env1_sus = m_parent-> m_env1Sus.value(); + const float env2_sus = m_parent-> m_env2Sus.value(); + + for( f_cnt_t f = 0; f < _frames; f++ ) + { + // envelope 1 + + // adjust phase for release + if( m_nph->isReleased() && m_env1_phase < 4.0f ) + { + if( m_env1_phase < 1.0f ) m_env1_phase = 5.0f; + else if( m_env1_phase < 2.0f ) m_env1_phase = 5.0f - fraction( m_env1_phase ); + else if( m_env1_phase < 3.0f ) m_env1_phase = 4.0f; + else m_env1_phase = 4.0f + fraction( m_env1_phase ); + } + + // process envelope + if( m_env1_phase < 1.0f ) // pre-delay phase + { + m_env1_buf[f] = 0.0f; + m_env1_phase = qMin( 1.0f, m_env1_phase + m_parent->m_env1_pre ); + } + else if( m_env1_phase < 2.0f ) // attack phase + { + m_env1_buf[f] = calcSlope( fraction( m_env1_phase ), env1_s ); + m_env1_phase = qMin( 2.0f, m_env1_phase + m_parent->m_env1_att ); + } + else if( m_env1_phase < 3.0f ) // hold phase + { + m_env1_buf[f] = 1.0f; + m_env1_phase = qMin( 3.0f, m_env1_phase + m_parent->m_env1_hold ); + } + else if( m_env1_phase < 4.0f ) // decay phase + { + const sample_t s = 1.0f - fraction( m_env1_phase ); + if( s <= env1_sus ) + { + m_env1_buf[f] = env1_sus; + } + else + { + m_env1_buf[f] = calcSlope( s, env1_s ); + m_env1_phase = qMin( 4.0f - env1_sus, m_env1_phase + m_parent->m_env1_dec ); + } + } + else if( m_env1_phase < 5.0f ) // release phase + { + m_env1_buf[f] = calcSlope( 1.0f - fraction( m_env1_phase ), env1_s ); + m_env1_phase += m_parent->m_env1_rel; + } + else m_env1_buf[f] = 0.0f; + +// qDebug( "env1 %f", m_env1_buf[f] ); + + // envelope 2 + + + + // adjust phase for release + if( m_nph->isReleased() && m_env2_phase < 4.0f ) + { + if( m_env2_phase < 1.0f ) m_env2_phase = 5.0f; + else if( m_env2_phase < 2.0f ) m_env2_phase = 5.0f - fraction( m_env2_phase ); + else if( m_env2_phase < 3.0f ) m_env2_phase = 4.0f; + else m_env2_phase = 4.0f + fraction( m_env2_phase ); + } + + // process envelope + if( m_env2_phase < 1.0f ) // pre-delay phase + { + m_env2_buf[f] = 0.0f; + m_env2_phase = qMin( 1.0f, m_env2_phase + m_parent->m_env2_pre ); + } + else if( m_env2_phase < 2.0f ) // attack phase + { + m_env2_buf[f] = calcSlope( fraction( m_env2_phase ), env2_s ); + m_env2_phase = qMin( 2.0f, m_env2_phase + m_parent->m_env2_att ); + } + else if( m_env2_phase < 3.0f ) // hold phase + { + m_env2_buf[f] = 1.0f; + m_env2_phase = qMin( 3.0f, m_env2_phase + m_parent->m_env2_hold ); + } + else if( m_env2_phase < 4.0f ) // decay phase + { + const sample_t s = 1.0f - fraction( m_env2_phase ); + if( s <= env2_sus ) + { + m_env2_buf[f] = env2_sus; + } + else + { + m_env2_buf[f] = calcSlope( s, env2_s ); + m_env2_phase = qMin( 4.0f - env2_sus, m_env2_phase + m_parent->m_env2_dec ); + } + } + else if( m_env2_phase < 5.0f ) // release phase + { + m_env2_buf[f] = calcSlope( 1.0f - fraction( m_env2_phase), env2_s ); + m_env2_phase += m_parent->m_env2_rel; + } + else m_env2_buf[f] = 0.0f; + + } + +} + + + +MonstroInstrument::MonstroInstrument( InstrumentTrack * _instrument_track ) : + Instrument( _instrument_track, &monstro_plugin_descriptor ), + + m_osc1Vol( 33.0, 0.0, 200.0, 0.1, this, tr( "Osc 1 Volume" ) ), + m_osc1Pan( 0.0, -100.0, 100.0, 0.1, this, tr( "Osc 1 Panning" ) ), + m_osc1Crs( 0.0, -24.0, 24.0, 1.0, this, tr( "Osc 1 Coarse detune" ) ), + m_osc1Ftl( 0.0, -100.0, 100.0, 1.0, this, tr( "Osc 1 Fine detune left" ) ), + m_osc1Ftr( 0.0, -100.0, 100.0, 1.0, this, tr( "Osc 1 Fine detune right" ) ), + m_osc1Spo( 0.0, -180.0, 180.0, 0.1, this, tr( "Osc 1 Stereo phase offset" ) ), + m_osc1Pw( 50.0, 0.0, 100.0, 0.01, this, tr( "Osc 1 Pulse width" ) ), + + m_osc2Vol( 33.0, 0.0, 200.0, 0.1, this, tr( "Osc 2 Volume" ) ), + m_osc2Pan( 0.0, -100.0, 100.0, 0.1, this, tr( "Osc 2 Panning" ) ), + m_osc2Crs( 0.0, -24.0, 24.0, 1.0, this, tr( "Osc 2 Coarse detune" ) ), + m_osc2Ftl( 0.0, -100.0, 100.0, 1.0, this, tr( "Osc 2 Fine detune left" ) ), + m_osc2Ftr( 0.0, -100.0, 100.0, 1.0, this, tr( "Osc 2 Fine detune right" ) ), + m_osc2Spo( 0.0, -180.0, 180.0, 0.1, this, tr( "Osc 2 Stereo phase offset" ) ), + m_osc2Wave( this, tr( "Osc 2 Waveform" ) ), + + m_osc3Vol( 33.0, 0.0, 200.0, 0.1, this, tr( "Osc 3 Volume" ) ), + m_osc3Pan( 0.0, -100.0, 100.0, 0.1, this, tr( "Osc 3 Panning" ) ), + m_osc3Crs( 0.0, -24.0, 24.0, 1.0, this, tr( "Osc 3 Coarse detune" ) ), + m_osc3Spo( 0.0, -180.0, 180.0, 0.1, this, tr( "Osc 3 Stereo phase offset" ) ), + m_osc3Sub( 0.0, -100.0, 100.0, 0.1, this, tr( "Osc 3 Sub-oscillator mix" ) ), + m_osc3Wave1( this, tr( "Osc 3 Waveform 1" ) ), + m_osc3Wave2( this, tr( "Osc 3 Waveform 2" ) ), + + m_lfo1Wave( this, tr( "LFO 1 Waveform" ) ), + m_lfo1Att( 0.0f, 0.0f, 2000.0f, 1.0f, 2000.0f, this, tr( "LFO 1 Attack" ) ), + m_lfo1Rate( 1.0f, 0.1, 20000.0, 0.1, 20000.0f, this, tr( "LFO 1 Rate" ) ), + m_lfo1Phs( 0.0, -180.0, 180.0, 0.1, this, tr( "LFO 1 Phase" ) ), + + m_lfo2Wave( this, tr( "LFO 2 Waveform" ) ), + m_lfo2Att( 0.0f, 0.0f, 2000.0f, 1.0f, 2000.0f, this, tr( "LFO 2 Attack" ) ), + m_lfo2Rate( 1.0f, 0.1, 20000.0, 0.1, 20000.0f, this, tr( "LFO 2 Rate" ) ), + m_lfo2Phs( 0.0, -180.0, 180.0, 0.1, this, tr( "LFO 2 Phase" ) ), + + m_env1Pre( 0.0f, 0.0f, 2000.0f, 1.0f, 2000.0f, this, tr( "Env 1 Pre-delay" ) ), + m_env1Att( 0.0f, 0.0f, 2000.0f, 1.0f, 2000.0f, this, tr( "Env 1 Attack" ) ), + m_env1Hold( 0.0f, 0.0f, 2000.0f, 1.0f, 2000.0f, this, tr( "Env 1 Hold" ) ), + m_env1Dec( 0.0f, 0.0f, 2000.0f, 1.0f, 2000.0f, this, tr( "Env 1 Decay" ) ), + m_env1Sus( 1.0f, 0.0f, 1.0f, 0.001f, this, tr( "Env 1 Sustain" ) ), + m_env1Rel( 0.0f, 0.0f, 2000.0f, 1.0f, 2000.0f, this, tr( "Env 1 Release" ) ), + m_env1Slope( 0.0f, -1.0f, 1.0f, 0.001f, this, tr( "Env 1 Slope" ) ), + + m_env2Pre( 0.0f, 0.0f, 2000.0f, 1.0f, 2000.0f, this, tr( "Env 2 Pre-delay" ) ), + m_env2Att( 0.0f, 0.0f, 2000.0f, 1.0f, 2000.0f, this, tr( "Env 2 Attack" ) ), + m_env2Hold( 0.0f, 0.0f, 2000.0f, 1.0f, 2000.0f, this, tr( "Env 2 Hold" ) ), + m_env2Dec( 0.0f, 0.0f, 2000.0f, 1.0f, 2000.0f, this, tr( "Env 2 Decay" ) ), + m_env2Sus( 1.0f, 0.0f, 1.0f, 0.001f, this, tr( "Env 2 Sustain" ) ), + m_env2Rel( 0.0f, 0.0f, 2000.0f, 1.0f, 2000.0f, this, tr( "Env 2 Release" ) ), + m_env2Slope( 0.0f, -1.0f, 1.0f, 0.001f, this, tr( "Env 2 Slope" ) ), + + m_o23Mod( 0, 0, NUM_MODS - 1, this, tr( "Osc2-3 modulation" ) ), + + m_selectedView( 0, 0, 1, this, tr( "Selected view" ) ), + + m_vol1env1( 0.0f, -1.0f, 1.0f, 0.001f, this, tr( "Vol1-Env1" ) ), + m_vol1env2( 0.0f, -1.0f, 1.0f, 0.001f, this, tr( "Vol1-Env2" ) ), + m_vol1lfo1( 0.0f, -1.0f, 1.0f, 0.001f, this, tr( "Vol1-LFO1" ) ), + m_vol1lfo2( 0.0f, -1.0f, 1.0f, 0.001f, this, tr( "Vol1-LFO2" ) ), + + m_vol2env1( 0.0f, -1.0f, 1.0f, 0.001f, this, tr( "Vol2-Env1" ) ), + m_vol2env2( 0.0f, -1.0f, 1.0f, 0.001f, this, tr( "Vol2-Env2" ) ), + m_vol2lfo1( 0.0f, -1.0f, 1.0f, 0.001f, this, tr( "Vol2-LFO1" ) ), + m_vol2lfo2( 0.0f, -1.0f, 1.0f, 0.001f, this, tr( "Vol2-LFO2" ) ), + + m_vol3env1( 0.0f, -1.0f, 1.0f, 0.001f, this, tr( "Vol3-Env1" ) ), + m_vol3env2( 0.0f, -1.0f, 1.0f, 0.001f, this, tr( "Vol3-Env2" ) ), + m_vol3lfo1( 0.0f, -1.0f, 1.0f, 0.001f, this, tr( "Vol3-LFO1" ) ), + m_vol3lfo2( 0.0f, -1.0f, 1.0f, 0.001f, this, tr( "Vol3-LFO2" ) ), + + m_phs1env1( 0.0f, -1.0f, 1.0f, 0.001f, this, tr( "Phs1-Env1" ) ), + m_phs1env2( 0.0f, -1.0f, 1.0f, 0.001f, this, tr( "Phs1-Env2" ) ), + m_phs1lfo1( 0.0f, -1.0f, 1.0f, 0.001f, this, tr( "Phs1-LFO1" ) ), + m_phs1lfo2( 0.0f, -1.0f, 1.0f, 0.001f, this, tr( "Phs1-LFO2" ) ), + + m_phs2env1( 0.0f, -1.0f, 1.0f, 0.001f, this, tr( "Phs2-Env1" ) ), + m_phs2env2( 0.0f, -1.0f, 1.0f, 0.001f, this, tr( "Phs2-Env2" ) ), + m_phs2lfo1( 0.0f, -1.0f, 1.0f, 0.001f, this, tr( "Phs2-LFO1" ) ), + m_phs2lfo2( 0.0f, -1.0f, 1.0f, 0.001f, this, tr( "Phs2-LFO2" ) ), + + m_phs3env1( 0.0f, -1.0f, 1.0f, 0.001f, this, tr( "Phs3-Env1" ) ), + m_phs3env2( 0.0f, -1.0f, 1.0f, 0.001f, this, tr( "Phs3-Env2" ) ), + m_phs3lfo1( 0.0f, -1.0f, 1.0f, 0.001f, this, tr( "Phs3-LFO1" ) ), + m_phs3lfo2( 0.0f, -1.0f, 1.0f, 0.001f, this, tr( "Phs3-LFO2" ) ), + + m_pit1env1( 0.0f, -1.0f, 1.0f, 0.001f, this, tr( "Pit1-Env1" ) ), + m_pit1env2( 0.0f, -1.0f, 1.0f, 0.001f, this, tr( "Pit1-Env2" ) ), + m_pit1lfo1( 0.0f, -1.0f, 1.0f, 0.001f, this, tr( "Pit1-LFO1" ) ), + m_pit1lfo2( 0.0f, -1.0f, 1.0f, 0.001f, this, tr( "Pit1-LFO2" ) ), + + m_pit2env1( 0.0f, -1.0f, 1.0f, 0.001f, this, tr( "Pit2-Env1" ) ), + m_pit2env2( 0.0f, -1.0f, 1.0f, 0.001f, this, tr( "Pit2-Env2" ) ), + m_pit2lfo1( 0.0f, -1.0f, 1.0f, 0.001f, this, tr( "Pit2-LFO1" ) ), + m_pit2lfo2( 0.0f, -1.0f, 1.0f, 0.001f, this, tr( "Pit2-LFO2" ) ), + + m_pit3env1( 0.0f, -1.0f, 1.0f, 0.001f, this, tr( "Pit3-Env1" ) ), + m_pit3env2( 0.0f, -1.0f, 1.0f, 0.001f, this, tr( "Pit3-Env2" ) ), + m_pit3lfo1( 0.0f, -1.0f, 1.0f, 0.001f, this, tr( "Pit3-LFO1" ) ), + m_pit3lfo2( 0.0f, -1.0f, 1.0f, 0.001f, this, tr( "Pit3-LFO2" ) ), + + m_pw1env1( 0.0f, -1.0f, 1.0f, 0.001f, this, tr( "PW1-Env1" ) ), + m_pw1env2( 0.0f, -1.0f, 1.0f, 0.001f, this, tr( "PW1-Env2" ) ), + m_pw1lfo1( 0.0f, -1.0f, 1.0f, 0.001f, this, tr( "PW1-LFO1" ) ), + m_pw1lfo2( 0.0f, -1.0f, 1.0f, 0.001f, this, tr( "PW1-LFO2" ) ), + + m_sub3env1( 0.0f, -1.0f, 1.0f, 0.001f, this, tr( "Sub3-Env1" ) ), + m_sub3env2( 0.0f, -1.0f, 1.0f, 0.001f, this, tr( "Sub3-Env2" ) ), + m_sub3lfo1( 0.0f, -1.0f, 1.0f, 0.001f, this, tr( "Sub3-LFO1" ) ), + m_sub3lfo2( 0.0f, -1.0f, 1.0f, 0.001f, this, tr( "Sub3-LFO2" ) ) + +{ +// setup waveboxes + setwavemodel( m_osc2Wave ) + setwavemodel( m_osc3Wave1 ) + setwavemodel( m_osc3Wave2 ) + setwavemodel( m_lfo1Wave ) + setwavemodel( m_lfo2Wave ) + +// make connections: + +// updateVolumes + + connect( &m_osc1Vol, SIGNAL( dataChanged() ), this, SLOT( updateVolumes() ) ); + connect( &m_osc1Pan, SIGNAL( dataChanged() ), this, SLOT( updateVolumes() ) ); + connect( &m_osc2Vol, SIGNAL( dataChanged() ), this, SLOT( updateVolumes() ) ); + connect( &m_osc2Pan, SIGNAL( dataChanged() ), this, SLOT( updateVolumes() ) ); + connect( &m_osc3Vol, SIGNAL( dataChanged() ), this, SLOT( updateVolumes() ) ); + connect( &m_osc3Pan, SIGNAL( dataChanged() ), this, SLOT( updateVolumes() ) ); + +// updateFreq + + connect( &m_osc1Crs, SIGNAL( dataChanged() ), this, SLOT( updateFreq() ) ); + connect( &m_osc2Crs, SIGNAL( dataChanged() ), this, SLOT( updateFreq() ) ); + connect( &m_osc3Crs, SIGNAL( dataChanged() ), this, SLOT( updateFreq() ) ); + + connect( &m_osc1Ftl, SIGNAL( dataChanged() ), this, SLOT( updateFreq() ) ); + connect( &m_osc2Ftl, SIGNAL( dataChanged() ), this, SLOT( updateFreq() ) ); + + connect( &m_osc1Ftr, SIGNAL( dataChanged() ), this, SLOT( updateFreq() ) ); + connect( &m_osc2Ftr, SIGNAL( dataChanged() ), this, SLOT( updateFreq() ) ); + +// updatePO + connect( &m_osc1Spo, SIGNAL( dataChanged() ), this, SLOT( updatePO() ) ); + connect( &m_osc2Spo, SIGNAL( dataChanged() ), this, SLOT( updatePO() ) ); + connect( &m_osc3Spo, SIGNAL( dataChanged() ), this, SLOT( updatePO() ) ); + +// updateEnvelope1 + + connect( &m_env1Pre, SIGNAL( dataChanged() ), this, SLOT( updateEnvelope1() ) ); + connect( &m_env1Att, SIGNAL( dataChanged() ), this, SLOT( updateEnvelope1() ) ); + connect( &m_env1Hold, SIGNAL( dataChanged() ), this, SLOT( updateEnvelope1() ) ); + connect( &m_env1Dec, SIGNAL( dataChanged() ), this, SLOT( updateEnvelope1() ) ); + connect( &m_env1Rel, SIGNAL( dataChanged() ), this, SLOT( updateEnvelope1() ) ); + +// updateEnvelope2 + + connect( &m_env2Pre, SIGNAL( dataChanged() ), this, SLOT( updateEnvelope2() ) ); + connect( &m_env2Att, SIGNAL( dataChanged() ), this, SLOT( updateEnvelope2() ) ); + connect( &m_env2Hold, SIGNAL( dataChanged() ), this, SLOT( updateEnvelope2() ) ); + connect( &m_env2Dec, SIGNAL( dataChanged() ), this, SLOT( updateEnvelope2() ) ); + connect( &m_env2Rel, SIGNAL( dataChanged() ), this, SLOT( updateEnvelope2() ) ); + +// updateLFOAtts + + connect( &m_lfo1Att, SIGNAL( dataChanged() ), this, SLOT( updateLFOAtts() ) ); + connect( &m_lfo2Att, SIGNAL( dataChanged() ), this, SLOT( updateLFOAtts() ) ); + +// updateSampleRate + + connect( engine::mixer(), SIGNAL( sampleRateChanged() ), this, SLOT( updateSamplerate() ) ); + + m_fpp = engine::mixer()->framesPerPeriod(); + + updateSamplerate(); + updateVolumes(); + updateFreq(); + updatePO(); +} + + +MonstroInstrument::~MonstroInstrument() +{ +} + + +void MonstroInstrument::playNote( NotePlayHandle * _n, + sampleFrame * _working_buffer ) +{ + if ( _n->totalFramesPlayed() == 0 || _n->m_pluginData == NULL ) + { + const sample_rate_t samplerate = m_samplerate; + _n->m_pluginData = new MonstroSynth( this, _n, samplerate, m_fpp ); + } + + const fpp_t frames = _n->framesLeftForCurrentPeriod(); + + MonstroSynth * ms = static_cast( _n->m_pluginData ); + + ms->renderOutput( frames, _working_buffer ); + + //applyRelease( _working_buffer, _n ); + + instrumentTrack()->processAudioBuffer( _working_buffer, frames, _n ); +} + +void MonstroInstrument::deleteNotePluginData( NotePlayHandle * _n ) +{ + delete static_cast( _n->m_pluginData ); +} + + +void MonstroInstrument::saveSettings( QDomDocument & _doc, + QDomElement & _this ) +{ + m_osc1Vol.saveSettings( _doc, _this, "o1vol" ); + m_osc1Pan.saveSettings( _doc, _this, "o1pan" ); + m_osc1Crs.saveSettings( _doc, _this, "o1crs" ); + m_osc1Ftl.saveSettings( _doc, _this, "o1ftl" ); + m_osc1Ftr.saveSettings( _doc, _this, "o1ftr" ); + m_osc1Spo.saveSettings( _doc, _this, "o1spo" ); + m_osc1Pw.saveSettings( _doc, _this, "o1pw" ); + + m_osc2Vol.saveSettings( _doc, _this, "o2vol" ); + m_osc2Pan.saveSettings( _doc, _this, "o2pan" ); + m_osc2Crs.saveSettings( _doc, _this, "o2crs" ); + m_osc2Ftl.saveSettings( _doc, _this, "o2ftl" ); + m_osc2Ftr.saveSettings( _doc, _this, "o2ftr" ); + m_osc2Spo.saveSettings( _doc, _this, "o2spo" ); + m_osc2Wave.saveSettings( _doc, _this, "o2wav" ); + + m_osc3Vol.saveSettings( _doc, _this, "o3vol" ); + m_osc3Pan.saveSettings( _doc, _this, "o3pan" ); + m_osc3Crs.saveSettings( _doc, _this, "o3crs" ); + m_osc3Spo.saveSettings( _doc, _this, "o3spo" ); + m_osc3Sub.saveSettings( _doc, _this, "o3sub" ); + m_osc3Wave1.saveSettings( _doc, _this, "o3wav1" ); + m_osc3Wave2.saveSettings( _doc, _this, "o3wav2" ); + + m_lfo1Wave.saveSettings( _doc, _this, "l1wav" ); + m_lfo1Att.saveSettings( _doc, _this, "l1att" ); + m_lfo1Rate.saveSettings( _doc, _this, "l1rat" ); + m_lfo1Phs.saveSettings( _doc, _this, "l1phs" ); + + m_lfo2Wave.saveSettings( _doc, _this, "l2wav" ); + m_lfo2Att.saveSettings( _doc, _this, "l2att" ); + m_lfo2Rate.saveSettings( _doc, _this, "l2rat" ); + m_lfo2Phs.saveSettings( _doc, _this, "l2phs" ); + + m_env1Pre.saveSettings( _doc, _this, "e1pre" ); + m_env1Att.saveSettings( _doc, _this, "e1att" ); + m_env1Hold.saveSettings( _doc, _this, "e1hol" ); + m_env1Dec.saveSettings( _doc, _this, "e1dec" ); + m_env1Sus.saveSettings( _doc, _this, "e1sus" ); + m_env1Rel.saveSettings( _doc, _this, "e1rel" ); + m_env1Slope.saveSettings( _doc, _this, "e1slo" ); + + m_env2Pre.saveSettings( _doc, _this, "e2pre" ); + m_env2Att.saveSettings( _doc, _this, "e2att" ); + m_env2Hold.saveSettings( _doc, _this, "e2hol" ); + m_env2Dec.saveSettings( _doc, _this, "e2dec" ); + m_env2Sus.saveSettings( _doc, _this, "e2sus" ); + m_env2Rel.saveSettings( _doc, _this, "e2rel" ); + m_env2Slope.saveSettings( _doc, _this, "e2slo" ); + + m_o23Mod.saveSettings( _doc, _this, "o23mo" ); + + m_vol1env1.saveSettings( _doc, _this, "v1e1" ); + m_vol1env2.saveSettings( _doc, _this, "v1e2" ); + m_vol1lfo1.saveSettings( _doc, _this, "v1l1" ); + m_vol1lfo2.saveSettings( _doc, _this, "v1l2" ); + + m_vol2env1.saveSettings( _doc, _this, "v2e1" ); + m_vol2env2.saveSettings( _doc, _this, "v2e2" ); + m_vol2lfo1.saveSettings( _doc, _this, "v2l1" ); + m_vol2lfo2.saveSettings( _doc, _this, "v2l2" ); + + m_vol3env1.saveSettings( _doc, _this, "v3e1" ); + m_vol3env2.saveSettings( _doc, _this, "v3e2" ); + m_vol3lfo1.saveSettings( _doc, _this, "v3l1" ); + m_vol3lfo2.saveSettings( _doc, _this, "v3l2" ); + + m_phs1env1.saveSettings( _doc, _this, "p1e1" ); + m_phs1env2.saveSettings( _doc, _this, "p1e2" ); + m_phs1lfo1.saveSettings( _doc, _this, "p1l1" ); + m_phs1lfo2.saveSettings( _doc, _this, "p1l2" ); + + m_phs2env1.saveSettings( _doc, _this, "p2e1" ); + m_phs2env2.saveSettings( _doc, _this, "p2e2" ); + m_phs2lfo1.saveSettings( _doc, _this, "p2l1" ); + m_phs2lfo2.saveSettings( _doc, _this, "p2l2" ); + + m_phs3env1.saveSettings( _doc, _this, "p3e1" ); + m_phs3env2.saveSettings( _doc, _this, "p3e2" ); + m_phs3lfo1.saveSettings( _doc, _this, "p3l1" ); + m_phs3lfo2.saveSettings( _doc, _this, "p3l2" ); + + m_pit1env1.saveSettings( _doc, _this, "f1e1" ); + m_pit1env2.saveSettings( _doc, _this, "f1e2" ); + m_pit1lfo1.saveSettings( _doc, _this, "f1l1" ); + m_pit1lfo2.saveSettings( _doc, _this, "f1l2" ); + + m_pit2env1.saveSettings( _doc, _this, "f2e1" ); + m_pit2env2.saveSettings( _doc, _this, "f2e2" ); + m_pit2lfo1.saveSettings( _doc, _this, "f2l1" ); + m_pit2lfo2.saveSettings( _doc, _this, "f2l2" ); + + m_pit3env1.saveSettings( _doc, _this, "f3e1" ); + m_pit3env2.saveSettings( _doc, _this, "f3e2" ); + m_pit3lfo1.saveSettings( _doc, _this, "f3l1" ); + m_pit3lfo2.saveSettings( _doc, _this, "f3l2" ); + + m_pw1env1.saveSettings( _doc, _this, "w1e1" ); + m_pw1env2.saveSettings( _doc, _this, "w1e2" ); + m_pw1lfo1.saveSettings( _doc, _this, "w1l1" ); + m_pw1lfo2.saveSettings( _doc, _this, "w1l2" ); + + m_sub3env1.saveSettings( _doc, _this, "s3e1" ); + m_sub3env2.saveSettings( _doc, _this, "s3e2" ); + m_sub3lfo1.saveSettings( _doc, _this, "s3l1" ); + m_sub3lfo2.saveSettings( _doc, _this, "s3l2" ); + +} + +void MonstroInstrument::loadSettings( const QDomElement & _this ) +{ + m_osc1Vol.loadSettings( _this, "o1vol" ); + m_osc1Pan.loadSettings( _this, "o1pan" ); + m_osc1Crs.loadSettings( _this, "o1crs" ); + m_osc1Ftl.loadSettings( _this, "o1ftl" ); + m_osc1Ftr.loadSettings( _this, "o1ftr" ); + m_osc1Spo.loadSettings( _this, "o1spo" ); + m_osc1Pw.loadSettings( _this, "o1pw" ); + + m_osc2Vol.loadSettings( _this, "o2vol" ); + m_osc2Pan.loadSettings( _this, "o2pan" ); + m_osc2Crs.loadSettings( _this, "o2crs" ); + m_osc2Ftl.loadSettings( _this, "o2ftl" ); + m_osc2Ftr.loadSettings( _this, "o2ftr" ); + m_osc2Spo.loadSettings( _this, "o2spo" ); + m_osc2Wave.loadSettings( _this, "o2wav" ); + + m_osc3Vol.loadSettings( _this, "o3vol" ); + m_osc3Pan.loadSettings( _this, "o3pan" ); + m_osc3Crs.loadSettings( _this, "o3crs" ); + m_osc3Spo.loadSettings( _this, "o3spo" ); + m_osc3Sub.loadSettings( _this, "o3sub" ); + m_osc3Wave1.loadSettings( _this, "o3wav1" ); + m_osc3Wave2.loadSettings( _this, "o3wav2" ); + + m_lfo1Wave.loadSettings( _this, "l1wav" ); + m_lfo1Att.loadSettings( _this, "l1att" ); + m_lfo1Rate.loadSettings( _this, "l1rat" ); + m_lfo1Phs.loadSettings( _this, "l1phs" ); + + m_lfo2Wave.loadSettings( _this, "l2wav" ); + m_lfo2Att.loadSettings( _this, "l2att" ); + m_lfo2Rate.loadSettings( _this, "l2rat" ); + m_lfo2Phs.loadSettings( _this, "l2phs" ); + + m_env1Pre.loadSettings( _this, "e1pre" ); + m_env1Att.loadSettings( _this, "e1att" ); + m_env1Hold.loadSettings( _this, "e1hol" ); + m_env1Dec.loadSettings( _this, "e1dec" ); + m_env1Sus.loadSettings( _this, "e1sus" ); + m_env1Rel.loadSettings( _this, "e1rel" ); + m_env1Slope.loadSettings( _this, "e1slo" ); + + m_env2Pre.loadSettings( _this, "e2pre" ); + m_env2Att.loadSettings( _this, "e2att" ); + m_env2Hold.loadSettings( _this, "e2hol" ); + m_env2Dec.loadSettings( _this, "e2dec" ); + m_env2Sus.loadSettings( _this, "e2sus" ); + m_env2Rel.loadSettings( _this, "e2rel" ); + m_env2Slope.loadSettings( _this, "e2slo" ); + + m_o23Mod.loadSettings( _this, "o23mo" ); + + m_vol1env1.loadSettings( _this, "v1e1" ); + m_vol1env2.loadSettings( _this, "v1e2" ); + m_vol1lfo1.loadSettings( _this, "v1l1" ); + m_vol1lfo2.loadSettings( _this, "v1l2" ); + + m_vol2env1.loadSettings( _this, "v2e1" ); + m_vol2env2.loadSettings( _this, "v2e2" ); + m_vol2lfo1.loadSettings( _this, "v2l1" ); + m_vol2lfo2.loadSettings( _this, "v2l2" ); + + m_vol3env1.loadSettings( _this, "v3e1" ); + m_vol3env2.loadSettings( _this, "v3e2" ); + m_vol3lfo1.loadSettings( _this, "v3l1" ); + m_vol3lfo2.loadSettings( _this, "v3l2" ); + + m_phs1env1.loadSettings( _this, "p1e1" ); + m_phs1env2.loadSettings( _this, "p1e2" ); + m_phs1lfo1.loadSettings( _this, "p1l1" ); + m_phs1lfo2.loadSettings( _this, "p1l2" ); + + m_phs2env1.loadSettings( _this, "p2e1" ); + m_phs2env2.loadSettings( _this, "p2e2" ); + m_phs2lfo1.loadSettings( _this, "p2l1" ); + m_phs2lfo2.loadSettings( _this, "p2l2" ); + + m_phs3env1.loadSettings( _this, "p3e1" ); + m_phs3env2.loadSettings( _this, "p3e2" ); + m_phs3lfo1.loadSettings( _this, "p3l1" ); + m_phs3lfo2.loadSettings( _this, "p3l2" ); + + m_pit1env1.loadSettings( _this, "f1e1" ); + m_pit1env2.loadSettings( _this, "f1e2" ); + m_pit1lfo1.loadSettings( _this, "f1l1" ); + m_pit1lfo2.loadSettings( _this, "f1l2" ); + + m_pit2env1.loadSettings( _this, "f2e1" ); + m_pit2env2.loadSettings( _this, "f2e2" ); + m_pit2lfo1.loadSettings( _this, "f2l1" ); + m_pit2lfo2.loadSettings( _this, "f2l2" ); + + m_pit3env1.loadSettings( _this, "f3e1" ); + m_pit3env2.loadSettings( _this, "f3e2" ); + m_pit3lfo1.loadSettings( _this, "f3l1" ); + m_pit3lfo2.loadSettings( _this, "f3l2" ); + + m_pw1env1.loadSettings( _this, "w1e1" ); + m_pw1env2.loadSettings( _this, "w1e2" ); + m_pw1lfo1.loadSettings( _this, "w1l1" ); + m_pw1lfo2.loadSettings( _this, "w1l2" ); + + m_sub3env1.loadSettings( _this, "s3e1" ); + m_sub3env2.loadSettings( _this, "s3e2" ); + m_sub3lfo1.loadSettings( _this, "s3l1" ); + m_sub3lfo2.loadSettings( _this, "s3l2" ); + +} + + +QString MonstroInstrument::nodeName() const +{ + return monstro_plugin_descriptor.name; +} + + +f_cnt_t MonstroInstrument::desiredReleaseFrames() const +{ + return qMax( 64, qMax( m_env1_relF, m_env2_relF ) ); +} + + +PluginView * MonstroInstrument::instantiateView( QWidget * _parent ) +{ + return( new MonstroView( this, _parent ) ); +} + + +void MonstroInstrument::updateVolumes() +{ + m_osc1l_vol = leftCh( m_osc1Vol.value(), m_osc1Pan.value() ); + m_osc1r_vol = rightCh( m_osc1Vol.value(), m_osc1Pan.value() ); + + m_osc2l_vol = leftCh( m_osc2Vol.value(), m_osc2Pan.value() ); + m_osc2r_vol = rightCh( m_osc2Vol.value(), m_osc2Pan.value() ); + + m_osc3l_vol = leftCh( m_osc3Vol.value(), m_osc3Pan.value() ); + m_osc3r_vol = rightCh( m_osc3Vol.value(), m_osc3Pan.value() ); +} + + +void MonstroInstrument::updateFreq() +{ + m_osc1l_freq = powf( 2.0d, m_osc1Crs.value() / 12.0d ) * + powf( 2.0d, m_osc1Ftl.value() / 1200.0d ); + m_osc1r_freq = powf( 2.0d, m_osc1Crs.value() / 12.0d ) * + powf( 2.0d, m_osc1Ftr.value() / 1200.0d ); + + m_osc2l_freq = powf( 2.0d, m_osc2Crs.value() / 12.0d ) * + powf( 2.0d, m_osc2Ftl.value() / 1200.0d ); + m_osc2r_freq = powf( 2.0d, m_osc2Crs.value() / 12.0d ) * + powf( 2.0d, m_osc2Ftr.value() / 1200.0d ); + + m_osc3_freq = powf( 2.0d, m_osc3Crs.value() / 12.0d ); +} + + +void MonstroInstrument::updatePO() +{ + m_osc1l_po = m_osc1Spo.value() / 360.0; + m_osc1r_po = ( m_osc1Spo.value() * -1.0 ) / 360.0; + + m_osc2l_po = m_osc2Spo.value() / 360.0; + m_osc2r_po = ( m_osc2Spo.value() * -1.0 ) / 360.0; + + m_osc3l_po = m_osc3Spo.value() / 360.0; + m_osc3r_po = ( m_osc3Spo.value() * -1.0 ) / 360.0; +} + +void MonstroInstrument::updateEnvelope1() +{ + if( m_env1Pre.value() == 0.0f ) m_env1_pre = 1.0; + else m_env1_pre = 1.0 / ( m_env1Pre.value() / 1000.0f ) / m_samplerate; + if( m_env1Att.value() == 0.0f ) m_env1_att = 1.0; + else m_env1_att = 1.0 / ( m_env1Att.value() / 1000.0f ) / m_samplerate; + if( m_env1Hold.value() == 0.0f ) m_env1_hold = 1.0; + else m_env1_hold = 1.0 / ( m_env1Hold.value() / 1000.0f ) / m_samplerate; + if( m_env1Dec.value() == 0.0f ) m_env1_dec = 1.0; + else m_env1_dec = 1.0 / ( m_env1Dec.value() / 1000.0f ) / m_samplerate; + if( m_env1Rel.value() == 0.0f ) m_env1_rel = 1.0; + else m_env1_rel = 1.0 / ( m_env1Rel.value() / 1000.0f ) / m_samplerate; + + m_env1_len = ( m_env1Pre.value() + m_env1Att.value() + m_env1Hold.value() + m_env1Dec.value() ) * m_samplerate / 1000.0f; + m_env1_relF = m_env1Rel.value() * m_samplerate / 1000.0f; +} +void MonstroInstrument::updateEnvelope2() +{ + if( m_env2Pre.value() == 0.0f ) m_env2_pre = 1.0; + else m_env2_pre = 1.0 / ( m_env2Pre.value() / 1000.0f ) / m_samplerate; + if( m_env2Att.value() == 0.0f ) m_env2_att = 1.0; + else m_env2_att = 1.0 / ( m_env2Att.value() / 1000.0f ) / m_samplerate; + if( m_env2Hold.value() == 0.0f ) m_env2_hold = 1.0; + else m_env2_hold = 1.0 / ( m_env2Hold.value() / 1000.0f ) / m_samplerate; + if( m_env2Dec.value() == 0.0f ) m_env2_dec = 1.0; + else m_env2_dec = 1.0 / ( m_env2Dec.value() / 1000.0f ) / m_samplerate; + if( m_env2Rel.value() == 0.0f ) m_env2_rel = 1.0; + else m_env2_rel = 1.0 / ( m_env2Rel.value() / 1000.0f ) / m_samplerate; + + m_env2_len = ( m_env2Pre.value() + m_env2Att.value() + m_env2Hold.value() + m_env2Dec.value() ) * m_samplerate / 1000.0f; + m_env2_relF = m_env2Rel.value() * m_samplerate / 1000.0f; +} + + +void MonstroInstrument::updateLFOAtts() +{ + m_lfo1_att = m_lfo1Att.value() * m_samplerate / 1000.0f; + m_lfo2_att = m_lfo2Att.value() * m_samplerate / 1000.0f; +} + + +void MonstroInstrument::updateSamplerate() +{ + m_samplerate = engine::mixer()->processingSampleRate(); + updateEnvelope1(); + updateEnvelope2(); + updateLFOAtts(); +} + + +MonstroView::MonstroView( Instrument * _instrument, + QWidget * _parent ) : + InstrumentView( _instrument, _parent ) +{ + m_operatorsView = setupOperatorsView( this ); + setWidgetBackground( m_operatorsView, "artwork_op" ); + m_operatorsView->show(); + m_operatorsView->move( 0, 0 ); + + m_matrixView = setupMatrixView( this ); + setWidgetBackground( m_matrixView, "artwork_mat" ); + m_matrixView->hide(); + m_matrixView->move( 0, 0 ); + +// "tab buttons" + + pixmapButton * m_opViewButton = new pixmapButton( this, NULL ); + m_opViewButton -> move( 0,0 ); + m_opViewButton -> setActiveGraphic( PLUGIN_NAME::getIconPixmap( "opview_active" ) ); + m_opViewButton -> setInactiveGraphic( PLUGIN_NAME::getIconPixmap( "opview_inactive" ) ); + toolTip::add( m_opViewButton, tr( "Operators view" ) ); + + pixmapButton * m_matViewButton = new pixmapButton( this, NULL ); + m_matViewButton -> move( 125,0 ); + m_matViewButton -> setActiveGraphic( PLUGIN_NAME::getIconPixmap( "matview_active" ) ); + m_matViewButton -> setInactiveGraphic( PLUGIN_NAME::getIconPixmap( "matview_inactive" ) ); + toolTip::add( m_matViewButton, tr( "Matrix view" ) ); + + m_selectedViewGroup = new automatableButtonGroup( this ); + m_selectedViewGroup -> addButton( m_opViewButton ); + m_selectedViewGroup -> addButton( m_matViewButton ); + + connect( m_opViewButton, SIGNAL( clicked() ), this, SLOT( updateLayout() ) ); + connect( m_matViewButton, SIGNAL( clicked() ), this, SLOT( updateLayout() ) ); +} + + +MonstroView::~MonstroView() +{ +} + + +void MonstroView::updateLayout() +{ + switch( m_selectedViewGroup->model()->value() ) + { + case OPVIEW: + m_operatorsView->show(); + m_matrixView->hide(); + break; + case MATVIEW: + m_operatorsView->hide(); + m_matrixView->show(); + break; + } +} + + +void MonstroView::modelChanged() +{ + MonstroInstrument * m = castModel(); + + m_osc1VolKnob-> setModel( &m-> m_osc1Vol ); + m_osc1PanKnob-> setModel( &m-> m_osc1Pan ); + m_osc1CrsKnob-> setModel( &m-> m_osc1Crs ); + m_osc1FtlKnob-> setModel( &m-> m_osc1Ftl ); + m_osc1FtrKnob-> setModel( &m-> m_osc1Ftr ); + m_osc1SpoKnob-> setModel( &m-> m_osc1Spo ); + m_osc1PwKnob-> setModel( &m-> m_osc1Pw ); + + m_osc2VolKnob-> setModel( &m-> m_osc2Vol ); + m_osc2PanKnob-> setModel( &m-> m_osc2Pan ); + m_osc2CrsKnob-> setModel( &m-> m_osc2Crs ); + m_osc2FtlKnob-> setModel( &m-> m_osc2Ftl ); + m_osc2FtrKnob-> setModel( &m-> m_osc2Ftr ); + m_osc2SpoKnob-> setModel( &m-> m_osc2Spo ); + m_osc2WaveBox-> setModel( &m-> m_osc2Wave ); + + m_osc3VolKnob-> setModel( &m-> m_osc3Vol ); + m_osc3PanKnob-> setModel( &m-> m_osc3Pan ); + m_osc3CrsKnob-> setModel( &m-> m_osc3Crs ); + m_osc3SpoKnob-> setModel( &m-> m_osc3Spo ); + m_osc3SubKnob-> setModel( &m-> m_osc3Sub ); + m_osc3Wave1Box-> setModel( &m-> m_osc3Wave1 ); + m_osc3Wave2Box-> setModel( &m-> m_osc3Wave2 ); + + m_lfo1WaveBox-> setModel( &m-> m_lfo1Wave ); + m_lfo1AttKnob-> setModel( &m-> m_lfo1Att ); + m_lfo1RateKnob-> setModel( &m-> m_lfo1Rate ); + m_lfo1PhsKnob-> setModel( &m-> m_lfo1Phs ); + + m_lfo2WaveBox-> setModel( &m-> m_lfo2Wave ); + m_lfo2AttKnob-> setModel( &m-> m_lfo2Att ); + m_lfo2RateKnob-> setModel( &m-> m_lfo2Rate ); + m_lfo2PhsKnob-> setModel( &m-> m_lfo2Phs ); + + m_env1PreKnob-> setModel( &m-> m_env1Pre ); + m_env1AttKnob-> setModel( &m-> m_env1Att ); + m_env1HoldKnob-> setModel( &m-> m_env1Hold ); + m_env1DecKnob-> setModel( &m-> m_env1Dec ); + m_env1SusKnob-> setModel( &m-> m_env1Sus ); + m_env1RelKnob-> setModel( &m-> m_env1Rel ); + m_env1SlopeKnob-> setModel( &m-> m_env1Slope ); + + m_env2PreKnob-> setModel( &m-> m_env2Pre ); + m_env2AttKnob-> setModel( &m-> m_env2Att ); + m_env2HoldKnob-> setModel( &m-> m_env2Hold ); + m_env2DecKnob-> setModel( &m-> m_env2Dec ); + m_env2SusKnob-> setModel( &m-> m_env2Sus ); + m_env2RelKnob-> setModel( &m-> m_env2Rel ); + m_env2SlopeKnob-> setModel( &m-> m_env2Slope ); + + m_o23ModGroup-> setModel( &m-> m_o23Mod ); + m_selectedViewGroup-> setModel( &m-> m_selectedView ); + + m_vol1env1Knob-> setModel( &m-> m_vol1env1 ); + m_vol1env2Knob-> setModel( &m-> m_vol1env2 ); + m_vol1lfo1Knob-> setModel( &m-> m_vol1lfo1 ); + m_vol1lfo2Knob-> setModel( &m-> m_vol1lfo2 ); + + m_vol2env1Knob-> setModel( &m-> m_vol2env1 ); + m_vol2env2Knob-> setModel( &m-> m_vol2env2 ); + m_vol2lfo1Knob-> setModel( &m-> m_vol2lfo1 ); + m_vol2lfo2Knob-> setModel( &m-> m_vol2lfo2 ); + + m_vol3env1Knob-> setModel( &m-> m_vol3env1 ); + m_vol3env2Knob-> setModel( &m-> m_vol3env2 ); + m_vol3lfo1Knob-> setModel( &m-> m_vol3lfo1 ); + m_vol3lfo2Knob-> setModel( &m-> m_vol3lfo2 ); + + m_phs1env1Knob-> setModel( &m-> m_phs1env1 ); + m_phs1env2Knob-> setModel( &m-> m_phs1env2 ); + m_phs1lfo1Knob-> setModel( &m-> m_phs1lfo1 ); + m_phs1lfo2Knob-> setModel( &m-> m_phs1lfo2 ); + + m_phs2env1Knob-> setModel( &m-> m_phs2env1 ); + m_phs2env2Knob-> setModel( &m-> m_phs2env2 ); + m_phs2lfo1Knob-> setModel( &m-> m_phs2lfo1 ); + m_phs2lfo2Knob-> setModel( &m-> m_phs2lfo2 ); + + m_phs3env1Knob-> setModel( &m-> m_phs3env1 ); + m_phs3env2Knob-> setModel( &m-> m_phs3env2 ); + m_phs3lfo1Knob-> setModel( &m-> m_phs3lfo1 ); + m_phs3lfo2Knob-> setModel( &m-> m_phs3lfo2 ); + + m_pit1env1Knob-> setModel( &m-> m_pit1env1 ); + m_pit1env2Knob-> setModel( &m-> m_pit1env2 ); + m_pit1lfo1Knob-> setModel( &m-> m_pit1lfo1 ); + m_pit1lfo2Knob-> setModel( &m-> m_pit1lfo2 ); + + m_pit2env1Knob-> setModel( &m-> m_pit2env1 ); + m_pit2env2Knob-> setModel( &m-> m_pit2env2 ); + m_pit2lfo1Knob-> setModel( &m-> m_pit2lfo1 ); + m_pit2lfo2Knob-> setModel( &m-> m_pit2lfo2 ); + + m_pit3env1Knob-> setModel( &m-> m_pit3env1 ); + m_pit3env2Knob-> setModel( &m-> m_pit3env2 ); + m_pit3lfo1Knob-> setModel( &m-> m_pit3lfo1 ); + m_pit3lfo2Knob-> setModel( &m-> m_pit3lfo2 ); + + m_pw1env1Knob-> setModel( &m-> m_pw1env1 ); + m_pw1env2Knob-> setModel( &m-> m_pw1env2 ); + m_pw1lfo1Knob-> setModel( &m-> m_pw1lfo1 ); + m_pw1lfo2Knob-> setModel( &m-> m_pw1lfo2 ); + + m_sub3env1Knob-> setModel( &m-> m_sub3env1 ); + m_sub3env2Knob-> setModel( &m-> m_sub3env2 ); + m_sub3lfo1Knob-> setModel( &m-> m_sub3lfo1 ); + m_sub3lfo2Knob-> setModel( &m-> m_sub3lfo2 ); + +} + + +void MonstroView::setWidgetBackground( QWidget * _widget, const QString & _pic ) +{ + _widget->setAutoFillBackground( true ); + QPalette pal; + pal.setBrush( _widget->backgroundRole(), + PLUGIN_NAME::getIconPixmap( _pic.toAscii().constData() ) ); + _widget->setPalette( pal ); +} + + +QWidget * MonstroView::setupOperatorsView( QWidget * _parent ) +{ + // operators view + + QWidget * view = new QWidget( _parent ); + view-> setFixedSize( 250, 250 ); + + makeknob( m_osc1VolKnob, KNOBCOL1, O1ROW, "Volume", "%", "osc1Knob" ) + makeknob( m_osc1PanKnob, KNOBCOL2, O1ROW, "Panning", "", "osc1Knob" ) + makeknob( m_osc1CrsKnob, KNOBCOL3, O1ROW, "Coarse detune", " seminotes", "osc1Knob" ) + makeknob( m_osc1FtlKnob, KNOBCOL4, O1ROW, "Finetune left", " cents", "osc1Knob" ) + makeknob( m_osc1FtrKnob, KNOBCOL5, O1ROW, "Finetune right", " cents", "osc1Knob" ) + makeknob( m_osc1SpoKnob, KNOBCOL6, O1ROW, "Stereo phase offset", "°", "osc1Knob" ) + makeknob( m_osc1PwKnob, KNOBCOL7, O1ROW, "Pulse width", "%", "osc1Knob" ) + + m_osc1VolKnob -> setVolumeKnob( true ); + + makeknob( m_osc2VolKnob, KNOBCOL1, O2ROW, "Volume", "%", "osc2Knob" ) + makeknob( m_osc2PanKnob, KNOBCOL2, O2ROW, "Panning", "", "osc2Knob" ) + makeknob( m_osc2CrsKnob, KNOBCOL3, O2ROW, "Coarse detune", " seminotes", "osc2Knob" ) + makeknob( m_osc2FtlKnob, KNOBCOL4, O2ROW, "Finetune left", " cents", "osc2Knob" ) + makeknob( m_osc2FtrKnob, KNOBCOL5, O2ROW, "Finetune right", " cents", "osc2Knob" ) + makeknob( m_osc2SpoKnob, KNOBCOL6, O2ROW, "Stereo phase offset", "°", "osc2Knob" ) + + m_osc2VolKnob -> setVolumeKnob( true ); + + m_osc2WaveBox = new comboBox( view ); + m_osc2WaveBox -> setGeometry( KNOBCOL7, O2ROW + 4, 42, 22 ); + m_osc2WaveBox->setFont( pointSize<8>( m_osc2WaveBox->font() ) ); + + makeknob( m_osc3VolKnob, KNOBCOL1, O3ROW, "Volume", "%", "osc3Knob" ) + makeknob( m_osc3PanKnob, KNOBCOL2, O3ROW, "Panning", "", "osc3Knob" ) + makeknob( m_osc3CrsKnob, KNOBCOL3, O3ROW, "Coarse detune", " seminotes", "osc3Knob" ) + makeknob( m_osc3SpoKnob, KNOBCOL4, O3ROW, "Stereo phase offset", "°", "osc3Knob" ) + makeknob( m_osc3SubKnob, KNOBCOL5, O3ROW, "Sub-osc mix", "", "osc3Knob" ) + + m_osc3Wave1Box = new comboBox( view ); + m_osc3Wave1Box -> setGeometry( 160, O3ROW + 4, 42, 22 ); + m_osc3Wave1Box->setFont( pointSize<8>( m_osc3Wave1Box->font() ) ); + + m_osc3Wave2Box = new comboBox( view ); + m_osc3Wave2Box -> setGeometry( 204, O3ROW + 4, 42, 22 ); + m_osc3Wave2Box->setFont( pointSize<8>( m_osc3Wave2Box->font() ) ); + + m_lfo1WaveBox = new comboBox( view ); + m_lfo1WaveBox -> setGeometry( 2, LFOROW + 7, 42, 22 ); + m_lfo1WaveBox->setFont( pointSize<8>( m_lfo1WaveBox->font() ) ); + + maketsknob( m_lfo1AttKnob, LFOCOL1, LFOROW, "Attack", " ms", "lfoKnob" ) + maketsknob( m_lfo1RateKnob, LFOCOL2, LFOROW, "Rate", " ms", "lfoKnob" ) + makeknob( m_lfo1PhsKnob, LFOCOL3, LFOROW, "Phase", "°", "lfoKnob" ) + + m_lfo2WaveBox = new comboBox( view ); + m_lfo2WaveBox -> setGeometry( 127, LFOROW + 7, 42, 22 ); + m_lfo2WaveBox->setFont( pointSize<8>( m_lfo2WaveBox->font() ) ); + + maketsknob( m_lfo2AttKnob, LFOCOL4, LFOROW, "Attack", " ms", "lfoKnob" ) + maketsknob( m_lfo2RateKnob, LFOCOL5, LFOROW, "Rate", " ms", "lfoKnob" ) + makeknob( m_lfo2PhsKnob, LFOCOL6, LFOROW, "Phase", "°", "lfoKnob" ) + + maketsknob( m_env1PreKnob, KNOBCOL1, E1ROW, "Pre-delay", " ms", "envKnob" ) + maketsknob( m_env1AttKnob, KNOBCOL2, E1ROW, "Attack", " ms", "envKnob" ) + maketsknob( m_env1HoldKnob, KNOBCOL3, E1ROW, "Hold", " ms", "envKnob" ) + maketsknob( m_env1DecKnob, KNOBCOL4, E1ROW, "Decay", " ms", "envKnob" ) + makeknob( m_env1SusKnob, KNOBCOL5, E1ROW, "Sustain", "", "envKnob" ) + maketsknob( m_env1RelKnob, KNOBCOL6, E1ROW, "Release", " ms", "envKnob" ) + makeknob( m_env1SlopeKnob, KNOBCOL7, E1ROW, "Slope", "", "envKnob" ) + + maketsknob( m_env2PreKnob, KNOBCOL1, E2ROW, "Pre-delay", " ms", "envKnob" ) + maketsknob( m_env2AttKnob, KNOBCOL2, E2ROW, "Attack", " ms", "envKnob" ) + maketsknob( m_env2HoldKnob, KNOBCOL3, E2ROW, "Hold", " ms", "envKnob" ) + maketsknob( m_env2DecKnob, KNOBCOL4, E2ROW, "Decay", " ms", "envKnob" ) + makeknob( m_env2SusKnob, KNOBCOL5, E2ROW, "Sustain", "", "envKnob" ) + maketsknob( m_env2RelKnob, KNOBCOL6, E2ROW, "Release", " ms", "envKnob" ) + makeknob( m_env2SlopeKnob, KNOBCOL7, E2ROW, "Slope", "", "envKnob" ) + + // mod selector + pixmapButton * m_mixButton = new pixmapButton( view, NULL ); + m_mixButton -> move( 225, 185 ); + m_mixButton -> setActiveGraphic( PLUGIN_NAME::getIconPixmap( "mix_active" ) ); + m_mixButton -> setInactiveGraphic( PLUGIN_NAME::getIconPixmap( "mix_inactive" ) ); + toolTip::add( m_mixButton, tr( "Mix Osc2 with Osc3" ) ); + + pixmapButton * m_amButton = new pixmapButton( view, NULL ); + m_amButton -> move( 225, 185 + 15 ); + m_amButton -> setActiveGraphic( PLUGIN_NAME::getIconPixmap( "am_active" ) ); + m_amButton -> setInactiveGraphic( PLUGIN_NAME::getIconPixmap( "am_inactive" ) ); + toolTip::add( m_amButton, tr( "Modulate amplitude of Osc3 with Osc2" ) ); + + pixmapButton * m_fmButton = new pixmapButton( view, NULL ); + m_fmButton -> move( 225, 185 + 15*2 ); + m_fmButton -> setActiveGraphic( PLUGIN_NAME::getIconPixmap( "fm_active" ) ); + m_fmButton -> setInactiveGraphic( PLUGIN_NAME::getIconPixmap( "fm_inactive" ) ); + toolTip::add( m_fmButton, tr( "Modulate frequency of Osc3 with Osc2" ) ); + + pixmapButton * m_pmButton = new pixmapButton( view, NULL ); + m_pmButton -> move( 225, 185 + 15*3 ); + m_pmButton -> setActiveGraphic( PLUGIN_NAME::getIconPixmap( "pm_active" ) ); + m_pmButton -> setInactiveGraphic( PLUGIN_NAME::getIconPixmap( "pm_inactive" ) ); + toolTip::add( m_pmButton, tr( "Modulate phase of Osc3 with Osc2" ) ); + + m_o23ModGroup = new automatableButtonGroup( view ); + m_o23ModGroup-> addButton( m_mixButton ); + m_o23ModGroup-> addButton( m_amButton ); + m_o23ModGroup-> addButton( m_fmButton ); + m_o23ModGroup-> addButton( m_pmButton ); + + return( view ); +} + + +QWidget * MonstroView::setupMatrixView( QWidget * _parent ) +{ + // matrix view + + QWidget * view = new QWidget( _parent ); + view-> setFixedSize( 250, 250 ); + + makeknob( m_vol1env1Knob, MATCOL1, MATROW1, "Modulation amount", "", "matrixKnob" ) + makeknob( m_vol1env2Knob, MATCOL2, MATROW1, "Modulation amount", "", "matrixKnob" ) + makeknob( m_vol1lfo1Knob, MATCOL3, MATROW1, "Modulation amount", "", "matrixKnob" ) + makeknob( m_vol1lfo2Knob, MATCOL4, MATROW1, "Modulation amount", "", "matrixKnob" ) + + makeknob( m_vol2env1Knob, MATCOL1, MATROW3, "Modulation amount", "", "matrixKnob" ) + makeknob( m_vol2env2Knob, MATCOL2, MATROW3, "Modulation amount", "", "matrixKnob" ) + makeknob( m_vol2lfo1Knob, MATCOL3, MATROW3, "Modulation amount", "", "matrixKnob" ) + makeknob( m_vol2lfo2Knob, MATCOL4, MATROW3, "Modulation amount", "", "matrixKnob" ) + + makeknob( m_vol3env1Knob, MATCOL1, MATROW5, "Modulation amount", "", "matrixKnob" ) + makeknob( m_vol3env2Knob, MATCOL2, MATROW5, "Modulation amount", "", "matrixKnob" ) + makeknob( m_vol3lfo1Knob, MATCOL3, MATROW5, "Modulation amount", "", "matrixKnob" ) + makeknob( m_vol3lfo2Knob, MATCOL4, MATROW5, "Modulation amount", "", "matrixKnob" ) + + makeknob( m_phs1env1Knob, MATCOL1, MATROW2, "Modulation amount", "", "matrixKnob" ) + makeknob( m_phs1env2Knob, MATCOL2, MATROW2, "Modulation amount", "", "matrixKnob" ) + makeknob( m_phs1lfo1Knob, MATCOL3, MATROW2, "Modulation amount", "", "matrixKnob" ) + makeknob( m_phs1lfo2Knob, MATCOL4, MATROW2, "Modulation amount", "", "matrixKnob" ) + + makeknob( m_phs2env1Knob, MATCOL1, MATROW4, "Modulation amount", "", "matrixKnob" ) + makeknob( m_phs2env2Knob, MATCOL2, MATROW4, "Modulation amount", "", "matrixKnob" ) + makeknob( m_phs2lfo1Knob, MATCOL3, MATROW4, "Modulation amount", "", "matrixKnob" ) + makeknob( m_phs2lfo2Knob, MATCOL4, MATROW4, "Modulation amount", "", "matrixKnob" ) + + makeknob( m_phs3env1Knob, MATCOL1, MATROW6, "Modulation amount", "", "matrixKnob" ) + makeknob( m_phs3env2Knob, MATCOL2, MATROW6, "Modulation amount", "", "matrixKnob" ) + makeknob( m_phs3lfo1Knob, MATCOL3, MATROW6, "Modulation amount", "", "matrixKnob" ) + makeknob( m_phs3lfo2Knob, MATCOL4, MATROW6, "Modulation amount", "", "matrixKnob" ) + + makeknob( m_pit1env1Knob, MATCOL5, MATROW1, "Modulation amount", "", "matrixKnob" ) + makeknob( m_pit1env2Knob, MATCOL6, MATROW1, "Modulation amount", "", "matrixKnob" ) + makeknob( m_pit1lfo1Knob, MATCOL7, MATROW1, "Modulation amount", "", "matrixKnob" ) + makeknob( m_pit1lfo2Knob, MATCOL8, MATROW1, "Modulation amount", "", "matrixKnob" ) + + makeknob( m_pit2env1Knob, MATCOL5, MATROW3, "Modulation amount", "", "matrixKnob" ) + makeknob( m_pit2env2Knob, MATCOL6, MATROW3, "Modulation amount", "", "matrixKnob" ) + makeknob( m_pit2lfo1Knob, MATCOL7, MATROW3, "Modulation amount", "", "matrixKnob" ) + makeknob( m_pit2lfo2Knob, MATCOL8, MATROW3, "Modulation amount", "", "matrixKnob" ) + + makeknob( m_pit3env1Knob, MATCOL5, MATROW5, "Modulation amount", "", "matrixKnob" ) + makeknob( m_pit3env2Knob, MATCOL6, MATROW5, "Modulation amount", "", "matrixKnob" ) + makeknob( m_pit3lfo1Knob, MATCOL7, MATROW5, "Modulation amount", "", "matrixKnob" ) + makeknob( m_pit3lfo2Knob, MATCOL8, MATROW5, "Modulation amount", "", "matrixKnob" ) + + makeknob( m_pw1env1Knob, MATCOL5, MATROW2, "Modulation amount", "", "matrixKnob" ) + makeknob( m_pw1env2Knob, MATCOL6, MATROW2, "Modulation amount", "", "matrixKnob" ) + makeknob( m_pw1lfo1Knob, MATCOL7, MATROW2, "Modulation amount", "", "matrixKnob" ) + makeknob( m_pw1lfo2Knob, MATCOL8, MATROW2, "Modulation amount", "", "matrixKnob" ) + + makeknob( m_sub3env1Knob, MATCOL5, MATROW6, "Modulation amount", "", "matrixKnob" ) + makeknob( m_sub3env2Knob, MATCOL6, MATROW6, "Modulation amount", "", "matrixKnob" ) + makeknob( m_sub3lfo1Knob, MATCOL7, MATROW6, "Modulation amount", "", "matrixKnob" ) + makeknob( m_sub3lfo2Knob, MATCOL8, MATROW6, "Modulation amount", "", "matrixKnob" ) + + return( view ); +} + +extern "C" +{ + +// necessary for getting instance out of shared lib +Plugin * PLUGIN_EXPORT lmms_plugin_main( Model *, void * _data ) +{ + return new MonstroInstrument( static_cast( _data ) ); +} + + +} + + + +#include "moc_Monstro.cxx" diff --git a/plugins/monstro/Monstro.h b/plugins/monstro/Monstro.h new file mode 100644 index 000000000..094859f62 --- /dev/null +++ b/plugins/monstro/Monstro.h @@ -0,0 +1,593 @@ +/* + * Monstro.h - a semi-modular 3-osc synth with modulation matrix + * + * Copyright (c) 2014 Vesa Kivimäki + * + * This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net + * + * 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 MONSTRO_H +#define MONSTRO_H + + +#include "Instrument.h" +#include "InstrumentView.h" +#include "AutomatableModel.h" +#include "automatable_button.h" +#include "TempoSyncKnob.h" +#include "NotePlayHandle.h" +#include "pixmap_button.h" +#include "combobox.h" +#include "Oscillator.h" +// #include "fastpow.h" // once grejppi's fastpow gets merged + + +#define makeknob( name, x, y, hint, unit, oname ) \ + name = new knob( knobStyled, view ); \ + name ->move( x, y ); \ + name ->setHintText( tr( hint ) + " ", unit ); \ + name ->setObjectName( oname ); \ + name ->setFixedSize( 20, 20 ); + +#define maketsknob( name, x, y, hint, unit, oname ) \ + name = new TempoSyncKnob( knobStyled, view ); \ + name ->move( x, y ); \ + name ->setHintText( tr( hint ) + " ", unit ); \ + name ->setObjectName( oname ); \ + name ->setFixedSize( 20, 20 ); + +#define setwavemodel( name ) \ + name .addItem( tr( "Sine wave" ), static_cast( new PluginPixmapLoader( "sin" ) ) ); \ + name .addItem( tr( "Triangle wave" ), static_cast( new PluginPixmapLoader( "tri" ) ) ); \ + name .addItem( tr( "Saw wave" ), static_cast( new PluginPixmapLoader( "saw" ) ) ); \ + name .addItem( tr( "Ramp wave" ), static_cast( new PluginPixmapLoader( "ramp" ) ) ); \ + name .addItem( tr( "Square wave" ), static_cast( new PluginPixmapLoader( "sqr" ) ) ); \ + name .addItem( tr( "Moog saw wave" ), static_cast( new PluginPixmapLoader( "moog" ) ) ); \ + name .addItem( tr( "Exponential wave" ), static_cast( new PluginPixmapLoader( "exp" ) ) ); \ + name .addItem( tr( "White noise" ), static_cast( new PluginPixmapLoader( "noise" ) ) ); + + + + +const int O1ROW = 22; +const int O2ROW = 22 + 39; +const int O3ROW = 22 + 39 * 2; +const int LFOROW = 22 + 39 * 3; +const int E1ROW = 22 + 39 * 4; +const int E2ROW = 22 + 39 * 5; + +const int KNOBCOL1 = 16; +const int KNOBCOL2 = 16 + 30; +const int KNOBCOL3 = 16 + 30 * 2; +const int KNOBCOL4 = 16 + 30 * 3; +const int KNOBCOL5 = 16 + 30 * 4; +const int KNOBCOL6 = 16 + 30 * 5; +const int KNOBCOL7 = 16 + 30 * 6; + +const int LFOCOL1 = KNOBCOL2; +const int LFOCOL2 = KNOBCOL2 + 26; +const int LFOCOL3 = KNOBCOL2 + 26*2; +const int LFOCOL4 = 171; +const int LFOCOL5 = 171 + 26; +const int LFOCOL6 = 171 + 26*2; + +const int MATCOL1 = 32; +const int MATCOL2 = 32 + 25; +const int MATCOL3 = 32 + 25*2; +const int MATCOL4 = 32 + 25*3; +const int MATCOL5 = 149; +const int MATCOL6 = 149 + 25; +const int MATCOL7 = 149 + 25*2; +const int MATCOL8 = 149 + 25*3; + +const int MATROW1 = 22; +const int MATROW2 = 22 + 39; +const int MATROW3 = 22 + 39*2; +const int MATROW4 = 22 + 39*3; +const int MATROW5 = 22 + 39*4; +const int MATROW6 = 22 + 39*5; + +const int OPVIEW = 0; +const int MATVIEW = 1; + +const int WAVE_SINE = 0; +const int WAVE_TRI = 1; +const int WAVE_SAW = 2; +const int WAVE_RAMP = 3; +const int WAVE_SQR = 4; +const int WAVE_MOOG = 5; +const int WAVE_EXP = 6; +const int WAVE_NOISE = 7; +const int NUM_WAVES = 8; + +const int MOD_MIX = 0; +const int MOD_AM = 1; +const int MOD_FM = 2; +const int MOD_PM = 3; +const int NUM_MODS = 4; + +const float MODCLIP = 2.0; + +class MonstroInstrument; +class MonstroView; + +// use grejppi's once it's merged +inline double fastPow( double a, double b ) +{ + union + { + double d; + int32_t x[2]; + } u = { a }; + u.x[1] = static_cast( b * ( u.x[1] - 1072632447 ) + 1072632447 ); + u.x[0] = 0; + return u.d; +} + + +class MonstroSynth +{ +public: + MonstroSynth( MonstroInstrument * _i, NotePlayHandle * _nph, + const sample_rate_t _samplerate, fpp_t _frames ); + virtual ~MonstroSynth(); + + void renderOutput( fpp_t _frames, sampleFrame * _buf ); + + inline sample_rate_t samplerate() const + { + return m_samplerate; + } + +private: + + MonstroInstrument * m_parent; + NotePlayHandle * m_nph; + const sample_rate_t m_samplerate; + fpp_t m_fpp; + + sample_t * m_env1_buf; + sample_t * m_env2_buf; + sample_t * m_lfo1_buf; + sample_t * m_lfo2_buf; + + void renderModulators( fpp_t _frames ); + + // linear interpolation + inline sample_t interpolate( sample_t s1, sample_t s2, float x ) + { + return s1 + ( s2 - s1 ) * x; + } + + + inline sample_t calcSlope( sample_t _s, float _slope ) + { + if( _slope == 0.0f ) return _s; + const double exp = fastPow( 10.0, static_cast( _slope * -1.0 ) ); + return fastPow( _s, exp ); + } + + inline sample_t oscillate( int _wave, const float _ph ) + { + switch( _wave ) + { + case WAVE_SINE: + return Oscillator::sinSample( _ph ); + break; + case WAVE_TRI: + return Oscillator::triangleSample( _ph ); + break; + case WAVE_SAW: + return Oscillator::sawSample( _ph ); + break; + case WAVE_RAMP: + return Oscillator::sawSample( _ph ) * -1.0; + break; + case WAVE_SQR: + return Oscillator::squareSample( _ph ); + break; + case WAVE_MOOG: + return Oscillator::moogSawSample( _ph ); + break; + case WAVE_EXP: + return Oscillator::expSample( _ph ); + break; + case WAVE_NOISE: + default: + return Oscillator::noiseSample( _ph ); + break; + } + return 0.0; + } + + + float m_osc1l_phase; + float m_osc1r_phase; + float m_osc2l_phase; + float m_osc2r_phase; + float m_osc3l_phase; + float m_osc3r_phase; + + sample_t m_env1_phase; + sample_t m_env2_phase; + + sample_t m_lfo1_last; + sample_t m_lfo2_last; + +}; + +class MonstroInstrument : public Instrument +{ + Q_OBJECT +public: + MonstroInstrument( InstrumentTrack * _instrument_track ); + virtual ~MonstroInstrument(); + + virtual void playNote( NotePlayHandle * _n, + sampleFrame * _working_buffer ); + virtual void deleteNotePluginData( NotePlayHandle * _n ); + + virtual void saveSettings( QDomDocument & _doc, + QDomElement & _this ); + virtual void loadSettings( const QDomElement & _this ); + + virtual QString nodeName() const; + + virtual f_cnt_t desiredReleaseFrames() const; + + virtual PluginView * instantiateView( QWidget * _parent ); + +public slots: + void updateVolumes(); + void updateFreq(); + void updatePO(); + void updateEnvelope1(); + void updateEnvelope2(); + void updateLFOAtts(); + void updateSamplerate(); + +protected: + float m_osc1l_vol; + float m_osc1r_vol; + float m_osc2l_vol; + float m_osc2r_vol; + float m_osc3l_vol; + float m_osc3r_vol; + + float m_osc1l_freq; + float m_osc1r_freq; + float m_osc2l_freq; + float m_osc2r_freq; + float m_osc3_freq; + + float m_osc1l_po; + float m_osc1r_po; + float m_osc2l_po; + float m_osc2r_po; + float m_osc3l_po; + float m_osc3r_po; + + float m_env1_pre; + float m_env1_att; + float m_env1_hold; + float m_env1_dec; + float m_env1_rel; + + float m_env2_pre; + float m_env2_att; + float m_env2_hold; + float m_env2_dec; + float m_env2_rel; + + f_cnt_t m_env1_len; + f_cnt_t m_env2_len; + + f_cnt_t m_env1_relF; + f_cnt_t m_env2_relF; + + f_cnt_t m_lfo1_att; + f_cnt_t m_lfo2_att; + + sample_rate_t m_samplerate; + fpp_t m_fpp; + +private: + inline float leftCh( float _vol, float _pan ) + { + return ( _pan <= 0 ? 1.0 : 1.0 - ( _pan / 100.0 ) ) * _vol / 100.0; + } + + inline float rightCh( float _vol, float _pan ) + { + return ( _pan >= 0 ? 1.0 : 1.0 + ( _pan / 100.0 ) ) * _vol / 100.0; + } + +////////////////////////////////////// +// models of // +// operator view knobs // +// // +////////////////////////////////////// + + FloatModel m_osc1Vol; + FloatModel m_osc1Pan; + FloatModel m_osc1Crs; + FloatModel m_osc1Ftl; + FloatModel m_osc1Ftr; + FloatModel m_osc1Spo; + FloatModel m_osc1Pw; + + FloatModel m_osc2Vol; + FloatModel m_osc2Pan; + FloatModel m_osc2Crs; + FloatModel m_osc2Ftl; + FloatModel m_osc2Ftr; + FloatModel m_osc2Spo; + ComboBoxModel m_osc2Wave; + + FloatModel m_osc3Vol; + FloatModel m_osc3Pan; + FloatModel m_osc3Crs; + FloatModel m_osc3Spo; + FloatModel m_osc3Sub; + ComboBoxModel m_osc3Wave1; + ComboBoxModel m_osc3Wave2; + + ComboBoxModel m_lfo1Wave; + TempoSyncKnobModel m_lfo1Att; + TempoSyncKnobModel m_lfo1Rate; + FloatModel m_lfo1Phs; + + ComboBoxModel m_lfo2Wave; + TempoSyncKnobModel m_lfo2Att; + TempoSyncKnobModel m_lfo2Rate; + FloatModel m_lfo2Phs; + + TempoSyncKnobModel m_env1Pre; + TempoSyncKnobModel m_env1Att; + TempoSyncKnobModel m_env1Hold; + TempoSyncKnobModel m_env1Dec; + FloatModel m_env1Sus; + TempoSyncKnobModel m_env1Rel; + FloatModel m_env1Slope; + + TempoSyncKnobModel m_env2Pre; + TempoSyncKnobModel m_env2Att; + TempoSyncKnobModel m_env2Hold; + TempoSyncKnobModel m_env2Dec; + FloatModel m_env2Sus; + TempoSyncKnobModel m_env2Rel; + FloatModel m_env2Slope; + + IntModel m_o23Mod; + + IntModel m_selectedView; + +////////////////////////////////////// +// models of // +// modulation matrix view knobs // +// // +////////////////////////////////////// + + FloatModel m_vol1env1; + FloatModel m_vol1env2; + FloatModel m_vol1lfo1; + FloatModel m_vol1lfo2; + + FloatModel m_vol2env1; + FloatModel m_vol2env2; + FloatModel m_vol2lfo1; + FloatModel m_vol2lfo2; + + FloatModel m_vol3env1; + FloatModel m_vol3env2; + FloatModel m_vol3lfo1; + FloatModel m_vol3lfo2; + + FloatModel m_phs1env1; + FloatModel m_phs1env2; + FloatModel m_phs1lfo1; + FloatModel m_phs1lfo2; + + FloatModel m_phs2env1; + FloatModel m_phs2env2; + FloatModel m_phs2lfo1; + FloatModel m_phs2lfo2; + + FloatModel m_phs3env1; + FloatModel m_phs3env2; + FloatModel m_phs3lfo1; + FloatModel m_phs3lfo2; + + FloatModel m_pit1env1; + FloatModel m_pit1env2; + FloatModel m_pit1lfo1; + FloatModel m_pit1lfo2; + + FloatModel m_pit2env1; + FloatModel m_pit2env2; + FloatModel m_pit2lfo1; + FloatModel m_pit2lfo2; + + FloatModel m_pit3env1; + FloatModel m_pit3env2; + FloatModel m_pit3lfo1; + FloatModel m_pit3lfo2; + + FloatModel m_pw1env1; + FloatModel m_pw1env2; + FloatModel m_pw1lfo1; + FloatModel m_pw1lfo2; + + FloatModel m_sub3env1; + FloatModel m_sub3env2; + FloatModel m_sub3lfo1; + FloatModel m_sub3lfo2; + + friend class MonstroSynth; + friend class MonstroView; + +}; + +class MonstroView : public InstrumentView +{ + Q_OBJECT +public: + MonstroView( Instrument * _instrument, + QWidget * _parent ); + virtual ~MonstroView(); + +protected slots: + void updateLayout(); + +private: + virtual void modelChanged(); + + void setWidgetBackground( QWidget * _widget, const QString & _pic ); + QWidget * setupOperatorsView( QWidget * _parent ); + QWidget * setupMatrixView( QWidget * _parent ); + +////////////////////////////////////// +// // +// operator view knobs // +// // +////////////////////////////////////// + + knob * m_osc1VolKnob; + knob * m_osc1PanKnob; + knob * m_osc1CrsKnob; + knob * m_osc1FtlKnob; + knob * m_osc1FtrKnob; + knob * m_osc1SpoKnob; + knob * m_osc1PwKnob; + + knob * m_osc2VolKnob; + knob * m_osc2PanKnob; + knob * m_osc2CrsKnob; + knob * m_osc2FtlKnob; + knob * m_osc2FtrKnob; + knob * m_osc2SpoKnob; + comboBox * m_osc2WaveBox; + + knob * m_osc3VolKnob; + knob * m_osc3PanKnob; + knob * m_osc3CrsKnob; + knob * m_osc3SpoKnob; + knob * m_osc3SubKnob; + comboBox * m_osc3Wave1Box; + comboBox * m_osc3Wave2Box; + + comboBox * m_lfo1WaveBox; + TempoSyncKnob * m_lfo1AttKnob; + TempoSyncKnob * m_lfo1RateKnob; + knob * m_lfo1PhsKnob; + + comboBox * m_lfo2WaveBox; + TempoSyncKnob * m_lfo2AttKnob; + TempoSyncKnob * m_lfo2RateKnob; + knob * m_lfo2PhsKnob; + + TempoSyncKnob * m_env1PreKnob; + TempoSyncKnob * m_env1AttKnob; + TempoSyncKnob * m_env1HoldKnob; + TempoSyncKnob * m_env1DecKnob; + knob * m_env1SusKnob; + TempoSyncKnob * m_env1RelKnob; + knob * m_env1SlopeKnob; + + TempoSyncKnob * m_env2PreKnob; + TempoSyncKnob * m_env2AttKnob; + TempoSyncKnob * m_env2HoldKnob; + TempoSyncKnob * m_env2DecKnob; + knob * m_env2SusKnob; + TempoSyncKnob * m_env2RelKnob; + knob * m_env2SlopeKnob; + + automatableButtonGroup * m_o23ModGroup; + + automatableButtonGroup * m_selectedViewGroup; + + QWidget * m_operatorsView; + QWidget * m_matrixView; + +///////////////////////////////// +// // +// matrix view knobs // +// // +///////////////////////////////// + + knob * m_vol1env1Knob; + knob * m_vol1env2Knob; + knob * m_vol1lfo1Knob; + knob * m_vol1lfo2Knob; + + knob * m_vol2env1Knob; + knob * m_vol2env2Knob; + knob * m_vol2lfo1Knob; + knob * m_vol2lfo2Knob; + + knob * m_vol3env1Knob; + knob * m_vol3env2Knob; + knob * m_vol3lfo1Knob; + knob * m_vol3lfo2Knob; + + knob * m_phs1env1Knob; + knob * m_phs1env2Knob; + knob * m_phs1lfo1Knob; + knob * m_phs1lfo2Knob; + + knob * m_phs2env1Knob; + knob * m_phs2env2Knob; + knob * m_phs2lfo1Knob; + knob * m_phs2lfo2Knob; + + knob * m_phs3env1Knob; + knob * m_phs3env2Knob; + knob * m_phs3lfo1Knob; + knob * m_phs3lfo2Knob; + + knob * m_pit1env1Knob; + knob * m_pit1env2Knob; + knob * m_pit1lfo1Knob; + knob * m_pit1lfo2Knob; + + knob * m_pit2env1Knob; + knob * m_pit2env2Knob; + knob * m_pit2lfo1Knob; + knob * m_pit2lfo2Knob; + + knob * m_pit3env1Knob; + knob * m_pit3env2Knob; + knob * m_pit3lfo1Knob; + knob * m_pit3lfo2Knob; + + knob * m_pw1env1Knob; + knob * m_pw1env2Knob; + knob * m_pw1lfo1Knob; + knob * m_pw1lfo2Knob; + + knob * m_sub3env1Knob; + knob * m_sub3env2Knob; + knob * m_sub3lfo1Knob; + knob * m_sub3lfo2Knob; + +}; + + +#endif diff --git a/plugins/monstro/am_active.png b/plugins/monstro/am_active.png new file mode 100644 index 0000000000000000000000000000000000000000..785ac4faeacfee72670864a07d7a1f7c735a3801 GIT binary patch literal 730 zcmV<00ww*4P)e zSad^gZEa<4bO1wgWnpw>WFU8GbZ8()Nlj2!fese{00KfuL_t(I%Z-#fYZXxxg}=4W z6hgH1i=RwiwFt|Lc|~%LlE&r z9ygDh*S#~_;+&aW3&nxMz?r?*UhAxNMzvba0VGw+-I2uqK4rbTlK~tY8An+s>c~)* zAq!YAkdO>YY>&+p1@1XTE5}*_n z+`P)B0=E@mnE}w?f2Vm}wLJ1a72rP}=p|!fq{NvH;+uHOb`RX!rw{IXB zzTTkm4Vsu{m#It3$&K&h-eUq&Vk)D7iN*f!i$IW>^nf&k6AmzJ`~oUga8 z5xRS@u5EExQuimr1iUbIm)g)UdoNw5d(VEB-j3sV#d2V1n0%#9@1Y}6suKq$it6w0 z_rV8K$<2@gonoLU2d|oMS|wI48z~@#I+?IFHmyp!klLn5 zcyc-0GDTIRYikRs0;(W99e}0cQiwb1>+5rO$I5%$cAo$GyZmkcH;A+BM6GX2-v9sr M07*qoM6N<$f)*e?a{vGU literal 0 HcmV?d00001 diff --git a/plugins/monstro/am_inactive.png b/plugins/monstro/am_inactive.png new file mode 100644 index 0000000000000000000000000000000000000000..4b177193048bd1b8a4f45b5d16926fd75fb3fdd5 GIT binary patch literal 525 zcmV+o0`mQdP)e zSad^gZEa<4bO1wgWnpw>WFU8GbZ8()Nlj2!fese{00DJLL_t(I%bk?H&gw7>Ku=mg z9gu(yh`s>>BQL|m3&I<~))g@$#E*(ZhYlT}Eow@Ar{>ZR`0fQuRwUa=j_o*VFc=7c zQp%`^pp@c&rHU638UT~Y1k18eN}2VYlx0a-mfY`milQLTbF|hJMZt2p#1at`{0UV> z^hgO{y$bwRMCAEE5kYIsd_L!VJ{$XLwPH4#al74&&G&tL-$z9L5ZJYgmU-NsO$9lb{)oNi`R;?i~36IAkqtS@*cucq3B@DxwzbZw)-+#&sK)J3f z)9Li%Nzq!HDXDa^SkzPg_EA6Xd--g>nGo|y^m;uJ5tC|l+i$e*AVh>eP7LxB%$8ki P00000NkvXXu0mjfT+P~| literal 0 HcmV?d00001 diff --git a/plugins/monstro/artwork_mat.png b/plugins/monstro/artwork_mat.png new file mode 100644 index 0000000000000000000000000000000000000000..1a4240b5102b959a79c8c0512a5a0778eaaf5b1d GIT binary patch literal 61598 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 z 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 Of6DS2a-6QB2eHV0l>Lb4zQv( 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