209 { |
209 { |
210 #ifdef DEBUG_AUDIO |
210 #ifdef DEBUG_AUDIO |
211 QTime now(QTime::currentTime()); |
211 QTime now(QTime::currentTime()); |
212 qDebug()<<now.second()<<"s "<<now.msec()<<"ms :open()"; |
212 qDebug()<<now.second()<<"s "<<now.msec()<<"ms :open()"; |
213 #endif |
213 #endif |
|
214 if (!(settings.frequency() >= 8000 && settings.frequency() <= 48000)) { |
|
215 errorState = QAudio::OpenError; |
|
216 deviceState = QAudio::StoppedState; |
|
217 emit stateChanged(deviceState); |
|
218 qWarning("QAudioOutput: open error, frequency out of range."); |
|
219 return false; |
|
220 } |
214 if(buffer_size == 0) { |
221 if(buffer_size == 0) { |
215 // Default buffer size, 200ms, default period size is 40ms |
222 // Default buffer size, 200ms, default period size is 40ms |
216 buffer_size = settings.frequency()*settings.channels()*(settings.sampleSize()/8)*0.2; |
223 buffer_size = settings.frequency()*settings.channels()*(settings.sampleSize()/8)*0.2; |
217 period_size = buffer_size/5; |
224 period_size = buffer_size/5; |
218 } else { |
225 } else { |
287 { |
294 { |
288 if(deviceState == QAudio::StoppedState) |
295 if(deviceState == QAudio::StoppedState) |
289 return; |
296 return; |
290 |
297 |
291 deviceState = QAudio::StoppedState; |
298 deviceState = QAudio::StoppedState; |
|
299 errorState = QAudio::NoError; |
292 int delay = (buffer_size-bytesFree())*1000/(settings.frequency() |
300 int delay = (buffer_size-bytesFree())*1000/(settings.frequency() |
293 *settings.channels()*(settings.sampleSize()/8)); |
301 *settings.channels()*(settings.sampleSize()/8)); |
294 waveOutReset(hWaveOut); |
302 waveOutReset(hWaveOut); |
295 Sleep(delay+10); |
303 Sleep(delay+10); |
296 |
304 |
338 return intervalTime; |
346 return intervalTime; |
339 } |
347 } |
340 |
348 |
341 qint64 QAudioOutputPrivate::processedUSecs() const |
349 qint64 QAudioOutputPrivate::processedUSecs() const |
342 { |
350 { |
343 return totalTimeValue; |
351 if (deviceState == QAudio::StoppedState) |
|
352 return 0; |
|
353 qint64 result = qint64(1000000) * totalTimeValue / |
|
354 (settings.channels()*(settings.sampleSize()/8)) / |
|
355 settings.frequency(); |
|
356 |
|
357 return result; |
344 } |
358 } |
345 |
359 |
346 qint64 QAudioOutputPrivate::write( const char *data, qint64 len ) |
360 qint64 QAudioOutputPrivate::write( const char *data, qint64 len ) |
347 { |
361 { |
348 // Write out some audio data |
362 // Write out some audio data |
|
363 if (deviceState != QAudio::ActiveState && deviceState != QAudio::IdleState) |
|
364 return 0; |
349 |
365 |
350 char* p = (char*)data; |
366 char* p = (char*)data; |
351 int l = (int)len; |
367 int l = (int)len; |
352 |
368 |
353 WAVEHDR* current; |
369 WAVEHDR* current; |
383 EnterCriticalSection(&waveOutCriticalSection); |
399 EnterCriticalSection(&waveOutCriticalSection); |
384 qDebug("write out l=%d, waveFreeBlockCount=%d", |
400 qDebug("write out l=%d, waveFreeBlockCount=%d", |
385 current->dwBufferLength,waveFreeBlockCount); |
401 current->dwBufferLength,waveFreeBlockCount); |
386 LeaveCriticalSection(&waveOutCriticalSection); |
402 LeaveCriticalSection(&waveOutCriticalSection); |
387 #endif |
403 #endif |
388 totalTimeValue += current->dwBufferLength |
404 totalTimeValue += current->dwBufferLength; |
389 /(settings.channels()*(settings.sampleSize()/8)) |
|
390 *1000000/settings.frequency();; |
|
391 waveCurrentBlock++; |
405 waveCurrentBlock++; |
392 waveCurrentBlock %= buffer_size/period_size; |
406 waveCurrentBlock %= buffer_size/period_size; |
393 current = &waveBlocks[waveCurrentBlock]; |
407 current = &waveBlocks[waveCurrentBlock]; |
394 current->dwUser = 0; |
408 current->dwUser = 0; |
|
409 errorState = QAudio::NoError; |
|
410 if (deviceState != QAudio::ActiveState) { |
|
411 deviceState = QAudio::ActiveState; |
|
412 emit stateChanged(deviceState); |
|
413 } |
395 } |
414 } |
396 return (len-l); |
415 return (len-l); |
397 } |
416 } |
398 |
417 |
399 void QAudioOutputPrivate::resume() |
418 void QAudioOutputPrivate::resume() |
407 } |
426 } |
408 } |
427 } |
409 |
428 |
410 void QAudioOutputPrivate::suspend() |
429 void QAudioOutputPrivate::suspend() |
411 { |
430 { |
412 if(deviceState == QAudio::ActiveState) { |
431 if(deviceState == QAudio::ActiveState || deviceState == QAudio::IdleState) { |
|
432 int delay = (buffer_size-bytesFree())*1000/(settings.frequency() |
|
433 *settings.channels()*(settings.sampleSize()/8)); |
413 waveOutPause(hWaveOut); |
434 waveOutPause(hWaveOut); |
|
435 Sleep(delay+10); |
414 deviceState = QAudio::SuspendedState; |
436 deviceState = QAudio::SuspendedState; |
415 errorState = QAudio::NoError; |
437 errorState = QAudio::NoError; |
416 emit stateChanged(deviceState); |
438 emit stateChanged(deviceState); |
417 } |
439 } |
418 } |
440 } |
431 } |
453 } |
432 } |
454 } |
433 |
455 |
434 bool QAudioOutputPrivate::deviceReady() |
456 bool QAudioOutputPrivate::deviceReady() |
435 { |
457 { |
|
458 if(deviceState == QAudio::StoppedState) |
|
459 return false; |
|
460 |
436 if(pullMode) { |
461 if(pullMode) { |
437 int chunks = bytesAvailable/period_size; |
462 int chunks = bytesAvailable/period_size; |
438 #ifdef DEBUG_AUDIO |
463 #ifdef DEBUG_AUDIO |
439 qDebug()<<"deviceReady() avail="<<bytesAvailable<<" bytes, period size="<<period_size<<" bytes"; |
464 qDebug()<<"deviceReady() avail="<<bytesAvailable<<" bytes, period size="<<period_size<<" bytes"; |
440 qDebug()<<"deviceReady() no. of chunks that can fit ="<<chunks<<", chunks in bytes ="<<chunks*period_size; |
465 qDebug()<<"deviceReady() no. of chunks that can fit ="<<chunks<<", chunks in bytes ="<<chunks*period_size; |
463 waveOutPause(hWaveOut); |
488 waveOutPause(hWaveOut); |
464 int input = period_size*chunks; |
489 int input = period_size*chunks; |
465 int l = audioSource->read(audioBuffer,input); |
490 int l = audioSource->read(audioBuffer,input); |
466 if(l > 0) { |
491 if(l > 0) { |
467 int out= write(audioBuffer,l); |
492 int out= write(audioBuffer,l); |
468 if(out > 0) |
493 if(out > 0) { |
469 deviceState = QAudio::ActiveState; |
494 if (deviceState != QAudio::ActiveState) { |
|
495 deviceState = QAudio::ActiveState; |
|
496 emit stateChanged(deviceState); |
|
497 } |
|
498 } |
|
499 if ( out < l) { |
|
500 // Didnt write all data |
|
501 audioSource->seek(audioSource->pos()-(l-out)); |
|
502 } |
470 if(startup) |
503 if(startup) |
471 waveOutRestart(hWaveOut); |
504 waveOutRestart(hWaveOut); |
472 } else if(l == 0) { |
505 } else if(l == 0) { |
473 bytesAvailable = bytesFree(); |
506 bytesAvailable = bytesFree(); |
474 |
507 |
476 EnterCriticalSection(&waveOutCriticalSection); |
509 EnterCriticalSection(&waveOutCriticalSection); |
477 check = waveFreeBlockCount; |
510 check = waveFreeBlockCount; |
478 LeaveCriticalSection(&waveOutCriticalSection); |
511 LeaveCriticalSection(&waveOutCriticalSection); |
479 if(check == buffer_size/period_size) { |
512 if(check == buffer_size/period_size) { |
480 errorState = QAudio::UnderrunError; |
513 errorState = QAudio::UnderrunError; |
481 deviceState = QAudio::IdleState; |
514 if (deviceState != QAudio::IdleState) { |
482 emit stateChanged(deviceState); |
515 deviceState = QAudio::IdleState; |
|
516 emit stateChanged(deviceState); |
|
517 } |
483 } |
518 } |
484 |
519 |
485 } else if(l < 0) { |
520 } else if(l < 0) { |
486 bytesAvailable = bytesFree(); |
521 bytesAvailable = bytesFree(); |
487 errorState = QAudio::IOError; |
522 errorState = QAudio::IOError; |
488 } |
523 } |
489 } |
524 } else { |
490 if(deviceState != QAudio::ActiveState) |
525 int buffered; |
|
526 EnterCriticalSection(&waveOutCriticalSection); |
|
527 buffered = waveFreeBlockCount; |
|
528 LeaveCriticalSection(&waveOutCriticalSection); |
|
529 errorState = QAudio::UnderrunError; |
|
530 if (buffered >= buffer_size/period_size && deviceState == QAudio::ActiveState) { |
|
531 deviceState = QAudio::IdleState; |
|
532 emit stateChanged(deviceState); |
|
533 } |
|
534 } |
|
535 if(deviceState != QAudio::ActiveState && deviceState != QAudio::IdleState) |
491 return true; |
536 return true; |
492 |
537 |
493 if((timeStamp.elapsed() + elapsedTimeOffset) > intervalTime) { |
538 if((timeStamp.elapsed() + elapsedTimeOffset) > intervalTime) { |
494 emit notify(); |
539 emit notify(); |
495 elapsedTimeOffset = timeStamp.elapsed() + elapsedTimeOffset - intervalTime; |
540 elapsedTimeOffset = timeStamp.elapsed() + elapsedTimeOffset - intervalTime; |