hydrogen 1.2.3
Sampler.cpp
Go to the documentation of this file.
1/*
2 * Hydrogen
3 * Copyright(c) 2002-2008 by Alex >Comix< Cominu [comix@users.sourceforge.net]
4 * Copyright(c) 2008-2024 The hydrogen development team [hydrogen-devel@lists.sourceforge.net]
5 *
6 * http://www.hydrogen-music.org
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY, without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program. If not, see https://www.gnu.org/licenses
20 *
21 */
22
23#include <cassert>
24#include <cmath>
25#include <cstdlib>
26
27#include <core/IO/AudioOutput.h>
29
30#include <core/Basics/Adsr.h>
33#include <core/Globals.h>
34#include <core/Hydrogen.h>
40#include <core/Basics/Note.h>
42#include <core/Basics/Sample.h>
43#include <core/Basics/Song.h>
44#include <core/Basics/Pattern.h>
47#include <core/EventQueue.h>
48
49#include <core/FX/Effects.h>
51
52#include <iostream>
53#include <QDebug>
54
55namespace H2Core
56{
57
58static std::shared_ptr<Instrument> createInstrument(int id, const QString& filepath, float volume )
59{
60 auto pInstrument = std::make_shared<Instrument>( id, filepath );
61 pInstrument->set_volume( volume );
62 auto pLayer = std::make_shared<InstrumentLayer>( Sample::load( filepath ) );
63 auto pComponent = std::make_shared<InstrumentComponent>( 0 );
64
65 pComponent->set_layer( pLayer, 0 );
66 pInstrument->get_components()->push_back( pComponent );
67 return pInstrument;
68}
69
71 : m_pMainOut_L( nullptr )
72 , m_pMainOut_R( nullptr )
73 , m_pPreviewInstrument( nullptr )
74 , m_interpolateMode( Interpolation::InterpolateMode::Linear )
75{
76
77
78 m_pMainOut_L = new float[ MAX_BUFFER_SIZE ];
79 m_pMainOut_R = new float[ MAX_BUFFER_SIZE ];
80
82
83 QString sEmptySampleFilename = Filesystem::empty_sample_path();
84
85 // instrument used in file preview
86 m_pPreviewInstrument = createInstrument( EMPTY_INSTR_ID, sEmptySampleFilename, 0.8 );
87 m_pPreviewInstrument->set_is_preview_instrument( true );
88
89 // dummy instrument used for playback track
92}
93
94
96{
97 INFOLOG( "DESTROY" );
98
99 delete[] m_pMainOut_L;
100 delete[] m_pMainOut_R;
101
102 m_pPreviewInstrument = nullptr;
104}
105
109float const Sampler::K_NORM_DEFAULT = 1.33333333333333;
110
111void Sampler::process( uint32_t nFrames )
112{
113 auto pHydrogen = Hydrogen::get_instance();
114 auto pSong = pHydrogen->getSong();
115 if ( pSong == nullptr ) {
116 ERRORLOG( "no song" );
117 return;
118 }
119
120 memset( m_pMainOut_L, 0, nFrames * sizeof( float ) );
121 memset( m_pMainOut_R, 0, nFrames * sizeof( float ) );
122
123 // Track output queues are zeroed by
124 // audioEngine_process_clearAudioBuffers()
125
126 for ( auto& pComponent : *pSong->getComponents() ) {
127 pComponent->reset_outs(nFrames);
128 }
129
130 // Max notes limit
131 int nMaxNotes = Preferences::get_instance()->m_nMaxNotes;
132 while ( ( int )m_playingNotesQueue.size() > nMaxNotes ) {
133 Note * pOldNote = m_playingNotesQueue[ 0 ];
135 pOldNote->get_instrument()->dequeue();
136 WARNINGLOG( QString( "Number of playing notes [%1] exceeds maximum [%2]. Dropping note [%3]" )
137 .arg( m_playingNotesQueue.size() ).arg( nMaxNotes )
138 .arg( pOldNote->toQString() ) );
139 delete pOldNote; // FIXME: send note-off instead of removing the note from the list?
140 }
141
142 // Render next `nFrames` audio frames of all playing notes.
143 unsigned i = 0;
144 Note* pNote;
145 while ( i < m_playingNotesQueue.size() ) {
146 pNote = m_playingNotesQueue[ i ];
147 if ( renderNote( pNote, nFrames ) ) {
148 // End of note was reached during rendering.
149 m_playingNotesQueue.erase( m_playingNotesQueue.begin() + i );
150 pNote->get_instrument()->dequeue();
151 m_queuedNoteOffs.push_back( pNote );
152 } else {
153 // As finished notes are poped above
154 ++i;
155 }
156 }
157
158 if ( m_queuedNoteOffs.size() > 0 ) {
159 MidiOutput* pMidiOut = pHydrogen->getMidiOutput();
160 if ( pMidiOut != nullptr ) {
161 //Queue midi note off messages for notes that have a length specified for them
162 while ( ! m_queuedNoteOffs.empty() ) {
163 pNote = m_queuedNoteOffs[0];
164
165 if ( ! pNote->get_instrument()->is_muted() ){
166 pMidiOut->handleQueueNoteOff(
167 pNote->get_instrument()->get_midi_out_channel(),
168 pNote->get_midi_key(),
169 pNote->get_midi_velocity() );
170 }
171
172 m_queuedNoteOffs.erase( m_queuedNoteOffs.begin() );
173
174 if ( pNote != nullptr ){
175 delete pNote;
176 }
177
178 pNote = nullptr;
179 }
180 }
181 }
182
183 processPlaybackTrack(nFrames);
184}
185
187 return m_playingNotesQueue.size() > 0;
188}
189
191{
192 assert( pNote );
193 if ( pNote == nullptr ) {
194 ERRORLOG( "Invalid note" );
195 return;
196 }
197
198 pNote->get_adsr()->attack();
199 auto pInstr = pNote->get_instrument();
200
201 // mute group
202 int nMuteGrp = pInstr->get_mute_group();
203 if ( nMuteGrp != -1 ) {
204 // remove all notes using the same mute group
205 for ( const auto& pOtherNote: m_playingNotesQueue ) { // delete older note
206 if ( ( pOtherNote->get_instrument() != pInstr ) &&
207 ( pOtherNote->get_instrument()->get_mute_group() == nMuteGrp ) ) {
208 pOtherNote->get_adsr()->release();
209 }
210 }
211 }
212
213 //note off notes
214 if ( pNote->get_note_off() ){
215 for ( const auto& pOtherNote: m_playingNotesQueue ) {
216 if ( ( pOtherNote->get_instrument() == pInstr ) ) {
217 //ERRORLOG("note_off");
218 pOtherNote->get_adsr()->release();
219 }
220 }
221 }
222
223 pInstr->enqueue();
224 if ( ! pNote->get_note_off() ){
225 m_playingNotesQueue.push_back( pNote );
226 }
227}
228
230{
231 for ( const auto& pNote: m_playingNotesQueue ) {
232 if ( ( pNote->get_midi_msg() == key) ) {
233 pNote->get_adsr()->release();
234 }
235 }
236}
237
238
242{
243 auto pInstr = pNote->get_instrument();
244 // find the notes using the same instrument, and release them
245 for ( const auto& pNote: m_playingNotesQueue ) {
246 if ( pNote->get_instrument() == pInstr ) {
247 pNote->get_adsr()->release();
248 }
249 }
250
251 delete pNote;
252}
253
254
255// functions for pan parameters and laws-----------------
256
257float Sampler::getRatioPan( float fPan_L, float fPan_R ) {
258 if ( fPan_L < 0. || fPan_R < 0. || ( fPan_L == 0. && fPan_R == 0.) ) { // invalid input
259 WARNINGLOG( "Invalid (panL, panR): both zero or some is negative. Pan set to center." );
260 return 0.; // default central value
261 } else {
262 if ( fPan_L >= fPan_R ) {
263 return fPan_R / fPan_L - 1.;
264 } else {
265 return 1. - fPan_L / fPan_R;
266 }
267 }
268}
269
270
272 // the straight polygonal pan law interpreting fPan as the "ratio" parameter
273 if ( fPan <= 0 ) {
274 return 1.;
275 } else {
276 return ( 1. - fPan );
277 }
278}
279
281 // the constant power pan law interpreting fPan as the "ratio" parameter
282 if ( fPan <= 0 ) {
283 return 1. / sqrt( 1 + ( 1. + fPan ) * ( 1. + fPan ) );
284 } else {
285 return ( 1. - fPan ) / sqrt( 1 + ( 1. - fPan ) * ( 1. - fPan ) );
286 }
287}
288
289float Sampler::ratioConstSumPanLaw( float fPan ) {
290 // the constant Sum pan law interpreting fPan as the "ratio" parameter
291 if ( fPan <= 0 ) {
292 return 1. / ( 2. + fPan );
293 } else {
294 return ( 1. - fPan ) / ( 2. - fPan );
295 }
296}
297
299 // the constant power pan law interpreting fPan as the "linear" parameter
300 if ( fPan <= 0 ) {
301 return 1.;
302 } else {
303 return ( 1. - fPan ) / ( 1. + fPan );
304 }
305}
306
308 // the constant power pan law interpreting fPan as the "linear" parameter
309 return ( 1. - fPan ) / sqrt( 2. * ( 1 + fPan * fPan ) );
310}
311
312float Sampler::linearConstSumPanLaw( float fPan ) {
313 // the constant Sum pan law interpreting fPan as the "linear" parameter
314 return ( 1. - fPan ) * 0.5;
315}
316
318 // the constant power pan law interpreting fPan as the "polar" parameter
319 float fTheta = 0.25 * M_PI * ( fPan + 1 );
320 if ( fPan <= 0 ) {
321 return 1.;
322 } else {
323 return cos( fTheta ) / sin( fTheta );
324 }
325}
326
328 // the constant power pan law interpreting fPan as the "polar" parameter
329 float fTheta = 0.25 * M_PI * ( fPan + 1 );
330 return cos( fTheta );
331}
332
333float Sampler::polarConstSumPanLaw( float fPan ) {
334 // the constant Sum pan law interpreting fPan as the "polar" parameter
335 float fTheta = 0.25 * M_PI * ( fPan + 1 );
336 return cos( fTheta ) / ( cos( fTheta ) + sin( fTheta ) );
337}
338
340 // the straight polygonal pan law interpreting fPan as the "quadratic" parameter
341 if ( fPan <= 0 ) {
342 return 1.;
343 } else {
344 return sqrt( ( 1. - fPan ) / ( 1. + fPan ) );
345 }
346}
347
349 // the constant power pan law interpreting fPan as the "quadratic" parameter
350 return sqrt( ( 1. - fPan ) * 0.5 );
351}
352
354 // the constant Sum pan law interpreting fPan as the "quadratic" parameter
355 return sqrt( 1. - fPan ) / ( sqrt( 1. - fPan ) + sqrt( 1. + fPan ) );
356}
357
358float Sampler::linearConstKNormPanLaw( float fPan, float k ) {
359 // the constant k norm pan law interpreting fPan as the "linear" parameter
360 return ( 1. - fPan ) / pow( ( pow( (1. - fPan), k ) + pow( (1. + fPan), k ) ), 1./k );
361}
362
363float Sampler::quadraticConstKNormPanLaw( float fPan, float k ) {
364 // the constant k norm pan law interpreting fPan as the "quadratic" parameter
365 return sqrt( 1. - fPan ) / pow( ( pow( (1. - fPan), 0.5 * k ) + pow( (1. + fPan), 0.5 * k ) ), 1./k );
366}
367
368float Sampler::polarConstKNormPanLaw( float fPan, float k ) {
369 // the constant k norm pan law interpreting fPan as the "polar" parameter
370 float fTheta = 0.25 * M_PI * ( fPan + 1 );
371 float cosTheta = cos( fTheta );
372 return cosTheta / pow( ( pow( cosTheta, k ) + pow( sin( fTheta ), k ) ), 1./k );
373}
374
375float Sampler::ratioConstKNormPanLaw( float fPan, float k) {
376 // the constant k norm pan law interpreting fPan as the "ratio" parameter
377 if ( fPan <= 0 ) {
378 return 1. / pow( ( 1. + pow( (1. + fPan), k ) ), 1./k );
379 } else {
380 return ( 1. - fPan ) / pow( ( 1. + pow( (1. - fPan), k ) ), 1./k );
381 }
382}
383
384// function to direct the computation to the selected pan law.
385inline float Sampler::panLaw( float fPan, std::shared_ptr<Song> pSong ) {
386 int nPanLawType = pSong->getPanLawType();
387 if ( nPanLawType == RATIO_STRAIGHT_POLYGONAL ) {
388 return ratioStraightPolygonalPanLaw( fPan );
389 } else if ( nPanLawType == RATIO_CONST_POWER ) {
390 return ratioConstPowerPanLaw( fPan );
391 } else if ( nPanLawType == RATIO_CONST_SUM ) {
392 return ratioConstSumPanLaw( fPan );
393 } else if ( nPanLawType == LINEAR_STRAIGHT_POLYGONAL ) {
394 return linearStraightPolygonalPanLaw( fPan );
395 } else if ( nPanLawType == LINEAR_CONST_POWER ) {
396 return linearConstPowerPanLaw( fPan );
397 } else if ( nPanLawType == LINEAR_CONST_SUM ) {
398 return linearConstSumPanLaw( fPan );
399 } else if ( nPanLawType == POLAR_STRAIGHT_POLYGONAL ) {
400 return polarStraightPolygonalPanLaw( fPan );
401 } else if ( nPanLawType == POLAR_CONST_POWER ) {
402 return polarConstPowerPanLaw( fPan );
403 } else if ( nPanLawType == POLAR_CONST_SUM ) {
404 return polarConstSumPanLaw( fPan );
405 } else if ( nPanLawType == QUADRATIC_STRAIGHT_POLYGONAL ) {
407 } else if ( nPanLawType == QUADRATIC_CONST_POWER ) {
408 return quadraticConstPowerPanLaw( fPan );
409 } else if ( nPanLawType == QUADRATIC_CONST_SUM ) {
410 return quadraticConstSumPanLaw( fPan );
411 } else if ( nPanLawType == LINEAR_CONST_K_NORM ) {
412 return linearConstKNormPanLaw( fPan, pSong->getPanLawKNorm() );
413 } else if ( nPanLawType == POLAR_CONST_K_NORM ) {
414 return polarConstKNormPanLaw( fPan, pSong->getPanLawKNorm() );
415 } else if ( nPanLawType == RATIO_CONST_K_NORM ) {
416 return ratioConstKNormPanLaw( fPan, pSong->getPanLawKNorm() );
417 } else if ( nPanLawType == QUADRATIC_CONST_K_NORM ) {
418 return quadraticConstKNormPanLaw( fPan, pSong->getPanLawKNorm() );
419 } else {
420 WARNINGLOG( "Unknown pan law type. Set default." );
421 pSong->setPanLawType( RATIO_STRAIGHT_POLYGONAL );
422 return ratioStraightPolygonalPanLaw( fPan );
423 }
424}
425
427 if ( m_playingNotesQueue.size() == 0 ) {
428 return;
429 }
430
431 for ( auto ppNote : m_playingNotesQueue ) {
432 ppNote->computeNoteStart();
433
434 // For notes of custom length we have to rescale the amount of the
435 // sample still left for rendering to properly adopt the tempo change.
436 //
437 // This is only done on manual tempo changes, like changes through the
438 // BPM widget, but not when passing a tempo marker. In case
439 // UsedTickSize() of a note is -1, the timeline was activated when
440 // picked up by the audio engine.
441 //
442 // BUG adding/deleting a tempo marker or toggling the timeline is not
443 // properly handled in here. But since this only occurs seldomly and
444 // this code only takes effect if a note with custom length is currently
445 // rendered, we skip this edge case.
446 if ( ppNote->isPartiallyRendered() && ppNote->get_length() != -1 &&
447 ppNote->getUsedTickSize() != -1 ) {
448
449 double fTickMismatch;
450 const auto pSong = Hydrogen::get_instance()->getSong();
451
452 // Do so for all layers of all components current processed.
453 for ( auto& [ nnCompo, ppLayer ] : ppNote->get_layers_selected() ) {
454 const auto pSample = ppNote->getSample( nnCompo,
455 ppLayer->nSelectedLayer );
456 const int nNewNoteLength =
458 ppNote->get_position() + ppNote->get_length(),
459 &fTickMismatch, pSample->get_sample_rate() ) -
461 ppNote->get_position(), &fTickMismatch,
462 pSample->get_sample_rate() );
463
464 // The ratio between the old and new note length determines the
465 // scaling of the length. This is only applied to the part of
466 // the sample _not_ rendered yet to ensure consistency.
467 //
468 // BUG When handling several tempo changes while rendering a
469 // single note, calculating the ratio between note lengths is
470 // not a proper drop in for the tempo change anymore as the
471 // original note length and not the patched one from the last
472 // change is required. But this is too much of an edge-case and
473 // won't be covered here.
474 const int nSamplePosition =
475 static_cast<int>(std::floor(ppLayer->fSamplePosition));
476
477 ppLayer->nNoteLength = nSamplePosition +
478 static_cast<int>(std::round(
479 static_cast<float>(ppLayer->nNoteLength - nSamplePosition) *
480 nNewNoteLength /
481 static_cast<float>(ppLayer->nNoteLength)));
482 }
483 }
484 }
485}
486
488 if ( m_playingNotesQueue.size() == 0 ) {
489 return;
490 }
491
492 const long nTickOffset =
493 static_cast<long>(std::floor(Hydrogen::get_instance()->getAudioEngine()->
494 getTransportPosition()->getTickOffsetSongSize()));
495
496 for ( auto nnote : m_playingNotesQueue ) {
497
498 // DEBUGLOG( QString( "pos: %1 -> %2, nTickOffset: %3, note: %4" )
499 // .arg( nnote->get_position() )
500 // .arg( std::max( nnote->get_position() + nTickOffset,
501 // static_cast<long>(0) ) )
502 // .arg( nTickOffset )
503 // .arg( nnote->toQString( "", true ) ) );
504
505 nnote->set_position( std::max( nnote->get_position() + nTickOffset,
506 static_cast<long>(0) ) );
507 nnote->computeNoteStart();
508
509 // DEBUGLOG( QString( "new note: %1" )
510 // .arg( nnote->toQString( "", true ) ) );
511
512 }
513}
514
515//------------------------------------------------------------------
516
517bool Sampler::renderNote( Note* pNote, unsigned nBufferSize )
518{
519 auto pHydrogen = Hydrogen::get_instance();
520 auto pSong = pHydrogen->getSong();
521 if ( pSong == nullptr ) {
522 ERRORLOG( "no song" );
523 return true;
524 }
525
526 auto pInstr = pNote->get_instrument();
527 if ( pInstr == nullptr ) {
528 ERRORLOG( "NULL instrument" );
529 return true;
530 }
531
532 long long nFrame;
533 auto pAudioDriver = pHydrogen->getAudioOutput();
534 if ( pAudioDriver == nullptr ) {
535 ERRORLOG( "AudioDriver is not ready!" );
536 return true;
537 }
538
539 auto pAudioEngine = pHydrogen->getAudioEngine();
540 if ( pAudioEngine->getState() == AudioEngine::State::Playing ||
541 pAudioEngine->getState() == AudioEngine::State::Testing ) {
542 nFrame = pAudioEngine->getTransportPosition()->getFrame();
543 } else {
544 // use this to support realtime events when transport is not
545 // rolling.
546 nFrame = pAudioEngine->getRealtimeFrame();
547 }
548
549 // Only if the Sampler has not started rendering the note yet we
550 // care about its starting position. Else we would encounter
551 // glitches when relocating transport during playback or starting
552 // transport while using realtime playback.
553 long long nInitialBufferPos = 0;
554 if ( ! pNote->isPartiallyRendered() ) {
555 long long nNoteStartInFrames = pNote->getNoteStart();
556
557 // DEBUGLOG(QString( "nFrame: %1, note pos: %2, pAudioEngine->getTransportPosition()->getTickSize(): %3, pAudioEngine->getTransportPosition()->getTick(): %4, pAudioEngine->getTransportPosition()->getFrame(): %5, nNoteStartInFrames: %6 ")
558 // .arg( nFrame ).arg( pNote->get_position() )
559 // .arg( pAudioEngine->getTransportPosition()->getTickSize() )
560 // .arg( pAudioEngine->getTransportPosition()->getTick() )
561 // .arg( pAudioEngine->getTransportPosition()->getFrame() )
562 // .arg( nNoteStartInFrames )
563 // .append( pNote->toQString( "", true ) ) );
564
565 if ( nNoteStartInFrames > nFrame ) {
566 // The note doesn't start right at the beginning of the
567 // buffer rendered in this cycle.
568 nInitialBufferPos = nNoteStartInFrames - nFrame;
569
570 if ( nBufferSize < nInitialBufferPos ) {
571 // this note is not valid. it's in the future...let's skip it....
572 ERRORLOG( QString( "Note pos in the future?? nFrame: %1, note start: %2, nInitialBufferPos: %3, nBufferSize: %4" )
573 .arg( nFrame ).arg( pNote->getNoteStart() )
574 .arg( nInitialBufferPos ).arg( nBufferSize ) );
575
576 return true;
577 }
578 }
579 }
580
581 // new instrument and note pan interaction--------------------------
582 // notePan moves the RESULTANT pan in a smaller pan range centered at instrumentPan
583
601 float fPan = pInstr->getPan() + pNote->getPan() * ( 1 - fabs( pInstr->getPan() ) );
602
603 // Pass fPan to the Pan Law
604 float fPan_L = panLaw( fPan, pSong );
605 float fPan_R = panLaw( -fPan, pSong );
606
607 // In PreFader mode of the per track output of the JACK driver we
608 // disregard the instrument pan along with all other settings
609 // available in the Mixer. The Note pan, however, will be used.
610 float fNotePan_L = 0;
611 float fNotePan_R = 0;
612 if ( pHydrogen->hasJackAudioDriver() &&
615 fNotePan_L = panLaw( pNote->getPan(), pSong );
616 fNotePan_R = panLaw( -1 * pNote->getPan(), pSong );
617 }
618 //---------------------------------------------------------
619
620 auto pComponents = pInstr->get_components();
621 bool nReturnValues[ pComponents->size() ];
622
623 for( int i = 0; i < pComponents->size(); i++ ){
624 nReturnValues[i] = false;
625 }
626
627 int nReturnValueIndex = 0;
628 int nAlreadySelectedLayer = -1;
629 bool bComponentFound = false;
630
631 for ( const auto& pCompo : *pComponents ) {
632 std::shared_ptr<DrumkitComponent> pMainCompo = nullptr;
633
634 if ( pNote->get_specific_compo_id() != -1 &&
635 pNote->get_specific_compo_id() != pCompo->get_drumkit_componentID() ) {
636 nReturnValueIndex++;
637 continue;
638 }
639 bComponentFound = true;
640
641 if ( pInstr->is_preview_instrument() ||
642 pInstr->is_metronome_instrument() ){
643 pMainCompo = pSong->getComponents()->front();
644 } else {
645 int nComponentID = pCompo->get_drumkit_componentID();
646 if ( nComponentID >= 0 ) {
647 pMainCompo = pSong->getComponent( nComponentID );
648 } else {
649 /* Invalid component found. This is possible on loading older or broken song files. */
650 pMainCompo = pSong->getComponents()->front();
651 }
652 }
653
654 assert(pMainCompo);
655
656 auto pSample = pNote->getSample( pCompo->get_drumkit_componentID(),
657 nAlreadySelectedLayer );
658 if ( pSample == nullptr ) {
659 nReturnValues[nReturnValueIndex] = true;
660 nReturnValueIndex++;
661 continue;
662 }
663
664 auto pSelectedLayer =
665 pNote->get_layer_selected( pCompo->get_drumkit_componentID() );
666
667 // For round robin and random selection we will use the same
668 // layer again for all other samples.
669 if ( nAlreadySelectedLayer != -1 &&
670 pInstr->sample_selection_alg() != Instrument::VELOCITY ) {
671 nAlreadySelectedLayer = pSelectedLayer->nSelectedLayer;
672 }
673
674 if( pSelectedLayer->nSelectedLayer == -1 ) {
675 ERRORLOG( "Sample selection did not work." );
676 nReturnValues[nReturnValueIndex] = true;
677 nReturnValueIndex++;
678 continue;
679 }
680 auto pLayer = pCompo->get_layer( pSelectedLayer->nSelectedLayer );
681 float fLayerGain = pLayer->get_gain();
682 float fLayerPitch = pLayer->get_pitch();
683
684 if ( pSelectedLayer->fSamplePosition >= pSample->get_frames() ) {
685 // Due to rounding errors in renderNoteResample() the
686 // sample position can occassionaly exceed the maximum
687 // frames of a sample. AFAICS this is not itself
688 // harmful. So, we just log a warning if the difference is
689 // larger, which might be caused by a different problem.
690 if ( pSelectedLayer->fSamplePosition >= pSample->get_frames() + 3 ) {
691 WARNINGLOG( QString( "sample position [%1] out of bounds [0,%2]. The layer has been resized during note play?" )
692 .arg( pSelectedLayer->fSamplePosition )
693 .arg( pSample->get_frames() ) );
694 }
695 nReturnValues[nReturnValueIndex] = true;
696 nReturnValueIndex++;
697 continue;
698 }
699
700 float fCost_L = 1.0f;
701 float fCost_R = 1.0f;
702 float fCostTrack_L = 1.0f;
703 float fCostTrack_R = 1.0f;
704
705 bool bIsMutedForExport = ( pHydrogen->getIsExportSessionActive() &&
706 ! pInstr->is_currently_exported() );
707 bool bAnyInstrumentIsSoloed = pSong->getInstrumentList()->isAnyInstrumentSoloed();
708 bool bIsMutedBecauseOfSolo = ( bAnyInstrumentIsSoloed &&
709 ! pInstr->is_soloed() );
710
711 /*
712 * Is instrument muted?
713 *
714 * This can be the case either if:
715 * - the song, instrument or component is muted
716 * - if we're in an export session and we're doing per-instruments exports,
717 * but this instrument is not currently being exported.
718 * - if at least one instrument is soloed (but not this instrument)
719 */
720 if ( bIsMutedForExport || pInstr->is_muted() || pSong->getIsMuted() ||
721 pMainCompo->is_muted() || bIsMutedBecauseOfSolo) {
722 fCost_L = 0.0;
723 fCost_R = 0.0;
726 fCostTrack_L = 0.0;
727 fCostTrack_R = 0.0;
728 }
729
730 } else {
731 float fMonoGain = 1.0;
732 if ( pInstr->get_apply_velocity() ) {
733 fMonoGain *= pNote->get_velocity(); // note velocity
734 }
735
736 fMonoGain *= fLayerGain; // layer gain
737 fMonoGain *= pInstr->get_gain(); // instrument gain
738 fMonoGain *= pCompo->get_gain(); // Component gain
739 fMonoGain *= pMainCompo->get_volume(); // Component volument
740 fMonoGain *= pInstr->get_volume(); // instrument volume
741 fMonoGain *= pSong->getVolume(); // song volume
742
743 fCost_L = fMonoGain * fPan_L; // pan
744 fCost_R = fMonoGain * fPan_R; // pan
747 fCostTrack_R = fCost_R * 2;
748 fCostTrack_L = fCost_L * 2;
749 }
750 }
751
752 // direct track outputs only use velocity
755 if ( pInstr->get_apply_velocity() ) {
756 fCostTrack_L *= pNote->get_velocity();
757 }
758 fCostTrack_L *= fLayerGain;
759
760 fCostTrack_R = fCostTrack_L;
761
762 fCostTrack_L *= fNotePan_L;
763 fCostTrack_R *= fNotePan_R;
764 }
765
766 // Se non devo fare resample (drumkit) posso evitare di utilizzare i float e gestire il tutto in
767 // maniera ottimizzata
768 // constant^12 = 2, so constant = 2^(1/12) = 1.059463.
769 // float nStep = 1.0;1.0594630943593
770
771 float fTotalPitch = pNote->get_total_pitch() + fLayerPitch;
772
773 // Once the Sampler does start rendering a note we also push
774 // it to all connected MIDI devices.
775 if ( (int) pSelectedLayer->fSamplePosition == 0 && ! pInstr->is_muted() ) {
776 if ( pHydrogen->getMidiOutput() != nullptr ){
777 pHydrogen->getMidiOutput()->handleQueueNote( pNote );
778 }
779 }
780
781 // Actual rendering.
782 nReturnValues[nReturnValueIndex] = renderNoteResample( pSample, pNote, pSelectedLayer, pCompo, pMainCompo, nBufferSize, nInitialBufferPos, fCost_L, fCost_R, fCostTrack_L, fCostTrack_R, fLayerPitch );
783
784 nReturnValueIndex++;
785 }
786
787 // Sanity check whether the note could be rendered.
788 if ( ! bComponentFound ) {
789 ERRORLOG( QString( "Specific note component [%1] not found in instrument associated with note: [%2]" )
790 .arg( pNote->get_specific_compo_id() )
791 .arg( pNote->toQString() ) );
792 return true;
793 }
794
795 for ( const auto& bReturnValue : nReturnValues ) {
796 if ( ! bReturnValue ) {
797 return false;
798 }
799 }
800 return true;
801}
802
803bool Sampler::processPlaybackTrack(int nBufferSize)
804{
805 Hydrogen* pHydrogen = Hydrogen::get_instance();
806 auto pAudioDriver = pHydrogen->getAudioOutput();
807 auto pAudioEngine = pHydrogen->getAudioEngine();
808 std::shared_ptr<Song> pSong = pHydrogen->getSong();
809
810 if ( pSong == nullptr ) {
811 ERRORLOG( "No song set yet" );
812 return true;
813 }
814
815 if ( pAudioDriver == nullptr ) {
816 ERRORLOG( "AudioDriver is not ready!" );
817 return true;
818 }
819
821 ( pAudioEngine->getState() != AudioEngine::State::Playing ||
822 pAudioEngine->getState() == AudioEngine::State::Testing ) ||
823 pHydrogen->getMode() != Song::Mode::Song ) {
824 return true;
825 }
826
827 const auto pCompo = m_pPlaybackTrackInstrument->get_components()->front();
828 if ( pCompo == nullptr ) {
829 ERRORLOG( "Invalid component of playback instrument" );
830 return true;
831 }
832
833 auto pSample = pCompo->get_layer(0)->get_sample();
834 if ( pSample == nullptr ) {
835 ERRORLOG( "Unable to process playback track" );
838 // Disable the playback track
839 pHydrogen->loadPlaybackTrack( "" );
841 return true;
842 }
843
844 float fVal_L;
845 float fVal_R;
846
847 auto pSample_data_L = pSample->get_data_l();
848 auto pSample_data_R = pSample->get_data_r();
849
850 float fInstrPeak_L = m_pPlaybackTrackInstrument->get_peak_l(); // this value will be reset to 0 by the mixer..
851 float fInstrPeak_R = m_pPlaybackTrackInstrument->get_peak_r(); // this value will be reset to 0 by the mixer..
852
853 int nAvail_bytes = 0;
854 int nInitialBufferPos = 0;
855
856 const long long nFrame = pAudioEngine->getTransportPosition()->getFrame();
857 const long long nFrameOffset =
858 pAudioEngine->getTransportPosition()->getFrameOffsetTempo();
859
860 if ( pSample->get_sample_rate() == pAudioDriver->getSampleRate() ) {
861 // No resampling
862 m_nPlayBackSamplePosition = nFrame - nFrameOffset;
863
864 nAvail_bytes = pSample->get_frames() - m_nPlayBackSamplePosition;
865
866 if ( nAvail_bytes > nBufferSize ) {
867 nAvail_bytes = nBufferSize;
868 }
869
870 int nInitialSamplePos = ( int ) m_nPlayBackSamplePosition;
871 int nSamplePos = nInitialSamplePos;
872
873 int nFinalBufferPos = nInitialBufferPos + nAvail_bytes;
874
875 if ( m_nPlayBackSamplePosition > pSample->get_frames() ) {
876 //playback track has ended..
877 return true;
878 }
879
880 for ( int nBufferPos = nInitialBufferPos; nBufferPos < nFinalBufferPos; ++nBufferPos ) {
881 fVal_L = pSample_data_L[ nSamplePos ];
882 fVal_R = pSample_data_R[ nSamplePos ];
883
884 fVal_L = fVal_L * 1.0f * pSong->getPlaybackTrackVolume(); //costr
885 fVal_R = fVal_R * 1.0f * pSong->getPlaybackTrackVolume(); //cost l
886
887 //pDrumCompo->set_outs( nBufferPos, fVal_L, fVal_R );
888
889 // to main mix
890 if ( fVal_L > fInstrPeak_L ) {
891 fInstrPeak_L = fVal_L;
892 }
893 if ( fVal_R > fInstrPeak_R ) {
894 fInstrPeak_R = fVal_R;
895 }
896
897 m_pMainOut_L[nBufferPos] += fVal_L;
898 m_pMainOut_R[nBufferPos] += fVal_R;
899
900 ++nSamplePos;
901 }
902 } else {
903 //Perform resampling
904 double fSamplePos = 0;
905 int nSampleFrames = pSample->get_frames();
906 float fStep = 1;
907 fStep *= ( float )pSample->get_sample_rate() / pAudioDriver->getSampleRate(); // Adjust for audio driver sample rate
908
909
910 if ( nFrame == 0 ){
911 fSamplePos = 0;
912 } else {
913 fSamplePos = ( nFrame - nFrameOffset ) * fStep;
914 }
915
916 nAvail_bytes = ( int )( ( float )( pSample->get_frames() - fSamplePos ) / fStep );
917
918 if ( nAvail_bytes > nBufferSize ) {
919 nAvail_bytes = nBufferSize;
920 }
921
922 int nFinalBufferPos = nInitialBufferPos + nAvail_bytes;
923
924 for ( int nBufferPos = nInitialBufferPos; nBufferPos < nFinalBufferPos; ++nBufferPos ) {
925 int nSamplePos = ( int ) fSamplePos;
926 double fDiff = fSamplePos - nSamplePos;
927 if ( ( nSamplePos + 1 ) >= nSampleFrames ) {
928 //we reach the last audioframe.
929 //set this last frame to zero do nothing wrong.
930 fVal_L = 0.0;
931 fVal_R = 0.0;
932 } else {
933 // some interpolation methods need 4 frames data.
934 float last_l;
935 float last_r;
936 if ( ( nSamplePos + 2 ) >= nSampleFrames ) {
937 last_l = 0.0;
938 last_r = 0.0;
939 } else {
940 last_l = pSample_data_L[nSamplePos + 2];
941 last_r = pSample_data_R[nSamplePos + 2];
942 }
943
944 switch( m_interpolateMode ){
945
946 case Interpolation::InterpolateMode::Linear:
947 fVal_L = pSample_data_L[nSamplePos] * (1 - fDiff ) + pSample_data_L[nSamplePos + 1] * fDiff;
948 fVal_R = pSample_data_R[nSamplePos] * (1 - fDiff ) + pSample_data_R[nSamplePos + 1] * fDiff;
949 break;
950 case Interpolation::InterpolateMode::Cosine:
951 fVal_L = Interpolation::cosine_Interpolate( pSample_data_L[nSamplePos], pSample_data_L[nSamplePos + 1], fDiff);
952 fVal_R = Interpolation::cosine_Interpolate( pSample_data_R[nSamplePos], pSample_data_R[nSamplePos + 1], fDiff);
953 break;
954 case Interpolation::InterpolateMode::Third:
955 fVal_L = Interpolation::third_Interpolate( pSample_data_L[ nSamplePos -1], pSample_data_L[nSamplePos], pSample_data_L[nSamplePos + 1], last_l, fDiff);
956 fVal_R = Interpolation::third_Interpolate( pSample_data_R[ nSamplePos -1], pSample_data_R[nSamplePos], pSample_data_R[nSamplePos + 1], last_r, fDiff);
957 break;
958 case Interpolation::InterpolateMode::Cubic:
959 fVal_L = Interpolation::cubic_Interpolate( pSample_data_L[ nSamplePos -1], pSample_data_L[nSamplePos], pSample_data_L[nSamplePos + 1], last_l, fDiff);
960 fVal_R = Interpolation::cubic_Interpolate( pSample_data_R[ nSamplePos -1], pSample_data_R[nSamplePos], pSample_data_R[nSamplePos + 1], last_r, fDiff);
961 break;
962 case Interpolation::InterpolateMode::Hermite:
963 fVal_L = Interpolation::hermite_Interpolate( pSample_data_L[ nSamplePos -1], pSample_data_L[nSamplePos], pSample_data_L[nSamplePos + 1], last_l, fDiff);
964 fVal_R = Interpolation::hermite_Interpolate( pSample_data_R[ nSamplePos -1], pSample_data_R[nSamplePos], pSample_data_R[nSamplePos + 1], last_r, fDiff);
965 break;
966 }
967 }
968
969 fVal_L *= pSong->getPlaybackTrackVolume();
970 fVal_R *= pSong->getPlaybackTrackVolume();
971
972 if ( fVal_L > fInstrPeak_L ) {
973 fInstrPeak_L = fVal_L;
974 }
975 if ( fVal_R > fInstrPeak_R ) {
976 fInstrPeak_R = fVal_R;
977 }
978
979 m_pMainOut_L[nBufferPos] += fVal_L;
980 m_pMainOut_R[nBufferPos] += fVal_R;
981
982
983 fSamplePos += fStep;
984 } //for
985 }
986
987 m_pPlaybackTrackInstrument->set_peak_l( fInstrPeak_L );
988 m_pPlaybackTrackInstrument->set_peak_r( fInstrPeak_R );
989
990 return true;
991}
992
994 std::shared_ptr<Sample> pSample,
995 Note *pNote,
996 std::shared_ptr<SelectedLayerInfo> pSelectedLayerInfo,
997 std::shared_ptr<InstrumentComponent> pCompo,
998 std::shared_ptr<DrumkitComponent> pDrumCompo,
999 int nBufferSize,
1000 int nInitialBufferPos,
1001 float fCost_L,
1002 float fCost_R,
1003 float fCostTrack_L,
1004 float fCostTrack_R,
1005 float fLayerPitch
1006)
1007{
1008 auto pHydrogen = Hydrogen::get_instance();
1009 auto pAudioDriver = pHydrogen->getAudioOutput();
1010 auto pSong = pHydrogen->getSong();
1011
1012 if ( pSong == nullptr ) {
1013 ERRORLOG( "Invalid song" );
1014 return true;
1015 }
1016
1017 if ( pNote == nullptr ) {
1018 ERRORLOG( "Invalid note" );
1019 return true;
1020 }
1021
1022 if ( pAudioDriver == nullptr ) {
1023 ERRORLOG( "AudioDriver is not ready!" );
1024 return true;
1025 }
1026
1027 auto pInstrument = pNote->get_instrument();
1028 if ( pInstrument == nullptr ) {
1029 ERRORLOG( "Invalid note instrument" );
1030 return true;
1031 }
1032
1033 const float fNotePitch = pNote->get_total_pitch() + fLayerPitch;
1034 const bool bResample = fNotePitch != 0 ||
1035 pSample->get_sample_rate() != pAudioDriver->getSampleRate();
1036
1037 float fStep;
1038 if ( bResample ){
1039 fStep = Note::pitchToFrequency( fNotePitch );
1040
1041 // Adjust for audio driver sample rate
1042 fStep *= static_cast<float>(pSample->get_sample_rate()) /
1043 static_cast<float>(pAudioDriver->getSampleRate());
1044 }
1045 else {
1046 fStep = 1;
1047 }
1048
1049 auto pSample_data_L = pSample->get_data_l();
1050 auto pSample_data_R = pSample->get_data_r();
1051 const int nSampleFrames = pSample->get_frames();
1052 // The number of frames of the sample left to process.
1053 const int nRemainingFrames = static_cast<int>(
1054 (static_cast<float>(nSampleFrames) - pSelectedLayerInfo->fSamplePosition) /
1055 fStep );
1056
1057 bool bRetValue = true; // the note is ended
1058 int nAvail_bytes;
1059 if ( nRemainingFrames > nBufferSize - nInitialBufferPos ) {
1060 // It The number of frames of the sample left to process
1061 // exceeds what's available in the current process cycle of
1062 // the Sampler. Clip it.
1063 nAvail_bytes = nBufferSize - nInitialBufferPos;
1064 // the note is not ended yet
1065 bRetValue = false;
1066 }
1067 else if ( pInstrument->is_filter_active() && pNote->filter_sustain() ) {
1068 // If filter is causing note to ring, process more samples.
1069 nAvail_bytes = nBufferSize - nInitialBufferPos;
1070 }
1071 else {
1072 nAvail_bytes = nRemainingFrames;
1073 }
1074
1075 double fSamplePos = pSelectedLayerInfo->fSamplePosition;
1076 const int nFinalBufferPos = nInitialBufferPos + nAvail_bytes;
1077
1078 int nNoteEnd;
1079 // If the user set a custom length of the note in the PatternEditor, we will
1080 // use it to trigger the releases of the note. Otherwise, the whole sample
1081 // will be played back.
1082 if ( pNote->get_length() != -1 &&
1083 pNote->get_adsr()->getState() != ADSR::State::Release ) {
1084 if ( pSelectedLayerInfo->nNoteLength == -1 ) {
1085 // The length of a note is only calculated once when first
1086 // encountering it. This makes us robust again glitches due to tempo
1087 // changes.
1088 double fTickMismatch;
1089
1090 pSelectedLayerInfo->nNoteLength =
1092 pNote->get_position() + pNote->get_length(),
1093 &fTickMismatch, pSample->get_sample_rate() ) -
1095 pNote->get_position(), &fTickMismatch,
1096 pSample->get_sample_rate() );
1097 }
1098
1099 nNoteEnd = std::min(nFinalBufferPos + 1, static_cast<int>(
1100 (static_cast<float>(pSelectedLayerInfo->nNoteLength) -
1101 pSelectedLayerInfo->fSamplePosition) / fStep ));
1102
1103 if ( nNoteEnd < 0 ) {
1104 if ( ! pInstrument->is_filter_active() ) {
1105 // In case resonance filtering is active the sampler stops
1106 // rendering of the sample at the custom note length but let's
1107 // the filter itself ring on.
1108 ERRORLOG( QString( "Note end located within the previous processing cycle. nNoteEnd: %1, nNoteLength: %2, fSamplePosition: %3, nFinalBufferPos: %4, fStep: %5")
1109 .arg( nNoteEnd ).arg( pSelectedLayerInfo->nNoteLength )
1110 .arg( pSelectedLayerInfo->fSamplePosition )
1111 .arg( nFinalBufferPos ).arg( fStep ) );
1112 }
1113 nNoteEnd = 0;
1114 }
1115 }
1116 else {
1117 // Do not apply release but play the whole sample instead. In case we
1118 // already released a note of custom length, we will use the whole
1119 // buffer to apply the release decay.
1120 nNoteEnd = nFinalBufferPos + 1;
1121 }
1122
1123 float fInstrPeak_L = pInstrument->get_peak_l(); // this value will be reset to 0 by the mixer..
1124 float fInstrPeak_R = pInstrument->get_peak_r(); // this value will be reset to 0 by the mixer..
1125
1126 auto pADSR = pNote->get_adsr();
1127 float fVal_L;
1128 float fVal_R;
1129
1130#ifdef H2CORE_HAVE_JACK
1131 float* pTrackOutL = nullptr;
1132 float* pTrackOutR = nullptr;
1133
1134 if ( Preferences::get_instance()->m_bJackTrackOuts ) {
1135 auto pJackAudioDriver = dynamic_cast<JackAudioDriver*>( pAudioDriver );
1136 if ( pJackAudioDriver != nullptr ) {
1137 pTrackOutL = pJackAudioDriver->getTrackOut_L( pInstrument, pCompo );
1138 pTrackOutR = pJackAudioDriver->getTrackOut_R( pInstrument, pCompo );
1139 }
1140 }
1141#endif
1142
1143 float buffer_L[MAX_BUFFER_SIZE];
1144 float buffer_R[MAX_BUFFER_SIZE];
1145
1146 // Main rendering loop.
1147 // With some re-work, more of this could likely be vectorised fairly easily.
1148 // - assert no buffer aliasing
1149 // - template and multiple instantiations for is_filter_active x each interpolation method
1150 // - iterate LP IIR filter coefficients to longer IIR filter to fit vector width
1151 //
1152 for ( int nBufferPos = nInitialBufferPos; nBufferPos < nFinalBufferPos;
1153 ++nBufferPos ) {
1154
1155 int nSamplePos = static_cast<int>(fSamplePos);
1156 double fDiff = fSamplePos - nSamplePos;
1157 if ( ( nSamplePos - 1 ) >= nSampleFrames ) {
1158 //we reach the last audioframe.
1159 //set this last frame to zero do nothing wrong.
1160 fVal_L = 0.0;
1161 fVal_R = 0.0;
1162 } else {
1163 if ( ! bResample ) {
1164 if ( nSamplePos < nSampleFrames ) {
1165 fVal_L = pSample_data_L[ nSamplePos ];
1166 fVal_R = pSample_data_R[ nSamplePos ];
1167 } else {
1168 fVal_L = 0.0;
1169 fVal_R = 0.0;
1170 }
1171 }
1172 else {
1173 // Gather frame samples
1174 float l0, l1, l2, l3, r0, r1, r2, r3;
1175 // Short-circuit: the common case is that all required frames are within the sample.
1176 if ( nSamplePos >= 1 && nSamplePos + 2 < nSampleFrames ) {
1177 l0= pSample_data_L[ nSamplePos-1 ];
1178 l1 = pSample_data_L[ nSamplePos ];
1179 l2 = pSample_data_L[ nSamplePos+1 ];
1180 l3 = pSample_data_L[ nSamplePos+2 ];
1181 r0 = pSample_data_R[ nSamplePos-1 ];
1182 r1 = pSample_data_R[ nSamplePos ];
1183 r2 = pSample_data_R[ nSamplePos+1 ];
1184 r3 = pSample_data_R[ nSamplePos+2 ];
1185 } else {
1186 l0 = l1 = l2 = l3 = r0 = r1 = r2 = r3 = 0.0;
1187 // Some required frames are off the beginning or end of the sample.
1188 if ( nSamplePos >= 1 && nSamplePos < nSampleFrames + 1 ) {
1189 l0 = pSample_data_L[ nSamplePos-1 ];
1190 r0 = pSample_data_R[ nSamplePos-1 ];
1191 }
1192 // Each successive frame may be past the end of the sample so check individually.
1193 if ( nSamplePos < nSampleFrames ) {
1194 l1 = pSample_data_L[ nSamplePos ];
1195 r1 = pSample_data_R[ nSamplePos ];
1196 if ( nSamplePos+1 < nSampleFrames ) {
1197 l2 = pSample_data_L[ nSamplePos+1 ];
1198 r2 = pSample_data_R[ nSamplePos+1 ];
1199 if ( nSamplePos+2 < nSampleFrames ) {
1200 l3 = pSample_data_L[ nSamplePos+2 ];
1201 r3 = pSample_data_R[ nSamplePos+2 ];
1202 }
1203 }
1204 }
1205 }
1206
1207 // Interpolate frame values from Sample domain to audio output range
1208 switch ( m_interpolateMode ) {
1209 case Interpolation::InterpolateMode::Linear:
1210 fVal_L = l1 * (1 - fDiff ) + l2 * fDiff;
1211 fVal_R = r1 * (1 - fDiff ) + r2 * fDiff;
1212 break;
1213 case Interpolation::InterpolateMode::Cosine:
1214 fVal_L = Interpolation::cosine_Interpolate( l1, l2, fDiff);
1215 fVal_R = Interpolation::cosine_Interpolate( r1, r2, fDiff);
1216 break;
1217 case Interpolation::InterpolateMode::Third:
1218 fVal_L = Interpolation::third_Interpolate( l0, l1, l2, l3, fDiff);
1219 fVal_R = Interpolation::third_Interpolate( r0, r1, r2, r3, fDiff);
1220 break;
1221 case Interpolation::InterpolateMode::Cubic:
1222 fVal_L = Interpolation::cubic_Interpolate( l0, l1, l2, l3, fDiff);
1223 fVal_R = Interpolation::cubic_Interpolate( r0, r1, r2, r3, fDiff);
1224 break;
1225 case Interpolation::InterpolateMode::Hermite:
1226 fVal_L = Interpolation::hermite_Interpolate( l0, l1, l2, l3, fDiff);
1227 fVal_R = Interpolation::hermite_Interpolate( r0, r1, r2, r3, fDiff);
1228 break;
1229 }
1230 }
1231 }
1232
1233 buffer_L[nBufferPos] = fVal_L;
1234 buffer_R[nBufferPos] = fVal_R;
1235
1236 fSamplePos += fStep;
1237 }
1238
1239 if ( pADSR->applyADSR( buffer_L, buffer_R, nFinalBufferPos, nNoteEnd,
1240 fStep ) ) {
1241 bRetValue = true;
1242 }
1243
1244 // Low pass resonant filter
1245 if ( pInstrument->is_filter_active() ) {
1246 for ( int nBufferPos = nInitialBufferPos; nBufferPos < nFinalBufferPos;
1247 ++nBufferPos ) {
1248
1249 fVal_L = buffer_L[ nBufferPos ];
1250 fVal_R = buffer_R[ nBufferPos ];
1251
1252 pNote->compute_lr_values( &fVal_L, &fVal_R );
1253
1254 buffer_L[ nBufferPos ] = fVal_L;
1255 buffer_R[ nBufferPos ] = fVal_R;
1256
1257 }
1258 }
1259
1260 // Mix rendered sample buffer to track and mixer output
1261 for ( int nBufferPos = nInitialBufferPos; nBufferPos < nFinalBufferPos;
1262 ++nBufferPos ) {
1263
1264 fVal_L = buffer_L[ nBufferPos ];
1265 fVal_R = buffer_R[ nBufferPos ];
1266
1267#ifdef H2CORE_HAVE_JACK
1268 if ( pTrackOutL ) {
1269 pTrackOutL[nBufferPos] += fVal_L * fCostTrack_L;
1270 }
1271 if ( pTrackOutR ) {
1272 pTrackOutR[nBufferPos] += fVal_R * fCostTrack_R;
1273 }
1274#endif
1275
1276 fVal_L *= fCost_L;
1277 fVal_R *= fCost_R;
1278
1279 // update instr peak
1280 if ( fVal_L > fInstrPeak_L ) {
1281 fInstrPeak_L = fVal_L;
1282 }
1283 if ( fVal_R > fInstrPeak_R ) {
1284 fInstrPeak_R = fVal_R;
1285 }
1286
1287 pDrumCompo->set_outs( nBufferPos, fVal_L, fVal_R );
1288
1289 // to main mix
1290 m_pMainOut_L[nBufferPos] += fVal_L;
1291 m_pMainOut_R[nBufferPos] += fVal_R;
1292
1293 }
1294
1295 if ( pInstrument->is_filter_active() && pNote->filter_sustain() ) {
1296 // Note is still ringing, do not end.
1297 bRetValue = false;
1298 }
1299
1300 pSelectedLayerInfo->fSamplePosition += nAvail_bytes * fStep;
1301 pInstrument->set_peak_l( fInstrPeak_L );
1302 pInstrument->set_peak_r( fInstrPeak_R );
1303
1304
1305#ifdef H2CORE_HAVE_LADSPA
1306 // LADSPA
1307 // change the below return logic if you add code after that ifdef
1308 if ( pInstrument->is_muted() || pSong->getIsMuted() ) {
1309 return bRetValue;
1310 }
1311 float masterVol = pSong->getVolume();
1312 for ( unsigned nFX = 0; nFX < MAX_FX; ++nFX ) {
1314 float fLevel = pInstrument->get_fx_level( nFX );
1315 if ( pFX != nullptr && fLevel != 0.0 ) {
1316 fLevel = fLevel * pFX->getVolume();
1317
1318 float *pBuf_L = pFX->m_pBuffer_L;
1319 float *pBuf_R = pFX->m_pBuffer_R;
1320
1321 float fFXCost_L = fLevel * masterVol;
1322 float fFXCost_R = fLevel * masterVol;
1323
1324 int nBufferPos = nInitialBufferPos;
1325 for ( int i = 0; i < nAvail_bytes; ++i ) {
1326
1327 fVal_L = buffer_L[ nBufferPos ];
1328 fVal_R = buffer_R[ nBufferPos ];
1329
1330 pBuf_L[ nBufferPos ] += fVal_L * fFXCost_L;
1331 pBuf_R[ nBufferPos ] += fVal_R * fFXCost_R;
1332 ++nBufferPos;
1333 }
1334 }
1335 }
1336#endif
1337 return bRetValue;
1338}
1339
1340
1341void Sampler::stopPlayingNotes( std::shared_ptr<Instrument> pInstr )
1342{
1343 if ( pInstr ) { // stop all notes using this instrument
1344 for ( unsigned i = 0; i < m_playingNotesQueue.size(); ) {
1345 Note *pNote = m_playingNotesQueue[ i ];
1346 assert( pNote );
1347 if ( pNote->get_instrument() == pInstr ) {
1348 delete pNote;
1349 pInstr->dequeue();
1350 m_playingNotesQueue.erase( m_playingNotesQueue.begin() + i );
1351 }
1352 ++i;
1353 }
1354 } else { // stop all notes
1355 // delete all copied notes in the playing notes queue
1356 for ( unsigned i = 0; i < m_playingNotesQueue.size(); ++i ) {
1357 Note *pNote = m_playingNotesQueue[i];
1358 pNote->get_instrument()->dequeue();
1359 delete pNote;
1360 }
1361 m_playingNotesQueue.clear();
1362 }
1363}
1364
1365
1366
1368void Sampler::preview_sample(std::shared_ptr<Sample> pSample, int nLength )
1369{
1370 if ( m_pPreviewInstrument == nullptr ) {
1371 ERRORLOG( "Invalid preview instrument" );
1372 return;
1373 }
1374
1375 if ( ! m_pPreviewInstrument->hasSamples() ) {
1376 return;
1377 }
1378
1380
1381 for (const auto& pComponent: *m_pPreviewInstrument->get_components()) {
1382 auto pLayer = pComponent->get_layer( 0 );
1383
1384 pLayer->set_sample( pSample );
1385
1386 Note *pPreviewNote = new Note( m_pPreviewInstrument, 0, 1.0, 0.f, nLength );
1387
1389 noteOn( pPreviewNote );
1390
1391 }
1392
1394}
1395
1396
1397
1398void Sampler::preview_instrument( std::shared_ptr<Instrument> pInstr )
1399{
1400 if ( pInstr == nullptr ) {
1401 ERRORLOG( "Invalid instrument" );
1402 return;
1403 }
1404
1405 if ( ! pInstr->hasSamples() ) {
1406 return;
1407 }
1408
1409 std::shared_ptr<Instrument> pOldPreview;
1411
1413
1414 pOldPreview = m_pPreviewInstrument;
1415 m_pPreviewInstrument = pInstr;
1416 pInstr->set_is_preview_instrument(true);
1417
1418 Note *pPreviewNote = new Note( m_pPreviewInstrument, 0, 1.0, 0.f, MAX_NOTES );
1419
1420 noteOn( pPreviewNote ); // exclusive note
1422}
1423
1424bool Sampler::isInstrumentPlaying( std::shared_ptr<Instrument> instrument )
1425{
1426 if ( instrument ) { // stop all notes using this instrument
1427 for ( unsigned j = 0; j < m_playingNotesQueue.size(); j++ ) {
1428 if ( instrument->get_name() == m_playingNotesQueue[ j ]->get_instrument()->get_name()){
1429 return true;
1430 }
1431 }
1432 }
1433 return false;
1434}
1435
1437{
1438 Hydrogen* pHydrogen = Hydrogen::get_instance();
1439 std::shared_ptr<Song> pSong = pHydrogen->getSong();
1440 std::shared_ptr<Sample> pSample;
1441
1442 if ( pSong == nullptr ) {
1443 ERRORLOG( "No song set yet" );
1444 return;
1445 }
1446
1448 pSample = Sample::load( pSong->getPlaybackTrackFilename() );
1449 }
1450
1451 auto pPlaybackTrackLayer = std::make_shared<InstrumentLayer>( pSample );
1452
1453 m_pPlaybackTrackInstrument->get_components()->front()->set_layer( pPlaybackTrackLayer, 0 );
1455}
1456
1457};
1458
#define RIGHT_HERE
Macro intended to be used for the logging of the locking of the H2Core::AudioEngine.
Definition AudioEngine.h:59
#define PLAYBACK_INSTR_ID
Definition Instrument.h:37
#define EMPTY_INSTR_ID
Definition Instrument.h:34
#define INFOLOG(x)
Definition Object.h:237
#define WARNINGLOG(x)
Definition Object.h:238
#define ERRORLOG(x)
Definition Object.h:239
@ Playing
Transport is rolling.
@ Testing
State used during the unit tests of the AudioEngine.
void unlock()
Mutex unlocking of the AudioEngine.
void lock(const char *file, unsigned int line, const char *function)
Mutex locking of the AudioEngine.
static Effects * get_instance()
Returns a pointer to the current Effects singleton stored in __instance.
Definition Effects.h:54
LadspaFX * getLadspaFX(int nFX) const
Definition Effects.cpp:91
static EventQueue * get_instance()
Returns a pointer to the current EventQueue singleton stored in __instance.
Definition EventQueue.h:224
void push_event(const EventType type, const int nValue)
Queues the next event into the EventQueue.
static QString empty_sample_path()
returns system empty sample file path
Hydrogen Audio Engine.
Definition Hydrogen.h:54
std::shared_ptr< Song > getSong() const
Get the current song.
Definition Hydrogen.h:122
Song::PlaybackTrack getPlaybackTrackState() const
Wrapper around Song::getPlaybackTrackState().
Definition Hydrogen.cpp:240
Song::Mode getMode() const
static Hydrogen * get_instance()
Returns the current Hydrogen instance __instance.
Definition Hydrogen.h:83
AudioEngine * getAudioEngine() const
Definition Hydrogen.h:649
void loadPlaybackTrack(QString sFilename)
Wrapper function for loading the playback track.
Definition Hydrogen.cpp:262
AudioOutput * getAudioOutput() const
Used to display audio driver info.
Definition Hydrogen.cpp:719
JACK (Jack Audio Connection Kit) server driver.
float * getTrackOut_L(unsigned nTrack)
Get content of left output port of a specific track.
float * m_pBuffer_L
Definition LadspaFX.h:128
float * m_pBuffer_R
Definition LadspaFX.h:129
float getVolume() const
Definition LadspaFX.h:166
MIDI input base class.
Definition MidiOutput.h:41
virtual void handleQueueNoteOff(int channel, int key, int velocity)=0
A note plays an associated instrument with a velocity left and right pan.
Definition Note.h:102
int get_position() const
__position accessor
Definition Note.h:535
std::shared_ptr< SelectedLayerInfo > get_layer_selected(int CompoID)
Definition Note.h:620
bool isPartiallyRendered() const
Definition Note.cpp:221
bool filter_sustain() const
Filter output is sustaining note.
Definition Note.h:665
int get_specific_compo_id() const
__specific_compo_id accessor
Definition Note.h:525
std::shared_ptr< Instrument > get_instrument()
__instrument accessor
Definition Note.h:500
float get_total_pitch() const
Definition Note.cpp:423
void compute_lr_values(float *val_l, float *val_r)
compute left and right output based on filters
Definition Note.h:727
std::shared_ptr< Sample > getSample(int nComponentID, int nSelectedLayer=-1)
Returns the sample associated with the note for a specific InstrumentComponent nComponentID.
Definition Note.cpp:262
int get_length() const
__length accessor
Definition Note.h:560
int get_midi_key() const
return scaled key for midi output, !!! DO NOT CHECK IF INSTRUMENT IS SET !!!
Definition Note.h:682
float get_velocity() const
__velocity accessor
Definition Note.h:540
bool get_note_off() const
__note_off accessor
Definition Note.h:580
static double pitchToFrequency(double fPitch)
Convert a logarithmic pitch-space value in semitones to a frequency-domain value.
Definition Note.h:388
QString toQString(const QString &sPrefix="", bool bShort=true) const override
Formatted string version for debugging purposes.
Definition Note.cpp:536
std::shared_ptr< ADSR > get_adsr() const
get the ADSR of the note
Definition Note.h:495
long long getNoteStart() const
Definition Note.h:746
float getPan() const
get pan of the note.
Definition Note.h:545
int get_midi_velocity() const
midi velocity accessor
Definition Note.h:690
JackTrackOutputMode m_JackTrackOutputMode
Specifies which audio settings will be applied to the sample supplied in the JACK per track output po...
static Preferences * get_instance()
Returns a pointer to the current Preferences singleton stored in __instance.
@ postFader
Applies layer, component, and instrument gain, note and instrument pan, note velocity,...
@ preFader
Only layer gain and note velocity will be applied to the samples.
unsigned m_nMaxNotes
max notes
static std::shared_ptr< Sample > load(const QString &filepath, const License &license=License())
Definition Sample.cpp:136
static float linearConstKNormPanLaw(float fPan, float k)
Definition Sampler.cpp:358
void process(uint32_t nFrames)
Definition Sampler.cpp:111
void noteOff(Note *pNote)
Stop playing a note.
Definition Sampler.cpp:241
static const float K_NORM_DEFAULT
default k for pan law with such that L^k + R^k = const must be initialised in Sampler....
Definition Sampler.h:126
static float linearStraightPolygonalPanLaw(float fPan)
Definition Sampler.cpp:298
static float quadraticConstKNormPanLaw(float fPan, float k)
Definition Sampler.cpp:363
void preview_instrument(std::shared_ptr< Instrument > pInstr)
Definition Sampler.cpp:1398
void handleTimelineOrTempoChange()
Recalculates all note starts to make them valid again after a TempoMarker was added to or deleted fro...
Definition Sampler.cpp:426
static float linearConstPowerPanLaw(float fPan)
Definition Sampler.cpp:307
float * m_pMainOut_L
sampler main out (left channel)
Definition Sampler.h:163
static float ratioConstPowerPanLaw(float fPan)
Definition Sampler.cpp:280
bool processPlaybackTrack(int nBufferSize)
Definition Sampler.cpp:803
bool isRenderingNotes() const
Definition Sampler.cpp:186
float * m_pMainOut_R
sampler main out (right channel)
Definition Sampler.h:164
int m_nPlayBackSamplePosition
Definition Sampler.h:256
void reinitializePlaybackTrack()
Loading of the playback track.
Definition Sampler.cpp:1436
static float ratioStraightPolygonalPanLaw(float fPan)
Definition Sampler.cpp:271
bool renderNoteResample(std::shared_ptr< Sample > pSample, Note *pNote, std::shared_ptr< SelectedLayerInfo > pSelectedLayerInfo, std::shared_ptr< InstrumentComponent > pCompo, std::shared_ptr< DrumkitComponent > pDrumCompo, int nBufferSize, int nInitialBufferPos, float cost_L, float cost_R, float cost_track_L, float cost_track_R, float fLayerPitch)
Definition Sampler.cpp:993
static float quadraticConstSumPanLaw(float fPan)
Definition Sampler.cpp:353
static float ratioConstSumPanLaw(float fPan)
Definition Sampler.cpp:289
std::vector< Note * > m_queuedNoteOffs
Definition Sampler.h:241
std::shared_ptr< Instrument > m_pPlaybackTrackInstrument
Instrument used for the playback track feature.
Definition Sampler.h:244
static float polarConstPowerPanLaw(float fPan)
Definition Sampler.cpp:327
static float quadraticConstPowerPanLaw(float fPan)
Definition Sampler.cpp:348
float panLaw(float fPan, std::shared_ptr< Song > pSong)
function to direct the computation to the selected pan law function
Definition Sampler.cpp:385
int m_nMaxLayers
Maximum number of layers to be used in the Instrument editor.
Definition Sampler.h:254
static float ratioConstKNormPanLaw(float fPan, float k)
Definition Sampler.cpp:375
void noteOn(Note *pNote)
Start playing a note.
Definition Sampler.cpp:190
void midiKeyboardNoteOff(int key)
Definition Sampler.cpp:229
bool renderNote(Note *pNote, unsigned nBufferSize)
Render a note.
Definition Sampler.cpp:517
std::vector< Note * > m_playingNotesQueue
Definition Sampler.h:240
void stopPlayingNotes(std::shared_ptr< Instrument > pInstr=nullptr)
Definition Sampler.cpp:1341
static float quadraticStraightPolygonalPanLaw(float fPan)
Definition Sampler.cpp:339
Interpolation::InterpolateMode m_interpolateMode
Definition Sampler.h:273
static float linearConstSumPanLaw(float fPan)
Definition Sampler.cpp:312
static float polarConstKNormPanLaw(float fPan, float k)
Definition Sampler.cpp:368
void handleSongSizeChange()
Recalculates all note starts and positions to make them valid again after the song size changed,...
Definition Sampler.cpp:487
@ QUADRATIC_CONST_K_NORM
Definition Sampler.h:120
@ LINEAR_STRAIGHT_POLYGONAL
Definition Sampler.h:108
@ RATIO_STRAIGHT_POLYGONAL
Definition Sampler.h:105
@ POLAR_STRAIGHT_POLYGONAL
Definition Sampler.h:111
@ QUADRATIC_CONST_POWER
Definition Sampler.h:115
@ QUADRATIC_STRAIGHT_POLYGONAL
Definition Sampler.h:114
bool isInstrumentPlaying(std::shared_ptr< Instrument > pInstr)
Definition Sampler.cpp:1424
Sampler()
Constructor of the Sampler.
Definition Sampler.cpp:70
static float polarStraightPolygonalPanLaw(float fPan)
Definition Sampler.cpp:317
void preview_sample(std::shared_ptr< Sample > pSample, int length)
Preview, uses only the first layer.
Definition Sampler.cpp:1368
static float polarConstSumPanLaw(float fPan)
Definition Sampler.cpp:333
static float getRatioPan(float fPan_L, float fPan_R)
This function is used to load old version files (v<=1.1).
Definition Sampler.cpp:257
std::shared_ptr< Instrument > m_pPreviewInstrument
Instrument used for the preview feature.
Definition Sampler.h:247
@ Enabled
Valid file set and ready for playback.
@ Unavailable
No proper playback track file set yet.
static long long computeFrameFromTick(double fTick, double *fTickMismatch, int nSampleRate=0)
Calculates frame equivalent of fTick.
#define MAX_NOTES
Maximum number of notes.
Definition config.dox:79
#define MAX_BUFFER_SIZE
Maximum buffer size.
Definition config.dox:87
#define MAX_FX
Maximum number of effects.
Definition config.dox:83
static float cosine_Interpolate(float y1, float y2, double mu)
static float cubic_Interpolate(float y0, float y1, float y2, float y3, double mu)
static float hermite_Interpolate(float y0, float y1, float y2, float y3, double mu)
static float third_Interpolate(float y0, float y1, float y2, float y3, double mu)
static std::shared_ptr< Instrument > createInstrument(int id, const QString &filepath, float volume)
Definition Sampler.cpp:58
@ EVENT_ERROR
Definition EventQueue.h:87