/[svn]/linuxsampler/trunk/src/audiothread.cpp
ViewVC logotype

Diff of /linuxsampler/trunk/src/audiothread.cpp

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 34 by schoenebeck, Mon Feb 16 19:30:42 2004 UTC revision 35 by schoenebeck, Fri Mar 5 13:46:15 2004 UTC
# Line 22  Line 22 
22    
23  #include "audiothread.h"  #include "audiothread.h"
24    
25  AudioThread::AudioThread(AudioIO* pAudioIO, DiskThread* pDiskThread, gig::Instrument* pInstrument) {  AudioThread::AudioThread(AudioIO* pAudioIO) {
26      this->pAudioIO     = pAudioIO;      this->pAudioIO     = pAudioIO;
27      this->pDiskThread  = pDiskThread;      this->pDiskThread  = new DiskThread(((pAudioIO->MaxSamplesPerCycle() << MAX_PITCH) << 1) + 6); //FIXME: assuming stereo
28      this->pInstrument  = pInstrument;      this->pInstrument  = NULL;
29      this->Pitch        = 0;      this->Pitch        = 0;
30      Voice::pDiskThread = pDiskThread;      Voice::pDiskThread = this->pDiskThread;
31      Voice::pEngine     = this;      Voice::pEngine     = this;
32      pEventQueue        = new RingBuffer<ModulationSystem::Event>(MAX_EVENTS_PER_FRAGMENT);      pEventQueue        = new RingBuffer<ModulationSystem::Event>(MAX_EVENTS_PER_FRAGMENT);
33      pEventPool         = new RTELMemoryPool<ModulationSystem::Event>(MAX_EVENTS_PER_FRAGMENT);      pEventPool         = new RTELMemoryPool<ModulationSystem::Event>(MAX_EVENTS_PER_FRAGMENT);
# Line 38  AudioThread::AudioThread(AudioIO* pAudio Line 38  AudioThread::AudioThread(AudioIO* pAudio
38          pCCEvents[i] = new RTEList<ModulationSystem::Event>(pEventPool);          pCCEvents[i] = new RTEList<ModulationSystem::Event>(pEventPool);
39      }      }
40      for (uint i = 0; i < 128; i++) {      for (uint i = 0; i < 128; i++) {
41          pMIDIKeyInfo[i].pActiveVoices    = new RTEList<Voice>(pVoicePool);          pMIDIKeyInfo[i].pActiveVoices = new RTEList<Voice>(pVoicePool);
42          pMIDIKeyInfo[i].KeyPressed       = false;          pMIDIKeyInfo[i].KeyPressed    = false;
43          pMIDIKeyInfo[i].Active           = false;          pMIDIKeyInfo[i].Active        = false;
44          pMIDIKeyInfo[i].pSelf            = NULL;          pMIDIKeyInfo[i].pSelf         = NULL;
45          pMIDIKeyInfo[i].pEvents          = new RTEList<ModulationSystem::Event>(pEventPool);          pMIDIKeyInfo[i].pEvents       = new RTEList<ModulationSystem::Event>(pEventPool);
46      }      }
47    
48      // FIXME: assuming stereo output      // FIXME: assuming stereo output
# Line 56  AudioThread::AudioThread(AudioIO* pAudio Line 56  AudioThread::AudioThread(AudioIO* pAudio
56      }      }
57      pVoicePool->clear();      pVoicePool->clear();
58    
59      // cache initial samples points (for actually needed samples)      pRIFF       = NULL;
60      dmsg(1,("Caching initial samples..."));      pGig        = NULL;
61      gig::Region* pRgn = this->pInstrument->GetFirstRegion();      pInstrument = NULL;
     while (pRgn) {  
         if (!pRgn->GetSample()->GetCache().Size) {  
             dmsg(2,("C"));  
             CacheInitialSamples(pRgn->GetSample());  
         }  
         for (uint i = 0; i < pRgn->DimensionRegions; i++) {  
             CacheInitialSamples(pRgn->pDimensionRegions[i]->pSample);  
         }  
   
         pRgn = this->pInstrument->GetNextRegion();  
     }  
