Show
Ignore:
Timestamp:
11/28/07 03:25:27 (13 years ago)
Author:
ppalmers
Message:

adapt motu code to new SP base class (compiles, needs real testing)

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • branches/ppalmers-streaming/src/libstreaming/motu/MotuTransmitStreamProcessor.cpp

    r732 r733  
    2222 */ 
    2323 
    24 #include "AmdtpTransmitStreamProcessor.h" 
    25 #include "AmdtpPort.h" 
     24#include "MotuTransmitStreamProcessor.h" 
     25#include "MotuPort.h" 
    2626#include "../StreamProcessorManager.h" 
    2727 
     
    4141{ 
    4242 
     43// A macro to extract specific bits from a native endian quadlet 
     44#define get_bits(_d,_start,_len) (((_d)>>((_start)-(_len)+1)) & ((1<<(_len))-1)) 
     45 
     46// Convert a full timestamp into an SPH timestamp as required by the MOTU 
     47static inline uint32_t fullTicksToSph(int64_t timestamp) { 
     48    return TICKS_TO_CYCLE_TIMER(timestamp) & 0x1ffffff; 
     49} 
     50 
    4351/* transmit */ 
    44 AmdtpTransmitStreamProcessor::AmdtpTransmitStreamProcessor ( int port, int dimension
     52MotuTransmitStreamProcessor::MotuTransmitStreamProcessor ( int port, unsigned int event_size
    4553        : StreamProcessor ( ePT_Transmit, port ) 
    46         , m_dimension ( dimension
    47         , m_dbc ( 0 ) 
     54        , m_event_size ( event_size
     55        , m_tx_dbc ( 0 ) 
    4856{} 
    4957 
     58 
     59unsigned int 
     60MotuTransmitStreamProcessor::getMaxPacketSize() { 
     61    int framerate = m_manager->getNominalRate(); 
     62    return framerate<=48000?616:(framerate<=96000?1032:1160); 
     63} 
     64 
     65unsigned int 
     66MotuTransmitStreamProcessor::getNominalFramesPerPacket() { 
     67    int framerate = m_manager->getNominalRate(); 
     68    return framerate<=48000?8:(framerate<=96000?16:32); 
     69} 
     70 
    5071enum StreamProcessor::eChildReturnValue 
    51 AmdtpTransmitStreamProcessor::generatePacketHeader ( 
     72MotuTransmitStreamProcessor::generatePacketHeader ( 
    5273    unsigned char *data, unsigned int *length, 
    5374    unsigned char *tag, unsigned char *sy, 
    5475    int cycle, unsigned int dropped, unsigned int max_length ) 
    5576{ 
    56     struct iec61883_packet *packet = ( struct iec61883_packet * ) data; 
    57     /* Our node ID can change after a bus reset, so it is best to fetch 
    58     * our node ID for each packet. */ 
    59     packet->sid = m_handler->getLocalNodeId() & 0x3f; 
    60  
    61     packet->dbs = m_dimension; 
    62     packet->fn = 0; 
    63     packet->qpc = 0; 
    64     packet->sph = 0; 
    65     packet->reserved = 0; 
    66     packet->dbc = m_dbc; 
    67     packet->eoh1 = 2; 
    68     packet->fmt = IEC61883_FMT_AMDTP; 
    69  
    70     *tag = IEC61883_TAG_WITH_CIP; 
    71     *sy = 0; 
     77    // The number of events per packet expected by the MOTU is solely 
     78    // dependent on the current sample rate.  An 'event' is one sample from 
     79    // all channels plus possibly other midi and control data. 
     80    signed n_events = getNominalFramesPerPacket(); 
     81 
     82    // Do housekeeping expected for all packets sent to the MOTU, even 
     83    // for packets containing no audio data. 
     84    *sy = 0x00; 
     85    *tag = 1;      // All MOTU packets have a CIP-like header 
     86    *length = n_events*m_event_size + 8; 
    7287 
    7388    signed int fc; 
     
    143158    // 2) there are enough packets 
    144159    //      => determine whether we have to send them in this packet 
    145     if ( fc < ( signed int ) m_syt_interval
     160    if ( fc < ( signed int ) getNominalFramesPerPacket()
    146161    { 
    147162        // not enough frames in the buffer, 
     
    201216            { 
    202217                // we are not that late and can still try to transmit the packet 
    203                 m_dbc += fillDataPacketHeader(packet, length, m_last_timestamp); 
     218                m_tx_dbc += fillDataPacketHeader((quadlet_t *)data, length, m_last_timestamp); 
     219                if (m_tx_dbc > 0xff) 
     220                    m_tx_dbc -= 0x100; 
    204221                return eCRV_Packet; 
    205222            } 
     
    212229        { 
    213230            // it's time send the packet 
    214             m_dbc += fillDataPacketHeader(packet, length, m_last_timestamp); 
     231            m_tx_dbc += fillDataPacketHeader((quadlet_t *)data, length, m_last_timestamp); 
     232            if (m_tx_dbc > 0xff) 
     233                m_tx_dbc -= 0x100; 
    215234            return eCRV_Packet; 
    216235        } 
     
    242261 
    243262enum StreamProcessor::eChildReturnValue 
    244 AmdtpTransmitStreamProcessor::generatePacketData ( 
     263MotuTransmitStreamProcessor::generatePacketData ( 
    245264    unsigned char *data, unsigned int *length, 
    246265    unsigned char *tag, unsigned char *sy, 
    247266    int cycle, unsigned int dropped, unsigned int max_length ) 
    248267{ 
    249     struct iec61883_packet *packet = ( struct iec61883_packet * ) data; 
    250     if ( m_data_buffer->readFrames ( m_syt_interval, ( char * ) ( data + 8 ) ) ) 
    251     { 
    252         // process all ports that should be handled on a per-packet base 
    253         // this is MIDI for AMDTP (due to the need of DBC) 
    254         if ( !encodePacketPorts ( ( quadlet_t * ) ( data+8 ), m_syt_interval, packet->dbc ) ) 
    255         { 
    256             debugWarning ( "Problem encoding Packet Ports\n" ); 
    257         } 
    258         debugOutput ( DEBUG_LEVEL_VERY_VERBOSE, "XMIT DATA: TSP=%011llu (%04u)\n", 
    259                     cycle, m_last_timestamp, ( unsigned int ) TICKS_TO_CYCLES ( m_last_timestamp ) ); 
     268    quadlet_t *quadlet = (quadlet_t *)data; 
     269    quadlet += 2; // skip the header 
     270    // Size of a single data frame in quadlets 
     271    unsigned dbs = m_event_size / 4; 
     272 
     273    // The number of events per packet expected by the MOTU is solely 
     274    // dependent on the current sample rate.  An 'event' is one sample from 
     275    // all channels plus possibly other midi and control data. 
     276    signed n_events = getNominalFramesPerPacket(); 
     277 
     278    if (m_data_buffer->readFrames(n_events, (char *)(data + 8))) { 
     279        float ticks_per_frame = m_manager->getSyncSource().getActualRate(); 
     280 
     281#if TESTTONE 
     282        // FIXME: remove this hacked in 1 kHz test signal to 
     283        // analog-1 when testing is complete. 
     284        signed int int_tpf = (int)ticks_per_frame; 
     285        unsigned char *sample = data+8+16; 
     286        for (i=0; i<n_events; i++, sample+=m_event_size) { 
     287            static signed int a_cx = 0; 
     288            // Each sample is 3 bytes with MSB in lowest address (ie:  
     289            // network byte order).  After byte order swap, the 24-bit 
     290            // MSB is in the second byte of val. 
     291            signed int val = htonl((int)(0x7fffff*sin((1000.0*2.0*M_PI/24576000.0)*a_cx))); 
     292            memcpy(sample,((char *)&val)+1,3); 
     293            if ((a_cx+=int_tpf) >= 24576000) { 
     294                a_cx -= 24576000; 
     295            } 
     296        } 
     297#endif 
     298 
     299        // Set up each frames's SPH. 
     300        for (unsigned int i=0; i<n_events; i++, quadlet += dbs) { 
     301//FIXME: not sure which is best for the MOTU 
     302//            int64_t ts_frame = addTicks(ts, (unsigned int)(i * ticks_per_frame)); 
     303            int64_t ts_frame = addTicks(m_last_timestamp, (unsigned int)(i * ticks_per_frame)); 
     304            *quadlet = htonl(fullTicksToSph(ts_frame)); 
     305        } 
     306 
     307        // Process all ports that should be handled on a per-packet base 
     308        // this is MIDI for AMDTP (due to the need of DBC, which is lost 
     309        // when putting the events in the ringbuffer) 
     310        // for motu this might also be control data, however as control 
     311        // data isn't time specific I would also include it in the period 
     312        // based processing 
     313 
     314        // FIXME: m_tx_dbc probably needs to be initialised to a non-zero 
     315        // value somehow so MIDI sync is possible.  For now we ignore 
     316        // this issue. 
     317        if (!encodePacketPorts((quadlet_t *)(data+8), n_events, m_tx_dbc)) { 
     318            debugWarning("Problem encoding Packet Ports\n"); 
     319        } 
     320 
    260321        return eCRV_OK; 
    261322    } 
     
    265326 
    266327enum StreamProcessor::eChildReturnValue 
    267 AmdtpTransmitStreamProcessor::generateSilentPacketHeader ( 
     328MotuTransmitStreamProcessor::generateSilentPacketHeader ( 
    268329    unsigned char *data, unsigned int *length, 
    269330    unsigned char *tag, unsigned char *sy, 
    270331    int cycle, unsigned int dropped, unsigned int max_length ) 
    271332{ 
    272     struct iec61883_packet *packet = ( struct iec61883_packet * ) data; 
    273333    debugOutput ( DEBUG_LEVEL_VERY_VERBOSE, "XMIT NONE: CY=%04u, TSP=%011llu (%04u)\n", 
    274334                cycle, m_last_timestamp, ( unsigned int ) TICKS_TO_CYCLES ( m_last_timestamp ) ); 
    275335 
    276     /* Our node ID can change after a bus reset, so it is best to fetch 
    277     * our node ID for each packet. */ 
    278     packet->sid = m_handler->getLocalNodeId() & 0x3f; 
    279  
    280     packet->dbs = m_dimension; 
    281     packet->fn = 0; 
    282     packet->qpc = 0; 
    283     packet->sph = 0; 
    284     packet->reserved = 0; 
    285     packet->dbc = m_dbc; 
    286     packet->eoh1 = 2; 
    287     packet->fmt = IEC61883_FMT_AMDTP; 
    288  
    289     *tag = IEC61883_TAG_WITH_CIP; 
    290     *sy = 0; 
    291  
    292     m_dbc += fillNoDataPacketHeader ( packet, length ); 
     336    // Do housekeeping expected for all packets sent to the MOTU, even 
     337    // for packets containing no audio data. 
     338    *sy = 0x00; 
     339    *tag = 1;      // All MOTU packets have a CIP-like header 
     340    *length = 8; 
     341 
     342    m_tx_dbc += fillNoDataPacketHeader ( (quadlet_t *)data, length ); 
    293343    return eCRV_OK; 
    294344} 
    295345 
    296346enum StreamProcessor::eChildReturnValue 
    297 AmdtpTransmitStreamProcessor::generateSilentPacketData ( 
     347MotuTransmitStreamProcessor::generateSilentPacketData ( 
    298348    unsigned char *data, unsigned int *length, 
    299349    unsigned char *tag, unsigned char *sy, 
     
    303353} 
    304354 
    305 unsigned int AmdtpTransmitStreamProcessor::fillDataPacketHeader ( 
    306     struct iec61883_packet *packet, unsigned int* length, 
     355unsigned int MotuTransmitStreamProcessor::fillDataPacketHeader ( 
     356    quadlet_t *data, unsigned int* length, 
    307357    uint32_t ts ) 
    308358{ 
    309  
    310     packet->fdf = m_fdf; 
    311  
    312     // convert the timestamp to SYT format 
    313     uint16_t timestamp_SYT = TICKS_TO_SYT ( ts ); 
    314     packet->syt = ntohs ( timestamp_SYT ); 
    315  
    316     *length = m_syt_interval*sizeof ( quadlet_t ) *m_dimension + 8; 
    317  
    318     return m_syt_interval; 
    319 
    320  
    321 unsigned int AmdtpTransmitStreamProcessor::fillNoDataPacketHeader ( 
    322     struct iec61883_packet *packet, unsigned int* length ) 
    323 
    324  
    325     // no-data packets have syt=0xFFFF 
    326     // and have the usual amount of events as dummy data (?) 
    327     packet->fdf = IEC61883_FDF_NODATA; 
    328     packet->syt = 0xffff; 
    329  
    330     // FIXME: either make this a setting or choose 
    331     bool send_payload=true; 
    332     if ( send_payload ) 
    333     { 
    334         // this means no-data packets with payload (DICE doesn't like that) 
    335         *length = 2*sizeof ( quadlet_t ) + m_syt_interval * m_dimension * sizeof ( quadlet_t ); 
    336         return m_syt_interval; 
    337     } 
    338     else 
    339     { 
    340         // dbc is not incremented 
    341         // this means no-data packets without payload 
    342         *length = 2*sizeof ( quadlet_t ); 
    343         return 0; 
    344     } 
    345 
    346  
    347 unsigned int 
    348 AmdtpTransmitStreamProcessor::getNominalPacketsNeeded(unsigned int nframes) 
    349 
    350     unsigned int nominal_frames_per_second = m_manager->getNominalRate(); 
    351     uint64_t nominal_ticks_per_frame = TICKS_PER_SECOND / nominal_frames_per_second; 
    352     uint64_t nominal_ticks = nominal_ticks_per_frame * nframes; 
    353     uint64_t nominal_packets = nominal_ticks / TICKS_PER_CYCLE; 
    354     return nominal_packets; 
    355 
    356  
    357 unsigned int 
    358 AmdtpTransmitStreamProcessor::getPacketsPerPeriod() 
    359 
    360     return getNominalPacketsNeeded(m_manager->getPeriodSize()); 
    361 
    362  
    363 bool AmdtpTransmitStreamProcessor::prepareChild() 
     359    quadlet_t *quadlet = (quadlet_t *)data; 
     360    // Size of a single data frame in quadlets 
     361    unsigned dbs = m_event_size / 4; 
     362 
     363    // The number of events per packet expected by the MOTU is solely 
     364    // dependent on the current sample rate.  An 'event' is one sample from 
     365    // all channels plus possibly other midi and control data. 
     366    signed n_events = getNominalFramesPerPacket(); 
     367 
     368    // construct the packet CIP-like header.  Even if this is a data-less 
     369    // packet the dbs field is still set as if there were data blocks 
     370    // present.  For data-less packets the dbc is the same as the previously 
     371    // transmitted block. 
     372    *quadlet = htonl(0x00000400 | ((m_handler->getLocalNodeId()&0x3f)<<24) | m_tx_dbc | (dbs<<16)); 
     373    quadlet++; 
     374    *quadlet = htonl(0x8222ffff); 
     375    quadlet++; 
     376    return n_events; 
     377
     378 
     379unsigned int MotuTransmitStreamProcessor::fillNoDataPacketHeader ( 
     380    quadlet_t *data, unsigned int* length ) 
     381
     382    quadlet_t *quadlet = (quadlet_t *)data; 
     383    // Size of a single data frame in quadlets 
     384    unsigned dbs = m_event_size / 4; 
     385    // construct the packet CIP-like header.  Even if this is a data-less 
     386    // packet the dbs field is still set as if there were data blocks 
     387    // present.  For data-less packets the dbc is the same as the previously 
     388    // transmitted block. 
     389    *quadlet = htonl(0x00000400 | ((m_handler->getLocalNodeId()&0x3f)<<24) | m_tx_dbc | (dbs<<16)); 
     390    quadlet++; 
     391    *quadlet = htonl(0x8222ffff); 
     392    quadlet++; 
     393    *length = 8; 
     394    return 0; 
     395
     396 
     397bool MotuTransmitStreamProcessor::prepareChild() 
    364398{ 
    365399    debugOutput ( DEBUG_LEVEL_VERBOSE, "Preparing (%p)...\n", this ); 
    366     switch ( m_manager->getNominalRate() ) 
    367     { 
    368         case 32000: 
    369             m_syt_interval = 8; 
    370             m_fdf = IEC61883_FDF_SFC_32KHZ; 
    371             break; 
    372         case 44100: 
    373             m_syt_interval = 8; 
    374             m_fdf = IEC61883_FDF_SFC_44K1HZ; 
    375             break; 
    376         default: 
    377         case 48000: 
    378             m_syt_interval = 8; 
    379             m_fdf = IEC61883_FDF_SFC_48KHZ; 
    380             break; 
    381         case 88200: 
    382             m_syt_interval = 16; 
    383             m_fdf = IEC61883_FDF_SFC_88K2HZ; 
    384             break; 
    385         case 96000: 
    386             m_syt_interval = 16; 
    387             m_fdf = IEC61883_FDF_SFC_96KHZ; 
    388             break; 
    389         case 176400: 
    390             m_syt_interval = 32; 
    391             m_fdf = IEC61883_FDF_SFC_176K4HZ; 
    392             break; 
    393         case 192000: 
    394             m_syt_interval = 32; 
    395             m_fdf = IEC61883_FDF_SFC_192KHZ; 
    396             break; 
    397     } 
    398  
    399     iec61883_cip_init ( 
    400         &m_cip_status, 
    401         IEC61883_FMT_AMDTP, 
    402         m_fdf, 
    403         m_manager->getNominalRate(), 
    404         m_dimension, 
    405         m_syt_interval ); 
    406  
     400 
     401 
     402#if 0 
    407403    for ( PortVectorIterator it = m_Ports.begin(); 
    408404            it != m_Ports.end(); 
     
    431427        } 
    432428    } 
     429#endif 
    433430 
    434431    debugOutput ( DEBUG_LEVEL_VERBOSE, "Prepared for:\n" ); 
    435     debugOutput ( DEBUG_LEVEL_VERBOSE, " Samplerate: %d, FDF: %d, DBS: %d, SYT: %d\n", 
    436                 m_manager->getNominalRate(), m_fdf, m_dimension, m_syt_interval ); 
     432    debugOutput ( DEBUG_LEVEL_VERBOSE, " Samplerate: %d\n", 
     433                m_manager->getNominalRate() ); 
    437434    debugOutput ( DEBUG_LEVEL_VERBOSE, " PeriodSize: %d, NbBuffers: %d\n", 
    438435                m_manager->getPeriodSize(), m_manager->getNbBuffers() ); 
    439436    debugOutput ( DEBUG_LEVEL_VERBOSE, " Port: %d, Channel: %d\n", 
    440                 m_port,m_channel ); 
     437                m_port, m_channel ); 
    441438    return true; 
    442439} 
     
    445442* compose the event streams for the packets from the port buffers 
    446443*/ 
    447 bool AmdtpTransmitStreamProcessor::processWriteBlock ( char *data, 
    448         unsigned int nevents, unsigned int offset ) 
    449 
     444bool MotuTransmitStreamProcessor::processWriteBlock(char *data, 
     445                       unsigned int nevents, unsigned int offset) { 
     446    bool no_problem=true; 
     447    unsigned int i; 
     448 
     449    // FIXME: ensure the MIDI and control streams are all zeroed until 
     450    // such time as they are fully implemented. 
     451    for (i=0; i<nevents; i++) { 
     452        memset(data+4+i*m_event_size, 0x00, 6); 
     453    } 
     454 
     455    for ( PortVectorIterator it = m_PeriodPorts.begin(); 
     456      it != m_PeriodPorts.end(); 
     457      ++it ) { 
     458        // If this port is disabled, don't process it 
     459        if((*it)->isDisabled()) {continue;}; 
     460 
     461        //FIXME: make this into a static_cast when not DEBUG? 
     462        Port *port=dynamic_cast<Port *>(*it); 
     463 
     464        switch(port->getPortType()) { 
     465 
     466        case Port::E_Audio: 
     467            if (encodePortToMotuEvents(static_cast<MotuAudioPort *>(*it), (quadlet_t *)data, offset, nevents)) { 
     468                debugWarning("Could not encode port %s to MBLA events",(*it)->getName().c_str()); 
     469                no_problem=false; 
     470            } 
     471            break; 
     472        // midi is a packet based port, don't process 
     473        //    case MotuPortInfo::E_Midi: 
     474        //        break; 
     475 
     476        default: // ignore 
     477            break; 
     478        } 
     479    } 
     480    return no_problem; 
     481
     482 
     483bool 
     484MotuTransmitStreamProcessor::transmitSilenceBlock(char *data, 
     485                       unsigned int nevents, unsigned int offset) { 
     486    // This is the same as the non-silence version, except that is 
     487    // doesn't read from the port buffers. 
    450488    bool no_problem = true; 
    451  
    452489    for ( PortVectorIterator it = m_PeriodPorts.begin(); 
    453           it != m_PeriodPorts.end(); 
    454           ++it ) 
    455     { 
    456         if ( (*it)->isDisabled() ) { continue; }; 
    457  
     490      it != m_PeriodPorts.end(); 
     491      ++it ) { 
    458492        //FIXME: make this into a static_cast when not DEBUG? 
    459         AmdtpPortInfo *pinfo = dynamic_cast<AmdtpPortInfo *> ( *it ); 
    460         assert ( pinfo ); // this should not fail!! 
    461  
    462         switch( pinfo->getFormat() ) 
    463         { 
    464             case AmdtpPortInfo::E_MBLA: 
    465                 if( encodePortToMBLAEvents(static_cast<AmdtpAudioPort *>(*it), (quadlet_t *)data, offset, nevents) ) 
    466                 { 
    467                     debugWarning ( "Could not encode port %s to MBLA events", (*it)->getName().c_str() ); 
    468                     no_problem = false; 
     493        Port *port=dynamic_cast<Port *>(*it); 
     494 
     495        switch(port->getPortType()) { 
     496 
     497        case Port::E_Audio: 
     498            if (encodeSilencePortToMotuEvents(static_cast<MotuAudioPort *>(*it), (quadlet_t *)data, offset, nevents)) { 
     499                debugWarning("Could not encode port %s to MBLA events",(*it)->getName().c_str()); 
     500                no_problem = false; 
     501            } 
     502            break; 
     503        // midi is a packet based port, don't process 
     504        //    case MotuPortInfo::E_Midi: 
     505        //        break; 
     506 
     507        default: // ignore 
     508            break; 
     509        } 
     510    } 
     511    return no_problem; 
     512
     513 
     514/** 
     515 * @brief encode a packet for the packet-based ports 
     516 * 
     517 * @param data Packet data 
     518 * @param nevents number of events in data (including events of other ports & port types) 
     519 * @param dbc DataBlockCount value for this packet 
     520 * @return true if all successfull 
     521 */ 
     522bool MotuTransmitStreamProcessor::encodePacketPorts(quadlet_t *data, unsigned int nevents, 
     523        unsigned int dbc) { 
     524    bool ok=true; 
     525    char byte; 
     526 
     527    // Use char here since the target address won't necessarily be 
     528    // aligned; use of an unaligned quadlet_t may cause issues on 
     529    // certain architectures.  Besides, the target for MIDI data going 
     530    // directly to the MOTU isn't structured in quadlets anyway; it is a 
     531    // sequence of 3 unaligned bytes. 
     532    unsigned char *target = NULL; 
     533 
     534    for ( PortVectorIterator it = m_PacketPorts.begin(); 
     535        it != m_PacketPorts.end(); 
     536        ++it ) { 
     537 
     538        Port *port=static_cast<Port *>(*it); 
     539         assert(port); // this should not fail!! 
     540 
     541        // Currently the only packet type of events for MOTU 
     542        // is MIDI in mbla.  However in future control data 
     543        // might also be sent via "packet" events. 
     544        // assert(pinfo->getFormat()==MotuPortInfo::E_Midi); 
     545 
     546        // FIXME: MIDI output is completely untested at present. 
     547        switch (port->getPortType()) { 
     548            case Port::E_Midi: { 
     549                MotuMidiPort *mp=static_cast<MotuMidiPort *>(*it); 
     550 
     551                // Send a byte if we can. MOTU MIDI data is 
     552                // sent using a 3-byte sequence starting at 
     553                // the port's position.  For now we'll 
     554                // always send in the first event of a 
     555                // packet, but this might need refinement 
     556                // later. 
     557                if (mp->canRead()) { 
     558                    mp->readEvent(&byte); 
     559                    target = (unsigned char *)data + mp->getPosition(); 
     560                    *(target++) = 0x01; 
     561                    *(target++) = 0x00; 
     562                    *(target++) = byte; 
    469563                } 
    470564                break; 
    471             case AmdtpPortInfo::E_SPDIF: // still unimplemented 
    472                 break; 
    473             default: // ignore 
    474                 break; 
    475         } 
    476     } 
    477     return no_problem; 
    478 
    479  
    480 bool 
    481 AmdtpTransmitStreamProcessor::transmitSilenceBlock( 
    482     char *data, unsigned int nevents, unsigned int offset) 
    483 
    484     bool no_problem = true; 
    485     for(PortVectorIterator it = m_PeriodPorts.begin(); 
    486         it != m_PeriodPorts.end(); 
    487         ++it ) 
    488     { 
    489         //FIXME: make this into a static_cast when not DEBUG? 
    490         AmdtpPortInfo *pinfo=dynamic_cast<AmdtpPortInfo *>(*it); 
    491         assert(pinfo); // this should not fail!! 
    492  
    493         switch( pinfo->getFormat() ) 
    494         { 
    495             case AmdtpPortInfo::E_MBLA: 
    496                 if ( encodeSilencePortToMBLAEvents(static_cast<AmdtpAudioPort *>(*it), (quadlet_t *)data, offset, nevents) ) 
    497                 { 
    498                     debugWarning("Could not encode port %s to MBLA events", (*it)->getName().c_str()); 
    499                     no_problem = false; 
    500                 } 
    501                 break; 
    502             case AmdtpPortInfo::E_SPDIF: // still unimplemented 
    503                 break; 
    504             default: // ignore 
    505                 break; 
    506         } 
    507     } 
    508     return no_problem; 
    509 
    510  
    511 /** 
    512 * @brief decode a packet for the packet-based ports 
    513 
    514 * @param data Packet data 
    515 * @param nevents number of events in data (including events of other ports & port types) 
    516 * @param dbc DataBlockCount value for this packet 
    517 * @return true if all successfull 
    518 */ 
    519 bool AmdtpTransmitStreamProcessor::encodePacketPorts ( quadlet_t *data, unsigned int nevents, unsigned int dbc ) 
    520 
    521     bool ok=true; 
    522     quadlet_t byte; 
    523  
    524     quadlet_t *target_event=NULL; 
    525     unsigned int j; 
    526  
    527     for ( PortVectorIterator it = m_PacketPorts.begin(); 
    528             it != m_PacketPorts.end(); 
    529             ++it ) 
    530     { 
    531  
    532 #ifdef DEBUG 
    533         AmdtpPortInfo *pinfo=dynamic_cast<AmdtpPortInfo *> ( *it ); 
    534         assert ( pinfo ); // this should not fail!! 
    535  
    536         // the only packet type of events for AMDTP is MIDI in mbla 
    537         assert ( pinfo->getFormat() ==AmdtpPortInfo::E_Midi ); 
    538 #endif 
    539  
    540         AmdtpMidiPort *mp=static_cast<AmdtpMidiPort *> ( *it ); 
    541  
    542         // we encode this directly (no function call) due to the high frequency 
    543         /* idea: 
    544         spec says: current_midi_port=(dbc+j)%8; 
    545         => if we start at (dbc+stream->location-1)%8, 
    546         we'll start at the right event for the midi port. 
    547         => if we increment j with 8, we stay at the right event. 
    548         */ 
    549         // FIXME: as we know in advance how big a packet is (syt_interval) we can 
    550         //        predict how much loops will be present here 
    551         // first prefill the buffer with NO_DATA's on all time muxed channels 
    552  
    553         for ( j = ( dbc & 0x07 ) +mp->getLocation(); j < nevents; j += 8 ) 
    554         { 
    555  
    556             quadlet_t tmpval; 
    557  
    558             target_event= ( quadlet_t * ) ( data + ( ( j * m_dimension ) + mp->getPosition() ) ); 
    559  
    560             if ( mp->canRead() )   // we can send a byte 
    561             { 
    562                 mp->readEvent ( &byte ); 
    563                 byte &= 0xFF; 
    564                 tmpval=htonl ( 
    565                         IEC61883_AM824_SET_LABEL ( ( byte ) <<16, 
    566                                                     IEC61883_AM824_LABEL_MIDI_1X ) ); 
    567  
    568                 debugOutput ( DEBUG_LEVEL_ULTRA_VERBOSE, "MIDI port %s, pos=%d, loc=%d, dbc=%d, nevents=%d, dim=%d\n", 
    569                             mp->getName().c_str(), mp->getPosition(), mp->getLocation(), dbc, nevents, m_dimension ); 
    570                 debugOutput ( DEBUG_LEVEL_ULTRA_VERBOSE, "base=%p, target=%p, value=%08X\n", 
    571                             data, target_event, tmpval ); 
    572  
    573             } 
    574             else 
    575             { 
    576                 // can't send a byte, either because there is no byte, 
    577                 // or because this would exceed the maximum rate 
    578                 tmpval=htonl ( 
    579                         IEC61883_AM824_SET_LABEL ( 0,IEC61883_AM824_LABEL_MIDI_NO_DATA ) ); 
    580             } 
    581  
    582             *target_event=tmpval; 
    583         } 
    584  
    585     } 
     565            } 
     566            default: 
     567                debugOutput(DEBUG_LEVEL_VERBOSE, "Unknown packet-type port type %d\n",port->getPortType()); 
     568                return ok; 
     569              } 
     570    } 
     571 
    586572    return ok; 
    587573} 
    588574 
    589  
    590 int AmdtpTransmitStreamProcessor::encodePortToMBLAEvents ( AmdtpAudioPort *p, quadlet_t *data, 
    591         unsigned int offset, unsigned int nevents ) 
    592 
     575int MotuTransmitStreamProcessor::encodePortToMotuEvents(MotuAudioPort *p, quadlet_t *data, 
     576                       unsigned int offset, unsigned int nevents) { 
     577// Encodes nevents worth of data from the given port into the given buffer.  The 
     578// format of the buffer is precisely that which will be sent to the MOTU. 
     579// The basic idea: 
     580//   iterate over the ports 
     581//     * get port buffer address 
     582//     * loop over events 
     583//         - pick right sample in event based upon PortInfo 
     584//         - convert sample from Port format (E_Int24, E_Float, ..) to MOTU 
     585//           native format 
     586// 
     587// We include the ability to start the transfer from the given offset within 
     588// the port (expressed in frames) so the 'efficient' transfer method can be 
     589// utilised. 
     590 
    593591    unsigned int j=0; 
    594592 
    595     quadlet_t *target_event; 
    596  
    597     target_event= ( quadlet_t * ) ( data + p->getPosition() ); 
    598  
    599     switch ( p->getDataType() ) 
    600     { 
     593    // Use char here since the target address won't necessarily be 
     594    // aligned; use of an unaligned quadlet_t may cause issues on certain 
     595    // architectures.  Besides, the target (data going directly to the MOTU) 
     596    // isn't structured in quadlets anyway; it mainly consists of packed 
     597    // 24-bit integers. 
     598    unsigned char *target; 
     599    target = (unsigned char *)data + p->getPosition(); 
     600 
     601    switch(p->getDataType()) { 
    601602        default: 
    602603        case Port::E_Int24: 
    603         { 
    604             quadlet_t *buffer= ( quadlet_t * ) ( p->getBufferAddress() ); 
    605  
    606             assert ( nevents + offset <= p->getBufferSize() ); 
    607  
    608             buffer+=offset; 
    609  
    610             for ( j = 0; j < nevents; j += 1 )   // decode max nsamples 
    611604            { 
    612                 *target_event = htonl ( ( * ( buffer ) & 0x00FFFFFF ) | 0x40000000 ); 
    613                 buffer++; 
    614                 target_event += m_dimension; 
    615             } 
    616         } 
    617         break; 
     605                quadlet_t *buffer=(quadlet_t *)(p->getBufferAddress()); 
     606 
     607                assert(nevents + offset <= p->getBufferSize()); 
     608 
     609                // Offset is in frames, but each port is only a single 
     610                // channel, so the number of frames is the same as the 
     611                // number of quadlets to offset (assuming the port buffer 
     612                // uses one quadlet per sample, which is the case currently). 
     613                buffer+=offset; 
     614 
     615                for(j = 0; j < nevents; j += 1) { // Decode nsamples 
     616                    *target = (*buffer >> 16) & 0xff; 
     617                    *(target+1) = (*buffer >> 8) & 0xff; 
     618                    *(target+2) = (*buffer) & 0xff; 
     619 
     620                    buffer++; 
     621                    target+=m_event_size; 
     622                } 
     623            } 
     624            break; 
    618625        case Port::E_Float: 
    619         { 
    620             const float multiplier = ( float ) ( 0x7FFFFF00 ); 
    621             float *buffer= ( float * ) ( p->getBufferAddress() ); 
    622  
    623             assert ( nevents + offset <= p->getBufferSize() ); 
    624  
    625             buffer+=offset; 
    626  
    627             for ( j = 0; j < nevents; j += 1 )   // decode max nsamples 
    628626            { 
    629  
    630                 // don't care for overflow 
    631                 float v = *buffer * multiplier;  // v: -231 .. 231 
    632                 unsigned int tmp = ( ( int ) v ); 
    633                 *target_event = htonl ( ( tmp >> 8 ) | 0x40000000 ); 
    634  
    635                 buffer++; 
    636                 target_event += m_dimension; 
    637             } 
    638         } 
    639         break; 
     627                const float multiplier = (float)(0x7FFFFF); 
     628                float *buffer=(float *)(p->getBufferAddress()); 
     629 
     630                assert(nevents + offset <= p->getBufferSize()); 
     631 
     632                buffer+=offset; 
     633 
     634                for(j = 0; j < nevents; j += 1) { // decode max nsamples 
     635                    unsigned int v = (int)(*buffer * multiplier); 
     636                    *target = (v >> 16) & 0xff; 
     637                    *(target+1) = (v >> 8) & 0xff; 
     638                    *(target+2) = v & 0xff; 
     639 
     640                    buffer++; 
     641                    target+=m_event_size; 
     642                } 
     643            } 
     644            break; 
    640645    } 
    641646 
    642647    return 0; 
    643648} 
    644 int AmdtpTransmitStreamProcessor::encodeSilencePortToMBLAEvents ( AmdtpAudioPort *p, quadlet_t *data, 
    645         unsigned int offset, unsigned int nevents ) 
    646 
     649 
     650int MotuTransmitStreamProcessor::encodeSilencePortToMotuEvents(MotuAudioPort *p, quadlet_t *data, 
     651                       unsigned int offset, unsigned int nevents)
    647652    unsigned int j=0; 
    648  
    649     quadlet_t *target_event; 
    650  
    651     target_event= ( quadlet_t * ) ( data + p->getPosition() ); 
    652  
    653     switch ( p->getDataType() ) 
    654     { 
    655         default: 
     653    unsigned char *target = (unsigned char *)data + p->getPosition(); 
     654 
     655    switch (p->getDataType()) { 
     656    default: 
    656657        case Port::E_Int24: 
    657658        case Port::E_Float: 
    658         { 
    659             for ( j = 0; j < nevents; j += 1 )   // decode max nsamples 
    660             { 
    661                 *target_event = htonl ( 0x40000000 ); 
    662                 target_event += m_dimension; 
    663             } 
     659        for (j = 0; j < nevents; j++) { 
     660            *target = *(target+1) = *(target+2) = 0; 
     661            target += m_event_size; 
    664662        } 
    665663        break;