22#include <core/config.h>
43#include <QtCore/QMutex>
44#include <QtCore/QMutexLocker>
113 , m_bOldLoopEnabled(
false )
114 , m_nLastRecordedMIDINoteTick( 0 )
115 , m_bSessionDrumkitNeedsRelinking(
false )
116 , m_bSessionIsExported(
false )
117 , m_nHihatOpenness( 127 )
120 ERRORLOG(
"Hydrogen audio engine is already running" );
121 throw H2Exception(
"Hydrogen audio engine is already running" );
128 m_pTimeline = std::make_shared<Timeline>();
129 m_pCoreActionController =
new CoreActionController();
134 m_pAudioEngine =
new AudioEngine();
142 m_pAudioEngine->startAudioDrivers();
145 m_nInstrumentLookupTable[i] = i;
149 toggleOscServer(
true );
159#ifdef H2CORE_HAVE_OSC
194#ifdef H2CORE_HAVE_OSC
223 std::shared_ptr<Song> pSong =
getSong();
224 if ( pSong !=
nullptr ) {
225 pSong->getPatternList()->set_to_old();
247 if (
__song ==
nullptr ) {
252 return __song->getPlaybackTrackState();
257 if (
__song ==
nullptr ) {
262 __song->setPlaybackTrackEnabled( bMuted );
269 if (
__song ==
nullptr ) {
274 if ( ! sFilename.isEmpty() &&
276 ERRORLOG( QString(
"Invalid playback track filename [%1]. File does not exist." )
281 if ( sFilename.isEmpty() ) {
282 INFOLOG(
"Disable playback track" );
283 __song->setPlaybackTrackEnabled(
false );
286 __song->setPlaybackTrackFilename( sFilename );
295 if ( pSong ==
nullptr ) {
299 std::shared_ptr<Song> pCurrentSong =
getSong();
300 if ( pSong == pCurrentSong ) {
309 if ( pCurrentSong !=
nullptr ) {
319 if ( pSong !=
nullptr ) {
320 pSong->setFilename( pCurrentSong->getFilename() );
334 if ( pSong !=
nullptr &&
337 std::max(
__song->getInstrumentList()->size() - 1, 0 );
352#ifdef H2CORE_HAVE_OSC
380 unsigned int nRealColumn = 0;
384 int scalar = ( 4 *
MAX_NOTES ) / ( res * nBase );
385 int currentPatternNumber;
387 std::shared_ptr<Song> pSong =
getSong();
389 if ( pSong ==
nullptr ) {
396 if ( ! bPlaySelectedInstrument ) {
397 if ( nInstrument >= (
int ) pSong->getInstrumentList()->size() ) {
399 ERRORLOG( QString(
"Provided instrument [%1] not found" )
400 .arg( nInstrument ) );
407 const Pattern* pCurrentPattern =
nullptr;
408 long nTickInPattern = 0;
409 const float fPan = 0;
416 PatternList* pPatternList = pSong->getPatternList();
417 auto pColumns = pSong->getPatternGroupVector();
420 if ( nColumn < 0 || nColumn >= pColumns->size() ) {
422 ERRORLOG( QString(
"Provided column [%1] out of bound [%2,%3)" )
423 .arg( nColumn ).arg( 0 )
424 .arg( pColumns->size() ) );
432 currentPatternNumber = -1;
433 for (
int n = 0; n < pColumn->
size(); n++ ) {
435 int nIndex = pPatternList->
index( pPattern );
436 if ( nIndex > currentPatternNumber ) {
437 currentPatternNumber = nIndex;
438 pCurrentPattern = pPattern;
447 PatternList *pPatternList = pSong->getPatternList();
456 if ( ! pCurrentPattern ) {
457 ERRORLOG(
"Current pattern invalid" );
468 unsigned qcolumn = ( unsigned )::round( nTickInPattern / (
double )scalar ) * scalar;
472 if ( qcolumn == pCurrentPattern->
get_length() ){
475 nTickInPattern = qcolumn;
478 auto pInstrumentList = pSong->getInstrumentList();
479 int nInstrumentNumber;
480 if ( bPlaySelectedInstrument ) {
485 auto pInstr = pInstrumentList->get( nInstrumentNumber );
486 if ( pInstr ==
nullptr ) {
487 ERRORLOG( QString(
"Unable to retrieved instrument [%1]. Plays selected instrument: [%2]" )
488 .arg( nInstrumentNumber )
489 .arg( bPlaySelectedInstrument ) );
495 if ( pCurrentPattern !=
nullptr &&
499 INFOLOG( QString(
"Recording [%1] to pattern: %2 (%3), tick: [%4/%5]." )
500 .arg( bNoteOff ?
"NoteOff" :
"NoteOn")
501 .arg( currentPatternNumber ).arg( pCurrentPattern->
get_name() )
502 .arg( nTickInPattern ).arg( pCurrentPattern->
get_length() ) );
504 bool bIsModified =
false;
508 int nPatternSize = pCurrentPattern->
get_length();
513 if ( bPlaySelectedInstrument ) {
515 static_cast<int>(
static_cast<double>(nNoteLength) *
519 for (
unsigned nNote = 0; nNote < nPatternSize; nNote++ ) {
522 Note *pNote = it->second;
523 if ( pNote !=
nullptr &&
539 noteAction.
m_column = nTickInPattern;
540 noteAction.
m_row = nInstrumentNumber;
541 noteAction.
m_pattern = currentPatternNumber;
543 noteAction.
f_pan = fPan;
547 if ( bPlaySelectedInstrument ) {
548 int divider = nNote / 12;
572 if ( ! pInstr->hasSamples() ) {
577 if ( bPlaySelectedInstrument ) {
579 if ( pSampler->isInstrumentPlaying( pInstr ) ) {
580 pSampler->midiKeyboardNoteOff( nNote );
584 Note *pNote2 =
new Note( pInstr, nRealColumn, fVelocity, fPan );
586 int divider = nNote / 12;
596 if ( pSampler->isInstrumentPlaying( pInstr ) ) {
597 Note *pNoteOff =
new Note( pInstr );
603 Note *pNote2 =
new Note( pInstr, nRealColumn, fVelocity, fPan );
621 ERRORLOG(
"can't set next pattern in song mode" );
635 ERRORLOG(
"can't set next pattern in song mode" );
647 double fCompressionLevel )
655 std::shared_ptr<Song> pSong =
getSong();
656 if ( pSong ==
nullptr ) {
678 if ( pDriver ==
nullptr || pDiskWriterDriver ==
nullptr ) {
679 ERRORLOG(
"Unable to start up DiskWriterDriver" );
681 if ( pDriver !=
nullptr ) {
687 pDiskWriterDriver->
setSampleRate(
static_cast<unsigned>(nSampleRate) );
701 pAudioEngine->
play();
706 pDiskWriterDriver->
write();
718 std::shared_ptr<Song> pSong =
getSong();
719 if ( pSong ==
nullptr ) {
732 pAudioEngine->
stop();
735 ERRORLOG(
"Unable to restart previous audio driver after exporting song." );
760 std::shared_ptr<Song> pSong =
getSong();
761 if ( pSong ==
nullptr ) {
765 PatternList* pPatternList = pSong->getPatternList();
767 for (
int nPattern = 0 ; nPattern < (int)pPatternList->
size() ; ++nPattern )
771 INFOLOG(
"Instrument " + pInst->get_name() +
" has notes" );
782 if ( pSong !=
nullptr ) {
786 pSong->removeInstrument( nInstrumentNumber,
false );
791 pSong->getInstrumentList()->size() ) {
809 static timeval oldTimeVal;
815 (now.tv_sec - oldTimeVal.tv_sec) * 1000.0
816 + (now.tv_usec - oldTimeVal.tv_usec) / 1000.0;
824 if ( fInterval < 60000.0 * 2 /
static_cast<float>(
MIN_BPM) ) {
832 static float fOldBpm1 = -1;
833 static float fOldBpm2 = -1;
834 static float fOldBpm3 = -1;
835 static float fOldBpm4 = -1;
836 static float fOldBpm5 = -1;
837 static float fOldBpm6 = -1;
838 static float fOldBpm7 = -1;
839 static float fOldBpm8 = -1;
841 float fBPM = 60000.0 / fInterval;
843 if ( fabs( fOldBpm1 - fBPM ) > 20 ) {
854 if ( fOldBpm1 == -1 ) {
865 fBPM = ( fBPM + fOldBpm1 + fOldBpm2 + fOldBpm3 + fOldBpm4 + fOldBpm5
866 + fOldBpm6 + fOldBpm7 + fOldBpm8 ) / 9.0;
868 INFOLOG( QString(
"avg BPM = %1" ).arg( fBPM ) );
883 if (
__song !=
nullptr ) {
899 ERRORLOG(
"m_pAudioDriver = NULL" );
952 if ( bTriggerEvent ) {
959#ifdef H2CORE_HAVE_JACK
960 if ( pSong ==
nullptr ) {
1036 double lastBeatTime = (double)(
1041 double currentBeatTime = (double)(
1045 double beatDiff =
m_nBeatCount == 1 ? 0 : currentBeatTime - lastBeatTime;
1060 double beatTotalDiffs = 0;
1064 double nBeatDiffAverage =
1068 float fBeatCountBpm =
1069 (float) ((
int) (60 / nBeatDiffAverage * 100))
1077 if (
__song !=
nullptr ) {
1078 __song->setBpm( fBeatCountBpm );
1089 unsigned bcsamplerate =
1091 unsigned long rtstartframe = 0;
1106 ( (float) rtstartframe
1107 / (float) bcsamplerate
1112 std::this_thread::sleep_for( std::chrono::milliseconds( sleeptime ) );
1135#ifdef H2CORE_HAVE_JACK
1146#ifdef H2CORE_HAVE_JACK
1163 std::shared_ptr<Instrument> pInstr =
nullptr;
1168 INFOLOG( QString(
"Deleting unused instrument (%1). "
1169 "%2 unused remain." )
1170 . arg( pInstr->get_name() )
1176 INFOLOG( QString(
"Instrument %1 still has %2 active notes. "
1177 "Delaying 'delete instrument' operation." )
1178 . arg( pInstr->get_name() )
1179 . arg( pInstr->is_queued() ) );
1195#ifdef H2CORE_HAVE_JACK
1208#ifdef H2CORE_HAVE_JACK
1223#ifdef H2CORE_HAVE_JACK
1229 return std::nan(
"");
1233 return std::nan(
"");
1237 return std::nan(
"");
1242#ifdef H2CORE_HAVE_JACK
1254#ifdef H2CORE_HAVE_OSC
1270 if (
__song !=
nullptr &&
__song->getIsTimelineActivated() &&
1282 if (
__song->getIsPatternEditorLocked() ) {
1291 if (
__song !=
nullptr &&
1292 bValue !=
__song->getIsPatternEditorLocked() ) {
1293 __song->setIsPatternEditorLocked( bValue );
1294 __song->setIsModified(
true );
1304 if (
__song !=
nullptr ) {
1305 return __song->getMode();
1312 if (
__song !=
nullptr && mode !=
__song->getMode() ) {
1320 if (
__song !=
nullptr ) {
1321 return __song->getActionMode();
1327 if (
__song !=
nullptr ) {
1328 __song->setActionMode( mode );
1336 return __song->getPatternMode();
1343 if (
__song !=
nullptr &&
1347 __song->setPatternMode( mode );
1373 __song !=
nullptr &&
__song->getIsTimelineActivated() ) {
1381#ifdef H2CORE_HAVE_OSC
1391#ifdef H2CORE_HAVE_OSC
1407#ifdef H2CORE_HAVE_OSC
1425 auto pInstrumentList =
getSong()->getInstrumentList();
1426 if ( pInstrumentList !=
nullptr ) {
1427 for (
unsigned nnInstr = 0; nnInstr < pInstrumentList->size(); ++nnInstr ) {
1428 auto pInstr = pInstrumentList->get( nnInstr );
1429 if ( pInstr ==
nullptr ) {
1433 if ( pInstr !=
nullptr ){
1434 for (
int nnComponent = 0; nnComponent < pInstr->get_components()->size();
1436 auto pInstrumentComponent = pInstr->get_component( nnComponent );
1437 if ( pInstrumentComponent ==
nullptr ) {
1442 auto pLayer = pInstrumentComponent->get_layer( nnLayer );
1443 if ( pLayer !=
nullptr ) {
1444 auto pSample = pLayer->get_sample();
1445 if ( pSample !=
nullptr ) {
1446 if( pSample->get_rubberband().use ) {
1447 auto pNewSample = std::make_shared<Sample>( pSample );
1449 if ( ! pNewSample->load( fBpm ) ){
1454 pLayer->set_sample( pNewSample );
1464 ERRORLOG(
"No InstrumentList present" );
1474 getSong()->setIsModified( bIsModified );
1480 return getSong()->getIsModified();
1487 return getSong()->getLastLoadedDrumkitPath();
1496 return getSong()->getLastLoadedDrumkitName();
1508 if ( bEnabled !=
getSong()->getIsTimelineActivated() ) {
1516 pPref->setUseTimelineBpm( bEnabled );
1517 getSong()->setIsTimelineActivated( bEnabled );
1525 pAudioEngine->handleTimelineChange();
1526 pAudioEngine->unlock();
1535 std::shared_ptr<Song> pSong =
getSong();
1536 if ( pSong ==
nullptr ) {
1539 const int nColumn =
static_cast<int>(
1540 std::floor(
static_cast<float>( nTick ) /
1541 static_cast<float>( nPatternSize ) ) );
1542 *pPatternStartTick =
static_cast<long>(nColumn * nPatternSize);
1546 long nTotalTick = 0;
1548 std::vector<PatternList*> *pPatternColumns = pSong->getPatternGroupVector();
1549 int nColumns = pPatternColumns->size();
1551 if ( nColumns == 0 ) {
1553 *pPatternStartTick = 0;
1563 for (
int i = 0; i < nColumns; ++i ) {
1565 if ( pColumn->
size() != 0 ) {
1571 if ( ( nTick >= nTotalTick ) && ( nTick < nTotalTick + nPatternSize ) ) {
1572 ( *pPatternStartTick ) = nTotalTick;
1575 nTotalTick += nPatternSize;
1585 if ( nTotalTick != 0 ) {
1586 nLoopTick = nTick % nTotalTick;
1589 for (
int i = 0; i < nColumns; ++i ) {
1591 if ( pColumn->
size() != 0 ) {
1597 if ( ( nLoopTick >= nTotalTick )
1598 && ( nLoopTick < nTotalTick + nPatternSize ) ) {
1599 ( *pPatternStartTick ) = nTotalTick;
1602 nTotalTick += nPatternSize;
1606 ( *pPatternStartTick ) = 0;
1613 if ( pSong ==
nullptr ) {
1615 return static_cast<long>(nColumn *
MAX_NOTES);
1618 const int nPatternGroups = pSong->getPatternGroupVector()->size();
1619 if ( nPatternGroups == 0 ) {
1624 if ( nColumn >= nPatternGroups ) {
1628 if ( pSong->isLoopEnabled() ) {
1629 nColumn = nColumn % nPatternGroups;
1631 WARNINGLOG( QString(
"Provided column [%1] is larger than the available number [%2]")
1632 .arg( nColumn ) .arg( nPatternGroups )
1638 std::vector<PatternList*> *pColumns = pSong->getPatternGroupVector();
1643 for (
int i = 0; i < nColumn; ++i ) {
1646 if( pColumn->
size() > 0)
1652 totalTick += nPatternSize;
1664 std::shared_ptr<Instrument> pInstrument =
nullptr;
1666 if (
__song !=
nullptr ) {
1671 auto pInstrList =
__song->getInstrumentList();
1672 if ( nSelectedInstrumentNumber >= pInstrList->size() ) {
1673 nSelectedInstrumentNumber = -1;
1676 if ( nSelectedInstrumentNumber != -1 ) {
1677 pInstrument = pInstrList->get( nSelectedInstrumentNumber );
1688 if (
__song ==
nullptr ) {
1693 if ( pPatternList ==
nullptr ) {
1712 sOutput = QString(
"%1[Hydrogen]\n" ).arg( sPrefix )
1713 .append( QString(
"%1%2__song: " ).arg( sPrefix ).arg( s ) );
1714 if (
__song !=
nullptr ) {
1715 sOutput.append( QString(
"%1" ).arg(
__song->toQString( sPrefix + s, bShort ) ) );
1717 sOutput.append( QString(
"nullptr\n" ) );
1719 sOutput.append( QString(
"%1%2m_ntaktoMeterCompute: %3\n" ).arg( sPrefix ).arg( s ).arg(
m_ntaktoMeterCompute ) )
1720 .append( QString(
"%1%2m_nbeatsToCount: %3\n" ).arg( sPrefix ).arg( s ).arg(
m_nbeatsToCount ) )
1721 .append( QString(
"%1%2m_nEventCount: %3\n" ).arg( sPrefix ).arg( s ).arg(
m_nEventCount ) )
1722 .append( QString(
"%1%2m_nTempoChangeCounter: %3\n" ).arg( sPrefix ).arg( s ).arg(
m_nTempoChangeCounter ) )
1723 .append( QString(
"%1%2m_nBeatCount: %3\n" ).arg( sPrefix ).arg( s ).arg(
m_nBeatCount ) )
1724 .append( QString(
"%1%2m_nBeatDiffs: [" ).arg( sPrefix ).arg( s ) );
1726 sOutput.append( QString(
" %1" ).arg( dd ) );
1728 sOutput.append( QString(
"]\n%1%2m_CurrentTime: %3" ).arg( sPrefix ).arg( s ).arg(
static_cast<long>(
m_CurrentTime.tv_sec ) ) )
1729 .append( QString(
"%1%2m_nCoutOffset: %3\n" ).arg( sPrefix ).arg( s ).arg(
m_nCoutOffset ) )
1730 .append( QString(
"%1%2m_nStartOffset: %3\n" ).arg( sPrefix ).arg( s ).arg(
m_nStartOffset ) )
1731 .append( QString(
"%1%2m_oldEngineMode: %3\n" ).arg( sPrefix ).arg( s )
1733 .append( QString(
"%1%2m_bOldLoopEnabled: %3\n" ).arg( sPrefix ).arg( s ).arg(
m_bOldLoopEnabled ) )
1735 .append( QString(
"%1%2m_GUIState: %3\n" ).arg( sPrefix ).arg( s ).arg(
static_cast<int>(
m_GUIState ) ) )
1736 .append( QString(
"%1%2m_pTimeline:\n" ).arg( sPrefix ).arg( s ) );
1738 sOutput.append( QString(
"%1" ).arg(
m_pTimeline->toQString( sPrefix + s, bShort ) ) );
1740 sOutput.append( QString(
"nullptr\n" ) );
1742 sOutput.append( QString(
"%1%2__instrument_death_row:\n" ).arg( sPrefix ).arg( s ) );
1744 if ( ii !=
nullptr ) {
1745 sOutput.append( QString(
"%1" ).arg( ii->toQString( sPrefix + s + s, bShort ) ) );
1747 sOutput.append( QString(
"nullptr\n" ) );
1751 .append( QString(
"%1%2m_pAudioEngine:\n" ).arg( sPrefix ).arg( s ) );
1753 sOutput.append( QString(
"%1" )
1756 sOutput.append( QString(
"nullptr\n" ) );
1758 sOutput.append( QString(
"%1%2lastMidiEvent: %3\n" ).arg( sPrefix ).arg( s )
1761 .append( QString(
"%1%2m_nHihatOpenness: %3\n" ).arg( sPrefix )
1763 .append( QString(
"%1%2m_nInstrumentLookupTable: [ %3 ... %4 ]\n" ).arg( sPrefix ).arg( s )
1768 sOutput = QString(
"%1[Hydrogen]" ).arg( sPrefix )
1769 .append( QString(
", __song: " ) );
1770 if (
__song !=
nullptr ) {
1771 sOutput.append( QString(
"%1" ).arg(
__song->toQString( sPrefix + s, bShort ) ) );
1773 sOutput.append( QString(
"nullptr" ) );
1777 .append( QString(
", m_nEventCount: %1" ).arg(
m_nEventCount ) )
1779 .append( QString(
", m_nBeatCount: %1" ).arg(
m_nBeatCount ) )
1780 .append( QString(
", m_nBeatDiffs: [" ) );
1782 sOutput.append( QString(
" %1" ).arg( dd ) );
1784 sOutput.append( QString(
"], m_CurrentTime: %1" ).arg(
static_cast<long>(
m_CurrentTime.tv_sec ) ) )
1785 .append( QString(
", m_nCoutOffset: %1" ).arg(
m_nCoutOffset ) )
1786 .append( QString(
", m_nStartOffset: %1" ).arg(
m_nStartOffset ) )
1787 .append( QString(
", m_oldEngineMode: %1" )
1791 .append( QString(
", m_GUIState: %1" ).arg(
static_cast<int>(
m_GUIState ) ) );
1792 sOutput.append( QString(
", m_pTimeline: " ) );
1794 sOutput.append( QString(
"%1" ).arg(
m_pTimeline->toQString( sPrefix, bShort ) ) );
1796 sOutput.append( QString(
"nullptr" ) );
1798 sOutput.append( QString(
", __instrument_death_row: [" ) );
1800 if ( ii !=
nullptr ) {
1801 sOutput.append( QString(
"%1" ).arg( ii->toQString( sPrefix + s + s, bShort ) ) );
1803 sOutput.append( QString(
" nullptr" ) );
1807 .append(
", m_pAudioEngine:" );
1809 sOutput.append( QString(
"%1" )
1812 sOutput.append( QString(
" nullptr" ) );
1814 sOutput.append( QString(
", lastMidiEvent: %1" )
1816 .append( QString(
", lastMidiEventParameter: %1" )
1819 .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.
@ Initialized
Not ready, but most pointers are now valid or NULL.
@ Playing
Transport is rolling.
void play()
Marks the audio engine to be started during the next call of the audioEngine_process() callback funct...
AudioOutput * createAudioDriver(const Preferences::AudioDriver &driver)
Create an audio driver using audioEngine_process() as its argument based on the provided choice and c...
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()
const std::shared_ptr< TransportPosition > getTransportPosition() 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.
Driver for export audio to disk.
void setCompressionLevel(double fCompressionLevel)
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)
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
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
bool addRealtimeNote(int instrument, float velocity, bool noteoff=false, int msg1=0)
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.
@ unavailable
No GUI available.
@ 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 bo...
void setSelectedInstrumentNumber(int nInstrument, bool bTriggerEvent=true)
std::shared_ptr< Timeline > getTimeline() const
SoundLibraryDatabase * m_pSoundLibraryDatabase
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.
float getJackTimebaseControllerBpm() const
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)
void releaseJackTimebaseControl()
Calling JackAudioDriver::releaseTimebaseControl() directly from the GUI.
std::shared_ptr< Instrument > getSelectedInstrument() const
int m_nHihatOpenness
Controls the instrument selection within a hihat group.
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 initJackTimebaseControl()
Calling JackAudioDriver::initTimebaseControl() directly from the GUI.
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.
bool startExportSession(int nSampleRate, int nSampleDepth, double fCompressionLevel=0.0)
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.
void initTimebaseControl()
Acquires control of JACK Timebase.
float getTimebaseControllerBpm() const
void releaseTimebaseControl()
Release Hydrogen from the JACK Timebase control.
Timebase
Whether Hydrogen or another program is in Timebase control.
@ Listener
An external program is Timebase controller and Hydrogen will disregard all tempo markers on the Timel...
@ None
Only normal clients registered.
Timebase getTimebaseState() const
static Logger * create_instance(const QString &sLogFilePath=QString(), bool bUseStdout=true, bool bLogTimestamps=false, bool bLogColors=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.
void setRecordEvents(bool value)
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.
This class holds information about all installed soundlibrary items.
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