Changeset 445 for trunk/libffado/src/libutil/TimeSource.cpp
- Timestamp:
- 04/02/07 12:35:17 (17 years ago)
- Files:
-
- trunk/libffado/src/libutil/TimeSource.cpp (modified) (15 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
trunk/libffado/src/libutil/TimeSource.cpp
r419 r445 1 /* $Id$ */2 3 1 /* 4 * FreeBob Streaming API 5 * FreeBob = Firewire (pro-)audio for linux 6 * 7 * http://freebob.sf.net 8 * 9 * Copyright (C) 2005,2006 Pieter Palmers <pieterpalmers@users.sourceforge.net> 10 * 11 * This program is free software {} you can redistribute it and/or modify 12 * it under the terms of the GNU General Public License as published by 13 * the Free Software Foundation {} either version 2 of the License, or 14 * (at your option) any later version. 15 * 16 * This program is distributed in the hope that it will be useful, 17 * but WITHOUT ANY WARRANTY {} without even the implied warranty of 18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 * GNU General Public License for more details. 20 * 21 * You should have received a copy of the GNU General Public License 22 * along with this program {} if not, write to the Free Software 23 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 24 * 25 * 26 * 27 */ 28 2 * Copyright (C) 2005-2007 by Pieter Palmers 3 * 4 * This file is part of FFADO 5 * FFADO = Free Firewire (pro-)audio drivers for linux 6 * 7 * FFADO is based upon FreeBoB. 8 * 9 * This library is free software; you can redistribute it and/or 10 * modify it under the terms of the GNU Lesser General Public 11 * License version 2.1, as published by the Free Software Foundation; 12 * 13 * This library is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 * Lesser General Public License for more details. 17 * 18 * You should have received a copy of the GNU Lesser General Public 19 * License along with this library; if not, write to the Free Software 20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 21 * MA 02110-1301 USA 22 */ 29 23 30 24 #include "TimeSource.h" … … 56 50 */ 57 51 void TimeSource::initSlaveTimeSource() { 58 f reebob_microsecs_t my_time;59 f reebob_microsecs_t master_time;60 f reebob_microsecs_t my_time2;61 f reebob_microsecs_t master_time2;62 52 ffado_microsecs_t my_time; 53 ffado_microsecs_t master_time; 54 ffado_microsecs_t my_time2; 55 ffado_microsecs_t master_time2; 56 63 57 if (m_Master) { 64 58 my_time=getCurrentTime(); 65 59 master_time=m_Master->getCurrentTime(); 66 60 67 61 struct timespec ts; 68 62 69 63 // sleep for ten milliseconds 70 64 ts.tv_sec=0; 71 65 ts.tv_nsec=10000000L; 72 66 73 67 nanosleep(&ts,NULL); 74 68 75 69 my_time2=getCurrentTime(); 76 70 master_time2=m_Master->getCurrentTime(); 77 71 78 72 float diff_slave=my_time2-my_time; 79 73 float diff_master=master_time2-master_time; 80 74 81 75 m_slave_rate=diff_slave/diff_master; 82 76 83 77 // average of the two offset estimates 84 m_slave_offset = my_time-wrapTime((f reebob_microsecs_t)(master_time*m_slave_rate));85 m_slave_offset += my_time2-wrapTime((f reebob_microsecs_t)(master_time2*m_slave_rate));78 m_slave_offset = my_time-wrapTime((ffado_microsecs_t)(master_time*m_slave_rate)); 79 m_slave_offset += my_time2-wrapTime((ffado_microsecs_t)(master_time2*m_slave_rate)); 86 80 m_slave_offset /= 2; 87 81 88 82 m_last_master_time=master_time2; 89 83 m_last_time=my_time2; … … 95 89 debugOutput(DEBUG_LEVEL_NORMAL,"init slave: slave rate=%f, slave_offset=%lu\n", 96 90 m_slave_rate, m_slave_offset 97 ); 98 } 99 100 101 } 102 103 /** 104 * Maps a time point of the master to a time point 91 ); 92 } 93 94 95 } 96 97 /** 98 * Maps a time point of the master to a time point 105 99 * on it's own timeline 106 100 * 107 101 * @return the mapped time point 108 102 */ 109 f reebob_microsecs_t TimeSource::mapMasterTime(freebob_microsecs_t master_time) {103 ffado_microsecs_t TimeSource::mapMasterTime(ffado_microsecs_t master_time) { 110 104 if(m_Master) { 111 105 // calculate the slave based upon the master 112 106 // and the estimated rate 113 107 114 108 // linear interpolation 115 109 int delta_master=master_time-m_last_master_time; 116 110 117 111 float offset=m_slave_rate * ((float)delta_master); 118 119 f reebob_microsecs_t mapped=m_last_time+(int)offset;120 112 113 ffado_microsecs_t mapped=m_last_time+(int)offset; 114 121 115 debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"map time: master=%d, offset=%f, slave_base=%lu, pred_ticks=%lu\n", 122 116 master_time, offset, m_last_time,mapped 123 117 ); 124 118 125 119 return wrapTime(mapped); 126 120 127 121 } else { 128 122 debugOutput( DEBUG_LEVEL_VERBOSE, "Requested map for non-slave TimeSource\n"); 129 123 130 124 return master_time; 131 125 } … … 140 134 for ( TimeSourceVectorIterator it = m_Slaves.begin(); 141 135 it != m_Slaves.end(); ++it ) { 142 143 // update the slave with the current 136 137 // update the slave with the current 144 138 // master time 145 139 if (!(*it)->updateTimeSource()) return false; 146 140 } 147 141 148 142 // this TimeSource has a master 149 143 if(m_Master) { 150 f reebob_microsecs_t my_time=getCurrentTime();151 f reebob_microsecs_t master_time=m_Master->getCurrentTime();152 153 // we assume that the master and slave time are 144 ffado_microsecs_t my_time=getCurrentTime(); 145 ffado_microsecs_t master_time=m_Master->getCurrentTime(); 146 147 // we assume that the master and slave time are 154 148 // measured at the same time, but that of course is 155 149 // not really true. The DLL will have to filter this 156 150 // out. 157 151 158 152 // the difference in master time 159 153 int64_t delta_master; … … 163 157 delta_master=m_Master->unWrapTime(master_time)-m_last_master_time; 164 158 } 165 159 166 160 // the difference in slave time 167 161 int64_t delta_slave; … … 171 165 delta_slave=unWrapTime(my_time)-m_last_time; 172 166 } 173 167 174 168 // the estimated slave difference 175 169 int delta_slave_est=(int)(m_slave_rate * ((double)delta_master)); 176 170 177 171 // the measured & estimated rate 178 172 double rate_meas=((double)delta_slave/(double)delta_master); 179 173 double rate_est=((double)m_slave_rate); 180 174 181 175 m_last_err=(rate_meas-rate_est); 182 176 183 177 m_slave_rate += 0.01*m_last_err; 184 178 185 179 debugOutput(DEBUG_LEVEL_VERBOSE,"update slave: master=%llu, master2=%llu, diff=%lld\n", 186 180 master_time, m_last_master_time, delta_master); … … 191 185 ); 192 186 193 187 194 188 m_last_master_time=master_time; 195 189 196 190 int64_t tmp = delta_slave_est; 197 191 tmp += m_last_time; 198 192 199 193 m_last_time = tmp; 200 201 202 194 195 196 203 197 } 204 198 … … 209 203 * Sets the master TimeSource for this timesource. 210 204 * This TimeSource will sync to the master TimeSource, 211 * making that it will be able to map a time point of 205 * making that it will be able to map a time point of 212 206 * the master to a time point on it's own timeline 213 207 * 214 * @param ts master TimeSource 208 * @param ts master TimeSource 215 209 * @return true if successful 216 210 */ … … 218 212 if (m_Master==NULL) { 219 213 m_Master=ts; 220 214 221 215 // initialize ourselves. 222 216 initSlaveTimeSource(); 223 217 224 218 return true; 225 219 } else return false; … … 238 232 * Registers a slave timesource to this master. 239 233 * A slave TimeSource will sync to this TimeSource, 240 * making that it will be able to map a time point of 241 * the master (this) TimeSource to a time point on 234 * making that it will be able to map a time point of 235 * the master (this) TimeSource to a time point on 242 236 * it's own timeline 243 237 * … … 247 241 bool TimeSource::registerSlave(TimeSource *ts) { 248 242 // TODO: we should check for circular master-slave relationships. 249 243 250 244 debugOutput( DEBUG_LEVEL_VERBOSE, "Registering slave (%p)\n", ts); 251 245 assert(ts); 252 246 253 247 // inherit debug level 254 ts->setVerboseLevel(getDebugLevel()); 255 248 ts->setVerboseLevel(getDebugLevel()); 249 256 250 if(ts->setMaster(this)) { 257 251 m_Slaves.push_back(ts); … … 275 269 it != m_Slaves.end(); ++it ) { 276 270 277 if ( *it == ts ) { 271 if ( *it == ts ) { 278 272 m_Slaves.erase(it); 279 273 ts->clearMaster(); … … 281 275 } 282 276 } 283 277 284 278 debugOutput( DEBUG_LEVEL_VERBOSE, " TimeSource (%p) not found\n", ts); 285 279 286 280 return false; 287 281 } … … 298 292 for ( TimeSourceVectorIterator it = m_Slaves.begin(); 299 293 it != m_Slaves.end(); ++it ) { 300 294 301 295 (*it)->setVerboseLevel(l); 302 296 } … … 313 307 debugOutputShort( DEBUG_LEVEL_NORMAL, " Last slave time : %llu\n",m_last_time ); 314 308 315 309 316 310 for ( TimeSourceVectorIterator it = m_Slaves.begin(); 317 311 it != m_Slaves.end(); ++it ) { 318 312 319 313 (*it)->printTimeSourceInfo(); 320 314 }