/[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 9 by schoenebeck, Wed Nov 5 14:47:10 2003 UTC revision 14 by schoenebeck, Fri Nov 21 15:40:40 2003 UTC
# Line 28  AudioThread::AudioThread(AudioIO* pAudio Line 28  AudioThread::AudioThread(AudioIO* pAudio
28      this->pInstrument = pInstrument;      this->pInstrument = pInstrument;
29      pCommandQueue     = new RingBuffer<command_t>(1024);      pCommandQueue     = new RingBuffer<command_t>(1024);
30      pVoices           = new Voice*[MAX_AUDIO_VOICES];      pVoices           = new Voice*[MAX_AUDIO_VOICES];
31        // allocate the ActiveVoicePool (for each midi key there is a variable size linked list
32        // of pointers to Voice objects)
33        ActiveVoicePool = new RTELMemoryPool<Voice*>(MAX_AUDIO_VOICES);
34      for (uint i = 0; i < MAX_AUDIO_VOICES; i++) {      for (uint i = 0; i < MAX_AUDIO_VOICES; i++) {
35          pVoices[i] = new Voice(pDiskThread);          pVoices[i] = new Voice(pDiskThread);
36      }      }
37      for (uint i = 0; i < 128; i++) {      for (uint i = 0; i < 128; i++) {
38          ActiveVoices[i] = NULL;          pActiveVoices[i] = new RTEList<Voice*>;
39      }      }
40        SustainedKeyPool = new RTELMemoryPool<sustained_key_t>(MAX_AUDIO_VOICES);
41    
42      pAudioSumBuffer = new float[pAudioIO->FragmentSize * pAudioIO->Channels];      pAudioSumBuffer = new float[pAudioIO->FragmentSize * pAudioIO->Channels];
43    
# Line 43  AudioThread::AudioThread(AudioIO* pAudio Line 47  AudioThread::AudioThread(AudioIO* pAudio
47      }      }
48    
49      // cache initial samples points (for actually needed samples)      // cache initial samples points (for actually needed samples)
50      dmsg(("Caching initial samples..."));      dmsg(1,("Caching initial samples..."));
51      gig::Region* pRgn = this->pInstrument->GetFirstRegion();      gig::Region* pRgn = this->pInstrument->GetFirstRegion();
52      while (pRgn) {      while (pRgn) {
53          if (!pRgn->GetSample()->GetCache().Size) {          if (!pRgn->GetSample()->GetCache().Size) {
54                dmsg(2,("C"));
55              CacheInitialSamples(pRgn->GetSample());              CacheInitialSamples(pRgn->GetSample());
56          }          }
57          for (uint i = 0; i < pRgn->DimensionRegions; i++) {          for (uint i = 0; i < pRgn->DimensionRegions; i++) {
# Line 55  AudioThread::AudioThread(AudioIO* pAudio Line 60  AudioThread::AudioThread(AudioIO* pAudio
60    
61          pRgn = this->pInstrument->GetNextRegion();          pRgn = this->pInstrument->GetNextRegion();
62      }      }
63      dmsg(("OK\n"));  
64        // sustain pedal value
65        PrevHoldCCValue = 0;
66        SustainPedal    = 0;
67    
68        dmsg(1,("OK\n"));
69  }  }
70    
71  AudioThread::~AudioThread() {  AudioThread::~AudioThread() {
# Line 69  AudioThread::~AudioThread() { Line 79  AudioThread::~AudioThread() {
79  }  }
80    
81  int AudioThread::Main() {  int AudioThread::Main() {
82      dmsg(("Audio thread running\n"));      dmsg(2,("Audio thread running\n"));
83    
84      while (true) {      while (true) {
85    
# Line 80  int AudioThread::Main() { Line 90  int AudioThread::Main() {
90    
91              switch (command.type) {              switch (command.type) {
92                  case command_type_note_on:                  case command_type_note_on:
93                      dmsg(("Audio Thread: Note on received\n"));                      dmsg(5,("Audio Thread: Note on received\n"));
94                      ActivateVoice(command.pitch, command.velocity);                      ActivateVoice(command.pitch, command.velocity);
95                      break;                      break;
96                  case command_type_note_off:                  case command_type_note_off:
97                      dmsg(("Audio Thread: Note off received\n"));                      dmsg(5,("Audio Thread: Note off received\n"));
98                      ReleaseVoice(command.pitch, command.velocity);                      ReleaseVoice(command.pitch, command.velocity);
99                      break;                      break;
100                    case command_type_continuous_controller:
101                        dmsg(5,("Audio Thread: MIDI CC received\n"));
102                        ContinuousController(command.channel, command.number, command.value);
103                        break;
104              }              }
105          }          }
106    
# Line 98  int AudioThread::Main() { Line 112  int AudioThread::Main() {
112    
113    
114          // render audio from all active voices          // render audio from all active voices
115            int active_voices = 0;
116          for (uint i = 0; i < MAX_AUDIO_VOICES; i++) {          for (uint i = 0; i < MAX_AUDIO_VOICES; i++) {
117              if (pVoices[i]->IsActive()) {              if (pVoices[i]->IsActive()) {
118                  pVoices[i]->RenderAudio();                  pVoices[i]->RenderAudio();
119                    if (pVoices[i]->IsActive()) active_voices++; // still active
120                    else { // voice reached end, is now inactive
121                        ReleaseVoice(pVoices[i]); // remove voice from the list of active voices
122                    }
123              }              }
124          }          }
125            // write that to the disk thread class so that it can print it
126            // on the console for debugging purposes
127            ActiveVoiceCount = active_voices;
128            if (ActiveVoiceCount > ActiveVoiceCountMax) ActiveVoiceCountMax = ActiveVoiceCount;
129    
130    
131          // check clipping in the audio sum, convert to sample_type          // check clipping in the audio sum, convert to sample_type
# Line 140  void AudioThread::ProcessNoteOff(uint8_t Line 163  void AudioThread::ProcessNoteOff(uint8_t
163      this->pCommandQueue->write(&cmd, 1);      this->pCommandQueue->write(&cmd, 1);
164  }  }
165    
166    // Will be called by the MIDIIn Thead to send MIDI continuos controller events
167    void AudioThread::ProcessContinuousController(uint8_t Channel, uint8_t Number, uint8_t Value) {
168        command_t cmd;
169        cmd.type     = command_type_continuous_controller;
170        cmd.channel  = Channel;
171        cmd.number   = Number;
172        cmd.value    = Value;
173        this->pCommandQueue->write(&cmd, 1);
174    }
175    
176  void AudioThread::ActivateVoice(uint8_t MIDIKey, uint8_t Velocity) {  void AudioThread::ActivateVoice(uint8_t MIDIKey, uint8_t Velocity) {
177      for (int i = 0; i < MAX_AUDIO_VOICES; i++) {      for (int i = 0; i < MAX_AUDIO_VOICES; i++) {
178          if (pVoices[i]->IsActive()) continue;          if (pVoices[i]->IsActive()) continue;
179          pVoices[i]->Trigger(MIDIKey, Velocity, this->pInstrument);          pVoices[i]->Trigger(MIDIKey, Velocity, this->pInstrument);
180          ActiveVoices[MIDIKey] = pVoices[i];          // add (append) a new voice to the corresponding MIDIKey active voices list
181            Voice** new_voice_ptr = ActiveVoicePool->alloc_append(pActiveVoices[MIDIKey]);
182            *new_voice_ptr = pVoices[i];
183            pVoices[i]->pSelfPtr = new_voice_ptr; // FIXME: hack to allow fast deallocation
184          return;          return;
185      }      }
186      std::cerr << "No free voice!" << std::endl << std::flush;      std::cerr << "No free voice!" << std::endl << std::flush;
187  }  }
188    
189  void AudioThread::ReleaseVoice(uint8_t MIDIKey, uint8_t Velocity) {  void AudioThread::ReleaseVoice(uint8_t MIDIKey, uint8_t Velocity) {
190      Voice* pVoice = ActiveVoices[MIDIKey];      // if sustain pedal is pressed postpone the Note-Off
191        if (SustainPedal) {
192            // alloc an element in the SustainedKeyPool and add the current midikey to it
193            sustained_key_t* key = SustainedKeyPool->alloc();
194            if (key == NULL) printf("ERROR: SustainedKeyPool FULL ! exiting\n"); // FIXME
195            key->midikey  = MIDIKey;
196            key->velocity = Velocity;
197        }
198        else {
199            // get the first voice in the list of active voices on the MIDI Key
200            Voice** pVoicePtr = pActiveVoices[MIDIKey]->first();
201            if (pVoicePtr) ReleaseVoice(*pVoicePtr);
202            else std::cerr << "Couldn't find active voice for note off command!" << std::endl << std::flush;
203        }
204    }
205    
206    void AudioThread::ReleaseVoice(Voice* pVoice) {
207      if (pVoice) {      if (pVoice) {
208          pVoice->Kill(); //TODO: for now we're rude and just kill the poor, poor voice immediately :), later we add a Release() method to the Voice class and call it here to let the voice go through it's release phase          if (pVoice->IsActive()) pVoice->Kill(); //TODO: for now we're rude and just kill the poor, poor voice immediately :), later we add a Release() method to the Voice class and call it here to let the voice go through it's release phase
209          ActiveVoices[MIDIKey] = NULL;  
210            // remove the voice from the list associated to this MIDI key
211            ActiveVoicePool->free(pVoice->pSelfPtr);
212        }
213        else std::cerr << "Couldn't find active voice to release!" << std::endl << std::flush;
214    }
215    
216    void AudioThread::ContinuousController(uint8_t Channel, uint8_t Number, uint8_t Value) {
217        dmsg(4,("AudioThread::ContinuousController c=%d n=%d v=%d\n", Channel, Number, Value));
218        if (Number == 64) {
219            if (Value >= 64 && PrevHoldCCValue < 64) {
220                dmsg(4,("PEDAL DOWN\n"));
221                SustainPedal = true;
222            }
223            if (Value < 64 && PrevHoldCCValue >= 64) {
224                dmsg(4,("PEDAL UP\n"));
225                SustainPedal = false;
226                for (sustained_key_t* key = SustainedKeyPool->first(); key; key = SustainedKeyPool->next()) {
227                    ReleaseVoice(key->midikey, key->velocity);
228                }
229                // empty the SustainedKeyPool (free all the elements)
230                SustainedKeyPool->empty();
231            }
232            PrevHoldCCValue = Value;
233      }      }
     else std::cerr << "Couldn't find active voice for note off command!" << std::endl << std::flush;  
234  }  }
235    
236  void AudioThread::CacheInitialSamples(gig::Sample* pSample) {  void AudioThread::CacheInitialSamples(gig::Sample* pSample) {
# Line 168  void AudioThread::CacheInitialSamples(gi Line 242  void AudioThread::CacheInitialSamples(gi
242          // border, to allow the interpolator do it's work even at the end of          // border, to allow the interpolator do it's work even at the end of
243          // the sample.          // the sample.
244          gig::buffer_t buf = pSample->LoadSampleDataWithNullSamplesExtension(pAudioIO->FragmentSize << MAX_PITCH);          gig::buffer_t buf = pSample->LoadSampleDataWithNullSamplesExtension(pAudioIO->FragmentSize << MAX_PITCH);
245          dmsg(("Cached %d Bytes, %d silence bytes.\n", buf.Size, buf.NullExtensionSize));          dmsg(4,("Cached %d Bytes, %d silence bytes.\n", buf.Size, buf.NullExtensionSize));
246      }      }
247      else { // we only cache NUM_RAM_PRELOAD_SAMPLES and stream the other sample points from disk      else { // we only cache NUM_RAM_PRELOAD_SAMPLES and stream the other sample points from disk
248          pSample->LoadSampleData(NUM_RAM_PRELOAD_SAMPLES);          pSample->LoadSampleData(NUM_RAM_PRELOAD_SAMPLES);

Legend:
Removed from v.9  
changed lines
  Added in v.14

  ViewVC Help
Powered by ViewVC