source: ext/midi/timer.c @ cd9b142

feature/autosinkfeature/cnnfeature/cnn_orgfeature/constantqfeature/crepefeature/crepe_orgfeature/pitchshiftfeature/pydocstringsfeature/timestretchfix/ffmpeg5pitchshiftsamplertimestretchyinfft+
Last change on this file since cd9b142 was b60dd4ae, checked in by Paul Brossier <piem@altern.org>, 20 years ago

moved midi functions to ext/

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