source: ext/midi/timer.c @ 1899f0d

feature/autosinkfeature/constantqfeature/pitchshiftfeature/pydocstringsfeature/timestretchpitchshiftsamplertimestretchyinfft+
Last change on this file since 1899f0d was 1899f0d, checked in by Paul Brossier <piem@altern.org>, 13 years ago

hack around timer.c to pass compilation on windows
hack around timer.c to pass compilation on windows

  • Property mode set to 100644
File size: 11.5 KB
Line 
1/*
2 *
3 * This library is free software; you can redistribute it and/or
4 * modify it under the terms of the GNU Library General Public License
5 * as published by the Free Software Foundation; either version 2 of
6 * the License, or (at your option) any later version.
7 *
8 * This library is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 * Library General Public License for more details.
12 * 
13 * You should have received a copy of the GNU Library General Public
14 * License along with this library; if not, write to the Free
15 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
16 * 02111-1307, USA
17 */
18
19/* this file originally taken from FluidSynth - A Software Synthesizer
20 * Copyright (C) 2003  Peter Hanappe and others.
21 */
22
23#include "aubio_priv.h"
24#include "timer.h"
25
26#if defined(WIN32)
27
28/*=============================================================*/
29/*                                                             */
30/*                           Win32                             */
31/*                                                             */
32/*=============================================================*/
33
34/***************************************************************
35 *
36 *               Timer
37 *
38 */
39#include <windef.h>
40
41#if 0
42#include <winbase.h>
43#endif
44
45struct _aubio_timer_t
46{
47  long msec;
48  aubio_timer_callback_t callback;
49  void* data;
50  HANDLE thread;
51  DWORD thread_id;
52  int cont;
53  int auto_destroy;
54};
55
56static int aubio_timer_count = 0;
57DWORD WINAPI aubio_timer_run(LPVOID data);
58
59aubio_timer_t* 
60new_aubio_timer(int msec, aubio_timer_callback_t callback, void* data, 
61           int new_thread, int auto_destroy)
62{
63  aubio_timer_t* timer = AUBIO_NEW(aubio_timer_t);
64  if (timer == NULL) {
65    AUBIO_ERR( "Out of memory");     
66    return NULL;
67  }
68
69  timer->cont = 1;
70  timer->msec = msec;
71  timer->callback = callback;
72  timer->data = data;
73  timer->thread = 0;
74  timer->auto_destroy = auto_destroy;
75
76  if (new_thread) {
77#if 0
78    timer->thread = CreateThread(NULL, 0, aubio_timer_run, (LPVOID) timer, 0, &timer->thread_id);
79#endif
80    if (timer->thread == NULL) {
81      AUBIO_ERR( "Couldn't create timer thread");     
82      AUBIO_FREE(timer);
83      return NULL;
84    }
85#if 0
86    SetThreadPriority(timer->thread, THREAD_PRIORITY_TIME_CRITICAL);
87#endif
88  } else {
89    aubio_timer_run((LPVOID) timer); 
90  }
91  return timer;
92}
93
94DWORD WINAPI
95aubio_timer_run(LPVOID data)
96{
97#if 0
98  int count = 0;
99  int cont = 1;
100  long start;
101  long delay;
102  aubio_timer_t* timer;
103  timer = (aubio_timer_t*) data;
104
105  if ((timer == NULL) || (timer->callback == NULL)) {
106    return 0;
107  }
108
109  SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_HIGHEST);
110
111  /* keep track of the start time for absolute positioning */
112  start = aubio_curtime();
113
114  while (cont) {
115
116    /* do whatever we have to do */
117    cont = (*timer->callback)(timer->data, aubio_curtime() - start);
118
119    count++;
120
121    /* to avoid incremental time errors, I calculate the delay between
122       two callbacks bringing in the "absolute" time (count *
123       timer->msec) */
124    delay = (count * timer->msec) - (aubio_curtime() - start);
125    if (delay > 0) {
126      Sleep(delay);
127    }
128
129    cont &= timer->cont;
130  }
131
132  AUBIO_DBG( "Timer thread finished");
133
134  if (timer->auto_destroy) {
135    AUBIO_FREE(timer);
136  }
137
138  ExitThread(0);
139#endif
140  return 0;
141}
142
143int 
144delete_aubio_timer(aubio_timer_t* timer)
145{
146  timer->cont = 0;
147  aubio_timer_join(timer); 
148  AUBIO_FREE(timer);
149  return AUBIO_OK;
150}
151
152int 
153aubio_timer_join(aubio_timer_t* timer)
154{
155#if 0
156  DWORD wait_result;
157  if (timer->thread == 0) {
158    return AUBIO_OK;
159  }
160  wait_result = WaitForSingleObject(timer->thread, INFINITE);
161  return (wait_result == WAIT_OBJECT_0)? AUBIO_OK : AUBIO_FAIL;
162#else
163  return 0;
164#endif
165}
166/***************************************************************
167 *
168 *               Time
169 */
170
171double rdtsc(void);
172double aubio_estimate_cpu_frequency(void);
173
174static double aubio_cpu_frequency = -1.0;
175
176void aubio_time_config(void)
177{
178  if (aubio_cpu_frequency < 0.0) {
179    aubio_cpu_frequency = aubio_estimate_cpu_frequency() / 1000000.0; 
180  }
181}
182
183double aubio_utime(void)
184{
185  return (rdtsc() / aubio_cpu_frequency);
186}
187
188double rdtsc(void)
189{
190#if 0
191  LARGE_INTEGER t;
192  QueryPerformanceCounter(&t);
193  return (double) t.QuadPart;
194#else
195  return 0.;
196#endif
197}
198
199double aubio_estimate_cpu_frequency(void)
200{
201#if 0
202  LONGLONG start, stop, ticks;
203  unsigned int before, after, delta;
204  double freq;
205
206  start = rdtsc();
207  stop = start;
208  before = aubio_curtime();
209  after = before;
210
211  while (1) {
212    if (after - before > 1000) {
213    break;
214    }
215    after = aubio_curtime();
216    stop = rdtsc();
217  }
218
219  delta = after - before;
220  ticks = stop - start;
221
222  freq = 1000 * ticks / delta;
223
224  return freq;
225
226#else
227#if 0
228  unsigned int before, after;
229  LARGE_INTEGER start, stop;
230
231  before = aubio_curtime();
232  QueryPerformanceCounter(&start);
233
234  Sleep(1000);
235 
236  after = aubio_curtime();
237  QueryPerformanceCounter(&stop);
238
239  return (double) 1000 * (stop.QuadPart - start.QuadPart) / (after - before);
240#endif
241  return 0;
242#endif
243}
244
245
246
247#elif defined(MACOS9)
248/*=============================================================*/
249/*                                                             */
250/*                           MacOS 9                           */
251/*                                                             */
252/*=============================================================*/
253
254
255/***************************************************************
256 *
257 *               Timer
258 */
259
260struct _aubio_timer_t
261{
262    TMTask myTmTask;
263  long msec;
264  unsigned int start;
265  unsigned int count;
266  int isInstalled;
267  aubio_timer_callback_t callback;
268  void* data;
269  int auto_destroy;
270};
271
272static TimerUPP myTimerUPP;
273
274void
275_timerCallback(aubio_timer_t *timer)
276{
277    int cont;
278  cont = (*timer->callback)(timer->data, aubio_curtime() - timer->start);
279  if (cont) {
280    PrimeTime((QElemPtr)timer, timer->msec);
281    } else {
282        timer->isInstalled = 0;
283    }
284  timer->count++;
285}
286
287aubio_timer_t* 
288new_aubio_timer(int msec, aubio_timer_callback_t callback, void* data, 
289           int new_thread, int auto_destroy)
290{
291  aubio_timer_t* timer = AUBIO_NEW(aubio_timer_t);
292  if (timer == NULL) {
293    AUBIO_ERR( "Out of memory");     
294    return NULL;
295  }
296
297    if (!myTimerUPP)
298        myTimerUPP = NewTimerProc(_timerCallback);
299
300  /* setup tmtask */
301    timer->myTmTask.tmAddr = myTimerUPP;
302    timer->myTmTask.qLink = NULL;
303    timer->myTmTask.qType = 0;
304    timer->myTmTask.tmCount = 0L;
305    timer->myTmTask.tmWakeUp = 0L;
306    timer->myTmTask.tmReserved = 0L;
307
308  timer->callback = callback;
309
310  timer->msec = msec;
311  timer->data = data;
312  timer->start = aubio_curtime();
313  timer->isInstalled = 1;
314  timer->count = 0;
315  timer->auto_destroy = auto_destroy;
316 
317  InsXTime((QElemPtr)timer);
318  PrimeTime((QElemPtr)timer, msec);
319
320  return timer;
321}
322
323int 
324delete_aubio_timer(aubio_timer_t* timer)
325{
326    if (timer->isInstalled) {
327        RmvTime((QElemPtr)timer);
328    }
329  AUBIO_FREE(timer);
330  return AUBIO_OK;
331}
332
333int 
334aubio_timer_join(aubio_timer_t* timer)
335{
336    if (timer->isInstalled) {
337        int count = timer->count;
338        /* wait until count has incremented */
339        while (count == timer->count) {}
340    }
341  return AUBIO_OK;
342}
343
344/***************************************************************
345 *
346 *               Time
347 */
348#define kTwoPower32 (4294967296.0)      /* 2^32 */
349
350void aubio_time_config(void)
351{
352}
353
354unsigned int aubio_curtime()
355{
356    /* could be optimized by not going though a double */
357    UnsignedWide    uS;
358    double mSf;
359    unsigned int ms;
360   
361    Microseconds(&uS);
362   
363  mSf = ((((double) uS.hi) * kTwoPower32) + uS.lo)/1000.0f;
364 
365  ms = mSf;
366 
367  return (ms);
368}
369
370
371
372#else
373
374/*=============================================================*/
375/*                                                             */
376/*                           POSIX                             */
377/*                                                             */
378/*=============================================================*/
379
380#include <pthread.h>
381#include <unistd.h>
382#include <sys/time.h>
383
384
385/***************************************************************
386 *
387 *               Timer
388 */
389 
390struct _aubio_timer_t
391{
392  long msec;
393  aubio_timer_callback_t callback;
394  void* data;
395  pthread_t thread;
396  int cont;
397  int auto_destroy;
398};
399
400void* 
401aubio_timer_start(void *data)
402{
403  int count = 0;
404  int cont = 1;
405  long start;
406  long delay;
407  aubio_timer_t* timer;
408  timer = (aubio_timer_t*) data;
409
410  /* keep track of the start time for absolute positioning */
411  start = aubio_curtime();
412
413  while (cont) {
414
415    /* do whatever we have to do */
416    cont = (*timer->callback)(timer->data, aubio_curtime() - start);
417
418    count++;
419
420    /* to avoid incremental time errors, calculate the delay between
421       two callbacks bringing in the "absolute" time (count *
422       timer->msec) */
423    delay = (count * timer->msec) - (aubio_curtime() - start);
424    if (delay > 0) {
425      usleep(delay * 1000);
426    }
427
428    cont &= timer->cont;
429  }
430
431  AUBIO_DBG( "Timer thread finished");
432  if (timer->thread != 0) {
433    pthread_exit(NULL);
434  }
435
436  if (timer->auto_destroy) {
437    AUBIO_FREE(timer);
438  }
439
440  return NULL;
441}
442
443aubio_timer_t* 
444new_aubio_timer(int msec, aubio_timer_callback_t callback, void* data, 
445           int new_thread, int auto_destroy)
446{
447  aubio_timer_t* timer = AUBIO_NEW(aubio_timer_t);
448  if (timer == NULL) {
449    AUBIO_ERR( "Out of memory");     
450    return NULL;
451  }
452  timer->msec = msec;
453  timer->callback = callback;
454  timer->data = data;
455  timer->cont = 1;
456  timer->thread = 0;
457  timer->auto_destroy = auto_destroy;
458
459  if (new_thread) {
460    if (pthread_create(&timer->thread, NULL, aubio_timer_start, (void*) timer)) {
461      AUBIO_ERR( "Failed to create the timer thread");
462      AUBIO_FREE(timer);
463      return NULL;
464    }
465  } else {
466    aubio_timer_start((void*) timer);
467  }
468  return timer;
469}
470
471int 
472delete_aubio_timer(aubio_timer_t* timer)
473{
474  timer->cont = 0;
475  aubio_timer_join(timer);
476  AUBIO_DBG( "Deleted player thread\n");
477  AUBIO_FREE(timer);
478  return AUBIO_OK;
479}
480
481int 
482aubio_timer_join(aubio_timer_t* timer)
483{
484  int err = 0;
485
486  if (timer->thread != 0) {
487    err = pthread_join(timer->thread, NULL);
488  } else
489    AUBIO_DBG( "Joined player thread\n");
490  return (err == 0)? AUBIO_OK : AUBIO_FAIL;
491}
492
493
494/***************************************************************
495 *
496 *               Time
497 */
498
499static double aubio_cpu_frequency = -1.0;
500
501double rdtsc(void);
502double aubio_estimate_cpu_frequency(void);
503
504void aubio_time_config(void)
505{
506  if (aubio_cpu_frequency < 0.0) {
507    aubio_cpu_frequency = aubio_estimate_cpu_frequency() / 1000000.0; 
508  }
509}
510
511unsigned int aubio_curtime()
512{
513  struct timeval now;
514  gettimeofday(&now, NULL);
515  return now.tv_sec * 1000 + now.tv_usec / 1000;
516}
517
518double aubio_utime(void)
519{
520  return (rdtsc() / aubio_cpu_frequency);
521}
522
523#if !defined(__i386__)
524
525double rdtsc(void)
526{
527  return 0.0;
528}
529
530double aubio_estimate_cpu_frequency(void)
531{
532  return 1.0;
533}
534
535#else
536
537double rdtsc(void)
538{
539  unsigned int a, b;
540
541  __asm__ ("rdtsc" : "=a" (a), "=d" (b));
542  return (double)b * (double)0x10000 * (double)0x10000 + a;
543}
544
545double aubio_estimate_cpu_frequency(void)
546{
547  double start, stop;
548  unsigned int a0, b0, a1, b1;
549  unsigned int before, after;
550
551  before = aubio_curtime(); 
552  __asm__ ("rdtsc" : "=a" (a0), "=d" (b0));
553
554  sleep(1);
555 
556  after = aubio_curtime();
557  __asm__ ("rdtsc" : "=a" (a1), "=d" (b1));
558
559
560  start = (double)b0 * (double)0x10000 * (double)0x10000 + a0;
561  stop = (double)b1 * (double)0x10000 * (double)0x10000 + a1;
562
563  return 1000 * (stop - start) / (after - before);
564}
565
566#endif
567
568#endif
Note: See TracBrowser for help on using the repository browser.