Changeset 228

Show
Ignore:
Timestamp:
05/28/06 05:43:20 (16 years ago)
Author:
pieterpalmers
Message:

- generic rate control added for ringbuffer based ports.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • branches/libfreebob-2.0/src/debugmodule/debugmodule.cpp

    r168 r228  
    7272 
    7373    va_start( arg, format ); 
    74     if ( printf( "%s: ", getPreSequence( level ) ) < 0 ) { 
    75         cerr << "Could not create debug string with printf" << endl; 
    76         return; 
    77     } 
     74 
    7875    if ( vprintf( format, arg ) < 0 ) { 
    7976        cerr << "Could not create debug string with printf" << endl; 
    8077        return; 
    8178    } 
    82     if ( printf( "%s", getPostSequence( level ) ) < 0 ) { 
    83         cerr << "Could not create debug string with printf" << endl; 
    84         return; 
    85     } 
     79     
    8680    va_end( arg ); 
    8781} 
  • branches/libfreebob-2.0/src/libstreaming/AmdtpPort.cpp

    r227 r228  
    3232namespace FreebobStreaming { 
    3333 
    34 AmdtpMidiPort::AmdtpMidiPort(std::string name,  
    35                            enum E_Direction direction, 
    36                            int position,  
    37                            int location,  
    38                            enum E_Formats format,  
    39                            int type) 
    40         : MidiPort(name, direction), 
    41           AmdtpPortInfo(name, position, location, format, type) 
    42           , m_countdown(0) 
    43 { 
    44         m_ringbuffer=freebob_ringbuffer_create(m_buffersize * getEventSize()); 
    45          
    46         if(!m_ringbuffer) { 
    47                 debugFatal("Could not allocate ringbuffer\n"); 
    48                 m_buffersize=0; 
    49         } 
    50          
    51 } 
    52  
    53 AmdtpMidiPort::~AmdtpMidiPort() { 
    54         if (m_ringbuffer) freebob_ringbuffer_free(m_ringbuffer); 
    55          
    56 } 
    57  
    58 /** 
    59  * The problem with MIDI ports is that there is no guaranteed availability of data. 
    60  * This function will return true if:  
    61  *  (1) there is a byte ready in the buffer 
    62  *  (2) we are allowed to send a byte 
    63  * 
    64  * it will also assume that you actually are sending a byte, and it will reset 
    65  * the countdown 
    66  * 
    67  * note on (2): the midi over 1394 spec limits the speed of sending midi data bytes. 
    68  *              For every (time muxed) channel, you can send only one midi byte every 
    69  *              320 microseconds. The packet rate is 8000pkt/sec, or 125us. Therefore 
    70  *              we wait (at least) two packets before sending another byte. This comes 
    71  *              down to 375us, so there is a slight limiting of the bandwidth. 
    72  * 
    73  * \todo fix the too long delay (375us instead of 320us) 
    74  * 
    75  * @return true if you can send a midi byte 
    76  */ 
    77 bool AmdtpMidiPort::canSend() { 
    78         bool byte_present_in_buffer; 
    79         assert(m_ringbuffer); 
    80          
    81         byte_present_in_buffer=(freebob_ringbuffer_read_space(m_ringbuffer)>=sizeof(char)); 
    82          
    83         if(byte_present_in_buffer && (m_countdown < 0)) { 
    84                 m_countdown=2; 
    85                 return true; 
    86         } 
    87         return false; 
    88 } 
    89  
    9034} // end of namespace FreebobStreaming 
  • branches/libfreebob-2.0/src/libstreaming/AmdtpPort.h

    r227 r228  
    8484                           int location,  
    8585                           enum E_Formats format,  
    86                            int type); 
     86                           int type) 
     87                : MidiPort(name, direction), 
     88                  AmdtpPortInfo(name, position, location, format, type)  
     89        {}; 
    8790 
    88         virtual ~AmdtpMidiPort(); 
    89          
    90         bool canSend(); ///< can we send a byte 
    91         void trigger(){m_countdown--;}; ///< call this every time a byte could have been sent 
     91 
     92        virtual ~AmdtpMidiPort() {}; 
    9293 
    9394protected: 
    94         int m_countdown; 
    9595         
    9696}; 
  • branches/libfreebob-2.0/src/libstreaming/AmdtpStreamProcessor.cpp

    r227 r228  
    268268                                        return false; 
    269269                                } 
     270                                 
     271                                // we use a timing unit of 10ns 
     272                                // this makes sure that for the max syt interval 
     273                                // we don't have rounding, and keeps the numbers low 
     274                                // we have 1 slot every 8 events 
     275                                // we have syt_interval events per packet 
     276                                // => syt_interval/8 slots per packet 
     277                                // packet rate is 8000pkt/sec => interval=125us 
     278                                // so the slot interval is (1/8000)/(syt_interval/8) 
     279                                // or: 1/(1000 * syt_interval) sec 
     280                                // which is 1e9/(1000*syt_interval) nsec 
     281                                // or 100000/syt_interval 'units' 
     282                                // the event interval is fixed to 320us = 32000 'units' 
     283                                if(!(*it)->useRateControl(true,(100000/m_syt_interval),32000, false)) { 
     284                                        debugFatal("Could not set signal type to PeriodSignalling"); 
     285                                        return false; 
     286                                } 
     287                                 
    270288                                // buffertype and datatype are dependant on the API 
    271289                                debugWarning("---------------- ! Doing hardcoded test setup ! --------------\n"); 
     
    433451                        bytes2write -= byteswritten; 
    434452                } 
    435                          
     453 
    436454                // the bytes2write should always be cluster aligned 
    437455                assert(bytes2write%cluster_size==0); 
    438                          
     456 
    439457        } 
    440458 
     
    555573                        target_event=(quadlet_t *)(data + ((j * m_dimension) + mp->getPosition())); 
    556574                         
    557                         if(mp->canSend()) { // we can send a byte 
     575                        if(mp->canRead()) { // we can send a byte 
    558576                                mp->readEvent(&byte); 
    559577                                *target_event=htonl( 
     
    566584                                        IEC61883_AM824_SET_LABEL(0,IEC61883_AM824_LABEL_MIDI_NO_DATA)); 
    567585                        } 
    568                         mp->trigger(); 
    569586                } 
    570587 
     
    10661083                        target_event=(quadlet_t *)(data + ((j * m_dimension) + mp->getPosition())); 
    10671084                        quadlet_t sample_int=ntohl(*target_event); 
     1085                        // FIXME: this assumes that 2X and 3X speed isn't used,  
     1086                        // because only the 1X slot is put into the ringbuffer 
    10681087                        if(IEC61883_AM824_GET_LABEL(sample_int) != IEC61883_AM824_LABEL_MIDI_NO_DATA) { 
    1069                                 sample_int=(sample_int >> 16) & 0xFF; 
     1088                                sample_int=(sample_int >> 16) & 0x000000FF; 
    10701089                                if(!mp->writeEvent(&sample_int)) { 
    10711090                                        debugWarning("Packet port events lost\n"); 
  • branches/libfreebob-2.0/src/libstreaming/Port.cpp

    r227 r228  
    4141        m_BufferType(E_PointerBuffer), 
    4242        m_enabled(true), 
     43        m_initialized(false), 
    4344        m_buffersize(0), 
    4445        m_eventsize(0), 
     
    4849        m_buffer(0), 
    4950        m_ringbuffer(0), 
    50         m_use_external_buffer(false) 
     51        m_use_external_buffer(false), 
     52        m_do_ratecontrol(false), 
     53        m_event_interval(0), 
     54        m_slot_interval(0), 
     55        m_rate_counter(0), 
     56        m_rate_counter_minimum(0), 
     57        m_average_ratecontrol(false) 
     58         
    5159{ 
    5260 
     
    284292        assert(m_ringbuffer); 
    285293         
    286         char *byte=(char *)event; 
    287         debugOutput( DEBUG_LEVEL_VERBOSE, "Writing event %02X to port %s\n",(*byte)&0xFF,m_Name.c_str()); 
    288          
    289         return (freebob_ringbuffer_write(m_ringbuffer, byte, m_eventsize)==m_eventsize); 
     294        debugOutput( DEBUG_LEVEL_VERY_VERBOSE, "Writing event %08X with size %d to port %s\n",*((quadlet_t *)event),m_eventsize, m_Name.c_str()); 
     295         
     296        return (freebob_ringbuffer_write(m_ringbuffer, (char *)event, m_eventsize)==m_eventsize); 
    290297} 
    291298 
     
    293300        assert(m_ringbuffer); 
    294301         
    295         char *byte=(char *)event; 
    296         unsigned int read=freebob_ringbuffer_read(m_ringbuffer, byte, m_eventsize); 
    297          
    298         debugOutput( DEBUG_LEVEL_VERBOSE, "Reading event %X from port %s\n",(*byte),m_Name.c_str()); 
     302        unsigned int read=freebob_ringbuffer_read(m_ringbuffer, (char *)event, m_eventsize); 
     303         
     304        debugOutput( DEBUG_LEVEL_VERY_VERBOSE, "Reading event %X with size %d from port %s\n",*((quadlet_t *)event),m_eventsize,m_Name.c_str()); 
    299305        return (read==m_eventsize); 
    300306} 
     
    304310        assert(m_ringbuffer); 
    305311         
    306         char *byte=(char *)event; 
    307312        unsigned int bytes2write=m_eventsize*nevents; 
    308313         
    309         return (freebob_ringbuffer_write(m_ringbuffer, byte,bytes2write)/m_eventsize); 
     314        unsigned int written=freebob_ringbuffer_write(m_ringbuffer, (char *)event,bytes2write)/m_eventsize; 
     315         
     316        if(written) { 
     317                int i=0; 
     318                quadlet_t * tmp=(quadlet_t *)event; 
     319                debugOutput( DEBUG_LEVEL_VERY_VERBOSE, "Written %d events (",written); 
     320                for (i=0;i<written;i++) { 
     321                        debugOutputShort(DEBUG_LEVEL_VERY_VERBOSE, "%X ", *(tmp+i)); 
     322                } 
     323                debugOutputShort(DEBUG_LEVEL_VERY_VERBOSE, ") to port %s\n",m_Name.c_str()); 
     324        } 
     325         
     326        return written; 
    310327 
    311328} 
     
    313330int Port::readEvents(void *event, unsigned int nevents) { 
    314331        assert(m_ringbuffer); 
    315         char *byte=(char *)event; 
    316332         
    317333        unsigned int bytes2read=m_eventsize*nevents; 
    318334         
    319         freebob_ringbuffer_read(m_ringbuffer, byte, bytes2read); 
    320         debugOutput( DEBUG_LEVEL_VERBOSE, "Reading events (%X) from port %s\n",(*byte),m_Name.c_str()); 
    321          
    322         return freebob_ringbuffer_read(m_ringbuffer, byte, bytes2read)/m_eventsize; 
    323 
    324  
     335        unsigned int read=freebob_ringbuffer_read(m_ringbuffer, (char *)event, bytes2read)/m_eventsize; 
     336         
     337        if(read) { 
     338                int i=0; 
     339                quadlet_t * tmp=(quadlet_t *)event; 
     340                debugOutput( DEBUG_LEVEL_VERY_VERBOSE, "Read %d events (",read); 
     341                for (i=0;i<read;i++) { 
     342                        debugOutputShort(DEBUG_LEVEL_VERY_VERBOSE, "%X ", *(tmp+i)); 
     343                } 
     344                debugOutputShort(DEBUG_LEVEL_VERY_VERBOSE, ") from port %s\n",m_Name.c_str()); 
     345        } 
     346         
     347        return read; 
     348
     349 
     350/* rate control */ 
     351bool Port::canRead() { 
     352        bool byte_present_in_buffer; 
     353         
     354        bool retval=false; 
     355         
     356        assert(m_ringbuffer); 
     357         
     358        byte_present_in_buffer=(freebob_ringbuffer_read_space(m_ringbuffer) >= m_eventsize); 
     359         
     360        if(byte_present_in_buffer) { 
     361                 
     362                if(!m_do_ratecontrol) { 
     363                        return true; 
     364                } 
     365                 
     366                if(m_rate_counter <= 0) { 
     367                        // update the counter 
     368                        if(m_average_ratecontrol) { 
     369                                m_rate_counter += m_event_interval; 
     370                                assert(m_rate_counter<m_event_interval); 
     371                        } else { 
     372                                m_rate_counter = m_event_interval; 
     373                        } 
     374                 
     375                        retval=true; 
     376                } else { 
     377                        debugOutput( DEBUG_LEVEL_VERY_VERBOSE, "Rate limit (%s)! rate_counter=%d \n",m_Name.c_str(),m_rate_counter); 
     378                 
     379                } 
     380        } 
     381         
     382         
     383        m_rate_counter -= m_slot_interval; 
     384         
     385        // we have to limit the decrement of the ratecounter somehow. 
     386        // m_rate_counter_minimum is initialized when enabling ratecontrol 
     387        if(m_rate_counter < m_rate_counter_minimum) { 
     388                m_rate_counter = m_rate_counter_minimum; 
     389        } 
     390         
     391        return retval; 
     392
     393 
     394bool Port::useRateControl(bool use, unsigned int slot_interval,  
     395                                    unsigned int event_interval, bool average) { 
     396 
     397        if (use) { 
     398                debugOutput(DEBUG_LEVEL_VERBOSE, "Enabling rate control for port %s...\n",m_Name.c_str()); 
     399                if(slot_interval>event_interval) { 
     400                        debugWarning("Rate control not needed!\n",m_Name.c_str()); 
     401                        m_do_ratecontrol=false; 
     402                        return false; 
     403                } 
     404                if(slot_interval==0) { 
     405                        debugFatal("Cannot have slot interval == 0!\n"); 
     406                        m_do_ratecontrol=false; 
     407                        return false; 
     408                } 
     409                if(event_interval==0) { 
     410                        debugFatal("Cannot have event interval == 0!\n"); 
     411                        m_do_ratecontrol=false; 
     412                        return false; 
     413                } 
     414                m_do_ratecontrol=use; 
     415                m_event_interval=event_interval; 
     416                m_slot_interval=slot_interval; 
     417                m_rate_counter=0; 
     418                 
     419                // NOTE: pretty arbitrary, but in average mode this limits the peak stream rate 
     420                m_rate_counter_minimum=-(2*event_interval); 
     421                 
     422                m_average_ratecontrol=average; 
     423 
     424        } else { 
     425                debugOutput(DEBUG_LEVEL_VERBOSE, "Disabling rate control for port %s...\n",m_Name.c_str()); 
     426                m_do_ratecontrol=use; 
     427        } 
     428        return true; 
     429
    325430 
    326431/* Private functions */ 
  • branches/libfreebob-2.0/src/libstreaming/Port.h

    r227 r228  
    198198        void setExternalBufferAddress(void *buff); 
    199199 
     200 
     201        /** 
     202         * \brief enable/disable ratecontrol 
     203         * 
     204         * Rate control is nescessary for some types of ports (most notably  
     205         * midi). The StreamProcessor that handles the port should call canRead() 
     206         * everytime a 'slot' that could be filled with an event passes. The canRead  
     207         * function will return true if  
     208         *  (1) there is an event ready in the buffer 
     209         *  (2) we are allowed to send an event in this slot 
     210         * 
     211         * Setting the rate works is done with the slot_interval and the event_interval 
     212         * parameters. On every call to canRead(), a counter is decremented with  
     213         * slot_interval. If the counter drops below 0, canRead() returns true and resets 
     214         * the counter to event_interval. 
     215         * 
     216         * e.g. for AMDTP midi, we are only allowed to send a midi byte every 320us 
     217         *      if the SYT interval is 8, there is exactly one midi slot every packet. 
     218         *      therefore the slot_interval is 1/8000s (=125us), and the event_interval  
     219         *      is 320us. 
     220         *       
     221         *      Note that the interval parameters are unitless, so you can adapt them 
     222         *      to your needs. In the AMDTP case for example, when the SYT interval is 32 
     223         *      (when the samplerate is 192kHz for example) there are 4 midi slots in 
     224         *      each packet, making the slot time interval 125us/4 = 31.25us.  
     225         *      The event time interval stays the same (320us). We can however set the 
     226         *      slot_interval to 3125 and the event_interval to 32000, as we can choose 
     227         *      the unit of the counter time step (chosen to be 10ns in this case). 
     228         * 
     229         * The average argument deserves some attention too. If average is true, we use 
     230         * average rate control. This means that on average there will be a delay of 
     231         * event_interval between two events, but that sometimes there can be a smaller 
     232         * delay. This mode fixes the average rate of the stream. 
     233         * If average is false, there will always be a minimal delay of event_interval 
     234         * between two events. This means that the maximum rate of the stream is fixed, 
     235         * and that the average rate will be lower than (or at max equal to) the rate in  
     236         * average mode. 
     237         * 
     238         * 
     239         * \note only works for the E_RingBuffer ports 
     240         * \note use before calling init() 
     241         * 
     242         * @param use set this to true to use rate control 
     243         * @param slot_interval the interval between slots 
     244         * @param event_interval the interval between events 
     245         * @param average use average rate control 
     246         * @return true if rate control was enabled/disabled successfully 
     247         */ 
     248        virtual bool useRateControl(bool use, unsigned int slot_interval,  
     249                                    unsigned int event_interval, bool average); 
     250         
     251        bool usingRateControl() { return m_do_ratecontrol;}; ///< are we using rate control? 
     252         
     253        /** 
     254         * Can we send an event in this slot. subject to rate control and  
     255         * byte availability. 
     256         * @return true if we can send an event on this slot 
     257         */ 
     258        bool canRead(); 
     259 
    200260        // FIXME: this is not really OO, but for performance??? 
    201261        void *getBufferAddress(); 
     
    228288        freebob_ringbuffer_t *m_ringbuffer; 
    229289        bool m_use_external_buffer; 
     290         
     291        bool m_do_ratecontrol; 
     292        int m_event_interval; 
     293        int m_slot_interval; 
     294        int m_rate_counter; 
     295        int m_rate_counter_minimum; 
     296        bool m_average_ratecontrol; 
    230297 
    231298        bool allocateInternalBuffer();