/[svn]/linuxsampler/trunk/src/engines/gig/Engine.cpp
ViewVC logotype

Diff of /linuxsampler/trunk/src/engines/gig/Engine.cpp

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

revision 242 by schoenebeck, Wed Sep 15 13:59:08 2004 UTC revision 244 by schoenebeck, Fri Sep 17 01:01:11 2004 UTC
# Line 37  namespace LinuxSampler { namespace gig { Line 37  namespace LinuxSampler { namespace gig {
37          pAudioOutputDevice = NULL;          pAudioOutputDevice = NULL;
38          pDiskThread        = NULL;          pDiskThread        = NULL;
39          pEventGenerator    = NULL;          pEventGenerator    = NULL;
40          pEventQueue        = new RingBuffer<Event>(MAX_EVENTS_PER_FRAGMENT);          pSysexBuffer       = new RingBuffer<uint8_t>(SYSEX_BUFFER_SIZE, 0);
41            pEventQueue        = new RingBuffer<Event>(MAX_EVENTS_PER_FRAGMENT, 0);
42          pEventPool         = new RTELMemoryPool<Event>(MAX_EVENTS_PER_FRAGMENT);          pEventPool         = new RTELMemoryPool<Event>(MAX_EVENTS_PER_FRAGMENT);
43          pVoicePool         = new RTELMemoryPool<Voice>(MAX_AUDIO_VOICES);          pVoicePool         = new RTELMemoryPool<Voice>(MAX_AUDIO_VOICES);
44          pActiveKeys        = new RTELMemoryPool<uint>(128);          pActiveKeys        = new RTELMemoryPool<uint>(128);
# Line 93  namespace LinuxSampler { namespace gig { Line 94  namespace LinuxSampler { namespace gig {
94          if (pEventPool)  delete pEventPool;          if (pEventPool)  delete pEventPool;
95          if (pVoicePool)  delete pVoicePool;          if (pVoicePool)  delete pVoicePool;
96          if (pActiveKeys) delete pActiveKeys;          if (pActiveKeys) delete pActiveKeys;
97            if (pSysexBuffer) delete pSysexBuffer;
98          if (pEventGenerator) delete pEventGenerator;          if (pEventGenerator) delete pEventGenerator;
99          if (pMainFilterParameters) delete[] pMainFilterParameters;          if (pMainFilterParameters) delete[] pMainFilterParameters;
100          if (pBasicFilterParameters) delete[] pBasicFilterParameters;          if (pBasicFilterParameters) delete[] pBasicFilterParameters;
# Line 155  namespace LinuxSampler { namespace gig { Line 157  namespace LinuxSampler { namespace gig {
157          ActiveVoiceCountMax = 0;          ActiveVoiceCountMax = 0;
158          GlobalVolume        = 1.0;          GlobalVolume        = 1.0;
159    
160            // reset to normal chromatic scale (means equal temper)
161            memset(&ScaleTuning[0], 0x00, 12);
162    
163          // set all MIDI controller values to zero          // set all MIDI controller values to zero
164          memset(ControllerTable, 0x00, 128);          memset(ControllerTable, 0x00, 128);
165    
# Line 408  namespace LinuxSampler { namespace gig { Line 413  namespace LinuxSampler { namespace gig {
413              pNextEvent = pEvents->next();              pNextEvent = pEvents->next();
414              switch (pEvent->Type) {              switch (pEvent->Type) {
415                  case Event::type_note_on:                  case Event::type_note_on:
416                      dmsg(5,("Audio Thread: Note on received\n"));                      dmsg(5,("Engine: Note on received\n"));
417                      ProcessNoteOn(pEvent);                      ProcessNoteOn(pEvent);
418                      break;                      break;
419                  case Event::type_note_off:                  case Event::type_note_off:
420                      dmsg(5,("Audio Thread: Note off received\n"));                      dmsg(5,("Engine: Note off received\n"));
421                      ProcessNoteOff(pEvent);                      ProcessNoteOff(pEvent);
422                      break;                      break;
423                  case Event::type_control_change:                  case Event::type_control_change:
424                      dmsg(5,("Audio Thread: MIDI CC received\n"));                      dmsg(5,("Engine: MIDI CC received\n"));
425                      ProcessControlChange(pEvent);                      ProcessControlChange(pEvent);
426                      break;                      break;
427                  case Event::type_pitchbend:                  case Event::type_pitchbend:
428                      dmsg(5,("Audio Thread: Pitchbend received\n"));                      dmsg(5,("Engine: Pitchbend received\n"));
429                      ProcessPitchbend(pEvent);                      ProcessPitchbend(pEvent);
430                      break;                      break;
431                    case Event::type_sysex:
432                        dmsg(5,("Engine: Sysex received\n"));
433                        ProcessSysex(pEvent);
434                        break;
435              }              }
436          }          }
437    
# Line 525  namespace LinuxSampler { namespace gig { Line 534  namespace LinuxSampler { namespace gig {
534      }      }
535    
536      /**      /**
537         *  Will be called by the MIDI input device whenever a MIDI system
538         *  exclusive message has arrived.
539         *
540         *  @param pData - pointer to sysex data
541         *  @param Size  - lenght of sysex data (in bytes)
542         */
543        void Engine::SendSysex(void* pData, uint Size) {
544            Event event = pEventGenerator->CreateEvent();
545            event.Type  = Event::type_sysex;
546            event.Size  = Size;
547            if (pEventQueue->write_space() > 0) {
548                if (pSysexBuffer->write_space() >= Size) {
549                    // copy sysex data to input buffer
550                    uint toWrite = Size;
551                    uint8_t* pPos = (uint8_t*) pData;
552                    while (toWrite) {
553                        const uint writeNow = RTMath::Min(toWrite, pSysexBuffer->write_space_to_end());
554                        pSysexBuffer->write(pPos, writeNow);
555                        toWrite -= writeNow;
556                        pPos    += writeNow;
557    
558                    }
559                    // finally place sysex event into input event queue
560                    pEventQueue->push(&event);
561                }
562                else dmsg(1,("Engine: Sysex message too large (%d byte) for input buffer (%d byte)!",Size,SYSEX_BUFFER_SIZE));
563            }
564            else dmsg(1,("Engine: Input event queue full!"));
565        }
566    
567        /**
568       *  Assigns and triggers a new voice for the respective MIDI key.       *  Assigns and triggers a new voice for the respective MIDI key.
569       *       *
570       *  @param pNoteOnEvent - key, velocity and time stamp of the event       *  @param pNoteOnEvent - key, velocity and time stamp of the event
# Line 737  namespace LinuxSampler { namespace gig { Line 777  namespace LinuxSampler { namespace gig {
777      }      }
778    
779      /**      /**
780         *  Reacts on MIDI system exclusive messages.
781         *
782         *  @param pSysexEvent - sysex data size and time stamp of the sysex event
783         */
784        void Engine::ProcessSysex(Event* pSysexEvent) {
785            RingBuffer<uint8_t>::NonVolatileReader reader = pSysexBuffer->get_non_volatile_reader();
786    
787            uint8_t exclusive_status, id;
788            if (!reader.pop(&exclusive_status)) goto free_sysex_data;
789            if (!reader.pop(&id))               goto free_sysex_data;
790            if (exclusive_status != 0xF0)       goto free_sysex_data;
791    
792            switch (id) {
793                case 0x41: { // Roland
794                    uint8_t device_id, model_id, cmd_id;
795                    if (!reader.pop(&device_id)) goto free_sysex_data;
796                    if (!reader.pop(&model_id))  goto free_sysex_data;
797                    if (!reader.pop(&cmd_id))    goto free_sysex_data;
798                    if (model_id != 0x42 /*GS*/) goto free_sysex_data;
799                    if (cmd_id != 0x12 /*DT1*/)  goto free_sysex_data;
800    
801                    // command address
802                    uint8_t addr[3]; // 2 byte addr MSB, followed by 1 byte addr LSB)
803                    const RingBuffer<uint8_t>::NonVolatileReader checksum_reader = reader; // so we can calculate the check sum later
804                    if (reader.read(&addr[0], 3) != 3) goto free_sysex_data;
805                    if (addr[0] == 0x40 && addr[1] == 0x00) { // System Parameters
806                    }
807                    else if (addr[0] == 0x40 && addr[1] == 0x01) { // Common Parameters
808                    }
809                    else if (addr[0] == 0x40 && (addr[1] & 0xf0) == 0x10) { // Part Parameters (1)
810                        switch (addr[3]) {
811                            case 0x40: { // scale tuning
812                                uint8_t scale_tunes[12]; // detuning of all 12 semitones of an octave
813                                if (reader.read(&scale_tunes[0], 12) != 12) goto free_sysex_data;
814                                uint8_t checksum;
815                                if (!reader.pop(&checksum))                      goto free_sysex_data;
816                                if (GSCheckSum(checksum_reader, 12) != checksum) goto free_sysex_data;
817                                for (int i = 0; i < 12; i++) scale_tunes[i] -= 64;
818                                AdjustScale((int8_t*) scale_tunes);
819                                break;
820                            }
821                        }
822                    }
823                    else if (addr[0] == 0x40 && (addr[1] & 0xf0) == 0x20) { // Part Parameters (2)
824                    }
825                    else if (addr[0] == 0x41) { // Drum Setup Parameters
826                    }
827                    break;
828                }
829            }
830    
831            free_sysex_data: // finally free sysex data
832            pSysexBuffer->increment_read_ptr(pSysexEvent->Size);
833        }
834    
835        /**
836         * Calculates the Roland GS sysex check sum.
837         *
838         * @param AddrReader - reader which currently points to the first GS
839         *                     command address byte of the GS sysex message in
840         *                     question
841         * @param DataSize   - size of the GS message data (in bytes)
842         */
843        uint8_t Engine::GSCheckSum(const RingBuffer<uint8_t>::NonVolatileReader AddrReader, uint DataSize) {
844            RingBuffer<uint8_t>::NonVolatileReader reader = AddrReader;
845            uint bytes = 3 /*addr*/ + DataSize;
846            uint8_t addr_and_data[bytes];
847            reader.read(&addr_and_data[0], bytes);
848            uint8_t sum = 0;
849            for (uint i = 0; i < bytes; i++) sum += addr_and_data[i];
850            return 128 - sum % 128;
851        }
852    
853        /**
854         * Allows to tune each of the twelve semitones of an octave.
855         *
856         * @param ScaleTunes - detuning of all twelve semitones (in cents)
857         */
858        void Engine::AdjustScale(int8_t ScaleTunes[12]) {
859            memcpy(&this->ScaleTuning[0], &ScaleTunes[0], 12); //TODO: currently not sample accurate
860        }
861    
862        /**
863       * Initialize the parameter sequence for the modulation destination given by       * Initialize the parameter sequence for the modulation destination given by
864       * by 'dst' with the constant value given by val.       * by 'dst' with the constant value given by val.
865       */       */
# Line 840  namespace LinuxSampler { namespace gig { Line 963  namespace LinuxSampler { namespace gig {
963      }      }
964    
965      String Engine::Version() {      String Engine::Version() {
966          String s = "$Revision: 1.11 $";          String s = "$Revision: 1.12 $";
967          return s.substr(11, s.size() - 13); // cut dollar signs, spaces and CVS macro keyword          return s.substr(11, s.size() - 13); // cut dollar signs, spaces and CVS macro keyword
968      }      }
969    

Legend:
Removed from v.242  
changed lines
  Added in v.244

  ViewVC Help
Powered by ViewVC