/[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 10 by senoner, Tue Nov 11 23:30:47 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 classes)
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    
41        SustainedKeyPool=new RTELMemoryPool<sustained_key_t>(200);
42    
43    
44    
45      pAudioSumBuffer = new float[pAudioIO->FragmentSize * pAudioIO->Channels];      pAudioSumBuffer = new float[pAudioIO->FragmentSize * pAudioIO->Channels];
46    
47      // set all voice outputs to the AudioSumBuffer      // set all voice outputs to the AudioSumBuffer
# Line 47  AudioThread::AudioThread(AudioIO* pAudio Line 54  AudioThread::AudioThread(AudioIO* pAudio
54      gig::Region* pRgn = this->pInstrument->GetFirstRegion();      gig::Region* pRgn = this->pInstrument->GetFirstRegion();
55      while (pRgn) {      while (pRgn) {
56          if (!pRgn->GetSample()->GetCache().Size) {          if (!pRgn->GetSample()->GetCache().Size) {
57    //printf("C");
58              CacheInitialSamples(pRgn->GetSample());              CacheInitialSamples(pRgn->GetSample());
59          }          }
60          for (uint i = 0; i < pRgn->DimensionRegions; i++) {          for (uint i = 0; i < pRgn->DimensionRegions; i++) {
# Line 55  AudioThread::AudioThread(AudioIO* pAudio Line 63  AudioThread::AudioThread(AudioIO* pAudio
63    
64          pRgn = this->pInstrument->GetNextRegion();          pRgn = this->pInstrument->GetNextRegion();
65      }      }
66    
67        // sustain pedal value
68        PrevHoldCCValue=0;
69        SustainPedal=0;
70    
71      dmsg(("OK\n"));      dmsg(("OK\n"));
72  }  }
73    
# Line 70  AudioThread::~AudioThread() { Line 83  AudioThread::~AudioThread() {
83    
84  int AudioThread::Main() {  int AudioThread::Main() {
85      dmsg(("Audio thread running\n"));      dmsg(("Audio thread running\n"));
86        //int fifofd=open("/tmp/fifo1",O_WRONLY);
87    
88      while (true) {      while (true) {
89    
# Line 87  int AudioThread::Main() { Line 101  int AudioThread::Main() {
101                      dmsg(("Audio Thread: Note off received\n"));                      dmsg(("Audio Thread: Note off received\n"));
102                      ReleaseVoice(command.pitch, command.velocity);                      ReleaseVoice(command.pitch, command.velocity);
103                      break;                      break;
104                    case command_type_continuous_controller:
105                        dmsg(("Audio Thread: MIDI CC received\n"));
106                        ContinuousController(command.channel, command.number, command.value);
107                        break;
108              }              }
109          }          }
110    
# Line 98  int AudioThread::Main() { Line 116  int AudioThread::Main() {
116    
117    
118          // render audio from all active voices          // render audio from all active voices
119            int act_voices=0;
120          for (uint i = 0; i < MAX_AUDIO_VOICES; i++) {          for (uint i = 0; i < MAX_AUDIO_VOICES; i++) {
121              if (pVoices[i]->IsActive()) {              if (pVoices[i]->IsActive()) {
122                  pVoices[i]->RenderAudio();                  pVoices[i]->RenderAudio();
123                    act_voices++;
124              }              }
125          }          }
126            // write that to the disk thread class so that it can print it
127            // on the console for debugging purposes
128            ActiveVoiceCount=act_voices;
129    
130    
131          // check clipping in the audio sum, convert to sample_type          // check clipping in the audio sum, convert to sample_type
# Line 119  int AudioThread::Main() { Line 142  int AudioThread::Main() {
142          // call audio driver to output sound          // call audio driver to output sound
143          int res = this->pAudioIO->Output();          int res = this->pAudioIO->Output();
144          if (res < 0) exit(EXIT_FAILURE);          if (res < 0) exit(EXIT_FAILURE);
145    
146            // FIXME remove because we use it only to write to a fifo to save the audio
147            //write(fifofd, pAudioIO->pOutputBuffer, pAudioIO->FragmentSize * pAudioIO->Channels * sizeof(short));
148            
149      }      }
150  }  }
151    
# Line 140  void AudioThread::ProcessNoteOff(uint8_t Line 167  void AudioThread::ProcessNoteOff(uint8_t
167      this->pCommandQueue->write(&cmd, 1);      this->pCommandQueue->write(&cmd, 1);
168  }  }
169    
170    // Will be called by the MIDIIn Thead to send MIDI continuos controller events
171    void AudioThread::ProcessContinuousController(uint8_t Channel, uint8_t Number, uint8_t Value) {
172        command_t cmd;
173        cmd.type     = command_type_continuous_controller;
174        cmd.channel  = Channel;
175        cmd.number   = Number;
176        cmd.value    = Value;
177        this->pCommandQueue->write(&cmd, 1);
178    }
179    
180    
181  void AudioThread::ActivateVoice(uint8_t MIDIKey, uint8_t Velocity) {  void AudioThread::ActivateVoice(uint8_t MIDIKey, uint8_t Velocity) {
182      for (int i = 0; i < MAX_AUDIO_VOICES; i++) {      for (int i = 0; i < MAX_AUDIO_VOICES; i++) {
183          if (pVoices[i]->IsActive()) continue;          if (pVoices[i]->IsActive()) continue;
184          pVoices[i]->Trigger(MIDIKey, Velocity, this->pInstrument);          pVoices[i]->Trigger(MIDIKey, Velocity, this->pInstrument);
185          ActiveVoices[MIDIKey] = pVoices[i];          // add (append) a new voice to the corresponding MIDIKey active voices list
186            Voice **new_voice_ptr=ActiveVoicePool->alloc_append(pActiveVoices[MIDIKey]);
187            *new_voice_ptr=pVoices[i];
188          return;          return;
189      }      }
190      std::cerr << "No free voice!" << std::endl << std::flush;      std::cerr << "No free voice!" << std::endl << std::flush;
191  }  }
192    
193  void AudioThread::ReleaseVoice(uint8_t MIDIKey, uint8_t Velocity) {  void AudioThread::ReleaseVoice(uint8_t MIDIKey, uint8_t Velocity) {
194      Voice* pVoice = ActiveVoices[MIDIKey];  
195    
196        // get the first voice in the list of active voices on the MIDI Key
197        Voice** pVoicePtr = pActiveVoices[MIDIKey]->first();
198        Voice *pVoice=*pVoicePtr;
199        
200      if (pVoice) {      if (pVoice) {
201    
202            // if sustain pedal is pressed postpone the Note-Off
203            if(SustainPedal) {
204                // alloc an element in the SustainedKeyPool and add the current midikey to it
205                sustained_key_t *key=SustainedKeyPool->alloc();
206                if(key == NULL) { /* FIXME */ printf("ERROR: SustainedKeyPool FULL ! exiting\n"); exit(0); }
207                key->midikey=MIDIKey;
208                key->velocity=Velocity;
209              return;
210            }
211    
212          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          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
213          ActiveVoices[MIDIKey] = NULL;  
214            // remove the voice from the list associated to this MIDI key
215            ActiveVoicePool->free(pVoicePtr);
216      }      }
217      else std::cerr << "Couldn't find active voice for note off command!" << std::endl << std::flush;      else std::cerr << "Couldn't find active voice for note off command!" << std::endl << std::flush;
218  }  }
219    
220    void AudioThread::ContinuousController(uint8_t Channel, uint8_t Number, uint8_t Value) {
221    //printf("AudioThread::ContinuousController c=%d n=%d v=%d\n",Channel, Number, Value);
222      if(Number == 64) {
223        if(Value >=64 && PrevHoldCCValue < 64) {
224          //printf("PEDAL DOWN\n");
225          SustainPedal=1;
226        }
227        if(Value < 64 && PrevHoldCCValue >=64) {
228          //printf("PEDAL UP\n");
229          SustainPedal=0;
230          sustained_key_t *key;
231          for(key = SustainedKeyPool->first(); key ; key=SustainedKeyPool->next() ) {
232            ReleaseVoice(key->midikey, key->velocity);
233          }
234          // empty the SustainedKeyPool (free all the elements)
235          SustainedKeyPool->empty();
236    
237          
238        }
239        PrevHoldCCValue=Value;
240      }
241    
242    }
243    
244    
245  void AudioThread::CacheInitialSamples(gig::Sample* pSample) {  void AudioThread::CacheInitialSamples(gig::Sample* pSample) {
246      if (!pSample || pSample->GetCache().Size) return;      if (!pSample || pSample->GetCache().Size) return;
247      if (pSample->SamplesTotal <= NUM_RAM_PRELOAD_SAMPLES) {      if (pSample->SamplesTotal <= NUM_RAM_PRELOAD_SAMPLES) {

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

  ViewVC Help
Powered by ViewVC