root/branches/transport_redesign_2/libs/hydrogen/src/hydrogen.cpp @ 1157

Revision 1157, 57.5 KB (checked in by gabriel@…, 4 years ago)

Fix a couple off-by-one bugs with GUI scrolling.

Still no audio output. Scrolling works as expected except for these:

  • H2 dies on a std::vector<> range out-of-bounds at exactly 2 bars from the end of the song.
  • The play head in the drum pattern editor only scrolls if the active pattern is the NEXT pattern to play. I.e. it's off-by-one.
  • The little arrows at the left that indicate which patterns are being used in "live" or "stacked" pattern mode are turning on/off in somewhat odd combinations whenever the bar changes.
Line 
1/*
2 * Hydrogen
3 * Copyright(c) 2002-2008 by Alex >Comix< Cominu [comix@users.sourceforge.net]
4 *
5 * http://www.hydrogen-music.org
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY, without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20 *
21 */
22
23/*
24 In redesigning the Sampler, the following responsibilities were
25 shifted over to the Sequencer (H2Core::Hydrogen):
26
27   o Must explicitly schedule Note On/Off events.  If Off event
28     omitted, the note will stop when the sample ends.
29
30   o Must supply a valid TransportPosition.
31
32   o SeqEvent::frame is always relative to the current process()
33     cycle.
34
35   o in Sampler::process(beg, end, pos, nFrames), beg and end
36     must be for this process() cycle only.  It will not be
37     checked.
38
39   o Sequencer is responsible for all scheduling the effects of all
40     humanize, lead/lag, et al features.
41
42   o It is undefined yet what to do for sample preview.  People need
43     some level of access to Sampler in an "anytime, anywhere"
44     fashion.  However, ATM it is not thread safe.  Currently, Sampler
45     has no mutexes or any other kind of lock.  I'd like to keep it
46     this way.  But this may mean that all "preview" features need to
47     be handled by the Sequencer somehow.
48
49 */
50
51#include "config.h"
52
53#ifdef WIN32
54#    include "hydrogen/timeHelper.h"
55#else
56#    include <unistd.h>
57#    include <sys/time.h>
58#endif
59
60#include <pthread.h>
61#include <cassert>
62#include <cstdio>
63#include <deque>
64#include <queue>
65#include <list>
66#include <iostream>
67#include <ctime>
68#include <cmath>
69
70#include <hydrogen/LocalFileMng.h>
71#include <hydrogen/event_queue.h>
72#include <hydrogen/adsr.h>
73#include <hydrogen/SoundLibrary.h>
74#include <hydrogen/h2_exception.h>
75#include <hydrogen/audio_engine.h>
76#include <hydrogen/instrument.h>
77#include <hydrogen/sample.h>
78#include <hydrogen/hydrogen.h>
79#include <hydrogen/Pattern.h>
80#include <hydrogen/note.h>
81#include <hydrogen/fx/LadspaFX.h>
82#include <hydrogen/fx/Effects.h>
83#include <hydrogen/IO/AudioOutput.h>
84#include <hydrogen/IO/JackOutput.h>
85#include <hydrogen/IO/NullDriver.h>
86#include <hydrogen/IO/MidiInput.h>
87#include <hydrogen/IO/CoreMidiDriver.h>
88#include <hydrogen/Preferences.h>
89#include <hydrogen/data_path.h>
90#include <hydrogen/sampler/Sampler.h>
91
92#include <hydrogen/Transport.h>
93#include "transport/H2Transport.h"
94#include <hydrogen/SeqEvent.h>
95#include <hydrogen/SeqScript.h>
96#include <hydrogen/SeqScriptIterator.h>
97#include "BeatCounter.h"
98#include "SongSequencer.h"
99
100#include "IO/OssDriver.h"
101#include "IO/FakeDriver.h"
102#include "IO/AlsaAudioDriver.h"
103#include "IO/PortAudioDriver.h"
104#include "IO/DiskWriterDriver.h"
105#include "IO/AlsaMidiDriver.h"
106#include "IO/PortMidiDriver.h"
107#include "IO/CoreAudioDriver.h"
108
109namespace H2Core
110{
111
112/**
113 * This class provides a thread-safe queue that can be written from
114 * anywhere to allow note on/off events.  It's primarily intended for
115 * GUI input, and not something like a MIDI input.  (However, MIDI
116 * input will probably use it temporarily.
117 *
118 * It provides a process() method that allows the events to be given
119 * to the master sequencer queue.
120 */
121class GuiInputQueue
122{
123private:
124        typedef std::list<SeqEvent> EvList;
125        EvList __events;
126        QMutex __mutex;
127
128public:
129        int process( SeqScript& seq, const TransportPosition& pos, uint32_t nframes ) {
130                // Set up quantization.
131                uint32_t quant_frame;
132
133                {
134                        // TODO:  This seems too complicated for what we're doing...
135                        Preferences *pref = Preferences::getInstance();
136                        TransportPosition quant(pos);
137                        quant.ceil(TransportPosition::TICK);
138
139                        double res = (double)pref->getPatternEditorGridResolution();
140                        double trip_f = pref->isPatternEditorUsingTriplets() ? (2.0/3.0) : 1.0; // Triplet factor
141                        double fquant_ticks = quant.ticks_per_beat * (4.0 / res) * trip_f;  // Round to scalar * beat resolution
142                        int quant_ticks = round(fquant_ticks) - quant.tick;
143                        if( quant_ticks > 0 ) {
144                                quant += quant_ticks;
145                        }
146
147                        quant_frame = quant.frame - pos.frame;
148                }
149
150                // Add events to 'seq'
151                QMutexLocker mx(&__mutex);
152                EvList::iterator k;
153                for( k=__events.begin() ; k!=__events.end() ; ++k ) {
154                        if( k->quantize ) {
155                                k->frame = quant_frame;
156                        }
157                        seq.insert(*k);
158                }
159                __events.clear();
160                return 0;
161        }
162
163        void note_on( const Note* pNote, bool quantize = false ) {
164                SeqEvent ev;
165                QMutexLocker mx(&__mutex);
166                ev.frame = 0;
167                ev.type = SeqEvent::NOTE_ON;
168                ev.note = *pNote;
169                ev.quantize = quantize;
170                ev.instrument_index =
171                        Hydrogen::get_instance()->getSong()
172                        ->get_instrument_list()->get_pos( pNote->get_instrument() );
173        }
174
175        void note_off( const Note* pNote, bool quantize = false ) {
176                SeqEvent ev;
177                QMutexLocker mx(&__mutex);
178                ev.frame = 0;
179                ev.type = SeqEvent::NOTE_OFF;
180                ev.note = *pNote;
181                ev.quantize = quantize;
182                ev.instrument_index =
183                        Hydrogen::get_instance()->getSong()
184                        ->get_instrument_list()->get_pos( pNote->get_instrument() );
185        }
186
187        void panic() {
188                SeqEvent ev;
189                QMutexLocker mx(&__mutex);
190                __events.clear();
191                ev.frame = 0;
192                ev.type = SeqEvent::ALL_OFF;
193                ev.instrument_index = 0;
194                __events.push_front(ev);
195        }
196
197        void clear() {
198                QMutexLocker mx(&__mutex);
199                __events.clear();
200        }
201
202};
203
204// GLOBALS
205
206/************************
207 * DEAD VARIABLES
208 ************************
209 * These are variables that are in the process of
210 * being removed in the transport redesign.
211 */
212#if 0
213//jack time master
214float m_nNewBpmJTM = 120;
215unsigned long m_nHumantimeFrames = 0;
216//~ jack time master
217int m_nPatternStartTick = -1;
218int m_nPatternTickPosition = 0;
219int m_nLookaheadFrames = 0;
220
221// used in findPatternInTick
222int m_nSongSizeInTicks = 0;
223
224struct timeval m_currentTickTime;
225
226unsigned long m_nRealtimeFrames = 0;
227unsigned m_nBufferSize = 0;
228
229std::priority_queue<Note*, std::deque<Note*>, std::greater<Note> > m_songNoteQueue;
230std::deque<Note*> m_midiNoteQueue;      ///< Midi Note FIFO
231
232PatternList* m_pNextPatterns;           ///< Next pattern (used only in Pattern mode)
233bool m_bAppendNextPattern;              ///< Add the next pattern to the list instead
234                                        /// of replace.
235bool m_bDeleteNextPattern;              ///< Delete the next pattern from the list.
236
237
238PatternList* m_pPlayingPatterns;
239int m_nSongPos;                         ///< Is the position inside the song
240
241#endif // 0
242/****** END OF DEAD VARIABLES ********/
243
244// info
245float m_fMasterPeak_L = 0.0f;           ///< Master peak (left channel)
246float m_fMasterPeak_R = 0.0f;           ///< Master peak (right channel)
247float m_fProcessTime = 0.0f;            ///< time used in process function
248float m_fMaxProcessTime = 0.0f;         ///< max ms usable in process with no xrun
249//~ info
250
251H2Transport* m_pTransport = 0;
252// This is *the* priority queue for scheduling notes/events to be
253// sent to the Sampler.
254SeqScript m_queue;
255GuiInputQueue m_GuiInput;
256SongSequencer m_SongSequencer;
257
258BeatCounter m_BeatCounter;
259
260AudioOutput *m_pAudioDriver = NULL;     ///< Audio output
261MidiInput *m_pMidiDriver = NULL;        ///< MIDI input
262
263Song *m_pSong;                          ///< Current song
264Instrument *m_pMetronomeInstrument = NULL;      ///< Metronome instrument
265unsigned long m_nFreeRollingFrameCounter;
266
267// Buffers used in the process function
268float *m_pMainBuffer_L = NULL;
269float *m_pMainBuffer_R = NULL;
270
271Hydrogen* hydrogenInstance = NULL;   ///< Hydrogen class instance (used for log)
272
273int  m_audioEngineState = STATE_UNINITIALIZED;  ///< Audio engine state
274
275int m_nSelectedPatternNumber;
276int m_nSelectedInstrumentNumber;
277bool m_sendPatternChange;
278
279#ifdef LADSPA_SUPPORT
280float m_fFXPeak_L[MAX_FX];
281float m_fFXPeak_R[MAX_FX];
282#endif
283
284// PROTOTYPES
285void    audioEngine_init();
286void    audioEngine_destroy();
287int     audioEngine_start( bool bLockEngine = false, unsigned nTotalFrames = 0 );
288void    audioEngine_stop( bool bLockEngine = false );
289void    audioEngine_setSong( Song *newSong );
290void    audioEngine_removeSong();
291static void     audioEngine_noteOn( Note *note );
292static void     audioEngine_noteOff( Note *note );
293int     audioEngine_process( uint32_t nframes, void *arg );
294inline void audioEngine_clearNoteQueue();
295inline void audioEngine_process_playNotes( unsigned long nframes );
296
297inline unsigned audioEngine_renderNote( Note* pNote, const unsigned& nBufferSize );
298    inline void audioEngine_updateNoteQueue( unsigned nFrames, const TransportPosition& pos );
299inline void audioEngine_prepNoteQueue();
300
301inline int findPatternInTick( int tick, bool loopMode, int *patternStartTick );
302
303void audioEngine_restartAudioDrivers();
304void audioEngine_startAudioDrivers();
305void audioEngine_stopAudioDrivers();
306
307inline timeval currentTime2()
308{
309        struct timeval now;
310        gettimeofday( &now, NULL );
311        return now;
312}
313
314
315
316inline int randomValue( int max )
317{
318        return rand() % max;
319}
320
321
322inline float getGaussian( float z )
323{
324        // gaussian distribution -- dimss
325        float x1, x2, w;
326        do {
327                x1 = 2.0 * ( ( ( float ) rand() ) / RAND_MAX ) - 1.0;
328                x2 = 2.0 * ( ( ( float ) rand() ) / RAND_MAX ) - 1.0;
329                w = x1 * x1 + x2 * x2;
330        } while ( w >= 1.0 );
331
332        w = sqrtf( ( -2.0 * logf( w ) ) / w );
333        return x1 * w * z + 0.0; // tunable
334}
335
336
337
338void audioEngine_raiseError( unsigned nErrorCode )
339{
340        EventQueue::get_instance()->push_event( EVENT_ERROR, nErrorCode );
341}
342
343
344/*
345void updateTickSize()
346{
347        float sampleRate = ( float )m_pAudioDriver->getSampleRate();
348        m_pAudioDriver->m_transport.m_nTickSize =
349                ( sampleRate * 60.0 /  m_pSong->__bpm / m_pSong->__resolution );
350}
351*/
352
353void audioEngine_init()
354{
355        _INFOLOG( "*** Hydrogen audio engine init ***" );
356
357        // check current state
358        if ( m_audioEngineState != STATE_UNINITIALIZED ) {
359                _ERRORLOG( "Error the audio engine is not in UNINITIALIZED state" );
360                AudioEngine::get_instance()->unlock();
361                return;
362        }
363
364        m_nFreeRollingFrameCounter = 0;
365        m_pSong = NULL;
366        m_nSelectedPatternNumber = 0;
367        m_nSelectedInstrumentNumber = 0;
368        m_pMetronomeInstrument = NULL;
369        m_pAudioDriver = NULL;
370
371        m_pMainBuffer_L = NULL;
372        m_pMainBuffer_R = NULL;
373
374        srand( time( NULL ) );
375
376        // Create metronome instrument
377        QString sMetronomeFilename = QString( "%1/click.wav" )
378                                        .arg( DataPath::get_data_path() );
379        m_pMetronomeInstrument =
380                new Instrument( sMetronomeFilename, "metronome", new ADSR() );
381        m_pMetronomeInstrument->set_layer(
382                new InstrumentLayer( Sample::load( sMetronomeFilename ) ),
383                0
384                );
385
386        // Change the current audio engine state
387        m_audioEngineState = STATE_INITIALIZED;
388
389        EventQueue::get_instance()->push_event( EVENT_STATE, STATE_INITIALIZED );
390}
391
392
393
394void audioEngine_destroy()
395{
396        // check current state
397        if ( m_audioEngineState != STATE_INITIALIZED ) {
398                _ERRORLOG( "Error the audio engine is not in INITIALIZED state" );
399                return;
400        }
401        AudioEngine::get_instance()->get_sampler()->panic();
402
403        AudioEngine::get_instance()->lock( "audioEngine_destroy" );
404        _INFOLOG( "*** Hydrogen audio engine shutdown ***" );
405
406        audioEngine_clearNoteQueue();
407
408        // change the current audio engine state
409        m_audioEngineState = STATE_UNINITIALIZED;
410        EventQueue::get_instance()->push_event( EVENT_STATE, STATE_UNINITIALIZED );
411
412        delete m_pMetronomeInstrument;
413        m_pMetronomeInstrument = NULL;
414
415        AudioEngine::get_instance()->unlock();
416}
417
418
419
420
421
422/// Start playing
423/// return 0 = OK
424/// return -1 = NULL Audio Driver
425/// return -2 = Driver connect() error
426int audioEngine_start( bool bLockEngine, unsigned nTotalFrames )
427{
428        if ( bLockEngine ) {
429                AudioEngine::get_instance()->lock( "audioEngine_start" );
430        }
431
432        _INFOLOG( "[audioEngine_start]" );
433
434        // check current state
435        if ( m_audioEngineState != STATE_READY ) {
436                _ERRORLOG( "Error the audio engine is not in READY state" );
437                if ( bLockEngine ) {
438                        AudioEngine::get_instance()->unlock();
439                }
440                return 0;       // FIXME!!
441        }
442
443        m_fMasterPeak_L = 0.0f;
444        m_fMasterPeak_R = 0.0f;
445        /*
446        m_pAudioDriver->m_transport.m_nFrames = nTotalFrames;   // reset total frames
447        m_nSongPos = -1;
448        m_nPatternStartTick = -1;
449        m_nPatternTickPosition = 0;
450
451        // prepare the tickSize for this song
452        updateTickSize();
453
454        */
455        m_pTransport->start();
456
457        if ( bLockEngine ) {
458                AudioEngine::get_instance()->unlock();
459        }
460        return 0; // per ora restituisco sempre OK
461}
462
463
464
465/// Stop the audio engine
466void audioEngine_stop( bool bLockEngine )
467{
468        if ( bLockEngine ) {
469                AudioEngine::get_instance()->lock( "audioEngine_stop" );
470        }
471        _INFOLOG( "[audioEngine_stop]" );
472
473        // check current state
474        if ( m_audioEngineState != STATE_READY ) {
475                _ERRORLOG( "Error the audio engine is not in READY state, can't stop." );
476                if ( bLockEngine ) {
477                        AudioEngine::get_instance()->unlock();
478                }
479                return;
480        }
481
482        // change the current audio engine state
483        /*
484        m_audioEngineState = STATE_READY;
485        */
486        m_pTransport->stop();
487        EventQueue::get_instance()->push_event( EVENT_STATE, STATE_READY );
488
489        m_fMasterPeak_L = 0.0f;
490        m_fMasterPeak_R = 0.0f;
491
492        audioEngine_clearNoteQueue();
493
494        if ( bLockEngine ) {
495                AudioEngine::get_instance()->unlock();
496        }
497}
498
499#if 0
500//// THIS IS DEAD CODE.  BUT, I NEED TO REFER TO IT
501//// WHEN RE-IMPLEMENTING LOOKAHEAD AND RANDOM PITCH.
502inline void audioEngine_process_playNotes( unsigned long nframes )
503{
504        unsigned int framepos;
505
506        if (  m_audioEngineState == STATE_PLAYING ) {
507                framepos = m_pAudioDriver->m_transport.m_nFrames;
508        } else {
509                // use this to support realtime events when not playing
510                framepos = m_nRealtimeFrames;
511        }
512
513        // reading from m_songNoteQueue
514        while ( !m_songNoteQueue.empty() ) {
515                Note *pNote = m_songNoteQueue.top();
516
517                // verifico se la nota rientra in questo ciclo
518                unsigned int noteStartInFrames =
519                        (int)( pNote->get_position() * m_pAudioDriver->m_transport.m_nTickSize );
520
521                // if there is a negative Humanize delay, take into account so
522                // we don't miss the time slice.  ignore positive delay, or we
523                // might end the queue processing prematurely based on NoteQueue
524                // placement.  the sampler handles positive delay.
525                if (pNote->m_nHumanizeDelay < 0) {
526                        noteStartInFrames += pNote->m_nHumanizeDelay;
527                }
528
529                // m_nTotalFrames <= NotePos < m_nTotalFrames + bufferSize
530                bool isNoteStart = ( ( noteStartInFrames >= framepos )
531                                     && ( noteStartInFrames < ( framepos + nframes ) ) );
532                bool isOldNote = noteStartInFrames < framepos;
533                if ( isNoteStart || isOldNote ) {
534
535                        // Humanize - Velocity parameter
536                        if ( m_pSong->get_humanize_velocity_value() != 0 ) {
537                                float random = m_pSong->get_humanize_velocity_value()
538                                               * getGaussian( 0.2 );
539                                pNote->set_velocity(
540                                        pNote->get_velocity()
541                                        + ( random
542                                            - ( m_pSong->get_humanize_velocity_value() / 2.0 ) )
543                                        );
544                                if ( pNote->get_velocity() > 1.0 ) {
545                                        pNote->set_velocity( 1.0 );
546                                } else if ( pNote->get_velocity() < 0.0 ) {
547                                        pNote->set_velocity( 0.0 );
548                                }
549                        }
550
551                        // Random Pitch ;)
552                        const float fMaxPitchDeviation = 2.0;
553                        pNote->set_pitch( pNote->get_pitch()
554                                          + ( fMaxPitchDeviation * getGaussian( 0.2 )
555                                              - fMaxPitchDeviation / 2.0 )
556                                          * pNote->get_instrument()->get_random_pitch_factor() );
557
558///new note off stuff
559//not in use for the moment, but it works! i am planing a bit more than only delete the note. better way is that
560//users can edit the sustain-curve to fade out the sample.
561//more details see sampler.cpp: Sampler::note_off( Note* note )
562
563                        //stop note bevore playing new note, only if set into the planned instrumenteditor checkbox `always stop note`
564                        //Instrument * noteInstrument = pNote->get_instrument();
565                        //if ( noteInstrument->is_stop_notes() ){
566                        //      AudioEngine::get_instance()->get_sampler()->note_off( pNote );
567                        //}
568///~new note off stuff
569
570                        // aggiungo la nota alla lista di note da eseguire
571                        AudioEngine::get_instance()->get_sampler()->note_on( pNote );
572                       
573                        m_songNoteQueue.pop(); // rimuovo la nota dalla lista di note
574                        pNote->get_instrument()->dequeue();
575                        // raise noteOn event
576                        int nInstrument = m_pSong->get_instrument_list()
577                                                 ->get_pos( pNote->get_instrument() );
578                        EventQueue::get_instance()->push_event( EVENT_NOTEON, nInstrument );
579                        continue;
580                } else {
581                        // this note will not be played
582                        break;
583                }
584        }
585}
586#endif // 0
587
588void audioEngine_clearNoteQueue()
589{
590        m_queue.clear();
591        m_GuiInput.clear();
592        AudioEngine::get_instance()->get_sampler()->panic();
593}
594
595/// Clear all audio buffers
596inline void audioEngine_process_clearAudioBuffers( uint32_t nFrames )
597{
598        // clear main out Left and Right
599        if ( m_pMainBuffer_L ) {
600                memset( m_pMainBuffer_L, 0, nFrames * sizeof( float ) );
601        }
602        if ( m_pMainBuffer_R ) {
603                memset( m_pMainBuffer_R, 0, nFrames * sizeof( float ) );
604        }
605
606        if ( m_audioEngineState == STATE_READY ) {
607#ifdef LADSPA_SUPPORT
608                Effects* pEffects = Effects::getInstance();
609                for ( unsigned i = 0; i < MAX_FX; ++i ) {       // clear FX buffers
610                        LadspaFX* pFX = pEffects->getLadspaFX( i );
611                        if ( pFX ) {
612                                assert( pFX->m_pBuffer_L );
613                                assert( pFX->m_pBuffer_R );
614                                memset( pFX->m_pBuffer_L, 0, nFrames * sizeof( float ) );
615                                memset( pFX->m_pBuffer_R, 0, nFrames * sizeof( float ) );
616                        }
617                }
618#endif
619        }
620}
621
622/// Main audio processing function. Called by audio drivers.
623int audioEngine_process( uint32_t nframes, void* /*arg*/ )
624{
625        m_nFreeRollingFrameCounter += nframes;
626
627        if ( AudioEngine::get_instance()->try_lock( "audioEngine_process" ) == false ) {
628                return 0;
629        }
630
631        if( Hydrogen::get_instance()->getState() != STATE_READY ) {
632                AudioEngine::get_instance()->unlock();
633                return 0;
634        }
635
636        timeval startTimeval = currentTime2();
637
638        Transport* xport = Hydrogen::get_instance()->get_transport();
639        TransportPosition pos;
640        xport->get_position(&pos);
641
642        // PROCESS ALL INPUT SOURCES
643        m_GuiInput.process(m_queue, pos, nframes);
644        #warning "TODO: get MidiDriver::process() in the mix."
645        // TODO: m_pMidiDriver->process(m_queue, pos, nframes);
646        m_SongSequencer.process(m_queue, pos, nframes, m_sendPatternChange);
647
648        // PROCESS ALL OUTPUTS
649
650        audioEngine_process_clearAudioBuffers( nframes );
651
652        /*
653        // always update note queue.. could come from pattern or realtime input
654        // (midi, keyboard)
655        audioEngine_updateNoteQueue( nframes, pos );
656
657        audioEngine_process_playNotes( nframes );
658        */
659
660        timeval renderTime_start = currentTime2();
661
662        // SAMPLER
663        Sampler* pSampler = AudioEngine::get_instance()->get_sampler();
664        pSampler->process( m_queue.begin_const(),
665                           m_queue.end_const(nframes),
666                           pos,
667                           nframes
668            );
669        float* out_L = AudioEngine::get_instance()->get_sampler()->__main_out_L;
670        float* out_R = AudioEngine::get_instance()->get_sampler()->__main_out_R;
671        for ( unsigned i = 0; i < nframes; ++i ) {
672                m_pMainBuffer_L[ i ] += out_L[ i ];
673                m_pMainBuffer_R[ i ] += out_R[ i ];
674        }
675
676        timeval renderTime_end = currentTime2();
677
678        timeval ladspaTime_start = renderTime_end;
679#ifdef LADSPA_SUPPORT
680        // Process LADSPA FX
681        if ( m_audioEngineState == STATE_READY ) {
682                for ( unsigned nFX = 0; nFX < MAX_FX; ++nFX ) {
683                        LadspaFX *pFX = Effects::getInstance()->getLadspaFX( nFX );
684                        if ( ( pFX ) && ( pFX->isEnabled() ) ) {
685                                pFX->processFX( nframes );
686                                float *buf_L = NULL;
687                                float *buf_R = NULL;
688                                if ( pFX->getPluginType() == LadspaFX::STEREO_FX ) {
689                                        buf_L = pFX->m_pBuffer_L;
690                                        buf_R = pFX->m_pBuffer_R;
691                                } else { // MONO FX
692                                        buf_L = pFX->m_pBuffer_L;
693                                        buf_R = buf_L;
694                                }
695                                for ( unsigned i = 0; i < nframes; ++i ) {
696                                        m_pMainBuffer_L[ i ] += buf_L[ i ];
697                                        m_pMainBuffer_R[ i ] += buf_R[ i ];
698                                        if ( buf_L[ i ] > m_fFXPeak_L[nFX] )
699                                                m_fFXPeak_L[nFX] = buf_L[ i ];
700                                        if ( buf_R[ i ] > m_fFXPeak_R[nFX] )
701                                                m_fFXPeak_R[nFX] = buf_R[ i ];
702                                }
703                        }
704                }
705        }
706#endif
707        timeval ladspaTime_end = currentTime2();
708
709        // update master peaks
710        float val_L;
711        float val_R;
712        if ( m_audioEngineState == STATE_READY ) {
713                for ( unsigned i = 0; i < nframes; ++i ) {
714                        val_L = m_pMainBuffer_L[i];
715                        val_R = m_pMainBuffer_R[i];
716                        if ( val_L > m_fMasterPeak_L ) {
717                                m_fMasterPeak_L = val_L;
718                        }
719                        if ( val_R > m_fMasterPeak_R ) {
720                                m_fMasterPeak_R = val_R;
721                        }
722                }
723        }
724
725//      float fRenderTime = (renderTime_end.tv_sec - renderTime_start.tv_sec) * 1000.0 + (renderTime_end.tv_usec - renderTime_start.tv_usec) / 1000.0;
726        float fLadspaTime =
727                ( ladspaTime_end.tv_sec - ladspaTime_start.tv_sec ) * 1000.0
728                + ( ladspaTime_end.tv_usec - ladspaTime_start.tv_usec ) / 1000.0;
729
730        timeval finishTimeval = currentTime2();
731        m_fProcessTime =
732                ( finishTimeval.tv_sec - startTimeval.tv_sec ) * 1000.0
733                + ( finishTimeval.tv_usec - startTimeval.tv_usec ) / 1000.0;
734
735        m_fMaxProcessTime = 1000.0 / ( (float)pos.frame_rate / nframes );
736
737#ifdef CONFIG_DEBUG
738        if ( m_fProcessTime > m_fMaxProcessTime ) {
739                _WARNINGLOG( "" );
740                _WARNINGLOG( "----XRUN----" );
741                _WARNINGLOG( QString( "XRUN of %1 msec (%2 > %3)" )
742                             .arg( ( m_fProcessTime - m_fMaxProcessTime ) )
743                             .arg( m_fProcessTime ).arg( m_fMaxProcessTime ) );
744                _WARNINGLOG( QString( "Ladspa process time = %1" ).arg( fLadspaTime ) );
745                _WARNINGLOG( "------------" );
746                _WARNINGLOG( "" );
747                // raise xRun event
748                EventQueue::get_instance()->push_event( EVENT_XRUN, -1 );
749        }
750#endif
751
752        AudioEngine::get_instance()->unlock();
753
754        if ( m_sendPatternChange ) {
755                EventQueue::get_instance()->push_event( EVENT_PATTERN_CHANGED, -1 );
756                m_sendPatternChange = false;
757        }
758
759        // Increment the transport
760        xport->processed_frames(nframes);
761
762        return 0;
763}
764
765void audioEngine_setupLadspaFX( unsigned nBufferSize )
766{
767        //_INFOLOG( "buffersize=" + to_string(nBufferSize) );
768
769        if ( m_pSong == NULL ) {
770                //_INFOLOG( "m_pSong=NULL" );
771                return;
772        }
773        if ( nBufferSize == 0 ) {
774                _ERRORLOG( "nBufferSize=0" );
775                return;
776        }
777
778#ifdef LADSPA_SUPPORT
779        for ( unsigned nFX = 0; nFX < MAX_FX; ++nFX ) {
780                LadspaFX *pFX = Effects::getInstance()->getLadspaFX( nFX );
781                if ( pFX == NULL ) {
782                        return;
783                }
784
785                pFX->deactivate();
786
787//              delete[] pFX->m_pBuffer_L;
788//              pFX->m_pBuffer_L = NULL;
789//              delete[] pFX->m_pBuffer_R;
790//              pFX->m_pBuffer_R = NULL;
791//              if ( nBufferSize != 0 ) {
792                //pFX->m_nBufferSize = nBufferSize;
793                //pFX->m_pBuffer_L = new float[ nBufferSize ];
794                //pFX->m_pBuffer_R = new float[ nBufferSize ];
795//              }
796
797                Effects::getInstance()->getLadspaFX( nFX )->connectAudioPorts(
798                    pFX->m_pBuffer_L,
799                    pFX->m_pBuffer_R,
800                    pFX->m_pBuffer_L,
801                    pFX->m_pBuffer_R
802                );
803                pFX->activate();
804        }
805#endif
806}
807
808
809
810void audioEngine_renameJackPorts()
811{
812#ifdef JACK_SUPPORT
813        // renames jack ports
814        if ( m_pSong == NULL ) {
815                return;
816        }
817        if ( m_pAudioDriver->get_class_name() == "JackOutput" ) {
818                static_cast< JackOutput* >( m_pAudioDriver )->makeTrackOutputs( m_pSong );
819        }
820
821        AudioEngine::get_instance()->get_sampler()->makeTrackOutputQueues();
822
823#endif
824}
825
826
827
828void audioEngine_setSong( Song *newSong )
829{
830        _WARNINGLOG( QString( "Set song: %1" ).arg( newSong->__name ) );
831
832        while( m_pSong != 0 ) {
833                audioEngine_removeSong();
834        }
835
836        AudioEngine::get_instance()->lock( "audioEngine_setSong" );
837
838        m_pTransport->stop();
839        audioEngine_stop( false );  // Also clears all note queues.
840
841        // check current state
842        if ( m_audioEngineState != STATE_PREPARED ) {
843                _ERRORLOG( "Error the audio engine is not in PREPARED state" );
844        }
845
846        EventQueue::get_instance()->push_event( EVENT_SELECTED_PATTERN_CHANGED, -1 );
847        EventQueue::get_instance()->push_event( EVENT_PATTERN_CHANGED, -1 );
848        EventQueue::get_instance()->push_event( EVENT_SELECTED_INSTRUMENT_CHANGED, -1 );
849
850        //sleep( 1 );
851
852        audioEngine_clearNoteQueue();
853
854        assert( m_pSong == NULL );
855        m_pSong = newSong;
856        m_pTransport->set_current_song(newSong);
857        m_SongSequencer.set_current_song(newSong);
858
859        // setup LADSPA FX
860        audioEngine_setupLadspaFX( m_pAudioDriver->getBufferSize() );
861
862        audioEngine_renameJackPorts();
863
864        // change the current audio engine state
865        m_audioEngineState = STATE_READY;
866
867        m_pTransport->locate( 0 );
868
869        AudioEngine::get_instance()->unlock();
870
871        EventQueue::get_instance()->push_event( EVENT_STATE, STATE_READY );
872}
873
874
875
876void audioEngine_removeSong()
877{
878        AudioEngine::get_instance()->lock( "audioEngine_removeSong" );
879
880        m_pTransport->stop();
881        audioEngine_stop( false );
882
883        // check current state
884        if ( m_audioEngineState != STATE_READY ) {
885                _ERRORLOG( "Error the audio engine is not in READY state" );
886                AudioEngine::get_instance()->unlock();
887                return;
888        }
889
890        m_pSong = NULL;
891        m_pTransport->set_current_song(0);
892        m_SongSequencer.set_current_song(0);
893
894        audioEngine_clearNoteQueue();
895
896        // change the current audio engine state
897        m_audioEngineState = STATE_PREPARED;
898        AudioEngine::get_instance()->unlock();
899
900        EventQueue::get_instance()->push_event( EVENT_STATE, STATE_PREPARED );
901}
902
903#if 0
904//// This is dead code, but I may want to refer to it
905//// when re-implementing features like lookahead
906inline void audioEngine_updateNoteQueue( unsigned nFrames, const TransportPosition& pos )
907{
908        static int nLastTick = -1;
909        bool bSendPatternChange = false;
910        int nMaxTimeHumanize = 2000;
911        int nLeadLagFactor = m_pAudioDriver->m_transport.m_nTickSize * 5;  // 5 ticks
912
913        unsigned int framepos;
914        if (  m_audioEngineState == STATE_PLAYING ) {
915                framepos = m_pAudioDriver->m_transport.m_nFrames;
916        } else {
917                // use this to support realtime events when not playing
918                framepos = m_nRealtimeFrames;
919        }
920
921        int tickNumber_start = 0;
922
923        // We need to look ahead in the song for notes with negative offsets
924        // from LeadLag or Humanize.  When starting from the beginning, we prime
925        // the note queue with notes between 0 and nFrames plus
926        // lookahead. lookahead should be equal or greater than the
927        // nLeadLagFactor + nMaxTimeHumanize.
928        int lookahead = nLeadLagFactor + nMaxTimeHumanize + 1;
929        m_nLookaheadFrames = lookahead;
930        if ( framepos == 0
931             || ( m_audioEngineState == STATE_PLAYING
932                  && m_pSong->get_mode() == Song::SONG_MODE
933                  && m_nSongPos == -1 ) ) {
934                tickNumber_start = (int)( framepos
935                                          / m_pAudioDriver->m_transport.m_nTickSize );
936        }
937        else {
938                tickNumber_start = (int)( (framepos + lookahead)
939                                          / m_pAudioDriver->m_transport.m_nTickSize );
940        }
941        int tickNumber_end = (int)( (framepos + nFrames + lookahead)
942                                    / m_pAudioDriver->m_transport.m_nTickSize );
943
944        int tick = tickNumber_start;
945
946//      _WARNINGLOG( "Lookahead: " + to_string( lookahead
947//                                              / m_pAudioDriver->m_transport.m_nTickSize ) );
948        // get initial timestamp for first tick
949        gettimeofday( &m_currentTickTime, NULL );
950       
951
952        while ( tick <= tickNumber_end ) {
953                if ( tick == nLastTick ) {
954                        ++tick;
955                        continue;
956                } else {
957                        nLastTick = tick;
958                }
959
960
961                // midi events now get put into the m_songNoteQueue as well,
962                // based on their timestamp
963                while ( m_midiNoteQueue.size() > 0 ) {
964                        Note *note = m_midiNoteQueue[0];
965
966                        if ( ( int )note->get_position() <= tick ) {
967                                // printf ("tick=%d  pos=%d\n", tick, note->getPosition());
968                                m_midiNoteQueue.pop_front();
969                                note->get_instrument()->enqueue();
970                                m_songNoteQueue.push( note );
971                        } else {
972                                break;
973                        }
974                }
975
976                if (  m_audioEngineState != STATE_PLAYING ) {
977                        // only keep going if we're playing
978                        continue;
979                }
980
981//              if ( m_nPatternStartTick == -1 ) { // for debugging pattern mode :s
982//                      _WARNINGLOG( "m_nPatternStartTick == -1; tick = "
983//                                   + to_string( tick ) );
984//              }
985
986
987                // SONG MODE
988                if ( m_pSong->get_mode() == Song::SONG_MODE ) {
989                        if ( m_pSong->get_pattern_group_vector()->size() == 0 ) {
990                                // there's no song!!
991                                _ERRORLOG( "no patterns in song." );
992                                m_pAudioDriver->stop();
993                                return -1;
994                        }
995
996                        m_nSongPos = findPatternInTick( tick,
997                                                        m_pSong->is_loop_enabled(),
998                                                        &m_nPatternStartTick );
999                        if ( m_nSongSizeInTicks != 0 ) {
1000                                m_nPatternTickPosition = ( tick - m_nPatternStartTick )
1001                                                         % m_nSongSizeInTicks;
1002                        } else {
1003                                m_nPatternTickPosition = tick - m_nPatternStartTick;
1004                        }
1005
1006                        if ( m_nPatternTickPosition == 0 ) {
1007                                bSendPatternChange = true;
1008                        }
1009
1010//                      PatternList *pPatternList =
1011//                               (*(m_pSong->getPatternGroupVector()))[m_nSongPos];
1012                        if ( m_nSongPos == -1 ) {
1013                                _INFOLOG( "song pos = -1" );
1014                                if ( m_pSong->is_loop_enabled() == true ) {
1015                                        m_nSongPos = findPatternInTick( 0,
1016                                                                        true,
1017                                                                        &m_nPatternStartTick );
1018                                } else {
1019                                        _INFOLOG( "End of Song" );
1020                                        return -1;
1021                                }
1022                        }
1023                        PatternList *pPatternList =
1024                                ( *( m_pSong->get_pattern_group_vector() ) )[m_nSongPos];
1025                        // copio tutti i pattern
1026                        m_pPlayingPatterns->clear();
1027                        if ( pPatternList ) {
1028                                for ( unsigned i = 0; i < pPatternList->get_size(); ++i ) {
1029                                        m_pPlayingPatterns->add( pPatternList->get( i ) );
1030                                }
1031                        }
1032                }
1033               
1034                // PATTERN MODE
1035                else if ( m_pSong->get_mode() == Song::PATTERN_MODE )   {
1036                        // per ora considero solo il primo pattern, se ce ne
1037                        // saranno piu' di uno bisognera' prendere quello piu'
1038                        // piccolo
1039
1040                        //m_nPatternTickPosition = tick % m_pCurrentPattern->getSize();
1041                        int nPatternSize = MAX_NOTES;
1042
1043                       
1044                        if ( Preferences::getInstance()->patternModePlaysSelected() )
1045                        {
1046                                m_pPlayingPatterns->clear();
1047                                Pattern * pSelectedPattern =
1048                                        m_pSong->get_pattern_list()
1049                                               ->get(m_nSelectedPatternNumber);
1050                                m_pPlayingPatterns->add( pSelectedPattern );
1051                        }
1052
1053
1054                        if ( m_pPlayingPatterns->get_size() != 0 ) {
1055                                Pattern *pFirstPattern = m_pPlayingPatterns->get( 0 );
1056                                nPatternSize = pFirstPattern->get_length();
1057                        }
1058
1059                        if ( nPatternSize == 0 ) {
1060                                _ERRORLOG( "nPatternSize == 0" );
1061                        }
1062
1063                        if ( ( tick == m_nPatternStartTick + nPatternSize )
1064                             || ( m_nPatternStartTick == -1 ) ) {
1065                                if ( m_pNextPatterns->get_size() > 0 ) {
1066                                        Pattern * p;
1067                                        for ( uint i = 0;
1068                                              i < m_pNextPatterns->get_size();
1069                                              i++ ) {
1070                                                p = m_pNextPatterns->get( i );
1071//                                              _WARNINGLOG( QString( "Got pattern # %1" )
1072//                                                           .arg( i + 1 ) );
1073                                                // if the pattern isn't playing
1074                                                // already, start it now.
1075                                                if ( ( m_pPlayingPatterns->del( p ) ) == NULL ) {
1076                                                        m_pPlayingPatterns->add( p );
1077                                                }
1078                                        }
1079                                        m_pNextPatterns->clear();
1080                                        bSendPatternChange = true;
1081                                }
1082                                if ( m_nPatternStartTick == -1 ) {
1083                                        m_nPatternStartTick = tick - (tick % nPatternSize);
1084//                                      _WARNINGLOG( "set Pattern Start Tick to "
1085//                                                   + to_string( m_nPatternStartTick ) );
1086                                } else {
1087                                        m_nPatternStartTick = tick;
1088                                }
1089                        }
1090                        m_nPatternTickPosition = tick - m_nPatternStartTick;
1091                        if ( m_nPatternTickPosition > nPatternSize ) {
1092                                m_nPatternTickPosition = tick % nPatternSize;
1093                        }
1094                }
1095
1096                // metronome
1097//              if (  ( m_nPatternStartTick == tick )
1098//                    || ( ( tick - m_nPatternStartTick ) % 48 == 0 ) ) {
1099                if ( m_nPatternTickPosition % 48 == 0 ) {
1100                        float fPitch;
1101                        float fVelocity;
1102//                      _INFOLOG( "Beat: " + to_string(m_nPatternTickPosition / 48 + 1)
1103//                                 + "@ " + to_string( tick ) );
1104                        if ( m_nPatternTickPosition == 0 ) {
1105                                fPitch = 3;
1106                                fVelocity = 1.0;
1107                                EventQueue::get_instance()->push_event( EVENT_METRONOME, 1 );
1108                        } else {
1109                                fPitch = 0;
1110                                fVelocity = 0.8;
1111                                EventQueue::get_instance()->push_event( EVENT_METRONOME, 0 );
1112                        }
1113                        if ( Preferences::getInstance()->m_bUseMetronome ) {
1114                                m_pMetronomeInstrument->set_volume(
1115                                        Preferences::getInstance()->m_fMetronomeVolume
1116                                        );
1117                                Note *pMetronomeNote = new Note( m_pMetronomeInstrument,
1118                                                                 tick,
1119                                                                 fVelocity,
1120                                                                 0.5,
1121                                                                 0.5,
1122                                                                 -1,
1123                                                                 fPitch
1124                                        );
1125                                m_pMetronomeInstrument->enqueue();
1126                                m_songNoteQueue.push( pMetronomeNote );
1127                        }
1128                }
1129
1130                // update the notes queue
1131                if ( m_pPlayingPatterns->get_size() != 0 ) {
1132                        for ( unsigned nPat = 0 ;
1133                              nPat < m_pPlayingPatterns->get_size() ;
1134                              ++nPat ) {
1135                                Pattern *pPattern = m_pPlayingPatterns->get( nPat );
1136                                assert( pPattern != NULL );
1137
1138                                Pattern::note_map_t::iterator pos;
1139                                for ( pos = pPattern->note_map.lower_bound( m_nPatternTickPosition ) ;
1140                                      pos != pPattern->note_map.upper_bound( m_nPatternTickPosition ) ;
1141                                      ++pos ) {
1142                                        Note *pNote = pos->second;
1143                                        if ( pNote ) {
1144                                                int nOffset = 0;
1145
1146                                                // Swing
1147                                                float fSwingFactor = m_pSong->get_swing_factor();
1148                                               
1149                                                if ( ( ( m_nPatternTickPosition % 12 ) == 0 )
1150                                                     && ( ( m_nPatternTickPosition % 24 ) != 0 ) ) {
1151                                                        // da l'accento al tick 4, 12, 20, 36...
1152                                                        nOffset += ( int )(
1153                                                                6.0
1154                                                                * m_pAudioDriver->m_transport.m_nTickSize
1155                                                                * fSwingFactor
1156                                                                );
1157                                                }
1158
1159                                                // Humanize - Time parameter
1160                                                if ( m_pSong->get_humanize_time_value() != 0 ) {
1161                                                        nOffset += ( int )(
1162                                                                getGaussian( 0.3 )
1163                                                                * m_pSong->get_humanize_time_value()
1164                                                                * nMaxTimeHumanize
1165                                                                );
1166                                                }
1167                                                //~
1168                                                // Lead or Lag - timing parameter
1169                                                nOffset += (int) ( pNote->get_leadlag()
1170                                                                   * nLeadLagFactor);
1171                                                //~
1172
1173                                                if((tick == 0) && (nOffset < 0)) {
1174                                                        nOffset = 0;
1175                                                }
1176                                                Note *pCopiedNote = new Note( pNote );
1177                                                pCopiedNote->set_position( tick );
1178
1179                                                // humanize time
1180                                                pCopiedNote->m_nHumanizeDelay = nOffset;
1181                                                pNote->get_instrument()->enqueue();
1182                                                m_songNoteQueue.push( pCopiedNote );
1183                                                //pCopiedNote->dumpInfo();
1184                                        }
1185                                }
1186                        }
1187                }
1188                ++tick;
1189        }
1190       
1191
1192        // audioEngine_process must send the pattern change event after mutex unlock
1193        if ( bSendPatternChange ) {
1194                return 2;
1195        }
1196        return 0;
1197}
1198#endif
1199
1200#if 0
1201//// This is dead code.  Obsoleted by new transport.
1202//// Left here... just in case.  :-)
1203/// restituisce l'indice relativo al patternGroup in base al tick
1204inline int findPatternInTick( int nTick, bool bLoopMode, int *pPatternStartTick )
1205{
1206        assert( m_pSong );
1207
1208        int nTotalTick = 0;
1209        m_nSongSizeInTicks = 0;
1210
1211        std::vector<PatternList*> *pPatternColumns = m_pSong->get_pattern_group_vector();
1212        int nColumns = pPatternColumns->size();
1213
1214        int nPatternSize;
1215        for ( int i = 0; i < nColumns; ++i ) {
1216                PatternList *pColumn = ( *pPatternColumns )[ i ];
1217                if ( pColumn->get_size() != 0 ) {
1218                        // tengo in considerazione solo il primo pattern. I
1219                        // pattern nel gruppo devono avere la stessa lunghezza.
1220                        nPatternSize = pColumn->get( 0 )->get_length();
1221                } else {
1222                        nPatternSize = MAX_NOTES;
1223                }
1224
1225                if ( ( nTick >= nTotalTick ) && ( nTick < nTotalTick + nPatternSize ) ) {
1226                        ( *pPatternStartTick ) = nTotalTick;
1227                        return i;
1228                }
1229                nTotalTick += nPatternSize;
1230        }
1231
1232        if ( bLoopMode ) {
1233                m_nSongSizeInTicks = nTotalTick;
1234                int nLoopTick = 0;
1235                if ( m_nSongSizeInTicks != 0 ) {
1236                        nLoopTick = nTick % m_nSongSizeInTicks;
1237                }
1238                nTotalTick = 0;
1239                for ( int i = 0; i < nColumns; ++i ) {
1240                        PatternList *pColumn = ( *pPatternColumns )[ i ];
1241                        if ( pColumn->get_size() != 0 ) {
1242                                // tengo in considerazione solo il primo
1243                                // pattern. I pattern nel gruppo devono avere la
1244                                // stessa lunghezza.
1245                                nPatternSize = pColumn->get( 0 )->get_length();
1246                        } else {
1247                                nPatternSize = MAX_NOTES;
1248                        }
1249
1250                        if ( ( nLoopTick >= nTotalTick )
1251                             && ( nLoopTick < nTotalTick + nPatternSize ) ) {
1252                                ( *pPatternStartTick ) = nTotalTick;
1253                                return i;
1254                        }
1255                        nTotalTick += nPatternSize;
1256                }
1257        }
1258
1259        QString err = QString( "[findPatternInTick] tick = %1. No pattern found" ).arg( QString::number(nTick) );
1260        _ERRORLOG( err );
1261        return -1;
1262}
1263#endif
1264
1265
1266void audioEngine_noteOn( Note *note )
1267{
1268        m_GuiInput.note_on(note);
1269        delete note;  // Why are we deleting the note?
1270}
1271
1272
1273
1274void audioEngine_noteOff( Note *note )
1275{
1276        if ( note == 0 ) return;
1277        m_GuiInput.note_off(note);
1278        delete note; // Why are we deleting the note?
1279}
1280
1281
1282
1283// unsigned long audioEngine_getTickPosition()
1284// {
1285//      return m_nPatternTickPosition;
1286// }
1287
1288
1289AudioOutput* createDriver( const QString& sDriver )
1290{
1291        _INFOLOG( QString( "Driver: '%1'" ).arg( sDriver ) );
1292        Preferences *pPref = Preferences::getInstance();
1293        AudioOutput *pDriver = NULL;
1294
1295        if ( sDriver == "Oss" ) {
1296                pDriver = new OssDriver( audioEngine_process );
1297                if ( pDriver->get_class_name() == "NullDriver" ) {
1298                        delete pDriver;
1299                        pDriver = NULL;
1300                }
1301        } else if ( sDriver == "Jack" ) {
1302                pDriver = new JackOutput( audioEngine_process );
1303                if ( pDriver->get_class_name() == "NullDriver" ) {
1304                        delete pDriver;
1305                        pDriver = NULL;
1306                } else {
1307#ifdef JACK_SUPPORT
1308                        static_cast<JackOutput*>(pDriver)->setConnectDefaults(
1309                                Preferences::getInstance()->m_bJackConnectDefaults
1310                                );
1311#endif
1312                }
1313        } else if ( sDriver == "Alsa" ) {
1314                pDriver = new AlsaAudioDriver( audioEngine_process );
1315                if ( pDriver->get_class_name() == "NullDriver" ) {
1316                        delete pDriver;
1317                        pDriver = NULL;
1318                }
1319        } else if ( sDriver == "PortAudio" ) {
1320                pDriver = new PortAudioDriver( audioEngine_process );
1321                if ( pDriver->get_class_name() == "NullDriver" ) {
1322                        delete pDriver;
1323                        pDriver = NULL;
1324                }
1325        }
1326//#ifdef Q_OS_MACX
1327        else if ( sDriver == "CoreAudio" ) {
1328                _INFOLOG( "Creating CoreAudioDriver" );
1329                pDriver = new CoreAudioDriver( audioEngine_process );
1330                if ( pDriver->get_class_name() == "NullDriver" ) {
1331                        delete pDriver;
1332                        pDriver = NULL;
1333                }
1334        }
1335//#endif
1336        else if ( sDriver == "Fake" ) {
1337                _WARNINGLOG( "*** Using FAKE audio driver ***" );
1338                pDriver = new FakeDriver( audioEngine_process );
1339        } else {
1340                _ERRORLOG( "Unknown driver " + sDriver );
1341                audioEngine_raiseError( Hydrogen::UNKNOWN_DRIVER );
1342        }
1343
1344        if ( pDriver  ) {
1345                // initialize the audio driver
1346                int res = pDriver->init( pPref->m_nBufferSize );
1347                if ( res != 0 ) {
1348                        _ERRORLOG( "Error starting audio driver [audioDriver::init()]" );
1349                        delete pDriver;
1350                        pDriver = NULL;
1351                }
1352        }
1353
1354        return pDriver;
1355}
1356
1357
1358/// Start all audio drivers
1359void audioEngine_startAudioDrivers()
1360{
1361        Preferences *preferencesMng = Preferences::getInstance();
1362
1363        AudioEngine::get_instance()->lock( "audioEngine_startAudioDrivers" );
1364
1365        _INFOLOG( "[audioEngine_startAudioDrivers]" );
1366
1367        // check current state
1368        if ( m_audioEngineState != STATE_INITIALIZED ) {
1369                _ERRORLOG( QString( "Error the audio engine is not in INITIALIZED"
1370                                    " state. state=%1" )
1371                           .arg( m_audioEngineState ) );
1372                AudioEngine::get_instance()->unlock();
1373                return;
1374        }
1375        if ( m_pAudioDriver ) { // check if the audio m_pAudioDriver is still alive
1376                _ERRORLOG( "The audio driver is still alive" );
1377        }
1378        if ( m_pMidiDriver ) {  // check if midi driver is still alive
1379                _ERRORLOG( "The MIDI driver is still active" );
1380        }
1381
1382
1383        QString sAudioDriver = preferencesMng->m_sAudioDriver;
1384//      sAudioDriver = "Auto";
1385        if ( sAudioDriver == "Auto" ) {
1386                if ( ( m_pAudioDriver = createDriver( "Jack" ) ) == NULL ) {
1387                        if ( ( m_pAudioDriver = createDriver( "Alsa" ) ) == NULL ) {
1388                                if ( ( m_pAudioDriver = createDriver( "CoreAudio" ) ) == NULL ) {
1389                                        if ( ( m_pAudioDriver = createDriver( "PortAudio" ) ) == NULL ) {
1390                                                if ( ( m_pAudioDriver = createDriver( "Oss" ) ) == NULL ) {
1391                                                        audioEngine_raiseError( Hydrogen::ERROR_STARTING_DRIVER );
1392                                                        _ERRORLOG( "Error starting audio driver" );
1393                                                        _ERRORLOG( "Using the NULL output audio driver" );
1394
1395                                                        // use the NULL output driver
1396                                                        m_pAudioDriver = new NullDriver( audioEngine_process );
1397                                                        m_pAudioDriver->init( 0 );
1398                                                }
1399                                        }
1400                                }
1401                        }
1402                }
1403        } else {
1404                m_pAudioDriver = createDriver( sAudioDriver );
1405                if ( m_pAudioDriver == NULL ) {
1406                        audioEngine_raiseError( Hydrogen::ERROR_STARTING_DRIVER );
1407                        _ERRORLOG( "Error starting audio driver" );
1408                        _ERRORLOG( "Using the NULL output audio driver" );
1409
1410                        // use the NULL output driver
1411                        m_pAudioDriver = new NullDriver( audioEngine_process );
1412                        m_pAudioDriver->init( 0 );
1413                }
1414        }
1415
1416        if ( preferencesMng->m_sMidiDriver == "ALSA" ) {
1417#ifdef ALSA_SUPPORT
1418                // Create MIDI driver
1419                m_pMidiDriver = new AlsaMidiDriver();
1420                m_pMidiDriver->open();
1421                m_pMidiDriver->setActive( true );
1422#endif
1423        } else if ( preferencesMng->m_sMidiDriver == "PortMidi" ) {
1424#ifdef PORTMIDI_SUPPORT
1425                m_pMidiDriver = new PortMidiDriver();
1426                m_pMidiDriver->open();
1427                m_pMidiDriver->setActive( true );
1428#endif
1429        } else if ( preferencesMng->m_sMidiDriver == "CoreMidi" ) {
1430#ifdef COREMIDI_SUPPORT
1431                m_pMidiDriver = new CoreMidiDriver();
1432                m_pMidiDriver->open();
1433                m_pMidiDriver->setActive( true );
1434#endif
1435        }
1436
1437        // change the current audio engine state
1438        if ( m_pSong == NULL ) {
1439                m_audioEngineState = STATE_PREPARED;
1440        } else {
1441                m_audioEngineState = STATE_READY;
1442        }
1443
1444
1445        // update the audiodriver reference in the sampler
1446        AudioEngine::get_instance()->get_sampler()->set_audio_output( m_pAudioDriver );
1447
1448        if ( m_pAudioDriver ) {
1449                int res = m_pAudioDriver->connect();
1450                if ( res != 0 ) {
1451                        audioEngine_raiseError( Hydrogen::ERROR_STARTING_DRIVER );
1452                        _ERRORLOG( "Error starting audio driver [audioDriver::connect()]" );
1453                        _ERRORLOG( "Using the NULL output audio driver" );
1454
1455                        delete m_pAudioDriver;
1456                        m_pAudioDriver = new NullDriver( audioEngine_process );
1457                        m_pAudioDriver->init( 0 );
1458                        m_pAudioDriver->connect();
1459                }
1460
1461                #warning "Caching output port buffer pointers is deprecated in " \
1462                    "JACK.  JACK 2.0 will require that output ports get a new " \
1463                    "buffer pointer for every process() cycle."
1464                if ( ( m_pMainBuffer_L = m_pAudioDriver->getOut_L() ) == NULL ) {
1465                        _ERRORLOG( "m_pMainBuffer_L == NULL" );
1466                }
1467                if ( ( m_pMainBuffer_R = m_pAudioDriver->getOut_R() ) == NULL ) {
1468                        _ERRORLOG( "m_pMainBuffer_R == NULL" );
1469                }
1470
1471#ifdef JACK_SUPPORT
1472                audioEngine_renameJackPorts();
1473#endif
1474
1475                audioEngine_setupLadspaFX( m_pAudioDriver->getBufferSize() );
1476        }
1477
1478
1479
1480        if ( m_audioEngineState == STATE_PREPARED ) {
1481                EventQueue::get_instance()->push_event( EVENT_STATE, STATE_PREPARED );
1482        } else if ( m_audioEngineState == STATE_READY ) {
1483                EventQueue::get_instance()->push_event( EVENT_STATE, STATE_READY );
1484        }
1485        // Unlocking earlier might execute the jack process() callback before we
1486        // are fully initialized.
1487        AudioEngine::get_instance()->unlock();
1488}
1489
1490
1491
1492/// Stop all audio drivers
1493void audioEngine_stopAudioDrivers()
1494{
1495        _INFOLOG( "[audioEngine_stopAudioDrivers]" );
1496
1497        AudioEngine::get_instance()->lock( "audioEngine_stopAudioDrivers" );
1498
1499        Hydrogen::get_instance()->get_transport()->stop();
1500
1501        if ( ( m_audioEngineState != STATE_PREPARED )
1502             && ( m_audioEngineState != STATE_READY ) ) {
1503                _ERRORLOG( QString( "Error: the audio engine is not in PREPARED"
1504                                    " or READY state. state=%1" )
1505                           .arg( m_audioEngineState ) );
1506                return;
1507        }
1508
1509        // delete MIDI driver
1510        if ( m_pMidiDriver ) {
1511                m_pMidiDriver->close();
1512                delete m_pMidiDriver;
1513                m_pMidiDriver = NULL;
1514        }
1515
1516        AudioEngine::get_instance()->get_sampler()->set_audio_output( NULL );
1517
1518        // delete audio driver
1519        if ( m_pAudioDriver ) {
1520                m_pAudioDriver->disconnect();
1521                delete m_pAudioDriver;
1522                m_pAudioDriver = NULL;
1523        }
1524
1525
1526        // change the current audio engine state
1527        m_audioEngineState = STATE_INITIALIZED;
1528        EventQueue::get_instance()->push_event( EVENT_STATE, STATE_INITIALIZED );
1529        AudioEngine::get_instance()->unlock();
1530}
1531
1532
1533
1534/// Restart all audio and midi drivers
1535void audioEngine_restartAudioDrivers()
1536{
1537        audioEngine_stopAudioDrivers();
1538        audioEngine_startAudioDrivers();
1539}
1540
1541
1542
1543
1544
1545
1546//----------------------------------------------------------------------------
1547//
1548// Implementation of Hydrogen class
1549//
1550//----------------------------------------------------------------------------
1551
1552/// static reference of Hydrogen class (Singleton)
1553Hydrogen* Hydrogen::__instance = NULL;
1554
1555
1556
1557
1558Hydrogen::Hydrogen()
1559                : Object( "Hydrogen" )
1560{
1561        if ( __instance ) {
1562                _ERRORLOG( "Hydrogen audio engine is already running" );
1563                throw H2Exception( "Hydrogen audio engine is already running" );
1564        }
1565
1566        _INFOLOG( "[Hydrogen]" );
1567
1568        hydrogenInstance = this;
1569        m_pTransport = new H2Transport;
1570
1571        audioEngine_init();
1572        // Prevent double creation caused by calls from MIDI thread
1573        __instance = this;
1574        audioEngine_startAudioDrivers();
1575
1576}
1577
1578
1579
1580Hydrogen::~Hydrogen()
1581{
1582        _INFOLOG( "[~Hydrogen]" );
1583        m_pTransport->stop();
1584        removeSong();
1585        audioEngine_stopAudioDrivers();
1586        audioEngine_destroy();
1587        __kill_instruments();
1588        delete m_pTransport;
1589        __instance = NULL;
1590}
1591
1592
1593
1594/// Return the Hydrogen instance
1595Hydrogen* Hydrogen::get_instance()
1596{
1597        if ( __instance == NULL ) {
1598                __instance = new Hydrogen();
1599        }
1600        return __instance;
1601}
1602
1603Transport* Hydrogen::get_transport()
1604{
1605        return static_cast<Transport*>(m_pTransport);
1606}
1607
1608/// Start the internal sequencer
1609void Hydrogen::sequencer_play()
1610{
1611        m_pTransport->start();
1612}
1613
1614/// Stop the internal sequencer
1615void Hydrogen::sequencer_stop()
1616{
1617        m_pTransport->stop();
1618}
1619
1620
1621
1622void Hydrogen::setSong( Song *pSong )
1623{
1624        while( m_pSong != 0 ) {
1625                removeSong();
1626        }
1627        audioEngine_setSong( pSong );
1628}
1629
1630
1631
1632void Hydrogen::removeSong()
1633{
1634        audioEngine_removeSong();
1635}
1636
1637
1638
1639Song* Hydrogen::getSong()
1640{
1641        return m_pSong;
1642}
1643
1644
1645
1646void Hydrogen::midi_noteOn( Note *note )
1647{
1648        audioEngine_noteOn( note );
1649}
1650
1651
1652
1653void Hydrogen::midi_noteOff( Note *note )
1654{
1655        audioEngine_noteOff( note );
1656}
1657
1658
1659
1660void Hydrogen::addRealtimeNote( int instrument,
1661                                float velocity,
1662                                float pan_L,
1663                                float pan_R,
1664                                float /* pitch */,
1665                                bool /* forcePlay */)
1666{
1667        Preferences *pref = Preferences::getInstance();
1668
1669        Instrument* i = getSong()->get_instrument_list()->get(instrument);
1670        Note note( i,
1671                   velocity,
1672                   pan_L,
1673                   pan_R,
1674                   -1
1675                );
1676        m_GuiInput.note_on(&note, pref->getQuantizeEvents());
1677
1678}
1679
1680
1681
1682float Hydrogen::getMasterPeak_L()
1683{
1684        return m_fMasterPeak_L;
1685}
1686
1687
1688
1689float Hydrogen::getMasterPeak_R()
1690{
1691        return m_fMasterPeak_R;
1692}
1693
1694
1695
1696unsigned long Hydrogen::getTickPosition()
1697{
1698        TransportPosition pos;
1699        m_pTransport->get_position(&pos);
1700        return pos.tick + (pos.beat-1) * pos.ticks_per_beat;
1701}
1702
1703PatternList* Hydrogen::getCurrentPatternList()
1704{
1705        TransportPosition pos;
1706        m_pTransport->get_position(&pos);
1707        return m_pSong->get_pattern_group_vector()->at(pos.bar);
1708}
1709
1710PatternList * Hydrogen::getNextPatterns()
1711{
1712        TransportPosition pos;
1713        m_pTransport->get_position(&pos);
1714        return m_pSong->get_pattern_group_vector()->at(pos.bar + 1);
1715}
1716
1717/// Set the next pattern (Pattern mode only)
1718void Hydrogen::sequencer_setNextPattern( int pos, bool /*appendPattern*/, bool /*deletePattern*/ )
1719{
1720        m_pSong->set_next_pattern(pos);
1721}
1722
1723
1724
1725int Hydrogen::getPatternPos()
1726{
1727        TransportPosition pos;
1728        m_pTransport->get_position(&pos);
1729        return pos.bar-1;
1730}
1731
1732
1733
1734void Hydrogen::restartDrivers()
1735{
1736        audioEngine_restartAudioDrivers();
1737}
1738
1739
1740
1741/// Export a song to a wav file, returns the elapsed time in mSec
1742void Hydrogen::startExportSong( const QString& filename )
1743{
1744        m_pTransport->stop();
1745        Preferences *pPref = Preferences::getInstance();
1746
1747        m_oldEngineMode = m_pSong->get_mode();
1748        m_bOldLoopEnabled = m_pSong->is_loop_enabled();
1749
1750        m_pSong->set_mode( Song::SONG_MODE );
1751        m_pSong->set_loop_enabled( false );
1752        unsigned nSamplerate = m_pAudioDriver->getSampleRate();
1753
1754        // stop all audio drivers
1755        audioEngine_stopAudioDrivers();
1756
1757        /*
1758                FIXME: Questo codice fa davvero schifo....
1759        */
1760
1761
1762        m_pAudioDriver = new DiskWriterDriver( audioEngine_process, nSamplerate, filename );
1763
1764        AudioEngine::get_instance()->get_sampler()->stop_playing_notes();
1765        AudioEngine::get_instance()->get_sampler()->set_audio_output( m_pAudioDriver );
1766
1767        // reset
1768        m_pTransport->locate( 0 );
1769
1770        int res = m_pAudioDriver->init( pPref->m_nBufferSize );
1771        if ( res != 0 ) {
1772                _ERRORLOG( "Error starting disk writer driver "
1773                           "[DiskWriterDriver::init()]" );
1774        }
1775
1776        m_pMainBuffer_L = m_pAudioDriver->getOut_L();
1777        m_pMainBuffer_R = m_pAudioDriver->getOut_R();
1778
1779        audioEngine_setupLadspaFX( m_pAudioDriver->getBufferSize() );
1780
1781        m_pTransport->locate(0);
1782
1783        res = m_pAudioDriver->connect();
1784        if ( res != 0 ) {
1785                _ERRORLOG( "Error starting disk writer driver "
1786                           "[DiskWriterDriver::connect()]" );
1787        }
1788}
1789
1790
1791
1792void Hydrogen::stopExportSong()
1793{
1794        if ( m_pAudioDriver->get_class_name() != "DiskWriterDriver" ) {
1795                return;
1796        }
1797
1798//      audioEngine_stopAudioDrivers();
1799        m_pAudioDriver->disconnect();
1800
1801        m_audioEngineState = STATE_INITIALIZED;
1802        delete m_pAudioDriver;
1803        m_pAudioDriver = NULL;
1804
1805        m_pMainBuffer_L = NULL;
1806        m_pMainBuffer_R = NULL;
1807
1808        m_pSong->set_mode( m_oldEngineMode );
1809        m_pSong->set_loop_enabled( m_bOldLoopEnabled );
1810
1811        audioEngine_startAudioDrivers();
1812
1813}
1814
1815
1816
1817/// Used to display audio driver info
1818AudioOutput* Hydrogen::getAudioOutput()
1819{
1820        return m_pAudioDriver;
1821}
1822
1823
1824
1825/// Used to display midi driver info
1826MidiInput* Hydrogen::getMidiInput()
1827{
1828        return m_pMidiDriver;
1829}
1830
1831
1832
1833void Hydrogen::setMasterPeak_L( float value )
1834{
1835        m_fMasterPeak_L = value;
1836}
1837
1838
1839
1840void Hydrogen::setMasterPeak_R( float value )
1841{
1842        m_fMasterPeak_R = value;
1843}
1844
1845
1846
1847int Hydrogen::getState()
1848{
1849        return m_audioEngineState;
1850}
1851
1852float Hydrogen::getProcessTime()
1853{
1854        return m_fProcessTime;
1855}
1856
1857
1858
1859float Hydrogen::getMaxProcessTime()
1860{
1861        return m_fMaxProcessTime;
1862}
1863
1864
1865
1866int Hydrogen::loadDrumkit( Drumkit *drumkitInfo )
1867{
1868        INFOLOG( drumkitInfo->getName() );
1869        m_currentDrumkit = drumkitInfo->getName();
1870        LocalFileMng fileMng;
1871        QString sDrumkitPath = fileMng.getDrumkitDirectory( drumkitInfo->getName() );
1872
1873
1874        //current instrument list
1875        InstrumentList *songInstrList = m_pSong->get_instrument_list();
1876
1877        //new instrument list
1878        InstrumentList *pDrumkitInstrList = drumkitInfo->getInstrumentList();
1879
1880        /*
1881                If the old drumkit is bigger then the new drumkit,
1882                delete all instruments with a bigger pos then
1883                pDrumkitInstrList->get_size(). Otherwise the instruments
1884                from our old instrumentlist with
1885                pos > pDrumkitInstrList->get_size() stay in the
1886                new instrumentlist
1887               
1888        wolke: info!
1889                this has moved to the end of this function
1890                because we get lost objects in memory
1891                now:
1892                1. the new drumkit will loaded
1893                2. all not used instruments will complete deleted
1894       
1895        old funktion:
1896        while ( pDrumkitInstrList->get_size() < songInstrList->get_size() )
1897        {
1898                songInstrList->del(songInstrList->get_size() - 1);
1899        }
1900        */
1901       
1902        //needed for the new delete function
1903        int instrumentDiff =  songInstrList->get_size() - pDrumkitInstrList->get_size();
1904
1905        for ( unsigned nInstr = 0; nInstr < pDrumkitInstrList->get_size(); ++nInstr ) {
1906                Instrument *pInstr = NULL;
1907                if ( nInstr < songInstrList->get_size() ) {
1908                        //instrument exists already
1909                        pInstr = songInstrList->get( nInstr );
1910                        assert( pInstr );
1911                } else {
1912                        pInstr = Instrument::create_empty();
1913                        // The instrument isn't playing yet; no need for locking
1914                        // :-) - Jakob Lund.  AudioEngine::get_instance()->lock(
1915                        // "Hydrogen::loadDrumkit" );
1916                        songInstrList->add( pInstr );
1917                        // AudioEngine::get_instance()->unlock();
1918                }
1919
1920                Instrument *pNewInstr = pDrumkitInstrList->get( nInstr );
1921                assert( pNewInstr );
1922                _INFOLOG( QString( "Loading instrument (%1 of %2) [%3]" )
1923                          .arg( nInstr )
1924                          .arg( pDrumkitInstrList->get_size() )
1925                          .arg( pNewInstr->get_name() ) );
1926               
1927                // creo i nuovi layer in base al nuovo strumento
1928                // Moved code from here right into the Instrument class - Jakob Lund.
1929                pInstr->load_from_placeholder( pNewInstr );
1930        }
1931
1932
1933//wolke: new delete funktion
1934        if ( instrumentDiff >=0 ){
1935                for ( int i = 0; i < instrumentDiff ; i++ ){
1936                        removeInstrument(
1937                                m_pSong->get_instrument_list()->get_size() - 1,
1938                                true
1939                                );
1940                }
1941        }
1942
1943        #ifdef JACK_SUPPORT
1944        AudioEngine::get_instance()->lock( "Hydrogen::loadDrumkit" );
1945                renameJackPorts();
1946        AudioEngine::get_instance()->unlock();
1947        #endif
1948
1949        return 0;       //ok
1950}
1951
1952
1953//this is also a new function and will used from the new delete function in
1954//Hydrogen::loadDrumkit to delete the instruments by number
1955void Hydrogen::removeInstrument( int instrumentnumber, bool conditional )
1956{
1957        Instrument *pInstr = m_pSong->get_instrument_list()->get( instrumentnumber );
1958
1959
1960        PatternList* pPatternList = getSong()->get_pattern_list();
1961       
1962        if ( conditional ) {
1963        // new! this check if a pattern has an active note if there is an note
1964        //inside the pattern the intrument would not be deleted
1965                for ( int nPattern = 0 ;
1966                      nPattern < (int)pPatternList->get_size() ;
1967                      ++nPattern ) {
1968                        if( pPatternList
1969                            ->get( nPattern )
1970                            ->references_instrument( pInstr ) ) {
1971                                return;
1972                        }
1973                }
1974        } else {
1975                getSong()->purge_instrument( pInstr );
1976        }
1977
1978        Song *pSong = getSong();
1979        InstrumentList* pList = pSong->get_instrument_list();
1980        if(pList->get_size()==1){
1981                AudioEngine::get_instance()->lock("HYdrogen::removeInstrument remove last instrument");
1982                Instrument* pInstr = pList->get( 0 );
1983                pInstr->set_name( (QString( "Instrument 1" )) );
1984                // remove all layers
1985                for ( int nLayer = 0; nLayer < MAX_LAYERS; nLayer++ ) {
1986                        InstrumentLayer* pLayer = pInstr->get_layer( nLayer );
1987                        delete pLayer;
1988                        pInstr->set_layer( NULL, nLayer );
1989                }               
1990        AudioEngine::get_instance()->unlock();
1991        EventQueue::get_instance()->push_event( EVENT_SELECTED_INSTRUMENT_CHANGED, -1 );
1992        INFOLOG("clear last instrument to empty instrument 1 instead delete the last instrument");
1993        return;
1994        }
1995
1996        // if the instrument was the last on the instruments list, select the
1997        // next-last
1998        if ( instrumentnumber
1999             >= (int)getSong()->get_instrument_list()->get_size() - 1 ) {
2000                Hydrogen::get_instance()
2001                        ->setSelectedInstrumentNumber(
2002                                std::max(0, instrumentnumber - 1)
2003                                );
2004        }
2005        // delete the instrument from the instruments list
2006        AudioEngine::get_instance()->lock( "Hydrogen::removeInstrument" );
2007        getSong()->get_instrument_list()->del( instrumentnumber );
2008        getSong()->__is_modified = true;
2009        AudioEngine::get_instance()->unlock();
2010       
2011        // At this point the instrument has been removed from both the
2012        // instrument list and every pattern in the song.  Hence there's no way
2013        // (NOTE) to play on that instrument, and once all notes have stopped
2014        // playing it will be save to delete.
2015        // the ugly name is just for debugging...
2016        QString xxx_name = QString( "XXX_%1" ) . arg( pInstr->get_name() );
2017        pInstr->set_name( xxx_name );
2018        __instrument_death_row.push_back( pInstr );
2019        __kill_instruments(); // checks if there are still notes.
2020       
2021        // this will force a GUI update.
2022        EventQueue::get_instance()->push_event( EVENT_SELECTED_INSTRUMENT_CHANGED, -1 );
2023}
2024
2025
2026void Hydrogen::raiseError( unsigned nErrorCode )
2027{
2028        audioEngine_raiseError( nErrorCode );
2029}
2030
2031
2032unsigned long Hydrogen::getRealtimeFrames()
2033{
2034        return m_nFreeRollingFrameCounter;
2035}
2036
2037/**
2038 * Get the ticks for pattern at pattern pos
2039 * @a int pos -- position in song
2040 * @return -1 if pos > number of patterns in the song, tick no. > 0 otherwise
2041 * The driver should be LOCKED when calling this!!
2042 */
2043long Hydrogen::getTickForPosition( int pos )
2044{
2045        int nPatternGroups = m_pSong->get_pattern_group_vector()->size();
2046        if( nPatternGroups == 0 ) return -1;   
2047
2048        if ( pos >= nPatternGroups ) {
2049                if ( m_pSong->is_loop_enabled() ) {
2050                        pos = pos % nPatternGroups;
2051                } else {
2052                        _WARNINGLOG( QString( "patternPos > nPatternGroups. pos:"
2053                                              " %1, nPatternGroups: %2")
2054                                     .arg( pos )
2055                                     .arg(  nPatternGroups ) );
2056                        return -1;
2057                }
2058        }
2059
2060        std::vector<PatternList*> *pColumns = m_pSong->get_pattern_group_vector();
2061        long totalTick = 0;
2062        int nPatternSize;
2063        Pattern *pPattern = NULL;
2064        for ( int i = 0; i < pos; ++i ) {
2065                PatternList *pColumn = ( *pColumns )[ i ];
2066                // prendo solo il primo. I pattern nel gruppo devono avere la
2067                // stessa lunghezza
2068                pPattern = pColumn->get( 0 );
2069                if ( pPattern ) {
2070                        nPatternSize = pPattern->get_length();
2071                } else {
2072                        nPatternSize = MAX_NOTES;
2073                }
2074
2075                totalTick += nPatternSize;
2076        }
2077        return totalTick;
2078}
2079
2080/// Set the position in the song
2081void Hydrogen::setPatternPos( int pos )
2082{
2083        m_pTransport->locate(pos+1, 1, 0);
2084}
2085
2086void Hydrogen::getLadspaFXPeak( int nFX, float *fL, float *fR )
2087{
2088#ifdef LADSPA_SUPPORT
2089        ( *fL ) = m_fFXPeak_L[nFX];
2090        ( *fR ) = m_fFXPeak_R[nFX];
2091#else
2092        ( *fL ) = 0;
2093        ( *fR ) = 0;
2094#endif
2095}
2096
2097
2098
2099void Hydrogen::setLadspaFXPeak( int nFX, float fL, float fR )
2100{
2101#ifdef LADSPA_SUPPORT
2102        m_fFXPeak_L[nFX] = fL;
2103        m_fFXPeak_R[nFX] = fR;
2104#endif
2105}
2106
2107
2108void Hydrogen::onTapTempoAccelEvent()
2109{
2110        m_BeatCounter.onTapTempoAccelEvent();
2111}
2112
2113void Hydrogen::setTapTempo( float fInterval )
2114{
2115        m_BeatCounter.setTapTempo(fInterval);
2116}
2117
2118
2119void Hydrogen::setBPM( float fBPM )
2120{
2121        if( (fBPM < 500.0) && (fBPM > 20.0) ) {
2122                m_pSong->__bpm = fBPM;
2123        }
2124}
2125
2126
2127
2128void Hydrogen::restartLadspaFX()
2129{
2130        if ( m_pAudioDriver ) {
2131                AudioEngine::get_instance()->lock( "Hydrogen::restartLadspaFX" );
2132                audioEngine_setupLadspaFX( m_pAudioDriver->getBufferSize() );
2133                AudioEngine::get_instance()->unlock();
2134        } else {
2135                _ERRORLOG( "m_pAudioDriver = NULL" );
2136        }
2137}
2138
2139
2140
2141int Hydrogen::getSelectedPatternNumber()
2142{
2143        return m_nSelectedPatternNumber;
2144}
2145
2146
2147
2148void Hydrogen::setSelectedPatternNumber( int nPat )
2149{
2150        // FIXME: controllare se e' valido..
2151        if ( nPat == m_nSelectedPatternNumber ) return;
2152       
2153       
2154        if ( Preferences::getInstance()->patternModePlaysSelected() ) {
2155                AudioEngine::get_instance()
2156                        ->lock( "Hydrogen::setSelectedPatternNumber" );
2157       
2158                m_nSelectedPatternNumber = nPat;
2159                AudioEngine::get_instance()->unlock();
2160        } else {
2161                m_nSelectedPatternNumber = nPat;
2162        }
2163
2164        EventQueue::get_instance()->push_event( EVENT_SELECTED_PATTERN_CHANGED, -1 );
2165}
2166
2167
2168
2169int Hydrogen::getSelectedInstrumentNumber()
2170{
2171        return m_nSelectedInstrumentNumber;
2172}
2173
2174
2175
2176void Hydrogen::setSelectedInstrumentNumber( int nInstrument )
2177{
2178        if ( m_nSelectedInstrumentNumber == nInstrument )       return;
2179
2180        m_nSelectedInstrumentNumber = nInstrument;
2181        EventQueue::get_instance()->push_event( EVENT_SELECTED_INSTRUMENT_CHANGED, -1 );
2182}
2183
2184
2185#ifdef JACK_SUPPORT
2186void Hydrogen::renameJackPorts()
2187{
2188        if( Preferences::getInstance()->m_bJackTrackOuts == true ){
2189                audioEngine_renameJackPorts();
2190        }
2191}
2192#endif
2193
2194
2195///BeatCounter
2196
2197void Hydrogen::setbeatsToCount( int beatstocount)
2198{
2199        m_BeatCounter.setBeatsToCount(beatstocount);
2200}
2201
2202
2203int Hydrogen::getbeatsToCount()
2204{
2205        return m_BeatCounter.getBeatsToCount();
2206}
2207
2208
2209void Hydrogen::setNoteLength( float notelength)
2210{
2211        m_BeatCounter.setNoteLength(notelength);
2212}
2213
2214
2215
2216float Hydrogen::getNoteLength()
2217{
2218        return m_BeatCounter.getNoteLength();
2219}
2220
2221
2222
2223int Hydrogen::getBcStatus()
2224{
2225        return m_BeatCounter.status();
2226}
2227
2228
2229void Hydrogen::setBcOffsetAdjust()
2230{
2231        m_BeatCounter.setOffsetAdjust();
2232}
2233
2234
2235void Hydrogen::handleBeatCounter()
2236{
2237        m_BeatCounter.trigger();
2238}
2239//~ beatcounter
2240
2241// jack transport master
2242
2243bool Hydrogen::setJackTimeMaster(bool if_none_already)
2244{
2245        return m_pTransport->setJackTimeMaster(if_none_already);
2246}
2247
2248void Hydrogen::clearJackTimeMaster()
2249{
2250        m_pTransport->clearJackTimeMaster();
2251}
2252
2253bool Hydrogen::getJackTimeMaster()
2254{
2255        return m_pTransport->getJackTimeMaster();
2256}
2257
2258//~ jack transport master
2259
2260/**
2261 * Toggles between SINGLE-PATTERN pattern mode, and STACKED pattern
2262 * mode.  In stacked pattern mode, more than one pattern may be
2263 * playing at once.  Also called "Live" mode.
2264 */
2265void Hydrogen::togglePlaysSelected()
2266{
2267        Preferences* P = Preferences::getInstance();
2268        bool isPlaysSelected = P->patternModePlaysSelected();
2269
2270        // NEED TO IMPLEMENT!!
2271        assert(false);
2272
2273        P->setPatternModePlaysSelected( !isPlaysSelected );
2274       
2275}
2276
2277void Hydrogen::__kill_instruments()
2278{
2279        int c = 0;
2280        Instrument * pInstr = NULL;
2281        while ( __instrument_death_row.size()
2282                && __instrument_death_row.front()->is_queued() == 0 ) {
2283                pInstr = __instrument_death_row.front();
2284                __instrument_death_row.pop_front();
2285                INFOLOG( QString( "Deleting unused instrument (%1). "
2286                                  "%2 unused remain." )
2287                        . arg( pInstr->get_name() )
2288                        . arg( __instrument_death_row.size() ) );
2289                delete pInstr;
2290                c++;
2291        }
2292        if ( __instrument_death_row.size() ) {
2293                pInstr = __instrument_death_row.front();
2294                INFOLOG( QString( "Instrument %1 still has %2 active notes. "
2295                                  "Delaying 'delete instrument' operation." )
2296                        . arg( pInstr->get_name() )
2297                        . arg( pInstr->is_queued() ) );
2298        }
2299}
2300
2301
2302
2303void Hydrogen::__panic()
2304{
2305        sequencer_stop();       
2306        AudioEngine::get_instance()->get_sampler()->stop_playing_notes();
2307}
2308
2309
2310};
2311
Note: See TracBrowser for help on using the browser.