/[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 30 by schoenebeck, Sun Jan 11 16:43:54 2004 UTC revision 31 by schoenebeck, Sun Jan 18 20:31:31 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) : Thread(true, 1, 0) {  AudioThread::AudioThread(AudioIO* pAudioIO, DiskThread* pDiskThread, gig::Instrument* pInstrument) {
26      this->pAudioIO    = pAudioIO;      this->pAudioIO    = pAudioIO;
27      this->pDiskThread = pDiskThread;      this->pDiskThread = pDiskThread;
28      this->pInstrument = pInstrument;      this->pInstrument = pInstrument;
# Line 43  AudioThread::AudioThread(AudioIO* pAudio Line 43  AudioThread::AudioThread(AudioIO* pAudio
43      }      }
44      SustainedKeyPool = new RTELMemoryPool<uint>(128);      SustainedKeyPool = new RTELMemoryPool<uint>(128);
45    
46      pAudioSumBuffer = new float[pAudioIO->FragmentSize * pAudioIO->Channels];      // FIXME: assuming stereo output
47        pAudioSumBuffer[0] = new float[pAudioIO->MaxSamplesPerCycle() * pAudioIO->Channels()];
48        pAudioSumBuffer[1] = &pAudioSumBuffer[0][pAudioIO->MaxSamplesPerCycle()];
49    
50      // set all voice outputs to the AudioSumBuffer      // set all voice outputs to the AudioSumBuffer
51      for (int i = 0; i < MAX_AUDIO_VOICES; i++) {      for (int i = 0; i < MAX_AUDIO_VOICES; i++) { //FIXME: assuming stereo
52          pVoices[i]->SetOutput(pAudioSumBuffer, pAudioIO->FragmentSize * 2);  //FIXME: assuming stereo          pVoices[i]->SetOutputLeft(pAudioSumBuffer[0],  pAudioIO->MaxSamplesPerCycle());
53            pVoices[i]->SetOutputRight(pAudioSumBuffer[1], pAudioIO->MaxSamplesPerCycle());
54      }      }
55    
56      // cache initial samples points (for actually needed samples)      // cache initial samples points (for actually needed samples)
# Line 66  AudioThread::AudioThread(AudioIO* pAudio Line 69  AudioThread::AudioThread(AudioIO* pAudio
69      }      }
70    
71      // initialize modulation system      // initialize modulation system
72      ModulationSystem::Initialize(pAudioIO->Samplerate, pAudioIO->FragmentSize);      ModulationSystem::Initialize(pAudioIO->SampleRate(), pAudioIO->MaxSamplesPerCycle());
73    
74      // sustain pedal value      // sustain pedal value
75      PrevHoldCCValue = 0;      PrevHoldCCValue = 0;
# Line 84  AudioThread::~AudioThread() { Line 87  AudioThread::~AudioThread() {
87          }          }
88      }      }
89      delete[] pVoices;      delete[] pVoices;
90        delete[] pAudioSumBuffer[0]; // this also frees the right channel buffer
91  }  }
92    
93  int AudioThread::Main() {  int AudioThread::RenderAudio(uint Samples) {
     dmsg(2,("Audio thread running\n"));  
94    
95        // read and process commands from the queue
96      while (true) {      while (true) {
97            command_t command;
98            if (!pCommandQueue->pop(&command)) break;
99    
100          // read and process commands from the queue          switch (command.type) {
101          while (true) {              case command_type_note_on:
102              command_t command;                  dmsg(5,("Audio Thread: Note on received\n"));
103              if (!pCommandQueue->pop(&command)) break;                  ProcessNoteOn(command.pitch, command.velocity);
104                    break;
105              switch (command.type) {              case command_type_note_off:
106                  case command_type_note_on:                  dmsg(5,("Audio Thread: Note off received\n"));
107                      dmsg(5,("Audio Thread: Note on received\n"));                  ProcessNoteOff(command.pitch, command.velocity);
108                      ProcessNoteOn(command.pitch, command.velocity);                  break;
109                      break;              case command_type_continuous_controller:
110                  case command_type_note_off:                  dmsg(5,("Audio Thread: MIDI CC received\n"));
111                      dmsg(5,("Audio Thread: Note off received\n"));                  ProcessControlChange(command.channel, command.number, command.value);
112                      ProcessNoteOff(command.pitch, command.velocity);                  break;
                     break;  
                 case command_type_continuous_controller:  
                     dmsg(5,("Audio Thread: MIDI CC received\n"));  
                     ProcessControlChange(command.channel, command.number, command.value);  
                     break;  
             }  
113          }          }
114        }
115    
116    
117          // zero out the output sum buffer      // zero out the output sum buffer (left and right channel)
118          memset(pAudioSumBuffer, 0, pAudioIO->FragmentSize * pAudioIO->Channels * sizeof(float));      memset(pAudioSumBuffer[0], 0, Samples * pAudioIO->Channels() * sizeof(float));
119    
120    
121          // render audio from all active voices      // render audio from all active voices
122          int active_voices = 0;      int active_voices = 0;
123          for (uint i = 0; i < MAX_AUDIO_VOICES; i++) {      for (uint i = 0; i < MAX_AUDIO_VOICES; i++) {
124              if (pVoices[i]->IsActive()) {          if (pVoices[i]->IsActive()) {
125                  pVoices[i]->RenderAudio();              pVoices[i]->Render(Samples);
126                  if (pVoices[i]->IsActive()) active_voices++; // still active              if (pVoices[i]->IsActive()) active_voices++; // still active
127                  else { // voice reached end, is now inactive              else { // voice reached end, is now inactive
128                      KillVoice(pVoices[i]); // remove voice from the list of active voices                  KillVoice(pVoices[i]); // remove voice from the list of active voices
                 }  
129              }              }
130          }          }
131          // write that to the disk thread class so that it can print it      }
132          // on the console for debugging purposes      // write that to the disk thread class so that it can print it
133          ActiveVoiceCount = active_voices;      // on the console for debugging purposes
134          if (ActiveVoiceCount > ActiveVoiceCountMax) ActiveVoiceCountMax = ActiveVoiceCount;      ActiveVoiceCount = active_voices;
135        if (ActiveVoiceCount > ActiveVoiceCountMax) ActiveVoiceCountMax = ActiveVoiceCount;
   
         // check clipping in the audio sum, convert to sample_type  
         // (from 32bit to 16bit sample) and copy to output buffer  
         float sample_point;  
         for (uint u = 0; u < pAudioIO->FragmentSize * pAudioIO->Channels; u++) {  
             sample_point = this->pAudioSumBuffer[u] * this->Volume;  
             if (sample_point < -32768.0) sample_point = -32768.0;  
             if (sample_point > 32767.0)  sample_point = 32767.0;  
             this->pAudioIO->pOutputBuffer[u] = (sample_t) sample_point;  
         }  
136    
137    
138          // call audio driver to output sound      return 0;
         int res = this->pAudioIO->Output();  
         if (res < 0) exit(EXIT_FAILURE);  
     }  
139  }  }
140    
141  /// Will be called by the MIDIIn Thread to let the audio thread trigger a new voice.  /// Will be called by the MIDIIn Thread to let the audio thread trigger a new voice.
# Line 319  void AudioThread::ProcessControlChange(u Line 306  void AudioThread::ProcessControlChange(u
306                          (*pVoicePtr)->Release();                          (*pVoicePtr)->Release();
307                          pVoicePtr = pVoicePtrNext;                          pVoicePtr = pVoicePtrNext;
308                      }                      }
309                        SustainedKeyPool->free(pMIDIKeyInfo[*key].pSustainPoolNode);
310                        pMIDIKeyInfo[*key].pSustainPoolNode = NULL;
311                        pMIDIKeyInfo[*key].Sustained        = false;
312                        pMIDIKeyInfo[*key].hSustainPtr      = NULL;
313                  }                  }
                 SustainedKeyPool->free(pMIDIKeyInfo[*key].pSustainPoolNode);  
                 pMIDIKeyInfo[*key].pSustainPoolNode = NULL;  
                 pMIDIKeyInfo[*key].Sustained   = false;  
                 pMIDIKeyInfo[*key].hSustainPtr = NULL;  
314              }              }
315              //SustainedKeyPool->empty();              //SustainedKeyPool->empty();
316          }          }
# Line 339  void AudioThread::CacheInitialSamples(gi Line 326  void AudioThread::CacheInitialSamples(gi
326          // number of '0' samples (silence samples) behind the official buffer          // number of '0' samples (silence samples) behind the official buffer
327          // 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
328          // the sample.          // the sample.
329          gig::buffer_t buf = pSample->LoadSampleDataWithNullSamplesExtension((pAudioIO->FragmentSize << MAX_PITCH) + 3);          gig::buffer_t buf = pSample->LoadSampleDataWithNullSamplesExtension((pAudioIO->MaxSamplesPerCycle() << MAX_PITCH) + 3);
330          dmsg(4,("Cached %d Bytes, %d silence bytes.\n", buf.Size, buf.NullExtensionSize));          dmsg(4,("Cached %d Bytes, %d silence bytes.\n", buf.Size, buf.NullExtensionSize));
331      }      }
332      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

Legend:
Removed from v.30  
changed lines
  Added in v.31

  ViewVC Help
Powered by ViewVC