Changeset 228
- Timestamp:
- 05/28/06 05:43:20 (16 years ago)
- Files:
-
- branches/libfreebob-2.0/src/debugmodule/debugmodule.cpp (modified) (1 diff)
- branches/libfreebob-2.0/src/libstreaming/AmdtpPort.cpp (modified) (1 diff)
- branches/libfreebob-2.0/src/libstreaming/AmdtpPort.h (modified) (1 diff)
- branches/libfreebob-2.0/src/libstreaming/AmdtpStreamProcessor.cpp (modified) (5 diffs)
- branches/libfreebob-2.0/src/libstreaming/Port.cpp (modified) (6 diffs)
- branches/libfreebob-2.0/src/libstreaming/Port.h (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
branches/libfreebob-2.0/src/debugmodule/debugmodule.cpp
r168 r228 72 72 73 73 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 78 75 if ( vprintf( format, arg ) < 0 ) { 79 76 cerr << "Could not create debug string with printf" << endl; 80 77 return; 81 78 } 82 if ( printf( "%s", getPostSequence( level ) ) < 0 ) { 83 cerr << "Could not create debug string with printf" << endl; 84 return; 85 } 79 86 80 va_end( arg ); 87 81 } branches/libfreebob-2.0/src/libstreaming/AmdtpPort.cpp
r227 r228 32 32 namespace FreebobStreaming { 33 33 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 buffer62 * (2) we are allowed to send a byte63 *64 * it will also assume that you actually are sending a byte, and it will reset65 * the countdown66 *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 every69 * 320 microseconds. The packet rate is 8000pkt/sec, or 125us. Therefore70 * we wait (at least) two packets before sending another byte. This comes71 * 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 byte76 */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 90 34 } // end of namespace FreebobStreaming branches/libfreebob-2.0/src/libstreaming/AmdtpPort.h
r227 r228 84 84 int location, 85 85 enum E_Formats format, 86 int type); 86 int type) 87 : MidiPort(name, direction), 88 AmdtpPortInfo(name, position, location, format, type) 89 {}; 87 90 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() {}; 92 93 93 94 protected: 94 int m_countdown;95 95 96 96 }; branches/libfreebob-2.0/src/libstreaming/AmdtpStreamProcessor.cpp
r227 r228 268 268 return false; 269 269 } 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 270 288 // buffertype and datatype are dependant on the API 271 289 debugWarning("---------------- ! Doing hardcoded test setup ! --------------\n"); … … 433 451 bytes2write -= byteswritten; 434 452 } 435 453 436 454 // the bytes2write should always be cluster aligned 437 455 assert(bytes2write%cluster_size==0); 438 456 439 457 } 440 458 … … 555 573 target_event=(quadlet_t *)(data + ((j * m_dimension) + mp->getPosition())); 556 574 557 if(mp->can Send()) { // we can send a byte575 if(mp->canRead()) { // we can send a byte 558 576 mp->readEvent(&byte); 559 577 *target_event=htonl( … … 566 584 IEC61883_AM824_SET_LABEL(0,IEC61883_AM824_LABEL_MIDI_NO_DATA)); 567 585 } 568 mp->trigger();569 586 } 570 587 … … 1066 1083 target_event=(quadlet_t *)(data + ((j * m_dimension) + mp->getPosition())); 1067 1084 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 1068 1087 if(IEC61883_AM824_GET_LABEL(sample_int) != IEC61883_AM824_LABEL_MIDI_NO_DATA) { 1069 sample_int=(sample_int >> 16) & 0x FF;1088 sample_int=(sample_int >> 16) & 0x000000FF; 1070 1089 if(!mp->writeEvent(&sample_int)) { 1071 1090 debugWarning("Packet port events lost\n"); branches/libfreebob-2.0/src/libstreaming/Port.cpp
r227 r228 41 41 m_BufferType(E_PointerBuffer), 42 42 m_enabled(true), 43 m_initialized(false), 43 44 m_buffersize(0), 44 45 m_eventsize(0), … … 48 49 m_buffer(0), 49 50 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 51 59 { 52 60 … … 284 292 assert(m_ringbuffer); 285 293 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); 290 297 } 291 298 … … 293 300 assert(m_ringbuffer); 294 301 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()); 299 305 return (read==m_eventsize); 300 306 } … … 304 310 assert(m_ringbuffer); 305 311 306 char *byte=(char *)event;307 312 unsigned int bytes2write=m_eventsize*nevents; 308 313 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; 310 327 311 328 } … … 313 330 int Port::readEvents(void *event, unsigned int nevents) { 314 331 assert(m_ringbuffer); 315 char *byte=(char *)event;316 332 317 333 unsigned int bytes2read=m_eventsize*nevents; 318 334 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 */ 351 bool 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 394 bool 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 } 325 430 326 431 /* Private functions */ branches/libfreebob-2.0/src/libstreaming/Port.h
r227 r228 198 198 void setExternalBufferAddress(void *buff); 199 199 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 200 260 // FIXME: this is not really OO, but for performance??? 201 261 void *getBufferAddress(); … … 228 288 freebob_ringbuffer_t *m_ringbuffer; 229 289 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; 230 297 231 298 bool allocateInternalBuffer();