43const char*
Note::__key_str[] = {
"C",
"Cs",
"D",
"Ef",
"E",
"F",
"Fs",
"G",
"Af",
"A",
"Bf",
"B" };
45Note::Note( std::shared_ptr<Instrument> pInstrument,
int nPosition,
float fVelocity,
float fPan,
int nLength,
float fPitch )
46 : __instrument( pInstrument ),
48 __specific_compo_id( -1 ),
49 __position( nPosition ),
50 __velocity( fVelocity ),
59 __humanize_delay( 0 ),
67 __just_recorded( false ),
68 __probability( 1.0f ),
70 m_fUsedTickSize( std::nan(
"") )
72 if ( pInstrument !=
nullptr ) {
73 __adsr = pInstrument->copy_adsr();
76 for (
const auto& pCompo : *pInstrument->get_components() ) {
77 std::shared_ptr<SelectedLayerInfo> pSampleInfo = std::make_shared<SelectedLayerInfo>();
78 pSampleInfo->nSelectedLayer = -1;
79 pSampleInfo->fSamplePosition = 0;
80 pSampleInfo->nNoteLength = -1;
91 __instrument( other->get_instrument() ),
93 __specific_compo_id( -1 ),
94 __position( other->get_position() ),
95 __velocity( other->get_velocity() ),
96 m_fPan( other->getPan() ),
97 __length( other->get_length() ),
98 __pitch( other->get_pitch() ),
99 __key( other->get_key() ),
100 __octave( other->get_octave() ),
102 __lead_lag( other->get_lead_lag() ),
103 __cut_off( other->get_cut_off() ),
104 __resonance( other->get_resonance() ),
105 __humanize_delay( other->get_humanize_delay() ),
106 __bpfb_l( other->get_bpfb_l() ),
107 __bpfb_r( other->get_bpfb_r() ),
108 __lpfb_l( other->get_lpfb_l() ),
109 __lpfb_r( other->get_lpfb_r() ),
110 __pattern_idx( other->get_pattern_idx() ),
111 __midi_msg( other->get_midi_msg() ),
112 __note_off( other->get_note_off() ),
113 __just_recorded( other->get_just_recorded() ),
114 __probability( other->get_probability() ),
115 m_nNoteStart( other->getNoteStart() ),
116 m_fUsedTickSize( other->getUsedTickSize() )
125 std::shared_ptr<SelectedLayerInfo> pSampleInfo = std::make_shared<SelectedLayerInfo>();
126 pSampleInfo->nSelectedLayer = mm.second->nSelectedLayer;
127 pSampleInfo->fSamplePosition = mm.second->fSamplePosition;
128 pSampleInfo->nNoteLength = mm.second->nNoteLength;
140 return std::clamp( fValue, fMin, fMax );
170 if ( pInstrumentList ==
nullptr ) {
171 assert( pInstrumentList );
172 ERRORLOG(
"Invalid instrument list" );
177 if ( pInstr ==
nullptr ) {
178 ERRORLOG( QString(
"Instrument with ID [%1] not found. Using empty instrument." )
184 __adsr = pInstr->copy_adsr();
186 for (
const auto& ppCompo : *pInstr->get_components() ) {
187 std::shared_ptr<SelectedLayerInfo> sampleInfo = std::make_shared<SelectedLayerInfo>();
188 sampleInfo->nSelectedLayer = -1;
189 sampleInfo->fSamplePosition = 0;
190 sampleInfo->nNoteLength = -1;
204 int l = str.length();
205 QString s_key = str.left( l-1 );
206 QString s_oct = str.mid( l-1, l );
207 if ( s_key.endsWith(
"-" ) ) {
208 s_key.replace(
"-",
"" );
209 s_oct.insert( 0,
"-" );
225 if ( ll.second->fSamplePosition > 0 ) {
236 auto pAudioEngine = pHydrogen->getAudioEngine();
238 double fTickMismatch;
251 if ( pHydrogen->isTimelineEnabled() ) {
264 std::shared_ptr<Sample> pSample;
267 ERRORLOG(
"Sample does not hold an instrument" );
271 auto pInstrCompo =
__instrument->get_component( nComponentID );
272 if ( pInstrCompo ==
nullptr ) {
273 ERRORLOG( QString(
"Unable to retrieve component [%1] of instrument [%2]" )
279 if ( pSelectedLayer ==
nullptr ) {
280 WARNINGLOG( QString(
"No SelectedLayer for component ID [%1] of instrument [%2]" )
285 if( pSelectedLayer->nSelectedLayer != -1 ||
286 nSelectedLayer != -1 ) {
291 int nLayer = pSelectedLayer->nSelectedLayer != -1 ?
292 pSelectedLayer->nSelectedLayer : nSelectedLayer;
294 if ( pSelectedLayer->nSelectedLayer != -1 &&
295 nSelectedLayer != -1 &&
296 pSelectedLayer->nSelectedLayer != nSelectedLayer ) {
297 WARNINGLOG( QString(
"Previously selected layer [%1] and requested layer [%2] differ. The previous one will be used." )
298 .arg( pSelectedLayer->nSelectedLayer )
299 .arg( nSelectedLayer ) );
302 auto pLayer = pInstrCompo->get_layer( nLayer );
303 if ( pLayer ==
nullptr ) {
304 ERRORLOG( QString(
"Unable to retrieve layer [%1] selected for component [%2] of instrument [%3]" )
310 pSample = pLayer->get_sample();
314 std::vector<int> possibleLayersVector;
319 auto pLayer = pInstrCompo->get_layer( nLayer );
320 if ( pLayer ==
nullptr ) {
324 if ( (
__velocity >= pLayer->get_start_velocity() ) &&
325 (
__velocity <= pLayer->get_end_velocity() ) ) {
327 possibleLayersVector.push_back( nLayer );
331 fRoundRobinID = pLayer->get_start_velocity();
341 if ( possibleLayersVector.size() == 0 ){
342 WARNINGLOG( QString(
"Velocity [%1] did fall into a hole between the instrument layers for component [%2] of instrument [%3]." )
347 float shortestDistance = 1.0f;
348 int nearestLayer = -1;
350 auto pLayer = pInstrCompo->get_layer( nLayer );
351 if ( pLayer ==
nullptr ){
355 if ( std::min( abs( pLayer->get_start_velocity() -
__velocity ),
356 abs( pLayer->get_start_velocity() -
__velocity ) ) <
359 std::min( abs( pLayer->get_start_velocity() -
__velocity ),
360 abs( pLayer->get_start_velocity() -
__velocity ) );
361 nearestLayer = nLayer;
366 if ( nearestLayer > -1 ){
367 possibleLayersVector.push_back( nearestLayer );
370 pInstrCompo->get_layer( nearestLayer )->get_start_velocity();
373 ERRORLOG( QString(
"No sample found for component [%1] of instrument [%2]" )
379 if( possibleLayersVector.size() > 0 ) {
384 nLayerPicked = possibleLayersVector[ 0 ];
388 nLayerPicked = possibleLayersVector[ rand() %
389 possibleLayersVector.size() ];
393 fRoundRobinID =
__instrument->get_id() * 10 + fRoundRobinID;
394 int nIndex = pSong->getLatestRoundRobin( fRoundRobinID ) + 1;
395 if ( nIndex >= possibleLayersVector.size() ) {
399 pSong->setLatestRoundRobin( fRoundRobinID, nIndex );
400 nLayerPicked = possibleLayersVector[ nIndex ];
405 ERRORLOG( QString(
"Unknown selection algorithm [%1] for instrument [%2]" )
411 pSelectedLayer->nSelectedLayer = nLayerPicked;
412 auto pLayer = pInstrCompo->get_layer( nLayerPicked );
413 pSample = pLayer->get_sample();
416 ERRORLOG(
"No samples found during random layer selection. This is a bug and shoul dn't happen!" );
438 if ( pSong !=
nullptr ) {
439 const float fRandomVelocityFactor = pSong->getHumanizeVelocityValue();
440 if ( fRandomVelocityFactor != 0 ) {
445 const float fRandomTimeFactor = pSong->getHumanizeTimeValue();
446 if ( fRandomTimeFactor != 0 ) {
454 const float fRandomPitchFactor =
__instrument->get_random_pitch_factor();
455 if ( fRandomPitchFactor != 0 ) {
464 if ( pSong !=
nullptr && pSong->getSwingFactor() > 0 ) {
478 double fTickMismatch;
484 pSong->getSwingFactor() );
504 bool bFound, bFound2;
505 float fPan = node->
read_float(
"pan", 0.f, &bFound,
true,
false,
true );
509 float fPanL = node->
read_float(
"pan_L", 1.f, &bFound,
false,
false, bSilent );
510 float fPanR = node->
read_float(
"pan_R", 1.f, &bFound2,
false,
false, bSilent );
511 if ( bFound && bFound2 ) {
514 WARNINGLOG( QString(
"Neither `pan` nor `pan_L` and `pan_R` were found. Falling back to `pan = 0`" ) );
520 node->
read_int(
"position", 0,
false,
false, bSilent ),
521 node->
read_float(
"velocity", 0.8f,
false,
false, bSilent ),
523 node->
read_int(
"length", -1,
true,
false, bSilent ),
524 node->
read_float(
"pitch", 0.0f,
false,
false, bSilent )
540 sOutput = QString(
"%1[Note]\n" ).arg( sPrefix )
541 .append( QString(
"%1%2instrument_id: %3\n" ).arg( sPrefix ).arg( s ).arg(
__instrument_id ) )
542 .append( QString(
"%1%2specific_compo_id: %3\n" ).arg( sPrefix ).arg( s ).arg(
__specific_compo_id ) )
543 .append( QString(
"%1%2position: %3\n" ).arg( sPrefix ).arg( s ).arg(
__position ) )
544 .append( QString(
"%1%2m_nNoteStart: %3\n" ).arg( sPrefix ).arg( s ).arg(
m_nNoteStart ) )
545 .append( QString(
"%1%2m_fUsedTickSize: %3\n" ).arg( sPrefix ).arg( s ).arg(
m_fUsedTickSize ) )
546 .append( QString(
"%1%2velocity: %3\n" ).arg( sPrefix ).arg( s ).arg(
__velocity ) )
547 .append( QString(
"%1%2pan: %3\n" ).arg( sPrefix ).arg( s ).arg(
m_fPan ) )
548 .append( QString(
"%1%2length: %3\n" ).arg( sPrefix ).arg( s ).arg(
__length ) )
549 .append( QString(
"%1%2pitch: %3\n" ).arg( sPrefix ).arg( s ).arg(
__pitch ) )
550 .append( QString(
"%1%2key: %3\n" ).arg( sPrefix ).arg( s ).arg(
__key ) )
551 .append( QString(
"%1%2octave: %3\n" ).arg( sPrefix ).arg( s ).arg(
__octave ) );
552 if (
__adsr !=
nullptr ) {
553 sOutput.append( QString(
"%1" )
554 .arg(
__adsr->toQString( sPrefix + s, bShort ) ) );
556 sOutput.append( QString(
"%1%2adsr: nullptr\n" ).arg( sPrefix ).arg( s ) );
559 sOutput.append( QString(
"%1%2lead_lag: %3\n" ).arg( sPrefix ).arg( s ).arg(
__lead_lag ) )
560 .append( QString(
"%1%2cut_off: %3\n" ).arg( sPrefix ).arg( s ).arg(
__cut_off ) )
561 .append( QString(
"%1%2resonance: %3\n" ).arg( sPrefix ).arg( s ).arg(
__resonance ) )
562 .append( QString(
"%1%2humanize_delay: %3\n" ).arg( sPrefix ).arg( s ).arg(
__humanize_delay ) )
563 .append( QString(
"%1%2key: %3\n" ).arg( sPrefix ).arg( s ).arg(
__key ) )
564 .append( QString(
"%1%2bpfb_l: %3\n" ).arg( sPrefix ).arg( s ).arg(
__bpfb_l ) )
565 .append( QString(
"%1%2bpfb_r: %3\n" ).arg( sPrefix ).arg( s ).arg(
__bpfb_r ) )
566 .append( QString(
"%1%2lpfb_l: %3\n" ).arg( sPrefix ).arg( s ).arg(
__lpfb_l ) )
567 .append( QString(
"%1%2lpfb_r: %3\n" ).arg( sPrefix ).arg( s ).arg(
__lpfb_r ) )
568 .append( QString(
"%1%2pattern_idx: %3\n" ).arg( sPrefix ).arg( s ).arg(
__pattern_idx ) )
569 .append( QString(
"%1%2midi_msg: %3\n" ).arg( sPrefix ).arg( s ).arg(
__midi_msg ) )
570 .append( QString(
"%1%2note_off: %3\n" ).arg( sPrefix ).arg( s ).arg(
__note_off ) )
571 .append( QString(
"%1%2just_recorded: %3\n" ).arg( sPrefix ).arg( s ).arg(
__just_recorded ) )
572 .append( QString(
"%1%2probability: %3\n" ).arg( sPrefix ).arg( s ).arg(
__probability ) );
574 sOutput.append( QString(
"%1" ).arg(
__instrument->toQString( sPrefix + s, bShort ) ) );
576 sOutput.append( QString(
"%1%2instrument: nullptr\n" ).arg( sPrefix ).arg( s ) );
578 sOutput.append( QString(
"%1%2layers_selected:\n" )
579 .arg( sPrefix ).arg( s ) );
581 if ( ll.second !=
nullptr ) {
582 sOutput.append( QString(
"%1%2[component: %3, selected layer: %4, sample position: %5, note length: %6]\n" )
583 .arg( sPrefix ).arg( s + s )
585 .arg( ll.second->nSelectedLayer )
586 .arg( ll.second->fSamplePosition )
587 .arg( ll.second->nNoteLength ) );
589 sOutput.append( QString(
"%1%2[component: %3, selected layer info: nullptr]\n" )
590 .arg( sPrefix ).arg( s + s )
596 sOutput = QString(
"[Note]" )
599 .append( QString(
", position: %1" ).arg(
__position ) )
600 .append( QString(
", m_nNoteStart: %1" ).arg(
m_nNoteStart ) )
602 .append( QString(
", velocity: %1" ).arg(
__velocity ) )
603 .append( QString(
", pan: %1" ).arg(
m_fPan ) )
604 .append( QString(
", length: %1" ).arg(
__length ) )
605 .append( QString(
", pitch: %1" ).arg(
__pitch ) )
606 .append( QString(
", key: %1" ).arg(
__key ) )
607 .append( QString(
", octave: %1" ).arg(
__octave ) );
608 if (
__adsr !=
nullptr ) {
609 sOutput.append( QString(
", [%1" )
610 .arg(
__adsr->toQString( sPrefix + s, bShort )
611 .replace(
"\n",
"]" ) ) );
613 sOutput.append(
", adsr: nullptr" );
616 sOutput.append( QString(
", lead_lag: %1" ).arg(
__lead_lag ) )
617 .append( QString(
", cut_off: %1" ).arg(
__cut_off ) )
618 .append( QString(
", resonance: %1" ).arg(
__resonance ) )
620 .append( QString(
", key: %1" ).arg(
__key ) )
621 .append( QString(
", bpfb_l: %1" ).arg(
__bpfb_l ) )
622 .append( QString(
", bpfb_r: %1" ).arg(
__bpfb_r ) )
623 .append( QString(
", lpfb_l: %1" ).arg(
__lpfb_l ) )
624 .append( QString(
", lpfb_r: %1" ).arg(
__lpfb_r ) )
625 .append( QString(
", pattern_idx: %1" ).arg(
__pattern_idx ) )
626 .append( QString(
", midi_msg: %1" ).arg(
__midi_msg ) )
627 .append( QString(
", note_off: %1" ).arg(
__note_off ) )
629 .append( QString(
", probability: %1" ).arg(
__probability ) );
631 sOutput.append( QString(
", instrument: %1" ).arg(
__instrument->get_name() ) );
633 sOutput.append( QString(
", instrument: nullptr" ) );
635 sOutput.append( QString(
", layers_selected: " ) );
637 if ( ll.second !=
nullptr ) {
638 sOutput.append( QString(
"[component: %1, selected layer: %2, sample position: %3, note length: %4] " )
640 .arg( ll.second->nSelectedLayer )
641 .arg( ll.second->fSamplePosition )
642 .arg( ll.second->nNoteLength ) );
644 sOutput.append( QString(
"[component: %1, selected layer info: nullptr]" )
693 ERRORLOG(QString(
"Unknown Key value [%1]" ).arg( key ) );
static constexpr float fHumanizePitchSD
Maximum value the standard deviation of the Gaussian distribution the random pitch contribution will ...
static constexpr float fHumanizeTimingSD
Maximum value the standard deviation of the Gaussian distribution the random pitch contribution will ...
static constexpr int nMaxTimeHumanize
Maximum time (in frames) a note's position can be off due to the humanization (lead-lag).
static constexpr float fHumanizeVelocitySD
Maximum value the standard deviation of the Gaussian distribution the random velocity contribution wi...
static QString sPrintIndention
String used to format the debugging string output of some core classes.
std::shared_ptr< Song > getSong() const
Get the current song.
static Hydrogen * get_instance()
Returns the current Hydrogen instance __instance.
static int getMaxLayers()
A note plays an associated instrument with a velocity left and right pan.
int __humanize_delay
frequency [0;1]
float m_fUsedTickSize
TransportPosition::m_fTickSize used to calculate m_nNoteStart.
std::shared_ptr< SelectedLayerInfo > get_layer_selected(int CompoID)
void swing()
Add swing contribution to __humanize_delay.
bool isPartiallyRendered() const
int __pattern_idx
index of the pattern holding this note for undo actions
std::shared_ptr< Instrument > __instrument
the instrument to be played by this note
void set_lead_lag(float value)
__lead_lag setter
static QString KeyToQString(Key key)
float m_fPan
pan of the note, [-1;1] from
float __lpfb_l
left low pass filter buffer
void set_humanize_delay(int value)
__humanize_delay setter
void set_key_octave(const QString &str)
parse str and set __key and __octave
int __position
note position in
void map_instrument(std::shared_ptr< InstrumentList > instruments)
find the corresponding instrument and point to it, or an empty instrument
static Note * load_from(XMLNode *node, std::shared_ptr< InstrumentList > instruments, bool bSilent=false)
load a note from an XMLNode
float __resonance
filter resonant
void set_probability(float value)
float __lead_lag
lead or lag offset of the note
std::shared_ptr< Instrument > get_instrument()
__instrument accessor
float get_total_pitch() const
bool __just_recorded
used in record+delete
void save_to(XMLNode *node)
void humanize()
Add random contributions to __pitch, __humanize_delay, and __velocity.
int __length
left to right, as requested by Sampler PanLaws
std::shared_ptr< Sample > getSample(int nComponentID, int nSelectedLayer=-1)
Returns the sample associated with the note for a specific InstrumentComponent nComponentID.
void set_instrument_id(int value)
__instrument_id setter
float __pitch
the frequency of the note
float __velocity
ticks inside the pattern
float __probability
note probability
QString key_to_string()
return a string representation of key-octave
void computeNoteStart()
Calculates the m_nNoteStart in frames corresponding to the __position in ticks and storing the used t...
void setPan(float val)
set pan of the note.
float __lpfb_r
right low pass filter buffer
void set_velocity(float value)
__velocity setter
QString toQString(const QString &sPrefix="", bool bShort=true) const override
Formatted string version for debugging purposes.
float __cut_off
filter cutoff [0;1]
std::map< int, std::shared_ptr< SelectedLayerInfo > > __layers_selected
std::shared_ptr< ADSR > __adsr
attack decay sustain release
void set_note_off(bool value)
__note_off setter
bool __note_off
note type on|off
long long m_nNoteStart
from __key an __octave
float __bpfb_l
left band pass filter buffer
Key __key
the key, [0;11]==[C;B]
Octave __octave
the octave [-3;3]
Note(std::shared_ptr< Instrument > pInstrument, int nPosition=0, float fVelocity=0.8, float fPan=0.0, int nLength=-1, float fPitch=0.0)
constructor
float __bpfb_r
right band pass filter buffer
int __instrument_id
the id of the instrument played by this note
int __specific_compo_id
play a specific component, -1 if playing all
static const char * __key_str[]
used to build QString
static float getGaussian(float fStandardDeviation)
Draws an uncorrelated random value from a Gaussian distribution of mean 0 and fStandardDeviation.
static float getRatioPan(float fPan_L, float fPan_R)
This function is used to load old version files (v<=1.1).
static long long computeFrameFromTick(double fTick, double *fTickMismatch, int nSampleRate=0)
Calculates frame equivalent of fTick.
XMLNode is a subclass of QDomNode with read and write values methods.
int read_int(const QString &node, int default_value, bool inexistent_ok=true, bool empty_ok=true, bool bSilent=false)
reads an integer stored into a child node
bool read_bool(const QString &node, bool default_value, bool inexistent_ok=true, bool empty_ok=true, bool bSilent=false)
reads a boolean stored into a child node
QString read_string(const QString &node, const QString &default_value, bool inexistent_ok=true, bool empty_ok=true, bool bSilent=false)
reads a string stored into a child node
float read_float(const QString &node, float default_value, bool inexistent_ok=true, bool empty_ok=true, bool bSilent=false)
reads a float stored into a child node
void write_float(const QString &node, const float value)
write a float into a child node
void write_string(const QString &node, const QString &value)
write a string into a child node
void write_bool(const QString &node, const bool value)
write a boolean into a child node
void write_int(const QString &node, const int value)
write an integer into a child node
#define MAX_NOTES
Maximum number of notes.
static float check_boundary(float fValue, float fMin, float fMax)