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