62    
63      // initialize modulation system      // initialize modulation system
64      ModulationSystem::Initialize(pAudioIO->SampleRate(), pAudioIO->MaxSamplesPerCycle());      ModulationSystem::Initialize(pAudioIO->SampleRate(), pAudioIO->MaxSamplesPerCycle());
# Line 78  AudioThread::AudioThread(AudioIO* pAudio Line 67  AudioThread::AudioThread(AudioIO* pAudio
67      PrevHoldCCValue = 0;      PrevHoldCCValue = 0;
68      SustainPedal    = 0;      SustainPedal    = 0;
69    
70        SuspensionRequested = false;
71        pthread_mutex_init(&__render_state_mutex, NULL);
72        pthread_cond_init(&__render_exit_condition, NULL);
73    
74        dmsg(1,("Starting disk thread..."));
75        pDiskThread->StartThread();
76      dmsg(1,("OK\n"));      dmsg(1,("OK\n"));
77  }  }
78    
79  AudioThread::~AudioThread() {  AudioThread::~AudioThread() {
80        if (pDiskThread) {
81            pDiskThread->StopThread();
82            delete pDiskThread;
83        }
84        if (pGig)  delete pGig;
85        if (pRIFF) delete pRIFF;
86      ModulationSystem::Close();      ModulationSystem::Close();
87      for (uint i = 0; i < 128; i++) {      for (uint i = 0; i < 128; i++) {
88          if (pMIDIKeyInfo[i].pActiveVoices) delete pMIDIKeyInfo[i].pActiveVoices;          if (pMIDIKeyInfo[i].pActiveVoices) delete pMIDIKeyInfo[i].pActiveVoices;
# Line 97  AudioThread::~AudioThread() { Line 98  AudioThread::~AudioThread() {
98      if (pVoicePool)  delete pVoicePool;      if (pVoicePool)  delete pVoicePool;
99      if (pActiveKeys) delete pActiveKeys;      if (pActiveKeys) delete pActiveKeys;
100      delete[] pAudioSumBuffer[0]; // this also frees the right channel buffer      delete[] pAudioSumBuffer[0]; // this also frees the right channel buffer
101        pthread_cond_destroy(&__render_exit_condition);
102        pthread_mutex_destroy(&__render_state_mutex);
103  }  }
104    
105  /**  /**
# Line 111  AudioThread::~AudioThread() { Line 114  AudioThread::~AudioThread() {
114   */   */
115  int AudioThread::RenderAudio(uint Samples) {  int AudioThread::RenderAudio(uint Samples) {
116    
117        // zero out the output sum buffer (left and right channel)
118        memset(pAudioSumBuffer[0], 0, Samples * pAudioIO->Channels() * sizeof(float));
119    
120    
121        // check if rendering process was requested to be interrupted (e.g. to load another instrument)
122        if (SuspensionRequested) {
123            pthread_cond_broadcast(&__render_exit_condition); // wake up anybody waiting for us
124            return 0;
125        }
126    
127    
128      // empty the event lists for the new fragment      // empty the event lists for the new fragment
129      pEvents->clear();      pEvents->clear();
130      for (uint i = 0; i < ModulationSystem::destination_count; i++) {      for (uint i = 0; i < ModulationSystem::destination_count; i++) {
# Line 156  int AudioThread::RenderAudio(uint Sample Line 170  int AudioThread::RenderAudio(uint Sample
170      }      }
171    
172    
     // zero out the output sum buffer (left and right channel)  
     memset(pAudioSumBuffer[0], 0, Samples * pAudioIO->Channels() * sizeof(float));  
   
   
173      // render audio from all active voices      // render audio from all active voices
174      int active_voices = 0;      int active_voices = 0;
175      uint* piKey = pActiveKeys->first();      uint* piKey = pActiveKeys->first();
# Line 435  void AudioThread::CacheInitialSamples(gi Line 445  void AudioThread::CacheInitialSamples(gi
445    
446      if (!pSample->GetCache().Size) std::cerr << "Unable to cache sample - maybe memory full!" << std::endl << std::flush;      if (!pSample->GetCache().Size) std::cerr << "Unable to cache sample - maybe memory full!" << std::endl << std::flush;
447  }  }
448    
449    /**
450     *  Load an instrument from a .gig file.
451     *
452     *  @param FileName   - file name of the Gigasampler instrument file
453     *  @param Instrument - index of the instrument in the .gig file
454     *  @returns          detailed description of the result of the method call
455     */
456    result_t AudioThread::LoadInstrument(const char* FileName, uint Instrument) {
457        result_t result;
458    
459        if (pInstrument) { // if already running
460            // signal audio thread not to enter render part anymore
461            SuspensionRequested = true;
462            // sleep until wakened by audio thread
463            pthread_mutex_lock(&__render_state_mutex);
464            pthread_cond_wait(&__render_exit_condition, &__render_state_mutex);
465            pthread_mutex_unlock(&__render_state_mutex);
466    
467            dmsg(1,("Freeing old instrument from memory..."));
468            delete pGig;
469            delete pRIFF;
470            pInstrument = NULL;
471            dmsg(1,("OK\n"));
472        }
473    
474        // loading gig file
475        try {
476            dmsg(1,("Loading gig file..."));
477            pRIFF       = new RIFF::File(FileName);
478            pGig        = new gig::File(pRIFF);
479            pInstrument = pGig->GetInstrument(Instrument);
480            if (!pInstrument) {
481                std::stringstream msg;
482                msg << "There's no instrument with index " << Instrument << ".";
483                std::cerr << msg << std::endl;
484                result.type    = result_type_error;
485                result.code    = LSCP_ERR_UNKNOWN;
486                result.message = msg.str();
487                return result;
488            }
489            pGig->GetFirstSample(); // just to complete instrument loading before we enter the realtime part
490            dmsg(1,("OK\n"));
491        }
492        catch (RIFF::Exception e) {
493            e.PrintMessage();
494            result.type    = result_type_error;
495            result.code    = LSCP_ERR_UNKNOWN;
496            result.message = e.Message;
497            return result;
498        }
499        catch (...) {
500            dmsg(1,("Unknown exception while trying to parse gig file.\n"));
501            result.type    = result_type_error;
502            result.code    = LSCP_ERR_UNKNOWN;
503            result.message = "Unknown exception while trying to parse gig file.";
504            return result;
505        }
506    
507        // cache initial samples points (for actually needed samples)
508        dmsg(1,("Caching initial samples..."));
509        gig::Region* pRgn = this->pInstrument->GetFirstRegion();
510        while (pRgn) {
511            if (!pRgn->GetSample()->GetCache().Size) {
512                dmsg(2,("C"));
513                CacheInitialSamples(pRgn->GetSample());
514            }
515            for (uint i = 0; i < pRgn->DimensionRegions; i++) {
516                CacheInitialSamples(pRgn->pDimensionRegions[i]->pSample);
517            }
518    
519            pRgn = this->pInstrument->GetNextRegion();
520        }
521        dmsg(1,("OK\n"));
522    
523        ResetInternal(); // reset engine
524    
525        // signal audio thread to continue with rendering
526        SuspensionRequested = false;
527    
528        // success
529        result.type = result_type_success;
530        return result;
531    }
532    
533    /**
534     *  Reset all voices and disk thread and clear input event queue and all
535     *  control and status variables.
536     */
537    void AudioThread::Reset() {
538        if (pInstrument) { // if already running
539            // signal audio thread not to enter render part anymore
540            SuspensionRequested = true;
541            // sleep until wakened by audio thread
542            pthread_mutex_lock(&__render_state_mutex);
543            pthread_cond_wait(&__render_exit_condition, &__render_state_mutex);
544            pthread_mutex_unlock(&__render_state_mutex);
545        }
546    
547        ResetInternal();
548    
549        // signal audio thread to continue with rendering
550        SuspensionRequested = false;
551    }
552    
553    /**
554     *  Reset all voices and disk thread and clear input event queue and all
555     *  control and status variables. This method is not thread safe!
556     */
557    void AudioThread::ResetInternal() {
558        this->Pitch         = 0;
559        PrevHoldCCValue     = 0; // sustain pedal value
560        SustainPedal        = 0;
561        ActiveVoiceCount    = 0;
562        ActiveVoiceCountMax = 0;
563    
564        // reset key info
565        for (uint i = 0; i < 128; i++) {
566            pMIDIKeyInfo[i].pActiveVoices->clear();
567            pMIDIKeyInfo[i].pEvents->clear();
568            pMIDIKeyInfo[i].KeyPressed = false;
569            pMIDIKeyInfo[i].Active     = false;
570            pMIDIKeyInfo[i].pSelf      = NULL;
571        }
572    
573        // reset all voices
574        for (Voice* pVoice = pVoicePool->first(); pVoice; pVoice = pVoicePool->next()) {
575            pVoice->Reset();
576        }
577    
578        // free all active keys
579        pActiveKeys->clear();
580    
581        // reset disk thread
582        pDiskThread->Reset();
583    
584        // delete all input events
585        pEventQueue->init();
586    }

Legend:
Removed from v.34  
changed lines
  Added in v.35

  ViewVC Help
Powered by ViewVC