--- linuxsampler/trunk/src/audiothread.cpp 2003/11/05 14:47:10 9 +++ linuxsampler/trunk/src/audiothread.cpp 2003/11/11 23:30:47 10 @@ -28,13 +28,20 @@ this->pInstrument = pInstrument; pCommandQueue = new RingBuffer(1024); pVoices = new Voice*[MAX_AUDIO_VOICES]; + // allocate the ActiveVoicePool (for each midi key there is a variable size linked list + // of pointers to Voice classes) + ActiveVoicePool=new RTELMemoryPool(MAX_AUDIO_VOICES); for (uint i = 0; i < MAX_AUDIO_VOICES; i++) { pVoices[i] = new Voice(pDiskThread); } for (uint i = 0; i < 128; i++) { - ActiveVoices[i] = NULL; + pActiveVoices[i] = new RTEList; } + SustainedKeyPool=new RTELMemoryPool(200); + + + pAudioSumBuffer = new float[pAudioIO->FragmentSize * pAudioIO->Channels]; // set all voice outputs to the AudioSumBuffer @@ -47,6 +54,7 @@ gig::Region* pRgn = this->pInstrument->GetFirstRegion(); while (pRgn) { if (!pRgn->GetSample()->GetCache().Size) { +//printf("C"); CacheInitialSamples(pRgn->GetSample()); } for (uint i = 0; i < pRgn->DimensionRegions; i++) { @@ -55,6 +63,11 @@ pRgn = this->pInstrument->GetNextRegion(); } + + // sustain pedal value + PrevHoldCCValue=0; + SustainPedal=0; + dmsg(("OK\n")); } @@ -70,6 +83,7 @@ int AudioThread::Main() { dmsg(("Audio thread running\n")); + //int fifofd=open("/tmp/fifo1",O_WRONLY); while (true) { @@ -87,6 +101,10 @@ dmsg(("Audio Thread: Note off received\n")); ReleaseVoice(command.pitch, command.velocity); break; + case command_type_continuous_controller: + dmsg(("Audio Thread: MIDI CC received\n")); + ContinuousController(command.channel, command.number, command.value); + break; } } @@ -98,11 +116,16 @@ // render audio from all active voices + int act_voices=0; for (uint i = 0; i < MAX_AUDIO_VOICES; i++) { if (pVoices[i]->IsActive()) { pVoices[i]->RenderAudio(); + act_voices++; } } + // write that to the disk thread class so that it can print it + // on the console for debugging purposes + ActiveVoiceCount=act_voices; // check clipping in the audio sum, convert to sample_type @@ -119,6 +142,10 @@ // call audio driver to output sound int res = this->pAudioIO->Output(); if (res < 0) exit(EXIT_FAILURE); + + // FIXME remove because we use it only to write to a fifo to save the audio + //write(fifofd, pAudioIO->pOutputBuffer, pAudioIO->FragmentSize * pAudioIO->Channels * sizeof(short)); + } } @@ -140,25 +167,81 @@ this->pCommandQueue->write(&cmd, 1); } +// Will be called by the MIDIIn Thead to send MIDI continuos controller events +void AudioThread::ProcessContinuousController(uint8_t Channel, uint8_t Number, uint8_t Value) { + command_t cmd; + cmd.type = command_type_continuous_controller; + cmd.channel = Channel; + cmd.number = Number; + cmd.value = Value; + this->pCommandQueue->write(&cmd, 1); +} + + void AudioThread::ActivateVoice(uint8_t MIDIKey, uint8_t Velocity) { for (int i = 0; i < MAX_AUDIO_VOICES; i++) { if (pVoices[i]->IsActive()) continue; pVoices[i]->Trigger(MIDIKey, Velocity, this->pInstrument); - ActiveVoices[MIDIKey] = pVoices[i]; + // add (append) a new voice to the corresponding MIDIKey active voices list + Voice **new_voice_ptr=ActiveVoicePool->alloc_append(pActiveVoices[MIDIKey]); + *new_voice_ptr=pVoices[i]; return; } std::cerr << "No free voice!" << std::endl << std::flush; } void AudioThread::ReleaseVoice(uint8_t MIDIKey, uint8_t Velocity) { - Voice* pVoice = ActiveVoices[MIDIKey]; + + + // get the first voice in the list of active voices on the MIDI Key + Voice** pVoicePtr = pActiveVoices[MIDIKey]->first(); + Voice *pVoice=*pVoicePtr; + if (pVoice) { + + // if sustain pedal is pressed postpone the Note-Off + if(SustainPedal) { + // alloc an element in the SustainedKeyPool and add the current midikey to it + sustained_key_t *key=SustainedKeyPool->alloc(); + if(key == NULL) { /* FIXME */ printf("ERROR: SustainedKeyPool FULL ! exiting\n"); exit(0); } + key->midikey=MIDIKey; + key->velocity=Velocity; + return; + } + 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 - ActiveVoices[MIDIKey] = NULL; + + // remove the voice from the list associated to this MIDI key + ActiveVoicePool->free(pVoicePtr); } else std::cerr << "Couldn't find active voice for note off command!" << std::endl << std::flush; } +void AudioThread::ContinuousController(uint8_t Channel, uint8_t Number, uint8_t Value) { +//printf("AudioThread::ContinuousController c=%d n=%d v=%d\n",Channel, Number, Value); + if(Number == 64) { + if(Value >=64 && PrevHoldCCValue < 64) { + //printf("PEDAL DOWN\n"); + SustainPedal=1; + } + if(Value < 64 && PrevHoldCCValue >=64) { + //printf("PEDAL UP\n"); + SustainPedal=0; + sustained_key_t *key; + for(key = SustainedKeyPool->first(); key ; key=SustainedKeyPool->next() ) { + ReleaseVoice(key->midikey, key->velocity); + } + // empty the SustainedKeyPool (free all the elements) + SustainedKeyPool->empty(); + + + } + PrevHoldCCValue=Value; + } + +} + + void AudioThread::CacheInitialSamples(gig::Sample* pSample) { if (!pSample || pSample->GetCache().Size) return; if (pSample->SamplesTotal <= NUM_RAM_PRELOAD_SAMPLES) {