Changeset 283

Show
Ignore:
Timestamp:
07/02/06 17:22:25 (16 years ago)
Author:
jwoithe
Message:

More additions for MOTU playback (transmit) functionality.
Bugfix for MOTU stream stop method.

Files:

Legend:

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

    r277 r283  
    4747MotuTransmitStreamProcessor::MotuTransmitStreamProcessor(int port, int framerate, 
    4848                unsigned int event_size) 
    49         : TransmitStreamProcessor(port, framerate), m_event_size(event_size) { 
     49        : TransmitStreamProcessor(port, framerate), m_event_size(event_size), 
     50        m_tx_dbc(0), m_cycle_count(-1), m_cycle_ofs(0.0), m_sph_ofs_dll(NULL) { 
    5051 
    5152} 
     
    8283                      int cycle, unsigned int dropped, unsigned int max_length) { 
    8384 
     85// FIXME: the actual delays in the system need to be worked out so 
     86// we can get this thing synchronised.  For now this seems to work. 
     87#define CYCLE_DELAY 1 
     88 
    8489        enum raw1394_iso_disposition retval = RAW1394_ISO_OK; 
    85          
     90        quadlet_t *quadlet = (quadlet_t *)data; 
     91        signed int i; 
     92 
    8693        // signal that we are running 
    8794        // this is to allow the manager to wait untill all streams are up&running 
     
    94101        m_running=true; 
    95102         
    96         // don't process the stream when it is not enabled. 
    97         // however, maybe we do have to generate (semi) valid packets 
    98         if (m_disabled) { 
    99                 *length = 0;  
    100                 *tag = 1; // TODO: is this correct for MOTU? 
    101                 *sy = 0; 
     103        // Initialise the cycle counter if this is the first time 
     104        // iso data has been requested. 
     105        if (m_cycle_count < 0) { 
     106                m_cycle_count = cycle; 
     107                m_cycle_ofs = 0.0; 
     108        } 
     109 
     110        // Do housekeeping expected for all packets sent to the MOTU, even 
     111        // for packets containing no audio data. 
     112        *sy = 0x00; 
     113        *tag = 1;      // All MOTU packets have a CIP-like header 
     114 
     115// FIXME: for now always just return NULL packets 
     116//*length = 0; 
     117//*tag = 0; 
     118//*sy = 0; 
     119//freebob_ringbuffer_read_advance(m_event_buffer, 6*m_event_size); 
     120//incrementFrameCounter(6); 
     121//return RAW1394_ISO_OK; 
     122         
     123        debugOutput( DEBUG_LEVEL_VERY_VERBOSE, "get packet...\n"); 
     124         
     125        // Size of a single data frame in quadlets 
     126        unsigned dbs = m_event_size / 4; 
     127 
     128        // The number of events expected by the MOTU is solely dependent on 
     129        // the current sample rate.  An 'event' is one sample from all channels 
     130        // plus possibly other midi and control data. 
     131        signed n_events = m_framerate<=48000?8:(m_framerate<=96000?16:32); 
     132 
     133        // Increment the dbc (data block count).  This is only done if the 
     134        // packet will contain events - that is, the stream is not disabled 
     135        // and we are due to send some data.  Otherwise a pad packet is sent 
     136        // which contains the DBC of the previously sent packet.  This 
     137        // regime also means that the very first packet containing data will 
     138        // have a DBC of n_events, which matches what is observed from other 
     139        // systems. 
     140        if (!m_disabled && m_cycle_count<=cycle) { 
     141                m_tx_dbc += n_events; 
     142                if (m_tx_dbc > 0xff) 
     143                        m_tx_dbc -= 0x100; 
     144        } 
     145 
     146        // construct the packet CIP-like header.  Even if this is a data-less  
     147        // packet the dbs field is still set as if there were data blocks  
     148        // present.  For data-less packets the dbc is the same as the previously 
     149        // transmitted block. 
     150        *quadlet = htonl(0x00000400 | ((getNodeId()&0x3f)<<24) | m_tx_dbc | (dbs<<16)); 
     151        quadlet++; 
     152        *quadlet = htonl(0x8222ffff); 
     153        quadlet++; 
     154        *length = 8; 
     155 
     156        // If the stream is disabled or the MOTU transmission cycle count is 
     157        // ahead of the ieee1394 cycle timer, we send a data-less packet 
     158        // with only the 8 byte CIP-like header set up previously. 
     159        if (m_disabled || m_cycle_count>cycle) { 
    102160                return RAW1394_ISO_OK; 
    103161        } 
    104162 
    105 // FIXME: for now always just return NULL packets 
    106 *length = 0; 
    107 *tag = 0; 
    108 *sy = 0; 
    109 freebob_ringbuffer_read_advance(m_event_buffer, 6*m_event_size); 
    110 incrementFrameCounter(6); 
    111 return RAW1394_ISO_OK; 
    112          
    113     debugOutput( DEBUG_LEVEL_VERY_VERBOSE, "get packet...\n"); 
    114          
    115         // construct the packet cip 
    116  
    117     // TODO: calculate read_size here. 
    118     // note: an 'event' is one sample from all channels + possibly other midi and control data 
    119     int nevents=0; // TODO: determine 
    120         unsigned int read_size=nevents*m_event_size; 
    121  
    122     // we read the packet data from a ringbuffer, because of efficiency 
    123     // that allows us to construct the packets one period at once 
     163        // Size of data to read from the event buffer, in bytes. 
     164        unsigned int read_size = n_events * m_event_size; 
     165 
     166        // We read the packet data from a ringbuffer because of efficiency; 
     167        // it allows us to construct the packets one period at once. 
    124168        if ((freebob_ringbuffer_read(m_event_buffer,(char *)(data+8),read_size)) <  
    125                                 read_size)  
    126         { 
    127         /* there is no more data in the ringbuffer */ 
    128         debugWarning("Transmit buffer underrun (cycle %d, FC=%d, PC=%d)\n",  
    129                  cycle, m_framecounter, m_handler->getPacketCount()); 
     169                                read_size) { 
     170                /* there is no more data in the ringbuffer */ 
     171                debugWarning("Transmit buffer underrun (cycle %d, FC=%d, PC=%d)\n",  
     172                        cycle, m_framecounter, m_handler->getPacketCount()); 
     173 
     174                // signal underrun 
     175                m_xruns++; 
     176 
     177                retval=RAW1394_ISO_DEFER; // make raw1394_loop_iterate exit its inner loop 
     178                n_events = 0; 
     179 
     180        } else { 
     181                retval=RAW1394_ISO_OK; 
     182                *length += read_size; 
     183 
     184#if 0 
     185if (cycle<=10) { 
     186  fprintf(stderr,"cycle %d, sending %d/%d (dbs %d)\n",cycle, 
     187    m_cycle_count, (int)m_cycle_ofs, dbs); 
     188
     189#endif 
     190                // Set up each frames's SPH.  Note that the (int) typecast 
     191                // appears to do rounding. 
     192                // FIXME: once working, make more efficient by removing 1 of the 
     193                // "trim to 8000" operations. 
     194                for (i=0; i<n_events; i++, quadlet += dbs) { 
     195                        *quadlet = htonl( (((m_cycle_count+CYCLE_DELAY)%8000)<<12) +  
     196                                        (int)m_cycle_ofs); 
     197                        m_cycle_ofs += m_sph_ofs_dll->get(); 
     198                        if (m_cycle_ofs >= 3072) { 
     199                                m_cycle_ofs -= 3072; 
     200                                if (++m_cycle_count > 7999) 
     201                                        m_cycle_count -= 8000; 
     202                        } 
     203                } 
     204#if 0 
     205//if (cycle==10) { 
     206if (m_cycle_count==7999 || m_cycle_count==0) { 
     207int j; 
     208  for (j=0; j<n_events; j++) { 
     209    for (i=0; i<25; i++) 
     210      fprintf(stderr,"%02hhx ",*(data+8+j*dbs*4+i)); 
     211    fprintf(stderr,"\n"); 
     212  } 
     213
     214#endif 
     215#if 0 
     216int j, glitch=0; 
     217j=0; 
     218while (j<n_events && !glitch) { 
     219  glitch=*(data+8+j*dbs*4+22)!=0 || *(data+8+j*dbs*4+23)!=0 ||*(data+8+j*dbs*4+24)!=0; 
     220  j++; 
     221
     222if (glitch) { 
     223  for (j=0; j<n_events; j++) { 
     224    for (i=0; i<27; i++) 
     225      fprintf(stderr,"%02hhx ",*(data+8+j*dbs*4+i)); 
     226    fprintf(stderr,"\n"); 
     227  } 
     228  fprintf(stderr,"\n"); 
     229
     230#endif 
     231 
     232 
     233                // Process all ports that should be handled on a per-packet base 
     234                // this is MIDI for AMDTP (due to the need of DBC, which is lost  
     235                // when putting the events in the ringbuffer) 
     236                // for motu this might also be control data, however as control 
     237                // data isn't time specific I would also include it in the period 
     238                // based processing 
    130239         
    131         // signal underrun 
    132         m_xruns++; 
    133  
    134         retval=RAW1394_ISO_DEFER; // make raw1394_loop_iterate exit its inner loop 
    135         *length=0; 
    136         nevents=0; 
    137  
    138     } else { 
    139         retval=RAW1394_ISO_OK; 
    140         *length = read_size + 8; 
    141          
    142         // process all ports that should be handled on a per-packet base 
    143         // this is MIDI for AMDTP (due to the need of DBC, which is lost  
    144         // when putting the events in the ringbuffer) 
    145         // for motu this might also be control data, however as control 
    146         // data isn't time specific I would also include it in the period 
    147         // based processing 
    148          
    149         int dbc=0;//get this from your packet, if you need it. otherwise change encodePacketPorts 
    150         if (!encodePacketPorts((quadlet_t *)(data+8), nevents, dbc)) { 
    151             debugWarning("Problem encoding Packet Ports\n"); 
    152         } 
    153     } 
    154      
    155     *tag = 1; // TODO: is this correct for MOTU? 
    156     *sy = 0; 
    157      
    158     // update the frame counter 
    159     incrementFrameCounter(nevents); 
    160     // keep this at the end, because otherwise the raw1394_loop_iterate functions inner loop 
    161     // keeps requesting packets, that are not nescessarily ready 
    162     if(m_framecounter>(signed int)m_period) { 
    163        retval=RAW1394_ISO_DEFER; 
    164     } 
    165          
    166     return retval; 
    167  
    168 
    169  
    170 bool MotuTransmitStreamProcessor::isOnePeriodReady() 
    171 {  
    172      // TODO: this is the way you can implement sync 
    173      //       only when this returns true, one period will be 
    174      //       transferred to the audio api side. 
    175      //       you can delay this moment as long as you 
    176      //       want (provided that there is enough buffer space) 
    177       
    178      // this implementation just waits until there is one period of samples 
    179      // transmitted from the buffer 
    180      return (m_framecounter > (signed int)m_period);  
     240                // FIXME: m_tx_dbc probably needs to be initialised to a non-zero 
     241                // value somehow so MIDI sync is possible.  For now we ignore 
     242                // this issue. 
     243                if (!encodePacketPorts((quadlet_t *)(data+8), n_events, m_tx_dbc)) { 
     244                        debugWarning("Problem encoding Packet Ports\n"); 
     245                } 
     246        } 
     247     
     248        // Update the frame counter 
     249        incrementFrameCounter(n_events); 
     250 
     251        // Keep this at the end, because otherwise the raw1394_loop_iterate 
     252        // functions inner loop keeps requesting packets, that are not 
     253        // nescessarily ready 
     254 
     255// Amdtp has this commented out 
     256        if (m_framecounter > (signed int)m_period) { 
     257                retval=RAW1394_ISO_DEFER; 
     258        } 
     259         
     260        return retval; 
     261
     262 
     263bool MotuTransmitStreamProcessor::isOnePeriodReady() {  
     264        // TODO: this is the way you can implement sync 
     265        //       only when this returns true, one period will be 
     266        //       transferred to the audio api side. 
     267        //       you can delay this moment as long as you 
     268        //       want (provided that there is enough buffer space) 
     269         
     270        // this implementation just waits until there is one period of samples 
     271        // transmitted from the buffer 
     272 
     273// Amdtp has this commented out and simply return true. 
     274        return (m_framecounter > (signed int)m_period);  
     275//      return true; 
    181276} 
    182277  
    183278bool MotuTransmitStreamProcessor::prefill() { 
    184     // this is needed because otherwise there is no data to be  
    185     // sent when the streaming starts 
    186      
    187     int i=m_nb_buffers; 
    188     while(i--) { 
    189         if(!transferSilence(m_period)) { 
    190             debugFatal("Could not prefill transmit stream\n"); 
    191             return false; 
    192         } 
    193     } 
    194      
    195     return true; 
    196      
     279        // this is needed because otherwise there is no data to be  
     280        // sent when the streaming starts 
     281     
     282        int i = m_nb_buffers; 
     283        while (i--) { 
     284                if(!transferSilence(m_period)) { 
     285                        debugFatal("Could not prefill transmit stream\n"); 
     286                        return false; 
     287                } 
     288        } 
     289        return true; 
    197290} 
    198291 
    199292bool MotuTransmitStreamProcessor::reset() { 
    200293 
    201     debugOutput( DEBUG_LEVEL_VERBOSE, "Resetting...\n"); 
    202  
    203     // reset the event buffer, discard all content 
    204     freebob_ringbuffer_reset(m_event_buffer); 
    205      
    206     // reset all non-device specific stuff 
    207     // i.e. the iso stream and the associated ports 
    208     if(!TransmitStreamProcessor::reset()) { 
    209         debugFatal("Could not do base class reset\n"); 
    210         return false; 
    211    
    212  
    213     // we should prefill the event buffer 
    214     if (!prefill()) { 
    215         debugFatal("Could not prefill buffers\n"); 
    216         return false;     
    217    
    218  
    219     return true; 
     294       debugOutput( DEBUG_LEVEL_VERBOSE, "Resetting...\n"); 
     295 
     296       // reset the event buffer, discard all content 
     297       freebob_ringbuffer_reset(m_event_buffer); 
     298     
     299       // reset all non-device specific stuff 
     300       // i.e. the iso stream and the associated ports 
     301       if (!TransmitStreamProcessor::reset()) { 
     302               debugFatal("Could not do base class reset\n"); 
     303               return false; 
     304       
     305 
     306       // we should prefill the event buffer 
     307       if (!prefill()) { 
     308               debugFatal("Could not prefill buffers\n"); 
     309               return false;     
     310       
     311 
     312       return true; 
    220313} 
    221314 
    222315bool MotuTransmitStreamProcessor::prepare() { 
    223316     
    224     debugOutput( DEBUG_LEVEL_VERBOSE, "Preparing...\n"); 
    225      
    226     // prepare all non-device specific stuff 
    227     // i.e. the iso stream and the associated ports 
    228     if(!TransmitStreamProcessor::prepare()) { 
    229         debugFatal("Could not prepare base class\n"); 
    230         return false; 
    231    
     317       debugOutput( DEBUG_LEVEL_VERBOSE, "Preparing...\n"); 
     318     
     319       // prepare all non-device specific stuff 
     320       // i.e. the iso stream and the associated ports 
     321       if (!TransmitStreamProcessor::prepare()) { 
     322               debugFatal("Could not prepare base class\n"); 
     323               return false; 
     324       
    232325 
    233326        m_PeriodStat.setName("XMT PERIOD"); 
     
    235328        m_WakeupStat.setName("XMT WAKEUP"); 
    236329 
    237     debugOutput( DEBUG_LEVEL_VERBOSE, "Event size: %d\n", m_event_size); 
    238      
    239     // allocate the event buffer 
    240     unsigned int ringbuffer_size_frames=m_nb_buffers * m_period; 
    241      
    242     if( !(m_event_buffer=freebob_ringbuffer_create( 
    243         m_event_size * ringbuffer_size_frames))) { 
    244                 debugFatal("Could not allocate memory event ringbuffer"); 
    245         return false; 
    246     } 
    247  
    248     // allocate the temporary event buffer 
    249     // this is needed for the efficient transfer() routine 
    250     // its size has to be equal to one 'event' 
    251     if( !(m_tmp_event_buffer=(char *)calloc(1,m_event_size))) { 
    252         debugFatal("Could not allocate temporary event buffer"); 
    253         freebob_ringbuffer_free(m_event_buffer); 
    254         return false; 
    255     } 
    256  
    257     // set the parameters of ports we can: 
    258     // we want the audio ports to be period buffered, 
    259     // and the midi ports to be packet buffered 
    260     for ( PortVectorIterator it = m_Ports.begin(); 
    261           it != m_Ports.end(); 
    262           ++it ) 
    263     { 
    264         debugOutput(DEBUG_LEVEL_VERBOSE, "Setting up port %s\n",(*it)->getName().c_str()); 
    265         if(!(*it)->setBufferSize(m_period)) { 
    266             debugFatal("Could not set buffer size to %d\n",m_period); 
    267             return false; 
    268         } 
    269          
    270          
    271         switch ((*it)->getPortType()) { 
    272             case Port::E_Audio: 
    273                 if(!(*it)->setSignalType(Port::E_PeriodSignalled)) { 
    274                     debugFatal("Could not set signal type to PeriodSignalling"); 
    275                     return false; 
    276                 } 
     330        debugOutput( DEBUG_LEVEL_VERBOSE, "Event size: %d\n", m_event_size); 
     331     
     332        // allocate the event buffer 
     333        unsigned int ringbuffer_size_frames=m_nb_buffers * m_period; 
     334     
     335        if( !(m_event_buffer=freebob_ringbuffer_create( 
     336          m_event_size * ringbuffer_size_frames))) { 
     337                debugFatal("Could not allocate memory event ringbuffer"); 
     338                return false; 
     339        } 
     340 
     341        // Allocate the temporary event buffer.  This is needed for the 
     342        // efficient transfer() routine.  Its size has to be equal to one 
     343        // 'event'. 
     344        if( !(m_tmp_event_buffer=(char *)calloc(1,m_event_size))) { 
     345                debugFatal("Could not allocate temporary event buffer"); 
     346                freebob_ringbuffer_free(m_event_buffer); 
     347                return false; 
     348        } 
     349 
     350        // Set the parameters of ports we can: we want the audio ports to be 
     351        // period buffered, and the midi ports to be packet buffered. 
     352        for ( PortVectorIterator it = m_Ports.begin(); 
     353          it != m_Ports.end(); 
     354          ++it ) { 
     355                debugOutput(DEBUG_LEVEL_VERBOSE, "Setting up port %s\n",(*it)->getName().c_str()); 
     356                if(!(*it)->setBufferSize(m_period)) { 
     357                        debugFatal("Could not set buffer size to %d\n",m_period); 
     358                        return false; 
     359                } 
     360 
     361                switch ((*it)->getPortType()) { 
     362                case Port::E_Audio: 
     363                        if (!(*it)->setSignalType(Port::E_PeriodSignalled)) { 
     364                                debugFatal("Could not set signal type to PeriodSignalling"); 
     365                                return false; 
     366                        } 
     367                        break; 
     368 
     369                case Port::E_Midi: 
     370                        if (!(*it)->setSignalType(Port::E_PacketSignalled)) { 
     371                                debugFatal("Could not set signal type to PacketSignalling"); 
     372                                return false; 
     373                        } 
     374                        break; 
    277375                 
    278                 break; 
    279             case Port::E_Midi: 
    280                 if(!(*it)->setSignalType(Port::E_PacketSignalled)) { 
    281                     debugFatal("Could not set signal type to PacketSignalling"); 
    282                     return false; 
    283                 } 
    284                  
    285                 break; 
    286                  
    287             case Port::E_Control: 
    288                 if(!(*it)->setSignalType(Port::E_PeriodSignalled)) { 
    289                     debugFatal("Could not set signal type to PeriodSignalling"); 
    290                     return false; 
    291                 } 
    292                  
    293                 break; 
    294             default: 
    295                 debugWarning("Unsupported port type specified\n"); 
    296                 break; 
    297         } 
    298     } 
    299  
    300     // the API specific settings of the ports are already set before 
    301     // this routine is called, therefore we can init&prepare the ports 
    302     if(!initPorts()) { 
    303         debugFatal("Could not initialize ports!\n"); 
    304         return false; 
    305     } 
    306  
    307     if(!preparePorts()) { 
    308         debugFatal("Could not initialize ports!\n"); 
    309         return false; 
    310     } 
    311  
    312     // we should prefill the event buffer 
    313     if (!prefill()) { 
    314         debugFatal("Could not prefill buffers\n"); 
    315         return false;     
    316     } 
    317  
    318     return true; 
    319  
     376                case Port::E_Control: 
     377                        if (!(*it)->setSignalType(Port::E_PeriodSignalled)) { 
     378                                debugFatal("Could not set signal type to PeriodSignalling"); 
     379                                return false; 
     380                        } 
     381                        break; 
     382 
     383                default: 
     384                        debugWarning("Unsupported port type specified\n"); 
     385                        break; 
     386                } 
     387        } 
     388 
     389        // The API specific settings of the ports are already set before 
     390        // this routine is called, therefore we can init&prepare the ports 
     391        if (!initPorts()) { 
     392                debugFatal("Could not initialize ports!\n"); 
     393                return false; 
     394        } 
     395 
     396        if(!preparePorts()) { 
     397                debugFatal("Could not initialize ports!\n"); 
     398                return false; 
     399        } 
     400 
     401        // We should prefill the event buffer 
     402        if (!prefill()) { 
     403                debugFatal("Could not prefill buffers\n"); 
     404                return false;     
     405        } 
     406 
     407        return true; 
    320408} 
    321409 
    322410bool MotuTransmitStreamProcessor::transferSilence(unsigned int size) { 
    323411     
    324     // this function should tranfer 'size' frames of 'silence' to the event buffer 
    325     unsigned int write_size=size*m_event_size; 
    326     char *dummybuffer=(char *)calloc(size,m_event_size); 
    327  
    328     transmitSilenceBlock(dummybuffer, size, 0); 
    329  
    330     if (freebob_ringbuffer_write(m_event_buffer,(char *)(dummybuffer),write_size) < write_size) { 
    331         debugWarning("Could not write to event buffer\n"); 
    332     } 
    333      
    334     free(dummybuffer); 
    335      
    336     return true; 
    337 
    338  
     412        // This function should tranfer 'size' frames of 'silence' to the event buffer 
     413        unsigned int write_size=size*m_event_size; 
     414        char *dummybuffer=(char *)calloc(size,m_event_size); 
     415 
     416        transmitSilenceBlock(dummybuffer, size, 0); 
     417 
     418        if (freebob_ringbuffer_write(m_event_buffer,(char *)(dummybuffer),write_size) < write_size) { 
     419                debugWarning("Could not write to event buffer\n"); 
     420        } 
     421 
     422        free(dummybuffer); 
     423 
     424        return true; 
     425
     426 
     427/** 
     428 * \brief write events queued for transmission from the port ringbuffers 
     429 * to the event buffer. 
     430 */ 
    339431bool MotuTransmitStreamProcessor::transfer() { 
    340     m_PeriodStat.mark(freebob_ringbuffer_read_space(m_event_buffer)/m_event_size); 
    341  
    342     debugOutput( DEBUG_LEVEL_VERY_VERBOSE, "Transferring period...\n"); 
    343     // TODO: improve 
     432       m_PeriodStat.mark(freebob_ringbuffer_read_space(m_event_buffer)/m_event_size); 
     433 
     434       debugOutput( DEBUG_LEVEL_VERY_VERBOSE, "Transferring period...\n"); 
     435       // TODO: improve 
    344436/* a naive implementation would look like this: 
    345437 
    346     unsigned int write_size=m_period*m_event_size; 
    347     char *dummybuffer=(char *)calloc(m_period,m_event_size); 
    348      
    349     transmitBlock(dummybuffer, m_period, 0, 0); 
    350  
    351     if (freebob_ringbuffer_write(m_event_buffer,(char *)(dummybuffer),write_size) < write_size) { 
    352         debugWarning("Could not write to event buffer\n"); 
    353     } 
    354  
    355  
    356     free(dummybuffer); 
     438        unsigned int write_size=m_period*m_event_size; 
     439        char *dummybuffer=(char *)calloc(m_period,m_event_size); 
     440 
     441        transmitBlock(dummybuffer, m_period, 0, 0); 
     442 
     443        if (freebob_ringbuffer_write(m_event_buffer,(char *)(dummybuffer),write_size) < write_size) { 
     444                debugWarning("Could not write to event buffer\n"); 
     445        } 
     446 
     447        free(dummybuffer); 
    357448*/ 
    358449/* but we're not that naive anymore... */ 
    359     int xrun; 
    360     unsigned int offset=0; 
     450       int xrun; 
     451       unsigned int offset=0; 
    361452 
    362453// FIXME: just return until we've got the transmit side of things functional 
    363 return true; 
    364  
    365     freebob_ringbuffer_data_t vec[2]; 
    366     // we received one period of frame
    367     // this is period_size*m_event_size of events 
    368     unsigned int bytes2write=m_period*m_event_size; 
    369  
    370     /* write events2write bytes to the ringbuffer  
    371     *  first see if it can be done in one read
    372     *  if so, ok.  
    373     *  otherwise write up to a multiple of events directly to the buffer 
    374     *  then do the buffer wrap around using ringbuffer_write 
    375     *  then write the remaining data directly to the buffer in a third pass  
    376     *  Make sure that we cannot end up on a non-cluster aligned position! 
    377     */ 
    378     while(bytes2write>0) { 
    379         int byteswritten=0; 
     454//return true; 
     455 
     456       freebob_ringbuffer_data_t vec[2]; 
     457       // There is one period of frames to transfer.  This i
     458        // period_size*m_event_size of events. 
     459       unsigned int bytes2write=m_period*m_event_size; 
     460 
     461        /* Write bytes2write bytes to the event ringbuffer.  First see if it can 
     462        * be done in one write; if so, ok
     463         * Otherwise write up to a multiple of events directly to the buffer 
     464         * then do the buffer wrap around using ringbuffer_write.  Then 
     465         * write the remaining data directly to the buffer in a third pass.  
     466         * Make sure that we cannot end up on a non-cluster aligned 
     467        * position! 
     468        */ 
     469       while(bytes2write>0) { 
     470               int byteswritten=0; 
    380471         
    381         unsigned int frameswritten=(m_period*m_event_size-bytes2write)/m_event_size; 
    382         offset=frameswritten; 
    383          
    384         freebob_ringbuffer_get_write_vector(m_event_buffer, vec); 
     472                unsigned int frameswritten=(m_period*m_event_size-bytes2write)/m_event_size; 
     473                offset=frameswritten; 
     474 
     475                freebob_ringbuffer_get_write_vector(m_event_buffer, vec); 
     476 
     477                if (vec[0].len==0) { // this indicates a full event buffer 
     478                        debugError("XMT: Event buffer overrun in processor %p\n",this); 
     479                        break; 
     480                } 
     481 
     482                /* If we don't take care we will get stuck in an infinite 
     483                 * loop because we align to a event boundary later.  The 
     484                 * remaining nb of bytes in one write operation can be 
     485                 * smaller than one event; this can happen because the 
     486                 * ringbuffer size is always a power of 2. 
     487                 */ 
     488                if(vec[0].len<m_event_size) { 
    385489             
    386         if(vec[0].len==0) { // this indicates a full event buffer 
    387             debugError("XMT: Event buffer overrun in processor %p\n",this); 
    388             break; 
    389         } 
     490                        // encode to the temporary buffer 
     491                        xrun = transmitBlock(m_tmp_event_buffer, 1, offset); 
    390492             
    391         /* if we don't take care we will get stuck in an infinite loop 
    392         * because we align to a event boundary later 
    393         * the remaining nb of bytes in one write operation can be  
    394         * smaller than one event 
    395         * this can happen because the ringbuffer size is always a power of 2 
    396         */ 
    397         if(vec[0].len<m_event_size) { 
     493                        if (xrun<0) { 
     494                                // xrun detected 
     495                                debugError("XMT: Frame buffer underrun in processor %p\n",this); 
     496                                break; 
     497                        } 
     498 
     499                        // Use the ringbuffer function to write one event. 
     500                        // The write function handles the wrap around. 
     501                        freebob_ringbuffer_write(m_event_buffer, 
     502                                m_tmp_event_buffer, m_event_size); 
     503                 
     504                        // we advanced one m_event_size 
     505                        bytes2write-=m_event_size; 
     506                 
     507                } else { 
    398508             
    399             // encode to the temporary buffer 
    400             xrun = transmitBlock(m_tmp_event_buffer, 1, offset); 
     509                        if (bytes2write>vec[0].len) { 
     510                                // align to an event boundary 
     511                                byteswritten=vec[0].len-(vec[0].len%m_event_size); 
     512                        } else { 
     513                                byteswritten=bytes2write; 
     514                        } 
     515 
     516                        xrun = transmitBlock(vec[0].buf, 
     517                                byteswritten/m_event_size, offset); 
    401518             
    402             if(xrun<0) { 
    403                 // xrun detected 
    404                 debugError("XMT: Frame buffer underrun in processor %p\n",this); 
    405                 break; 
    406             } 
    407                  
    408             // use the ringbuffer function to write one event  
    409             // the write function handles the wrap around. 
    410             freebob_ringbuffer_write(m_event_buffer, 
    411                          m_tmp_event_buffer, 
    412                          m_event_size); 
    413                  
    414             // we advanced one m_event_size 
    415             bytes2write-=m_event_size; 
    416                  
    417         } else { //  
    418              
    419             if(bytes2write>vec[0].len) { 
    420                 // align to an event boundary 
    421                 byteswritten=vec[0].len-(vec[0].len%m_event_size); 
    422             } else { 
    423                 byteswritten=bytes2write; 
    424             } 
    425                  
    426             xrun = transmitBlock(vec[0].buf, 
    427                          byteswritten/m_event_size, 
    428                          offset); 
    429              
    430             if(xrun<0) { 
    431                     // xrun detected 
    432                 debugError("XMT: Frame buffer underrun in processor %p\n",this); 
    433                 break; 
    434             } 
    435  
    436             freebob_ringbuffer_write_advance(m_event_buffer, byteswritten); 
    437             bytes2write -= byteswritten; 
    438         } 
    439  
    440         // the bytes2write should always be event aligned 
    441         assert(bytes2write%m_event_size==0); 
    442  
    443     } 
    444  
    445     return true; 
     519                        if (xrun<0) { 
     520                                // xrun detected 
     521                                debugError("XMT: Frame buffer underrun in processor %p\n",this); 
     522                                break; 
     523                        } 
     524 
     525                        freebob_ringbuffer_write_advance(m_event_buffer, byteswritten); 
     526                        bytes2write -= byteswritten; 
     527                } 
     528 
     529                // the bytes2write should always be event aligned 
     530                assert(bytes2write%m_event_size==0); 
     531        } 
     532 
     533        return true; 
    446534} 
    447535/*  
     
    450538 
    451539int MotuTransmitStreamProcessor::transmitBlock(char *data,  
    452                        unsigned int nevents, unsigned int offset) 
    453 
    454     int problem=0; 
    455  
    456     for ( PortVectorIterator it = m_PeriodPorts.begin(); 
    457           it != m_PeriodPorts.end(); 
    458           ++it ) 
    459     { 
    460         // if this port is disabled, don't process it 
    461         if((*it)->isDisabled()) {continue;}; 
     540                       unsigned int nevents, unsigned int offset) { 
     541        signed int problem=0; 
     542        unsigned int i; 
     543 
     544        // FIXME: ensure the MIDI and control streams are all zeroed until 
     545        // such time as they are fully implemented. 
     546        for (i=0; i<nevents; i++) { 
     547                memset(data+4+i*m_event_size, 0x00, 6); 
     548        } 
     549 
     550        for ( PortVectorIterator it = m_PeriodPorts.begin(); 
     551          it != m_PeriodPorts.end(); 
     552          ++it ) { 
     553                // If this port is disabled, don't process it 
     554                if((*it)->isDisabled()) {continue;}; 
    462555         
    463         //FIXME: make this into a static_cast when not DEBUG? 
    464  
    465         MotuPortInfo *pinfo=dynamic_cast<MotuPortInfo *>(*it); 
    466         assert(pinfo); // this should not fail!! 
    467  
    468 /*      This is the AMDTP way, the motu way is different 
    469         Leaving this in as reference 
    470          
    471         switch(pinfo->getFormat()) { 
    472          
    473          
    474         case MotuPortInfo::E_MBLA: 
    475             if(encodePortToMBLAEvents(static_cast<MotuAudioPort *>(*it), (quadlet_t *)data, offset, nevents)) { 
    476                 debugWarning("Could not encode port %s to MBLA events",(*it)->getName().c_str()); 
    477                 problem=1; 
    478             } 
    479             break; 
    480         case MotuPortInfo::E_SPDIF: // still unimplemented 
    481             break; 
    482         default: // ignore 
    483             break; 
    484         } 
    485 */ 
    486     } 
    487     return problem; 
    488  
     556                //FIXME: make this into a static_cast when not DEBUG? 
     557                Port *port=dynamic_cast<Port *>(*it); 
     558                 
     559                switch(port->getPortType()) { 
     560                 
     561                case Port::E_Audio: 
     562                        if (encodePortToMBLAEvents(static_cast<MotuAudioPort *>(*it), (quadlet_t *)data, offset, nevents)) { 
     563                                debugWarning("Could not encode port %s to MBLA events",(*it)->getName().c_str()); 
     564                                problem=1; 
     565                        } 
     566                        break; 
     567                // midi is a packet based port, don't process 
     568                //      case MotuPortInfo::E_Midi: 
     569                //              break; 
     570 
     571                default: // ignore 
     572                        break; 
     573                } 
     574        } 
     575        return problem; 
    489576} 
    490577 
    491578int MotuTransmitStreamProcessor::transmitSilenceBlock(char *data,  
    492                        unsigned int nevents, unsigned int offset) 
    493 
    494     int problem=0; 
    495  
    496     for ( PortVectorIterator it = m_PeriodPorts.begin(); 
    497           it != m_PeriodPorts.end(); 
    498           ++it ) 
    499     { 
    500  
    501         //FIXME: make this into a static_cast when not DEBUG? 
    502  
    503         MotuPortInfo *pinfo=dynamic_cast<MotuPortInfo *>(*it); 
    504         assert(pinfo); // this should not fail!! 
    505  
    506 /* this is the same as the non-silence version, except that is doesn't read from the port buffers 
    507         switch(pinfo->getFormat()) { 
    508          
    509  
    510         case MotuPortInfo::E_MBLA: 
    511             if(encodeSilencePortToMBLAEvents(static_cast<MotuAudioPort *>(*it), (quadlet_t *)data, offset, nevents)) { 
    512                 debugWarning("Could not encode port %s to MBLA events",(*it)->getName().c_str()); 
    513                 problem=1; 
    514             } 
    515             break; 
    516         case MotuPortInfo::E_SPDIF: // still unimplemented 
    517             break; 
    518         default: // ignore 
    519             break; 
    520         } 
    521         */ 
    522     } 
    523     return problem; 
    524  
     579                       unsigned int nevents, unsigned int offset) { 
     580        // This is the same as the non-silence version, except that is 
     581        // doesn't read from the port buffers. 
     582 
     583        int problem=0; 
     584 
     585        for ( PortVectorIterator it = m_PeriodPorts.begin(); 
     586          it != m_PeriodPorts.end(); 
     587          ++it ) { 
     588                //FIXME: make this into a static_cast when not DEBUG? 
     589                Port *port=dynamic_cast<Port *>(*it); 
     590                 
     591                switch(port->getPortType()) { 
     592                 
     593                case Port::E_Audio: 
     594                        if (encodeSilencePortToMBLAEvents(static_cast<MotuAudioPort *>(*it), (quadlet_t *)data, offset, nevents)) { 
     595                                debugWarning("Could not encode port %s to MBLA events",(*it)->getName().c_str()); 
     596                                problem=1; 
     597                        } 
     598                        break; 
     599                // midi is a packet based port, don't process 
     600                //      case MotuPortInfo::E_Midi: 
     601                //              break; 
     602 
     603                default: // ignore 
     604                        break; 
     605                } 
     606        } 
     607        return problem; 
    525608} 
    526609 
     
    575658not that in order to use the 'efficient' transfer method, you have to make sure that 
    576659you can start from an offset (expressed in frames). 
     660*/ 
     661#include <math.h> 
    577662 
    578663int MotuTransmitStreamProcessor::encodePortToMBLAEvents(MotuAudioPort *p, quadlet_t *data,  
    579                        unsigned int offset, unsigned int nevents) 
    580 
    581     unsigned int j=0; 
    582  
     664                       unsigned int offset, unsigned int nevents) { 
     665        unsigned int j=0; 
     666        unsigned char *target = (unsigned char *)data + p->getPosition(); 
     667 
     668// offset is offset into the port buffers 
     669//quadlet_t *buffer=(quadlet_t *)(p->getBufferAddress()); 
     670//assert(nevents + offset <= p->getBufferSize()); 
     671//buffer+=offset; 
     672 
     673 
     674// FIXME: use the form of the silence version here for testing 
     675        switch (p->getDataType()) { 
     676        default: 
     677        case Port::E_Int24: 
     678        case Port::E_Float: 
     679// send silence to all but selected analog channels 
     680                for (j = 0; j < nevents; j++) { 
     681signed int val; 
     682if (p->getPosition() == 16) { 
     683  val = 0x7fffff*sin(1000.0*2.0*M_PI*(m_cycle_count+((m_cycle_ofs+j*512)/3072.0))/8000.0); 
     684//val = 0; 
     685//  fprintf(stderr,".%d.",val); 
     686} else 
     687  val = 0; 
     688                        *target = (val >> 16) & 0xff; 
     689                        *(target+1) = (val >> 8) & 0xff; 
     690                        *(target+2) = val & 0xff; 
     691                        target += m_event_size; 
     692                } 
     693                break; 
     694        } 
     695 
     696 
     697/* 
    583698    quadlet_t *target_event; 
    584699 
     
    624739            break; 
    625740    } 
    626  
    627     return 0; 
    628 } 
    629741*/ 
    630 /* 
     742        return 0; 
     743
     744 
    631745int MotuTransmitStreamProcessor::encodeSilencePortToMBLAEvents(MotuAudioPort *p, quadlet_t *data,  
    632                        unsigned int offset, unsigned int nevents) 
    633 
    634     unsigned int j=0; 
    635  
    636     quadlet_t *target_event; 
    637  
    638     target_event=(quadlet_t *)(data + p->getPosition()); 
    639  
    640     switch(p->getDataType()) { 
    641         default: 
     746                       unsigned int offset, unsigned int nevents) { 
     747        unsigned int j=0; 
     748        unsigned char *target = (unsigned char *)data + p->getPosition(); 
     749 
     750        switch (p->getDataType()) { 
     751        default: 
    642752        case Port::E_Int24: 
    643753        case Port::E_Float: 
    644             { 
    645                 for(j = 0; j < nevents; j += 1) { // decode max nsamples 
    646                     *target_event = htonl(0x40000000); 
    647                     target_event += m_dimension; 
    648                 } 
    649             } 
    650             break; 
    651     } 
    652  
    653     return 0; 
    654 
    655 */ 
     754                for (j = 0; j < nevents; j++) { 
     755                        *target = *(target+1) = *(target+2) = 0; 
     756                        target += m_event_size; 
     757                } 
     758                break; 
     759        } 
     760 
     761        return 0; 
     762
    656763 
    657764/* --------------------- RECEIVE ----------------------- */ 
     
    704811// FIXME: just for debugging, print out the sph ofs DLL value 
    705812// once a second 
    706 if (cycle==0) { 
    707   fprintf(stderr, "sph_ofs_dll=%g\n",m_sph_ofs_dll->get()); 
    708 
     813//if (cycle==0) { 
     814//  fprintf(stderr, "sph_ofs_dll=%g\n",m_sph_ofs_dll->get()); 
     815//
    709816 
    710817    // If the packet length is 8 bytes (ie: just a CIP-like header) there is 
     
    725832                return RAW1394_ISO_OK; 
    726833        } 
    727          
     834 
    728835        // Signal that we're running 
    729836        if (n_events) m_running=true; 
     
    10191126        unsigned int ev; 
    10201127        signed int sph_ofs = ntohl(*(quadlet_t *)data) & 0xfff; 
     1128 
    10211129        if (m_last_cycle_ofs < 0) { 
    1022                 m_last_cycle_ofs = sph_ofs-m_sph_ofs_dll->get(); 
     1130                m_last_cycle_ofs = sph_ofs-(int)m_sph_ofs_dll->get(); 
    10231131        } 
    10241132        for (ev=0; ev<nevents; ev++) { 
     
    11151223                                assert(nevents + offset <= p->getBufferSize()); 
    11161224 
     1225                                // Offset is in frames, but each port is only a single 
     1226                                // channel, so the number of frames is the same as the 
     1227                                // number of quadlets to offset (assuming the port buffer 
     1228                                // uses one quadlet per sample, which is the case currently). 
    11171229                                buffer+=offset; 
    11181230 
  • branches/libfreebob-2.0/src/libstreaming/MotuStreamProcessor.h

    r277 r283  
    7272        virtual void setVerboseLevel(int l); 
    7373 
     74        void set_sph_ofs_dll(FreebobUtil::DelayLockedLoop *dll) {m_sph_ofs_dll=dll;}; 
     75 
    7476protected: 
    7577 
     
    8284         */ 
    8385        unsigned int m_event_size; 
    84          
     86 
     87        // Keep track of transmission data block count 
     88        unsigned int m_tx_dbc; 
     89 
     90        // Transmission cycle count and cycle offset 
     91        signed int m_cycle_count; 
     92        float m_cycle_ofs; 
     93 
     94        // Hook to the DLL in the receive stream which allows calculation 
     95        // of cycle offsets to put into frame SPHs.  This object is  
     96        // owned by the receive stream, so the transmit stream should 
     97        // not dispose of it. 
     98        FreebobUtil::DelayLockedLoop *m_sph_ofs_dll; 
     99 
    85100    bool prefill(); 
    86101     
     
    95110                          unsigned int offset); 
    96111                           
     112        int MotuTransmitStreamProcessor::encodePortToMBLAEvents( 
     113                MotuAudioPort *p, quadlet_t *data, unsigned int offset,  
     114                unsigned int nevents); 
     115        int MotuTransmitStreamProcessor::encodeSilencePortToMBLAEvents( 
     116                MotuAudioPort *p, quadlet_t *data, unsigned int offset,  
     117                unsigned int nevents); 
    97118 
    98119 
     
    133154        virtual void setVerboseLevel(int l); 
    134155         
     156        FreebobUtil::DelayLockedLoop *get_sph_ofs_dll(void) {return m_sph_ofs_dll;}; 
    135157        signed int setEventSize(unsigned int size); 
    136158        unsigned int getEventSize(void); 
  • branches/libfreebob-2.0/src/motu/motu_avdevice.cpp

    r277 r283  
    158158    int rate = 0; 
    159159 
    160     switch (q & ~MOTUFW_BASE_RATE_MASK) { 
     160    switch (q & MOTUFW_BASE_RATE_MASK) { 
    161161        case MOTUFW_BASE_RATE_44100: 
    162162            rate = 44100; 
     
    166166            break; 
    167167    } 
    168     switch (q & ~MOTUFW_RATE_MULTIPLIER_MASK) { 
     168    switch (q & MOTUFW_RATE_MULTIPLIER_MASK) { 
    169169        case MOTUFW_RATE_MULTIPLIER_2X: 
    170170            rate *= 2; 
     
    334334                return false; 
    335335        } 
     336 
     337        // Connect the transmit stream to the SPH offset DLL in the 
     338        // receive stream. 
     339        m_transmitProcessor->set_sph_ofs_dll(m_receiveProcessor->get_sph_ofs_dll()); 
    336340 
    337341        // now we add ports to the processor 
     
    472476                // settings when the iso control register is written. 
    473477                isoctrl &= 0xffbfffff; 
     478                isoctrl |= 0x00800000; 
    474479                WriteRegister(MOTUFW_REG_ISOCTRL, isoctrl); 
    475480                break; 
     
    479484                // settings when the iso control register is written. 
    480485                isoctrl &= 0xbfffffff; 
     486                isoctrl |= 0x80000000; 
    481487                WriteRegister(MOTUFW_REG_ISOCTRL, isoctrl); 
    482488                break;