Changeset 296

Show
Ignore:
Timestamp:
08/20/06 18:44:33 (16 years ago)
Author:
jwoithe
Message:

Code "ticks per frame" DLL inline to the MOTU receive stream processor for
efficiency. Fine-tune DLL integration coefficient to remove regular audio
glitches. Set teststreaming2.c to request realtime priority to facilitate
further testing. Cleanly deal with cycle wraparound in transmit stream
processor. Improve efficiency of 1 kHz tone generator in transmit stream
processor.

Files:

Legend:

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

    r294 r296  
    4545#define get_bits(_d,_start,_len) (((_d)>>((_start)-(_len)+1)) & ((1<<(_len))-1)) 
    4646 
    47  
    4847/* transmit */ 
    4948MotuTransmitStreamProcessor::MotuTransmitStreamProcessor(int port, int framerate, 
    5049                unsigned int event_size) 
    5150        : TransmitStreamProcessor(port, framerate), m_event_size(event_size), 
    52         m_tx_dbc(0), m_cycle_count(-1), m_cycle_ofs(0.0), m_sph_ofs_dll(NULL), 
     51        m_tx_dbc(0), m_cycle_count(-1), m_cycle_ofs(0.0), m_ticks_per_frame(NULL), 
    5352        m_closedown_count(-1) { 
    5453 
     
    10099        signed int i; 
    101100 
     101signed int corrected_cycle = cycle; 
     102 
    102103        // The MOTU transmit stream is 'always' ready 
    103104        m_running = true; 
     
    106107        // iso data has been requested. 
    107108        if (!m_disabled && m_cycle_count<0) { 
    108 debugOutput(DEBUG_LEVEL_VERBOSE, "tx enabled at cycle %d, dll=%g\n",cycle, 
    109   m_sph_ofs_dll->get()); 
    110109                m_cycle_count = cycle; 
    111110                m_cycle_ofs = 0.0; 
     
    129128// FIXME: some tests - attempt to recover sync after loss due to missed cycles 
    130129static signed int next_cycle = -1; 
    131 //static suseconds_t last_us = -1; 
     130//static suseconds_t us_stack[10] = {0,0,0,0,0,0,0,0,0,0}; 
     131//static int us_i = 0; 
    132132//struct timeval tv; 
    133133//gettimeofday(&tv, NULL); 
     134//us_stack[us_i] = tv.tv_usec + (tv.tv_sec%10)*1000000; 
     135//if (++us_i == 10) 
     136//  us_i = 0; 
     137 
    134138if (!m_disabled && next_cycle>=0 && cycle!=next_cycle) { 
    135139  debugOutput(DEBUG_LEVEL_VERBOSE, "tx cycle miss: %d requested, %d expected\n",cycle,next_cycle); 
    136140  debugOutput(DEBUG_LEVEL_VERBOSE, "tx stream: cycle=%d, ofs=%g\n",m_cycle_count, m_cycle_ofs); 
    137 //debugOutput(DEBUG_LEVEL_VERBOSE, "now=%d, last call=%d, diff=%d\n", 
    138 //  tv.tv_usec, last_us, tv.tv_usec>last_us?(tv.tv_usec-last_us):(1000000-last_us+tv.tv_usec)); 
     141 
     142// Print the times of the last 10 calls to this function 
     143//int i = us_i, l = -1; 
     144//  fprintf(stderr,"usec stack:\n"); 
     145//  do { 
     146//    fprintf(stderr, "  %d",us_stack[i]); 
     147//    if (l != -1)  
     148//      fprintf(stderr," (%d)",us_stack[i]-us_stack[l]); 
     149//    l = i; 
     150//    if (++i == 10)  
     151//      i = 0; 
     152//  } while (i != us_i); 
     153//  fprintf(stderr,"\n"); 
    139154 
    140155#if 0 
     
    147162#else 
    148163float ftmp; 
    149  
    150 // Calculate values of m_cycle_{count,ofs} which would be present 
    151 // for this cycle if the missed cycles hadn't been missed. 
    152 // These mathematical gymnastics *should* be functionally equivalent to 
    153 // the loop below.  Once it has proven correct it can replace the loop 
    154 // since it will be much faster most of the time. 
    155 signed int n_missed = (cycle>next_cycle)?cycle-next_cycle:8000-next_cycle+cycle; 
    156 signed int ma = ((n_events/2)+n_missed*3072.0/m_sph_ofs_dll->get())/n_events; 
    157 ma*=n_events; 
    158 ftmp = m_cycle_ofs+ma*m_sph_ofs_dll->get(); 
    159 //m_cycle_count = (int)(m_cycle_count+ftmp/3072) % 8000; 
    160 //m_cycle_ofs = fmod(ftmp, 3072); 
    161 //m_tx_dbc = (m_tx_dbc + ma) & 0xff; 
    162 debugOutput(DEBUG_LEVEL_VERBOSE, " calc %d: count=%d, ofs=%g\n", 
    163   ma, 
    164   (int)(m_cycle_count+ftmp/3072) % 8000, 
    165   fmod(ftmp,3072) 
    166 ); 
    167  
    168 signed int ccount, fcount; 
     164signed int ccount; 
    169165 
    170166  ccount = next_cycle; 
    171167  while (ccount!=cycle) { 
    172     if (ccount < m_cycle_count) { 
     168 
     169corrected_cycle = ccount; 
     170if (m_cycle_count-ccount > 7900) 
     171  corrected_cycle += 8000; 
     172 
     173    if (corrected_cycle < m_cycle_count) { 
    173174      if (++ccount == 8000) 
    174175        ccount = 0; 
     
    176177    } 
    177178    m_tx_dbc += n_events; 
    178  
    179 //    for (fcount=0; fcount<n_events; fcount++) { 
    180 //      m_cycle_ofs += m_sph_ofs_dll->get(); 
    181 //      if (m_cycle_ofs >= 3072) { 
    182 //        m_cycle_ofs -= 3072; 
    183 //        if (++m_cycle_count > 7999) 
    184 //          m_cycle_count -= 8000; 
    185 //      } 
    186 //    } 
    187 // Replace the above for loop with direct calculations to 
    188 // improve efficiency. 
    189     ftmp = m_cycle_ofs+n_events*m_sph_ofs_dll->get(); 
    190     m_cycle_count += ftmp/3072; 
     179    incrementFrameCounter(n_events); 
     180 
     181    ftmp = m_cycle_ofs+n_events*(*m_ticks_per_frame); 
     182    m_cycle_count += (unsigned int)ftmp/3072; 
     183    m_cycle_count %= 8000; 
    191184    m_cycle_ofs = fmod(ftmp, 3072); 
    192185 
     
    195188  } 
    196189  m_tx_dbc &= 0xff; 
    197   m_cycle_count %= 8000; 
    198190 
    199191#endif 
    200   debugOutput(DEBUG_LEVEL_VERBOSE, "  resuming with cyclecount=%d, cycleofs=%g (dll=%g)\n", 
    201     m_cycle_count, m_cycle_ofs, m_sph_ofs_dll->get()); 
     192  debugOutput(DEBUG_LEVEL_VERBOSE, "  resuming with cyclecount=%d, cycleofs=%g (ticksperfame=%g)\n", 
     193    m_cycle_count, m_cycle_ofs, *m_ticks_per_frame); 
    202194} 
    203195if (!m_disabled) 
     
    205197else 
    206198  next_cycle = -1; 
    207 //last_us = tv.tv_usec; 
     199 
     200        // Deal cleanly with potential wrap-around cycle counter conditions 
     201        corrected_cycle = cycle; 
     202        if (m_cycle_count-cycle > 7900) 
     203                corrected_cycle += 8000; 
    208204 
    209205        // Increment the dbc (data block count).  This is only done if the 
     
    213209        // first packet containing data will have a DBC of n_events, which 
    214210        // matches what is observed from other systems. 
    215         if (!m_disabled && cycle>=m_cycle_count) { 
     211        if (!m_disabled && corrected_cycle>=m_cycle_count) { 
    216212                m_tx_dbc += n_events; 
    217213                if (m_tx_dbc > 0xff) 
     
    232228        // ahead of the ieee1394 cycle timer, we send a data-less packet 
    233229        // with only the 8 byte CIP-like header set up previously. 
    234         if (m_disabled || cycle<m_cycle_count) { 
     230        if (m_disabled || corrected_cycle<m_cycle_count) { 
    235231                return RAW1394_ISO_OK; 
    236232        } 
     
    294290// is complete.  Note that the tone is *not* added during closedown. 
    295291if (m_closedown_count<0) { 
     292//static signed int a_cx=0, a_ofs=0; 
     293static signed int a_cx = 0; 
    296294signed int val; 
    297 val = (int)(0x7fffff*sin(1000.0*2.0*M_PI*(m_cycle_count+((m_cycle_ofs)/3072.0))/8000.0)); 
     295// val = (int)(0x7fffff*sin(1000.0*2.0*M_PI*(m_cycle_count+((m_cycle_ofs)/3072.0))/8000.0)); 
     296val = (int)(0x7fffff*sin(1000.0*2.0*M_PI*(a_cx/24576000.0))); 
     297if ((a_cx+=512) >= 24576000) { 
     298  a_cx -= 24576000; 
     299
     300//val = (int)(0x7fffff*sin(1000.0*2.0*M_PI*(a_cx+(float(a_ofs)/3072.0))/8000.0)); 
     301//if ((a_ofs+=512) >= 3072) { 
     302//  a_ofs -= 3072; 
     303//  if (++a_cx > 7999) 
     304//    a_cx -= 8000; 
     305//} 
    298306*(data+8+i*m_event_size+16) = (val >> 16) & 0xff; 
    299307*(data+8+i*m_event_size+17) = (val >> 8) & 0xff; 
    300308*(data+8+i*m_event_size+18) = val & 0xff; 
    301309} 
    302                         m_cycle_ofs += m_sph_ofs_dll->get()
     310                        m_cycle_ofs += *m_ticks_per_frame
    303311                        if (m_cycle_ofs >= 3072) { 
    304312                                m_cycle_ofs -= 3072; 
     
    862870        // would see if the audio clock was locked to the ieee1394 cycle 
    863871        // timer. 
    864         // FIXME: the value for the coefficient may be optimisable; the 
    865         // value used currently just mirrors that used in 
    866         // AmdtpReceiveStreamProcessor::putPacket for a similar purpose. 
    867         float coeffs[1]; 
    868         coeffs[0]=0.0005; 
    869         m_sph_ofs_dll = new FreebobUtil::DelayLockedLoop(1, coeffs); 
    870         m_sph_ofs_dll->setIntegrator(0, 24576000.0/framerate); 
     872        m_ticks_per_frame = 24576000.0/framerate; 
    871873} 
    872874 
     
    874876        freebob_ringbuffer_free(m_event_buffer); 
    875877        free(m_tmp_event_buffer); 
    876         delete m_sph_ofs_dll; 
    877878} 
    878879 
     
    900901// once a second 
    901902//if (cycle==0) { 
    902 //  fprintf(stderr, "sph_ofs_dll=%g\n",m_sph_ofs_dll->get()); 
     903//  fprintf(stderr, "m_ticks_per_frame=%g\n",*m_ticks_per_frame); 
    903904//} 
    904905 
     
    957958 
    958959//      if (m_last_cycle_ofs < 0) { 
    959 //              m_last_cycle_ofs = sph_ofs-(int)m_sph_ofs_dll->get(); 
     960//              m_last_cycle_ofs = sph_ofs-(int)(*m_ticks_per_frame); 
    960961//      } 
    961962        m_last_cycle_ofs = sph_ofs; 
    962963        for (ev=1; ev<n_events; ev++) { 
    963964                sph_ofs = ntohl(*(quadlet_t *)(data+8+ev*m_event_size)) & 0xfff; 
    964                 m_sph_ofs_dll->put((m_last_cycle_ofs<sph_ofs)? 
    965                         sph_ofs-m_last_cycle_ofs:sph_ofs+3072-m_last_cycle_ofs); 
     965                signed int sph_diff = (m_last_cycle_ofs<sph_ofs)? 
     966                        sph_ofs-m_last_cycle_ofs:sph_ofs+3072-m_last_cycle_ofs; 
     967                float err = sph_diff - m_ticks_per_frame; 
     968                // FIXME: originally we used a value of 0.0005 for the coefficient 
     969                // which mirrored the value used in 
     970                // AmdtpReceiveStreamProcessor::putPacket() for a similar purpose. 
     971                // However, tests showed that this introduced discontinuities in 
     972                // the output audio signal, so an alternative value was sought. 
     973                // Further tests are needed, but a value of 0.01 seems to work 
     974                // well, at least at a sample rate of 48 kHz. 
     975                m_ticks_per_frame += 0.01*err; 
     976 
    966977                m_last_cycle_ofs = sph_ofs; 
    967978        } 
     
    12621273 
    12631274        if (m_last_cycle_ofs < 0) { 
    1264                 m_last_cycle_ofs = sph_ofs-(int)m_sph_ofs_dll->get(); 
     1275//              m_last_cycle_ofs = sph_ofs-(int)(*m_ticks_per_frame); 
     1276                m_last_cycle_ofs = sph_ofs - m_ticks_per_frame; 
    12651277        } 
    12661278        for (ev=0; ev<nevents; ev++) { 
    12671279                sph_ofs = ntohl(*(quadlet_t *)(data+ev*m_event_size)) & 0xfff; 
    1268                 m_sph_ofs_dll->put((m_last_cycle_ofs<sph_ofs)? 
    1269                         sph_ofs-m_last_cycle_ofs:sph_ofs+3072-m_last_cycle_ofs); 
     1280                signed int sph_diff = (m_last_cycle_ofs<sph_ofs)? 
     1281                        sph_ofs-m_last_cycle_ofs:sph_ofs+3072-m_last_cycle_ofs; 
     1282                float err = sph_diff - m_ticks_per_frame; 
     1283                // FIXME: originally we used a value of 0.0005 for the coefficient 
     1284                // which mirrored the value used in 
     1285                // AmdtpReceiveStreamProcessor::putPacket() for a similar purpose. 
     1286                // However, tests showed that this introduced discontinuities in 
     1287                // the output audio signal, so an alternative value was sought. 
     1288                // Further tests are needed, but a value of 0.01 seems to work 
     1289                // well, at least at a sample rate of 48 kHz. 
     1290                m_ticks_per_frame += 0.01*err; 
     1291 
    12701292                m_last_cycle_ofs = sph_ofs; 
    12711293        } 
  • branches/libfreebob-2.0/src/libstreaming/MotuStreamProcessor.h

    r287 r296  
    7272        virtual void setVerboseLevel(int l); 
    7373 
    74         void set_sph_ofs_dll(FreebobUtil::DelayLockedLoop *dll) {m_sph_ofs_dll=dll;}; 
     74        void setTicksPerFrameDLL(float *dll) {m_ticks_per_frame=dll;}; 
    7575 
    7676        virtual bool preparedForStop(); 
     
    9494        float m_cycle_ofs; 
    9595 
    96         // Hook to the DLL in the receive stream which allows calculation 
    97         // of cycle offsets to put into frame SPHs.  This object is  
    98         // owned by the receive stream, so the transmit stream should 
    99         // not dispose of it. 
    100         FreebobUtil::DelayLockedLoop *m_sph_ofs_dll; 
     96        // Hook to the DLL in the receive stream which provides a 
     97        // continuously updated estimate of the number of ieee1394 ticks 
     98        // per audio frame. 
     99        float *m_ticks_per_frame; 
    101100 
    102101        // Used to keep track of the close-down zeroing of output data 
     
    159158        virtual void setVerboseLevel(int l); 
    160159         
    161         FreebobUtil::DelayLockedLoop *get_sph_ofs_dll(void) {return m_sph_ofs_dll;}; 
     160        float *getTicksPerFrameDLL(void) {return &m_ticks_per_frame;}; 
    162161        signed int setEventSize(unsigned int size); 
    163162        unsigned int getEventSize(void); 
     
    178177        unsigned int m_event_size; 
    179178 
    180         FreebobUtil::DelayLockedLoop *m_sph_ofs_dll; 
     179        // The integrator of a Delay-Locked Loop (DLL) used to provide a 
     180        // continuously updated estimate of the number of ieee1394 frames 
     181        // per audio frame at the current sample rate. 
     182        float m_ticks_per_frame; 
     183 
    181184        signed int m_last_cycle_ofs; 
    182185 
  • branches/libfreebob-2.0/src/motu/motu_avdevice.cpp

    r290 r296  
    399399        } 
    400400 
    401         // Connect the transmit stream to the SPH offset DLL in the 
    402         // receive stream. 
    403         m_transmitProcessor->set_sph_ofs_dll(m_receiveProcessor->get_sph_ofs_dll()); 
     401        // Connect the transmit stream ticks-per-frame hook to the 
     402        // ticks-per-frame DLL integrator in the receive stream. 
     403        m_transmitProcessor->setTicksPerFrameDLL(m_receiveProcessor->getTicksPerFrameDLL()); 
    404404 
    405405        // Now we add ports to the processor 
  • branches/libfreebob-2.0/tests/streaming/teststreaming2.c

    r285 r296  
    7979        dev_options.node_id=-1; 
    8080         
    81         dev_options.realtime=0
     81        dev_options.realtime=1
    8282        dev_options.packetizer_priority=60; 
    8383 
     
    231231//                      hexDumpToFile(fid_in[i],(unsigned char*)audiobuffer[i],samplesread*sizeof(freebob_sample_t)+1); 
    232232// FIXME: Dump analog1 as raw data to a separate binary file for testing 
    233 if (i==2) { 
    234   fwrite(audiobuffer[i],sizeof(freebob_sample_t),samplesread,of); 
    235 
     233//if (i==2) { 
     234//  fwrite(audiobuffer[i],sizeof(freebob_sample_t),samplesread,of); 
     235//
    236236                } 
    237237