22#include <core/config.h>
43#include <QtCore/QMutex>
44#include <QtCore/QMutexLocker>
106 , m_nSelectedPatternNumber( 0 )
107 , m_bExportSessionIsActive( false )
108 , m_GUIState(
GUIState::unavailable )
110 , m_nLastMidiEventParameter( 0 )
111 , m_CurrentTime( {0,0} )
113 , m_bOldLoopEnabled(
false )
114 , m_nLastRecordedMIDINoteTick( 0 )
115 , m_bSessionDrumkitNeedsRelinking(
false )
116 , m_bSessionIsExported(
false )
119 ERRORLOG(
"Hydrogen audio engine is already running" );
120 throw H2Exception(
"Hydrogen audio engine is already running" );
127 m_pTimeline = std::make_shared<Timeline>();
128 m_pCoreActionController =
new CoreActionController();
133 m_pAudioEngine =
new AudioEngine();
141 m_pAudioEngine->startAudioDrivers();
144 m_nInstrumentLookupTable[i] = i;
148 toggleOscServer(
true );
151 m_pSoundLibraryDatabase =
new SoundLibraryDatabase();
158#ifdef H2CORE_HAVE_OSC
191#ifdef H2CORE_HAVE_OSC
220 std::shared_ptr<Song> pSong =
getSong();
221 pSong->getPatternList()->set_to_old();
242 if (
__song ==
nullptr ) {
247 return __song->getPlaybackTrackState();
252 if (
__song ==
nullptr ) {
257 __song->setPlaybackTrackEnabled( bMuted );
264 if (
__song ==
nullptr ) {
269 if ( ! sFilename.isEmpty() &&
271 ERRORLOG( QString(
"Invalid playback track filename [%1]. File does not exist." )
276 if ( sFilename.isEmpty() ) {
277 INFOLOG(
"Disable playback track" );
278 __song->setPlaybackTrackEnabled(
false );
281 __song->setPlaybackTrackFilename( sFilename );
295 std::shared_ptr<Song> pCurrentSong =
getSong();
296 if ( pSong == pCurrentSong ) {
300 if ( pCurrentSong !=
nullptr ) {
310 pSong->setFilename( pCurrentSong->getFilename() );
325 std::max(
__song->getInstrumentList()->size() - 1, 0 );
338#ifdef H2CORE_HAVE_OSC
367 unsigned int nRealColumn = 0;
371 int scalar = ( 4 *
MAX_NOTES ) / ( res * nBase );
372 int currentPatternNumber;
374 std::shared_ptr<Song> pSong =
getSong();
376 if ( pSong ==
nullptr ) {
383 if ( ! bPlaySelectedInstrument ) {
384 if ( nInstrument >= (
int ) pSong->getInstrumentList()->size() ) {
386 ERRORLOG( QString(
"Provided instrument [%1] not found" )
387 .arg( nInstrument ) );
394 const Pattern* pCurrentPattern =
nullptr;
395 long nTickInPattern = 0;
402 PatternList* pPatternList = pSong->getPatternList();
403 auto pColumns = pSong->getPatternGroupVector();
406 if ( nColumn < 0 || nColumn >= pColumns->size() ) {
408 ERRORLOG( QString(
"Provided column [%1] out of bound [%2,%3)" )
409 .arg( nColumn ).arg( 0 )
410 .arg( pColumns->size() ) );
418 currentPatternNumber = -1;
419 for (
int n = 0; n < pColumn->
size(); n++ ) {
421 int nIndex = pPatternList->
index( pPattern );
422 if ( nIndex > currentPatternNumber ) {
423 currentPatternNumber = nIndex;
424 pCurrentPattern = pPattern;
433 PatternList *pPatternList = pSong->getPatternList();
442 if ( ! pCurrentPattern ) {
443 ERRORLOG(
"Current pattern invalid" );
454 unsigned qcolumn = ( unsigned )::round( nTickInPattern / (
double )scalar ) * scalar;
458 if ( qcolumn == pCurrentPattern->
get_length() ){
461 nTickInPattern = qcolumn;
464 auto pInstrumentList = pSong->getInstrumentList();
465 int nInstrumentNumber;
466 if ( bPlaySelectedInstrument ) {
471 auto pInstr = pInstrumentList->get( nInstrumentNumber );
472 if ( pInstr ==
nullptr ) {
473 ERRORLOG( QString(
"Unable to retrieved instrument [%1]. Plays selected instrument: [%2]" )
474 .arg( nInstrumentNumber )
475 .arg( bPlaySelectedInstrument ) );
481 if ( pCurrentPattern !=
nullptr &&
485 INFOLOG( QString(
"Recording [%1] to pattern: %2 (%3), tick: [%4/%5]." )
486 .arg( bNoteOff ?
"NoteOff" :
"NoteOn")
487 .arg( currentPatternNumber ).arg( pCurrentPattern->
get_name() )
488 .arg( nTickInPattern ).arg( pCurrentPattern->
get_length() ) );
490 bool bIsModified =
false;
494 int nPatternSize = pCurrentPattern->
get_length();
499 if ( bPlaySelectedInstrument ) {
501 static_cast<int>(
static_cast<double>(nNoteLength) *
505 for (
unsigned nNote = 0; nNote < nPatternSize; nNote++ ) {
508 Note *pNote = it->second;
509 if ( pNote !=
nullptr &&
525 noteAction.
m_column = nTickInPattern;
526 noteAction.
m_row = nInstrumentNumber;
527 noteAction.
m_pattern = currentPatternNumber;
529 noteAction.
f_pan = fPan;
533 if ( bPlaySelectedInstrument ) {
534 int divider = nNote / 12;
558 if ( ! pInstr->hasSamples() ) {
563 if ( bPlaySelectedInstrument ) {
565 if ( pSampler->isInstrumentPlaying( pInstr ) ) {
566 pSampler->midiKeyboardNoteOff( nNote );
570 Note *pNote2 =
new Note( pInstr, nRealColumn, fVelocity, fPan );
572 int divider = nNote / 12;
582 if ( pSampler->isInstrumentPlaying( pInstr ) ) {
583 Note *pNoteOff =
new Note( pInstr );
589 Note *pNote2 =
new Note( pInstr, nRealColumn, fVelocity, fPan );
606 ERRORLOG(
"can't set next pattern in song mode" );
620 ERRORLOG(
"can't set next pattern in song mode" );
639 std::shared_ptr<Song> pSong =
getSong();
640 if ( pSong ==
nullptr ) {
662 if ( pDriver ==
nullptr || pDiskWriterDriver ==
nullptr ) {
663 ERRORLOG(
"Unable to start up DiskWriterDriver" );
665 if ( pDriver !=
nullptr ) {
671 pDiskWriterDriver->
setSampleRate(
static_cast<unsigned>(nSampleRate) );
684 pAudioEngine->
play();
689 pDiskWriterDriver->
write();
701 std::shared_ptr<Song> pSong =
getSong();
713 ERRORLOG(
"Unable to restart previous audio driver after exporting song." );
738 std::shared_ptr<Song> pSong =
getSong();
739 PatternList* pPatternList = pSong->getPatternList();
741 for (
int nPattern = 0 ; nPattern < (int)pPatternList->
size() ; ++nPattern )
745 INFOLOG(
"Instrument " + pInst->get_name() +
" has notes" );
756 if ( pSong !=
nullptr ) {
760 pSong->removeInstrument( nInstrumentNumber,
false );
765 pSong->getInstrumentList()->size() ) {
783 static timeval oldTimeVal;
789 (now.tv_sec - oldTimeVal.tv_sec) * 1000.0
790 + (now.tv_usec - oldTimeVal.tv_usec) / 1000.0;
798 if ( fInterval < 60000.0 * 2 /
static_cast<float>(
MIN_BPM) ) {
808 static float fOldBpm1 = -1;
809 static float fOldBpm2 = -1;
810 static float fOldBpm3 = -1;
811 static float fOldBpm4 = -1;
812 static float fOldBpm5 = -1;
813 static float fOldBpm6 = -1;
814 static float fOldBpm7 = -1;
815 static float fOldBpm8 = -1;
817 float fBPM = 60000.0 / fInterval;
819 if ( fabs( fOldBpm1 - fBPM ) > 20 ) {
830 if ( fOldBpm1 == -1 ) {
841 fBPM = ( fBPM + fOldBpm1 + fOldBpm2 + fOldBpm3 + fOldBpm4 + fOldBpm5
842 + fOldBpm6 + fOldBpm7 + fOldBpm8 ) / 9.0;
844 INFOLOG( QString(
"avg BPM = %1" ).arg( fBPM ) );
873 ERRORLOG(
"m_pAudioDriver = NULL" );
926 if ( bTriggerEvent ) {
933#ifdef H2CORE_HAVE_JACK
934 if ( pSong ==
nullptr ) {
1012 double lastBeatTime = (double)(
1017 double currentBeatTime = (double)(
1021 double beatDiff =
m_nBeatCount == 1 ? 0 : currentBeatTime - lastBeatTime;
1036 double beatTotalDiffs = 0;
1040 double nBeatDiffAverage =
1044 float fBeatCountBpm =
1045 (float) ((
int) (60 / nBeatDiffAverage * 100))
1053 getSong()->setBpm( fBeatCountBpm );
1063 unsigned bcsamplerate =
1065 unsigned long rtstartframe = 0;
1080 ( (float) rtstartframe
1081 / (
float) bcsamplerate
1086 std::this_thread::sleep_for( std::chrono::milliseconds( sleeptime ) );
1109#ifdef H2CORE_HAVE_JACK
1120#ifdef H2CORE_HAVE_JACK
1137 std::shared_ptr<Instrument> pInstr =
nullptr;
1142 INFOLOG( QString(
"Deleting unused instrument (%1). "
1143 "%2 unused remain." )
1144 . arg( pInstr->get_name() )
1150 INFOLOG( QString(
"Instrument %1 still has %2 active notes. "
1151 "Delaying 'delete instrument' operation." )
1152 . arg( pInstr->get_name() )
1153 . arg( pInstr->is_queued() ) );
1169#ifdef H2CORE_HAVE_JACK
1182#ifdef H2CORE_HAVE_JACK
1197#ifdef H2CORE_HAVE_JACK
1202 return std::nan(
"No JACK driver");
1205 return std::nan(
"No audio driver");
1208 return std::nan(
"No JACK support");
1213#ifdef H2CORE_HAVE_JACK
1225#ifdef H2CORE_HAVE_OSC
1241 if (
__song->getIsTimelineActivated() &&
1253 if (
__song->getIsPatternEditorLocked() ) {
1262 if (
__song !=
nullptr &&
1263 bValue !=
__song->getIsPatternEditorLocked() ) {
1264 __song->setIsPatternEditorLocked( bValue );
1265 __song->setIsModified(
true );
1275 if (
__song !=
nullptr ) {
1276 return __song->getMode();
1283 if (
__song !=
nullptr && mode !=
__song->getMode() ) {
1291 if (
__song !=
nullptr ) {
1292 return __song->getActionMode();
1298 if (
__song !=
nullptr ) {
1299 __song->setActionMode( mode );
1307 return __song->getPatternMode();
1314 if (
__song !=
nullptr &&
1318 __song->setPatternMode( mode );
1343 }
else if (
getSong()->getIsTimelineActivated() ) {
1352#ifdef H2CORE_HAVE_OSC
1362#ifdef H2CORE_HAVE_OSC
1378#ifdef H2CORE_HAVE_OSC
1396 auto pInstrumentList =
getSong()->getInstrumentList();
1397 if ( pInstrumentList !=
nullptr ) {
1398 for (
unsigned nnInstr = 0; nnInstr < pInstrumentList->size(); ++nnInstr ) {
1399 auto pInstr = pInstrumentList->get( nnInstr );
1400 if ( pInstr ==
nullptr ) {
1404 if ( pInstr !=
nullptr ){
1405 for (
int nnComponent = 0; nnComponent < pInstr->get_components()->size();
1407 auto pInstrumentComponent = pInstr->get_component( nnComponent );
1408 if ( pInstrumentComponent ==
nullptr ) {
1413 auto pLayer = pInstrumentComponent->get_layer( nnLayer );
1414 if ( pLayer !=
nullptr ) {
1415 auto pSample = pLayer->get_sample();
1416 if ( pSample !=
nullptr ) {
1417 if( pSample->get_rubberband().use ) {
1418 auto pNewSample = std::make_shared<Sample>( pSample );
1420 if ( ! pNewSample->load( fBpm ) ){
1425 pLayer->set_sample( pNewSample );
1435 ERRORLOG(
"No InstrumentList present" );
1445 getSong()->setIsModified( bIsModified );
1451 return getSong()->getIsModified();
1458 return getSong()->getLastLoadedDrumkitPath();
1467 return getSong()->getLastLoadedDrumkitName();
1479 if ( bEnabled !=
getSong()->getIsTimelineActivated() ) {
1487 pPref->setUseTimelineBpm( bEnabled );
1488 getSong()->setIsTimelineActivated( bEnabled );
1496 pAudioEngine->handleTimelineChange();
1497 pAudioEngine->unlock();
1506 std::shared_ptr<Song> pSong =
getSong();
1509 long nTotalTick = 0;
1511 std::vector<PatternList*> *pPatternColumns = pSong->getPatternGroupVector();
1512 int nColumns = pPatternColumns->size();
1514 if ( nColumns == 0 ) {
1516 *pPatternStartTick = 0;
1526 for (
int i = 0; i < nColumns; ++i ) {
1528 if ( pColumn->
size() != 0 ) {
1534 if ( ( nTick >= nTotalTick ) && ( nTick < nTotalTick + nPatternSize ) ) {
1535 ( *pPatternStartTick ) = nTotalTick;
1538 nTotalTick += nPatternSize;
1548 if ( nTotalTick != 0 ) {
1549 nLoopTick = nTick % nTotalTick;
1552 for (
int i = 0; i < nColumns; ++i ) {
1554 if ( pColumn->
size() != 0 ) {
1560 if ( ( nLoopTick >= nTotalTick )
1561 && ( nLoopTick < nTotalTick + nPatternSize ) ) {
1562 ( *pPatternStartTick ) = nTotalTick;
1565 nTotalTick += nPatternSize;
1569 ( *pPatternStartTick ) = 0;
1578 const int nPatternGroups = pSong->getPatternGroupVector()->size();
1579 if ( nPatternGroups == 0 ) {
1584 if ( nColumn >= nPatternGroups ) {
1588 if ( pSong->isLoopEnabled() ) {
1589 nColumn = nColumn % nPatternGroups;
1591 WARNINGLOG( QString(
"Provided column [%1] is larger than the available number [%2]")
1592 .arg( nColumn ) .arg( nPatternGroups )
1598 std::vector<PatternList*> *pColumns = pSong->getPatternGroupVector();
1603 for (
int i = 0; i < nColumn; ++i ) {
1606 if( pColumn->
size() > 0)
1612 totalTick += nPatternSize;
1624 std::shared_ptr<Instrument> pInstrument =
nullptr;
1626 if (
__song !=
nullptr ) {
1631 auto pInstrList =
__song->getInstrumentList();
1632 if ( nSelectedInstrumentNumber >= pInstrList->size() ) {
1633 nSelectedInstrumentNumber = -1;
1636 if ( nSelectedInstrumentNumber != -1 ) {
1637 pInstrument = pInstrList->get( nSelectedInstrumentNumber );
1648 if (
__song ==
nullptr ) {
1653 if ( pPatternList ==
nullptr ) {
1672 sOutput = QString(
"%1[Hydrogen]\n" ).arg( sPrefix )
1673 .append( QString(
"%1%2__song: " ).arg( sPrefix ).arg( s ) );
1674 if (
__song !=
nullptr ) {
1675 sOutput.append( QString(
"%1" ).arg(
__song->toQString( sPrefix + s, bShort ) ) );
1677 sOutput.append( QString(
"nullptr\n" ) );
1679 sOutput.append( QString(
"%1%2m_ntaktoMeterCompute: %3\n" ).arg( sPrefix ).arg( s ).arg(
m_ntaktoMeterCompute ) )
1680 .append( QString(
"%1%2m_nbeatsToCount: %3\n" ).arg( sPrefix ).arg( s ).arg(
m_nbeatsToCount ) )
1681 .append( QString(
"%1%2m_nEventCount: %3\n" ).arg( sPrefix ).arg( s ).arg(
m_nEventCount ) )
1682 .append( QString(
"%1%2m_nTempoChangeCounter: %3\n" ).arg( sPrefix ).arg( s ).arg(
m_nTempoChangeCounter ) )
1683 .append( QString(
"%1%2m_nBeatCount: %3\n" ).arg( sPrefix ).arg( s ).arg(
m_nBeatCount ) )
1684 .append( QString(
"%1%2m_nBeatDiffs: [" ).arg( sPrefix ).arg( s ) );
1686 sOutput.append( QString(
" %1" ).arg( dd ) );
1688 sOutput.append( QString(
"]\n%1%2m_CurrentTime: %3" ).arg( sPrefix ).arg( s ).arg(
static_cast<long>(
m_CurrentTime.tv_sec ) ) )
1689 .append( QString(
"%1%2m_nCoutOffset: %3\n" ).arg( sPrefix ).arg( s ).arg(
m_nCoutOffset ) )
1690 .append( QString(
"%1%2m_nStartOffset: %3\n" ).arg( sPrefix ).arg( s ).arg(
m_nStartOffset ) )
1691 .append( QString(
"%1%2m_oldEngineMode: %3\n" ).arg( sPrefix ).arg( s )
1693 .append( QString(
"%1%2m_bOldLoopEnabled: %3\n" ).arg( sPrefix ).arg( s ).arg(
m_bOldLoopEnabled ) )
1695 .append( QString(
"%1%2m_GUIState: %3\n" ).arg( sPrefix ).arg( s ).arg(
static_cast<int>(
m_GUIState ) ) )
1696 .append( QString(
"%1%2m_pTimeline:\n" ).arg( sPrefix ).arg( s ) );
1698 sOutput.append( QString(
"%1" ).arg(
m_pTimeline->toQString( sPrefix + s, bShort ) ) );
1700 sOutput.append( QString(
"nullptr\n" ) );
1702 sOutput.append( QString(
"%1%2__instrument_death_row:\n" ).arg( sPrefix ).arg( s ) );
1704 if ( ii !=
nullptr ) {
1705 sOutput.append( QString(
"%1" ).arg( ii->toQString( sPrefix + s + s, bShort ) ) );
1707 sOutput.append( QString(
"nullptr\n" ) );
1711 .append( QString(
"%1%2m_pAudioEngine:\n" ).arg( sPrefix ).arg( s ) );
1713 sOutput.append( QString(
"%1" )
1716 sOutput.append( QString(
"nullptr\n" ) );
1718 sOutput.append( QString(
"%1%2lastMidiEvent: %3\n" ).arg( sPrefix ).arg( s )
1721 .append( QString(
"%1%2m_nInstrumentLookupTable: [ %3 ... %4 ]\n" ).arg( sPrefix ).arg( s )
1725 sOutput = QString(
"%1[Hydrogen]" ).arg( sPrefix )
1726 .append( QString(
", __song: " ) );
1727 if (
__song !=
nullptr ) {
1728 sOutput.append( QString(
"%1" ).arg(
__song->toQString( sPrefix + s, bShort ) ) );
1730 sOutput.append( QString(
"nullptr" ) );
1734 .append( QString(
", m_nEventCount: %1" ).arg(
m_nEventCount ) )
1736 .append( QString(
", m_nBeatCount: %1" ).arg(
m_nBeatCount ) )
1737 .append( QString(
", m_nBeatDiffs: [" ) );
1739 sOutput.append( QString(
" %1" ).arg( dd ) );
1741 sOutput.append( QString(
"], m_CurrentTime: %1" ).arg(
static_cast<long>(
m_CurrentTime.tv_sec ) ) )
1742 .append( QString(
", m_nCoutOffset: %1" ).arg(
m_nCoutOffset ) )
1743 .append( QString(
", m_nStartOffset: %1" ).arg(
m_nStartOffset ) )
1744 .append( QString(
", m_oldEngineMode: %1" )
1748 .append( QString(
", m_GUIState: %1" ).arg(
static_cast<int>(
m_GUIState ) ) );
1749 sOutput.append( QString(
", m_pTimeline: " ) );
1751 sOutput.append( QString(
"%1" ).arg(
m_pTimeline->toQString( sPrefix, bShort ) ) );
1753 sOutput.append( QString(
"nullptr" ) );
1755 sOutput.append( QString(
", __instrument_death_row: [" ) );
1757 if ( ii !=
nullptr ) {
1758 sOutput.append( QString(
"%1" ).arg( ii->toQString( sPrefix + s + s, bShort ) ) );
1760 sOutput.append( QString(
" nullptr" ) );
1764 .append(
", m_pAudioEngine:" );
1766 sOutput.append( QString(
"%1" )
1769 sOutput.append( QString(
" nullptr" ) );
1771 sOutput.append( QString(
", lastMidiEvent: %1" )
1774 .append( QString(
", m_nInstrumentLookupTable: [ %1 ... %2 ]" )
#define RIGHT_HERE
Macro intended to be used for the logging of the locking of the H2Core::AudioEngine.
#define FOREACH_NOTE_CST_IT_BOUND_LENGTH(_notes, _it, _bound, _pattern)
Iterate over all notes in column _bound in an immutable way if it is contained in _pattern.
int gettimeofday(struct timeval *tv, struct timezone *tz)
The audio engine deals with two distinct #TransportPosition.
void flushAndAddNextPattern(int nPatternNumber)
Add pattern nPatternNumber to #m_pNextPatterns as well as the whole content of #m_pPlayingPatterns.
void handleSelectedPattern()
Keeps the selected pattern in line with the one the transport position resides in while in Song::Mode...
void setSong(std::shared_ptr< Song >pNewSong)
void toggleNextPattern(int nPatternNumber)
Add pattern nPatternNumber to #m_pNextPatterns or deletes it in case it is already present.
@ Initialized
Not ready, but most pointers are now valid or NULL.
@ Playing
Transport is rolling.
void setNextBpm(float fNextBpm)
Stores the new speed into a separate variable which will be adopted during the next processing cycle.
AudioOutput * createAudioDriver(const QString &sDriver)
Create an audio driver using audioEngine_process() as its argument based on the provided choice and c...
void play()
Marks the audio engine to be started during the next call of the audioEngine_process() callback funct...
void updatePlayingPatterns()
Update the list of currently played patterns associated with m_pTransportPosition and m_pQueuingPosit...
void updateVirtualPatterns()
void stop()
Marks the audio engine to be stopped during the next call of the audioEngine_process() callback funct...
void unlock()
Mutex unlocking of the AudioEngine.
void lock(const char *file, unsigned int line, const char *function)
Mutex locking of the AudioEngine.
AudioOutput * getAudioDriver() const
void updateSongSize()
Function to be called every time the length of the current song does change, e.g.
Sampler * getSampler() const
void stopAudioDrivers()
Stops all audio and MIDI drivers.
void restartAudioDrivers()
QString toQString(const QString &sPrefix="", bool bShort=true) const override
Formatted string version for debugging purposes.
const std::shared_ptr< TransportPosition > getTransportPosition() const
MidiOutput * getMidiOutDriver() const
void raiseError(unsigned nErrorCode)
MidiInput * getMidiDriver() const
Base abstract class for audio output classes.
virtual unsigned getSampleRate()=0
static QString sPrintIndention
String used to format the debugging string output of some core classes.
bool locateToTick(long nTick, bool bWithJackBroadcast=true)
Relocates transport to a particular tick.
bool initExternalControlInterfaces()
Driver for export audio to disk.
void setSampleRate(unsigned nNewRate)
void setSampleDepth(int nNewDepth)
void setFileName(const QString &sFilename)
static EventQueue * get_instance()
Returns a pointer to the current EventQueue singleton stored in __instance.
void push_event(const EventType type, const int nValue)
Queues the next event into the EventQueue.
static void create_instance()
If __instance equals 0, a new EventQueue singleton will be created and stored in it.
std::vector< AddMidiNoteVector > m_addMidiNoteVector
Basic building block for the communication between the core of Hydrogen and its GUI.
static bool file_exists(const QString &path, bool silent=false)
returns true if the given path is an existing regular file
bool isTimelineEnabled() const
Convenience function checking whether using the Timeline tempo is set in the Preferences,...
GUIState m_GUIState
Specifies whether the Qt5 GUI is active.
void setMode(Song::Mode mode)
Wrapper around Song::setMode() which also triggers EVENT_SONG_MODE_ACTIVATION and should be used by a...
bool m_bExportSessionIsActive
void initBeatcounter()
Auxiliary function setting a bunch of global variables.
JackAudioDriver::Timebase getJackTimebaseState() const
std::shared_ptr< Timeline > m_pTimeline
Local instance of the Timeline object.
void midi_noteOn(Note *note)
bool startExportSession(int rate, int depth)
float getMasterBpm() const
void addRealtimeNote(int instrument, float velocity, float fPan=0.0f, bool noteoff=false, int msg1=0)
int m_nSelectedPatternNumber
Index of the pattern selected in the GUI or by a MIDI event.
Hydrogen()
Constructor, entry point, and initialization of the Hydrogen application.
long getTickForColumn(int nColumn) const
Get the total number of ticks passed up to a nColumn / pattern group.
int m_nStartOffset
ms default 0
void onJackMaster()
Calling JackAudioDriver::initTimebaseMaster() directly from the GUI.
Tempo
Specifies where the #AudioEngine does get its current tempo updates from.
@ Timeline
Only tempo markers on the Timeline are considered.
@ Jack
Hydrogen will disregard all internal tempo settings and uses the ones provided by the JACK server ins...
@ Song
BeatCounter, TapTempo, OSC and MIDI commands as well as the BPM widget in the PlayerControl are used ...
bool hasJackAudioDriver() const
void sequencer_stop()
Stop the internal sequencer.
void recreateOscServer()
Destroys and recreates the OscServer singleton in order to adopt a new OSC port.
void renameJackPorts(std::shared_ptr< Song > pSong)
Calls audioEngine_renameJackPorts() if Preferences::m_bJackTrackOuts is set to true.
~Hydrogen()
Destructor taking care of most of the clean up.
std::shared_ptr< Song > getSong() const
Get the current song.
int m_nSelectedInstrumentNumber
Instrument currently focused/selected in the GUI.
void toggleNextPattern(int nPatternNumber)
Wrapper around AudioEngine::toggleNextPattern().
QString getLastLoadedDrumkitPath() const
std::list< std::shared_ptr< Instrument > > __instrument_death_row
Deleting instruments too soon leads to potential crashes.
void removeInstrument(int nInstrumentNumber)
Delete an #Instrument.
void setIsTimelineActivated(bool bEnabled)
Wrapper around both Song::setIsTimelineActivated (recent) and Preferences::setUseTimelinebpm() (forme...
int m_nInstrumentLookupTable[MAX_INSTRUMENTS]
midi lookuptable
int getSelectedInstrumentNumber() const
void setPatternMode(Song::PatternMode mode)
Wrapper around Song::setPatternMode() which also triggers EVENT_STACKED_MODE_ACTIVATION and should be...
void onTapTempoAccelEvent()
Song::ActionMode getActionMode() const
bool isUnderSessionManagement() const
void setSong(std::shared_ptr< Song > newSong, bool bRelinking=true)
Sets the current song __song to newSong.
MidiInput * getMidiInput() const
Used to display midi driver info.
bool flushAndAddNextPattern(int nPatternNumber)
Wrapper around AudioEngine::flushAndAddNextPattern().
void setbeatsToCount(int beatstocount)
Updates m_nbeatsToCount.
GUIState
Specifies the state of the Qt GUI.
@ ready
There is a working GUI.
Song::PlaybackTrack getPlaybackTrackState() const
Wrapper around Song::getPlaybackTrackState().
int m_nLastRecordedMIDINoteTick
Onset of the recorded last in addRealtimeNote().
float m_ntaktoMeterCompute
beatcounter note length
std::shared_ptr< Song > __song
Pointer to the current song.
void setTapTempo(float fInterval)
Tempo getTempoSource() const
int getColumnForTick(long nTick, bool bLoopMode, long *pPatternStartTick) const
Find a PatternList/column corresponding to the supplied tick position nTick.
double m_nBeatDiffs[16]
beat diff
Song::Mode getMode() const
static void create_instance()
Creates all the instances used within Hydrogen in the right order.
void updateVirtualPatterns()
Processes the patterns added to any virtual ones in the #PatternList of the current Song and ensure b...
void setSelectedInstrumentNumber(int nInstrument, bool bTriggerEvent=true)
std::shared_ptr< Timeline > getTimeline() const
SoundLibraryDatabase * m_pSoundLibraryDatabase
void offJackMaster()
Calling JackAudioDriver::releaseTimebaseMaster() directly from the GUI.
void mutePlaybackTrack(const bool bMuted)
Wrapper around Song::setPlaybackTrackEnabled().
AudioEngine * m_pAudioEngine
Central instance of the audio engine.
MidiMessage::Event m_lastMidiEvent
Cache last incoming MIDI event to be used in MidiSenseWidget.
static Hydrogen * get_instance()
Returns the current Hydrogen instance __instance.
Song::PatternMode getPatternMode() const
static Hydrogen * __instance
Static reference to the Hydrogen singleton.
void __kill_instruments()
void updateSelectedPattern(bool bNeedsLock=true)
Updates the selected pattern to the one recorded note will be inserted to.
void setIsPatternEditorLocked(bool bValue)
MidiOutput * getMidiOutput() const
void startExportSong(const QString &filename)
Export a song to a wav file.
int m_nTempoChangeCounter
count tempochanges for timeArray
int m_nbeatsToCount
beatcounter beats to count
int m_nEventCount
beatcounter event
AudioEngine * getAudioEngine() const
void setNoteLength(float notelength)
std::shared_ptr< Instrument > getSelectedInstrument() const
int m_nLastMidiEventParameter
void loadPlaybackTrack(QString sFilename)
Wrapper function for loading the playback track.
AudioOutput * getAudioOutput() const
Used to display audio driver info.
void setIsModified(bool bIsModified)
Wrapper around Song::setIsModified() that checks whether a song is set.
void addInstrumentToDeathRow(std::shared_ptr< Instrument > pInstr)
Add pInstr to __instrument_death_row and triggers __kill_instruments().
bool instrumentHasNotes(std::shared_ptr< Instrument > pInst)
Test if an Instrument has some Note in the Pattern (used to test before deleting an Instrument)
QString toQString(const QString &sPrefix="", bool bShort=true) const override
Formatted string version for debugging purposes.
void setSessionDrumkitNeedsRelinking(bool bNeedsRelinking)
bool isPatternEditorLocked() const
Convenience function checking whether using the Pattern Editor is locked in the song settings and the...
void setActionMode(Song::ActionMode mode)
Wrapper around Song::setActionMode() which also triggers EVENT_ACTION_MODE_CHANGE and should be used ...
void setSelectedPatternNumber(int nPat, bool bNeedsLock=true, bool bForce=false)
Sets m_nSelectedPatternNumber.
bool hasJackTransport() const
void toggleOscServer(bool bEnable)
Starts/stops the OSC server.
bool getIsModified() const
Wrapper around Song::getIsModified() that checks whether a song is set.
timeval m_CurrentTime
timeval
QString getLastLoadedDrumkitName() const
CoreActionController * getCoreActionController() const
Song::Mode m_oldEngineMode
ms default 0
CoreActionController * m_pCoreActionController
Local instance of the CoreActionController object.
void raiseError(unsigned nErrorCode)
int m_nBeatCount
beatcounter beat to count
void sequencer_play()
Start the internal sequencer.
GUIState getGUIState() const
void recalculateRubberband(float fBpm)
Recalculates all Samples using RubberBand for a specific tempo fBpm.
static void setMaxLayers(int layers)
static int getMaxLayers()
JACK (Jack Audio Connection Kit) server driver.
Timebase
Whether Hydrogen or another program is Jack timebase master.
@ None
Only normal clients registered.
@ Slave
An external program is timebase master and Hydrogen will disregard all tempo markers on the Timeline ...
static Logger * create_instance(const QString &sLogFilePath=QString(), bool bUseStdout=true)
If __instance equals 0, a new H2Core::Logger singleton will be created and stored in it.
static QString EventToQString(Event event)
virtual void handleQueueAllNoteOff()=0
A note plays an associated instrument with a velocity left and right pan.
int get_position() const
__position accessor
void set_length(int value)
__length setter
std::shared_ptr< Instrument > get_instrument()
__instrument accessor
static double pitchToFrequency(double fPitch)
Convert a logarithmic pitch-space value in semitones to a frequency-domain value.
void set_note_off(bool value)
__note_off setter
void set_midi_info(Key key, Octave octave, int msg)
set __key, __octave and __midi_msg only if within acceptable range
PatternList is a collection of patterns.
int index(const Pattern *pattern) const
get the index of the pattern within the patterns
void flattened_virtual_patterns_compute()
call compute_flattened_virtual_patterns on each pattern
int longest_pattern_length(bool bIncludeVirtuals=true) const
Get the length of the longest pattern in the list.
int size() const
returns the numbers of patterns
Pattern * get(int idx)
get a pattern from the list
Pattern class is a Note container.
const QString & get_name() const
set the category of the pattern
bool references(std::shared_ptr< Instrument > instr)
check if this pattern contains a note referencing the given instrument
int get_length() const
set the denominator of the pattern
const notes_t * get_notes() const
get the virtual pattern set
std::multimap< int, Note * > notes_t
< multimap note type
static void create_instance()
If __instance equals 0, a new Playlist singleton will be created and stored in it.
Manager for User Preferences File (singleton)
bool inPunchArea(int pos)
static Preferences * get_instance()
Returns a pointer to the current Preferences singleton stored in __instance.
bool __playselectedinstrument
int getPatternEditorGridResolution()
bool isPatternEditorUsingTriplets()
static void create_instance()
If __instance equals 0, a new Preferences singleton will be created and stored in it.
@ USE_JACK_TRANSPORT
Specifies whether or not to use JACK transport capabilities.
int m_bJackTransportMode
Specifies whether or not Hydrogen will use the JACK transport system.
void setRecordEvents(bool value)
void reinitializePlaybackTrack()
Loading of the playback track.
void stopPlayingNotes(std::shared_ptr< Instrument > pInstr=nullptr)
@ None
Used in case no song is set and both pattern and song editor are not ready to operate yet.
ActionMode
Defines the type of user interaction experienced in the SongEditor.
@ drawMode
Holding a pressed left mouse key will draw/delete patterns in all grid cells encountered.
@ None
Used in case no song is set and both pattern and song editor are not ready to operate yet.
PlaybackTrack
Determines the state of the Playback track with respect to audio processing.
@ None
Null element used to indicate that either no song is present.
PatternMode
Determines how patterns will be added to AudioEngine::m_pPlayingPatterns if transport is in Song::Mod...
@ None
Null element used to indicate that either no song is present or Song::Mode::Song was selected.
@ Selected
Only one pattern - the one currently selected in the GUI - will be played back.
static void create_instance()
If __instance equals 0, a new MidiActionManager singleton will be created and stored in it.
static void create_instance()
If __instance equals 0, a new MidiMap singleton will be created and stored in it.
Non session manager client implementation.
static NsmClient * get_instance()
static void create_instance()
If __instance equals nullptr, a new NsmClient singleton will be created and stored in it.
void shutdown()
Causes the NSM client to not process events anymore.
void createInitialClient()
Actual setup, initialization, and registration of the NSM client.
OSC Server implementation.
static OscServer * get_instance()
Returns a pointer to the current OscServer singleton stored in __instance.
bool stop()
Stops the OSC server and makes it unavailable.
bool start()
Starts the OSC server and makes it available to handle commands.
static void create_instance(H2Core::Preferences *pPreferences)
If __instance equals nullptr, a new OscServer singleton will be created by calling the OscServer() co...
#define MAX_INSTRUMENTS
Maximum number of instruments allowed in Hydrogen.
#define MAX_NOTES
Maximum number of notes.
@ EVENT_PLAYBACK_TRACK_CHANGED
@ EVENT_ACTION_MODE_CHANGE
Switches between select mode (0) and draw mode (1) in the *SongEditor.
@ EVENT_SELECTED_INSTRUMENT_CHANGED
@ EVENT_PATTERN_MODIFIED
A pattern was added, deleted, or modified.
@ EVENT_TIMELINE_ACTIVATION
Enables/disables the usage of the Timeline.
@ EVENT_NEXT_PATTERNS_CHANGED
Used in Song::PatternMode::Stacked to indicate that a either AudioEngine::getNextPatterns() did chang...
@ EVENT_PATTERN_EDITOR_LOCKED
Locks the PatternEditor on the pattern currently played back.
@ EVENT_SONG_MODE_ACTIVATION
@ EVENT_SELECTED_PATTERN_CHANGED
Another pattern was selected via MIDI or the GUI without affecting the audio transport.
@ EVENT_STACKED_MODE_ACTIVATION
Song::PatternMode::Stacked (0) or Song::PatternMode::Selected (1) was activated.
Note::Octave no_octaveKeyVal