pa workaround for wdm-ks report of outputBufferDacTime
Adrian Smith
10 years ago
57 | 57 | LOG_WARN("error initialising port audio: %s", Pa_GetErrorText(err)); |
58 | 58 | return; |
59 | 59 | } |
60 | ||
60 | ||
61 | 61 | printf("Output devices:\n"); |
62 | 62 | for (i = 0; i < Pa_GetDeviceCount(); ++i) { |
63 | printf(" %i - %s [%s]\n", i, Pa_GetDeviceInfo(i)->name, Pa_GetHostApiInfo(Pa_GetDeviceInfo(i)->hostApi)->name); | |
63 | if (Pa_GetDeviceInfo(i)->maxOutputChannels) { | |
64 | printf(" %i - %s [%s]\n", i, Pa_GetDeviceInfo(i)->name, Pa_GetHostApiInfo(Pa_GetDeviceInfo(i)->hostApi)->name); | |
65 | } | |
64 | 66 | } |
65 | 67 | printf("\n"); |
66 | ||
68 | ||
67 | 69 | if ((err = Pa_Terminate()) != paNoError) { |
68 | 70 | LOG_WARN("error closing port audio: %s", Pa_GetErrorText(err)); |
69 | 71 | } |
327 | 329 | static int pa_callback(const void *pa_input, void *pa_output, unsigned long pa_frames_wanted, |
328 | 330 | const PaStreamCallbackTimeInfo *time_info, PaStreamCallbackFlags statusFlags, void *userData) { |
329 | 331 | int ret; |
332 | double stream_time; | |
330 | 333 | frames_t frames; |
331 | 334 | |
332 | 335 | optr = (u8_t *)pa_output; |
333 | 336 | |
334 | 337 | LOCK; |
335 | 338 | |
336 | output.device_frames = (unsigned)((time_info->outputBufferDacTime - Pa_GetStreamTime(pa.stream)) * output.current_sample_rate); | |
339 | stream_time = Pa_GetStreamTime(pa.stream); | |
340 | ||
341 | if (time_info->outputBufferDacTime > stream_time) { | |
342 | // workaround for wdm-ks which can return outputBufferDacTime with a different epoch | |
343 | output.device_frames = (unsigned)((time_info->outputBufferDacTime - stream_time) * output.current_sample_rate); | |
344 | } else { | |
345 | output.device_frames = 0; | |
346 | } | |
347 | ||
337 | 348 | output.updated = gettime_ms(); |
338 | 349 | |
339 | 350 | frames = _output_frames(pa_frames_wanted); |
131 | 131 | if (status.current_sample_rate && status.frames_played && status.frames_played > status.device_frames) { |
132 | 132 | ms_played = (u32_t)(((u64_t)(status.frames_played - status.device_frames) * (u64_t)1000) / (u64_t)status.current_sample_rate); |
133 | 133 | if (now > status.updated) ms_played += (now - status.updated); |
134 | LOG_SDEBUG("ms_played: %u (frames_played: %u device_frames: %u)", ms_played, status.frames_played, status.device_frames); | |
135 | } else if (status.frames_played && now > status.stream_start) { | |
136 | ms_played = now - status.stream_start; | |
137 | LOG_SDEBUG("ms_played: %u using elapsed time (frames_played: %u device_frames: %u)", ms_played, status.frames_played, status.device_frames); | |
134 | 138 | } else { |
139 | LOG_SDEBUG("ms_played: 0"); | |
135 | 140 | ms_played = 0; |
136 | 141 | } |
137 | 142 | |
158 | 163 | LOG_INFO("STAT: %s", event); |
159 | 164 | |
160 | 165 | if (loglevel == lSDEBUG) { |
161 | LOG_SDEBUG("received bytesL: %u streambuf: %u outputbuf: %u calc elapsed: %u real elapsed: %u (diff: %u) device: %u delay: %d", | |
166 | LOG_SDEBUG("received bytesL: %u streambuf: %u outputbuf: %u calc elapsed: %u real elapsed: %u (diff: %d) device: %u delay: %d", | |
162 | 167 | (u32_t)status.stream_bytes, status.stream_full, status.output_full, ms_played, now - status.stream_start, |
163 | 168 | ms_played - now + status.stream_start, status.device_frames * 1000 / status.current_sample_rate, now - status.updated); |
164 | 169 | } |