Changeset 296
- Timestamp:
- 08/20/06 18:44:33 (16 years ago)
- Files:
-
- branches/libfreebob-2.0/src/libstreaming/MotuStreamProcessor.cpp (modified) (16 diffs)
- branches/libfreebob-2.0/src/libstreaming/MotuStreamProcessor.h (modified) (4 diffs)
- branches/libfreebob-2.0/src/motu/motu_avdevice.cpp (modified) (1 diff)
- branches/libfreebob-2.0/tests/streaming/teststreaming2.c (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
branches/libfreebob-2.0/src/libstreaming/MotuStreamProcessor.cpp
r294 r296 45 45 #define get_bits(_d,_start,_len) (((_d)>>((_start)-(_len)+1)) & ((1<<(_len))-1)) 46 46 47 48 47 /* transmit */ 49 48 MotuTransmitStreamProcessor::MotuTransmitStreamProcessor(int port, int framerate, 50 49 unsigned int event_size) 51 50 : 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), 53 52 m_closedown_count(-1) { 54 53 … … 100 99 signed int i; 101 100 101 signed int corrected_cycle = cycle; 102 102 103 // The MOTU transmit stream is 'always' ready 103 104 m_running = true; … … 106 107 // iso data has been requested. 107 108 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());110 109 m_cycle_count = cycle; 111 110 m_cycle_ofs = 0.0; … … 129 128 // FIXME: some tests - attempt to recover sync after loss due to missed cycles 130 129 static 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; 132 132 //struct timeval tv; 133 133 //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 134 138 if (!m_disabled && next_cycle>=0 && cycle!=next_cycle) { 135 139 debugOutput(DEBUG_LEVEL_VERBOSE, "tx cycle miss: %d requested, %d expected\n",cycle,next_cycle); 136 140 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"); 139 154 140 155 #if 0 … … 147 162 #else 148 163 float 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; 164 signed int ccount; 169 165 170 166 ccount = next_cycle; 171 167 while (ccount!=cycle) { 172 if (ccount < m_cycle_count) { 168 169 corrected_cycle = ccount; 170 if (m_cycle_count-ccount > 7900) 171 corrected_cycle += 8000; 172 173 if (corrected_cycle < m_cycle_count) { 173 174 if (++ccount == 8000) 174 175 ccount = 0; … … 176 177 } 177 178 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; 191 184 m_cycle_ofs = fmod(ftmp, 3072); 192 185 … … 195 188 } 196 189 m_tx_dbc &= 0xff; 197 m_cycle_count %= 8000;198 190 199 191 #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); 202 194 } 203 195 if (!m_disabled) … … 205 197 else 206 198 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; 208 204 209 205 // Increment the dbc (data block count). This is only done if the … … 213 209 // first packet containing data will have a DBC of n_events, which 214 210 // matches what is observed from other systems. 215 if (!m_disabled && c ycle>=m_cycle_count) {211 if (!m_disabled && corrected_cycle>=m_cycle_count) { 216 212 m_tx_dbc += n_events; 217 213 if (m_tx_dbc > 0xff) … … 232 228 // ahead of the ieee1394 cycle timer, we send a data-less packet 233 229 // with only the 8 byte CIP-like header set up previously. 234 if (m_disabled || c ycle<m_cycle_count) {230 if (m_disabled || corrected_cycle<m_cycle_count) { 235 231 return RAW1394_ISO_OK; 236 232 } … … 294 290 // is complete. Note that the tone is *not* added during closedown. 295 291 if (m_closedown_count<0) { 292 //static signed int a_cx=0, a_ofs=0; 293 static signed int a_cx = 0; 296 294 signed 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)); 296 val = (int)(0x7fffff*sin(1000.0*2.0*M_PI*(a_cx/24576000.0))); 297 if ((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 //} 298 306 *(data+8+i*m_event_size+16) = (val >> 16) & 0xff; 299 307 *(data+8+i*m_event_size+17) = (val >> 8) & 0xff; 300 308 *(data+8+i*m_event_size+18) = val & 0xff; 301 309 } 302 m_cycle_ofs += m_sph_ofs_dll->get();310 m_cycle_ofs += *m_ticks_per_frame; 303 311 if (m_cycle_ofs >= 3072) { 304 312 m_cycle_ofs -= 3072; … … 862 870 // would see if the audio clock was locked to the ieee1394 cycle 863 871 // 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; 871 873 } 872 874 … … 874 876 freebob_ringbuffer_free(m_event_buffer); 875 877 free(m_tmp_event_buffer); 876 delete m_sph_ofs_dll;877 878 } 878 879 … … 900 901 // once a second 901 902 //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); 903 904 //} 904 905 … … 957 958 958 959 // 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); 960 961 // } 961 962 m_last_cycle_ofs = sph_ofs; 962 963 for (ev=1; ev<n_events; ev++) { 963 964 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 966 977 m_last_cycle_ofs = sph_ofs; 967 978 } … … 1262 1273 1263 1274 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; 1265 1277 } 1266 1278 for (ev=0; ev<nevents; ev++) { 1267 1279 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 1270 1292 m_last_cycle_ofs = sph_ofs; 1271 1293 } branches/libfreebob-2.0/src/libstreaming/MotuStreamProcessor.h
r287 r296 72 72 virtual void setVerboseLevel(int l); 73 73 74 void set _sph_ofs_dll(FreebobUtil::DelayLockedLoop *dll) {m_sph_ofs_dll=dll;};74 void setTicksPerFrameDLL(float *dll) {m_ticks_per_frame=dll;}; 75 75 76 76 virtual bool preparedForStop(); … … 94 94 float m_cycle_ofs; 95 95 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; 101 100 102 101 // Used to keep track of the close-down zeroing of output data … … 159 158 virtual void setVerboseLevel(int l); 160 159 161 FreebobUtil::DelayLockedLoop *get_sph_ofs_dll(void) {return m_sph_ofs_dll;};160 float *getTicksPerFrameDLL(void) {return &m_ticks_per_frame;}; 162 161 signed int setEventSize(unsigned int size); 163 162 unsigned int getEventSize(void); … … 178 177 unsigned int m_event_size; 179 178 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 181 184 signed int m_last_cycle_ofs; 182 185 branches/libfreebob-2.0/src/motu/motu_avdevice.cpp
r290 r296 399 399 } 400 400 401 // Connect the transmit stream t o the SPH offset DLL inthe402 // 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()); 404 404 405 405 // Now we add ports to the processor branches/libfreebob-2.0/tests/streaming/teststreaming2.c
r285 r296 79 79 dev_options.node_id=-1; 80 80 81 dev_options.realtime= 0;81 dev_options.realtime=1; 82 82 dev_options.packetizer_priority=60; 83 83 … … 231 231 // hexDumpToFile(fid_in[i],(unsigned char*)audiobuffer[i],samplesread*sizeof(freebob_sample_t)+1); 232 232 // 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 //} 236 236 } 237 237