52 |
52 |
53 #include <QtCore/qendian.h> |
53 #include <QtCore/qendian.h> |
54 #include <QtCore/qtimer.h> |
54 #include <QtCore/qtimer.h> |
55 #include <QtCore/qdebug.h> |
55 #include <QtCore/qdebug.h> |
56 |
56 |
57 #include <QtMultimedia/qaudiodeviceinfo.h> |
|
58 #include <QtMultimedia/qaudioinput.h> |
57 #include <QtMultimedia/qaudioinput.h> |
59 |
58 |
60 #include "qaudio_mac_p.h" |
59 #include "qaudio_mac_p.h" |
61 #include "qaudioinput_mac_p.h" |
60 #include "qaudioinput_mac_p.h" |
62 |
61 #include "qaudiodeviceinfo_mac_p.h" |
63 |
62 |
64 QT_BEGIN_NAMESPACE |
63 QT_BEGIN_NAMESPACE |
65 |
64 |
66 |
65 |
67 namespace |
66 namespace QtMultimediaInternal |
68 { |
67 { |
69 |
68 |
70 static const int default_buffer_size = 4 * 1024; |
69 static const int default_buffer_size = 4 * 1024; |
71 |
70 |
72 class QAudioBufferList |
71 class QAudioBufferList |
225 AudioStreamBasicDescription const& inputFormat, |
226 AudioStreamBasicDescription const& inputFormat, |
226 AudioStreamBasicDescription const& outputFormat, |
227 AudioStreamBasicDescription const& outputFormat, |
227 QObject* parent): |
228 QObject* parent): |
228 QObject(parent), |
229 QObject(parent), |
229 m_deviceError(false), |
230 m_deviceError(false), |
|
231 m_audioConverter(0), |
230 m_inputFormat(inputFormat), |
232 m_inputFormat(inputFormat), |
231 m_outputFormat(outputFormat) |
233 m_outputFormat(outputFormat) |
232 { |
234 { |
233 m_maxPeriodSize = maxPeriodSize; |
235 m_maxPeriodSize = maxPeriodSize; |
234 m_periodTime = m_maxPeriodSize / m_outputFormat.mBytesPerFrame * 1000 / m_outputFormat.mSampleRate; |
236 m_periodTime = m_maxPeriodSize / m_outputFormat.mBytesPerFrame * 1000 / m_outputFormat.mSampleRate; |
236 m_inputBufferList = new QAudioBufferList(m_inputFormat); |
238 m_inputBufferList = new QAudioBufferList(m_inputFormat); |
237 |
239 |
238 m_flushTimer = new QTimer(this); |
240 m_flushTimer = new QTimer(this); |
239 connect(m_flushTimer, SIGNAL(timeout()), SLOT(flushBuffer())); |
241 connect(m_flushTimer, SIGNAL(timeout()), SLOT(flushBuffer())); |
240 |
242 |
241 if (inputFormat.mSampleRate != outputFormat.mSampleRate) { |
243 if (toQAudioFormat(inputFormat) != toQAudioFormat(outputFormat)) { |
242 if (AudioConverterNew(&m_inputFormat, &m_outputFormat, &m_audioConverter) != noErr) { |
244 if (AudioConverterNew(&m_inputFormat, &m_outputFormat, &m_audioConverter) != noErr) { |
243 qWarning() << "QAudioInput: Unable to create an Audio Converter"; |
245 qWarning() << "QAudioInput: Unable to create an Audio Converter"; |
244 m_audioConverter = 0; |
246 m_audioConverter = 0; |
245 } |
247 } |
246 } |
248 } |
515 ds >> did >> mode; |
517 ds >> did >> mode; |
516 |
518 |
517 if (QAudio::Mode(mode) == QAudio::AudioOutput) |
519 if (QAudio::Mode(mode) == QAudio::AudioOutput) |
518 errorCode = QAudio::OpenError; |
520 errorCode = QAudio::OpenError; |
519 else { |
521 else { |
|
522 audioDeviceInfo = new QAudioDeviceInfoInternal(device, QAudio::AudioInput); |
520 isOpen = false; |
523 isOpen = false; |
521 audioDeviceId = AudioDeviceID(did); |
524 audioDeviceId = AudioDeviceID(did); |
522 audioUnit = 0; |
525 audioUnit = 0; |
523 startTime = 0; |
526 startTime = 0; |
524 totalFrames = 0; |
527 totalFrames = 0; |
525 audioBuffer = 0; |
528 audioBuffer = 0; |
526 internalBufferSize = default_buffer_size; |
529 internalBufferSize = QtMultimediaInternal::default_buffer_size; |
527 clockFrequency = AudioGetHostClockFrequency() / 1000; |
530 clockFrequency = AudioGetHostClockFrequency() / 1000; |
528 errorCode = QAudio::NoError; |
531 errorCode = QAudio::NoError; |
529 stateCode = QAudio::StoppedState; |
532 stateCode = QAudio::StoppedState; |
530 |
533 |
531 intervalTimer = new QTimer(this); |
534 intervalTimer = new QTimer(this); |
572 kAudioOutputUnitProperty_EnableIO, |
576 kAudioOutputUnitProperty_EnableIO, |
573 kAudioUnitScope_Input, |
577 kAudioUnitScope_Input, |
574 1, |
578 1, |
575 &enable, |
579 &enable, |
576 sizeof(enable)) != noErr) { |
580 sizeof(enable)) != noErr) { |
577 qWarning() << "QAudioInput: Unabled to switch to input mode (Enable Input)"; |
581 qWarning() << "QAudioInput: Unable to switch to input mode (Enable Input)"; |
578 return false; |
582 return false; |
579 } |
583 } |
580 |
584 |
581 enable = 0; |
585 enable = 0; |
582 if (AudioUnitSetProperty(audioUnit, |
586 if (AudioUnitSetProperty(audioUnit, |
583 kAudioOutputUnitProperty_EnableIO, |
587 kAudioOutputUnitProperty_EnableIO, |
584 kAudioUnitScope_Output, |
588 kAudioUnitScope_Output, |
585 0, |
589 0, |
586 &enable, |
590 &enable, |
587 sizeof(enable)) != noErr) { |
591 sizeof(enable)) != noErr) { |
588 qWarning() << "QAudioInput: Unabled to switch to input mode (Disable output)"; |
592 qWarning() << "QAudioInput: Unable to switch to input mode (Disable output)"; |
589 return false; |
593 return false; |
590 } |
594 } |
591 |
595 |
592 // register callback |
596 // register callback |
593 AURenderCallbackStruct cb; |
597 AURenderCallbackStruct cb; |
614 qWarning() << "QAudioInput: Unable to use configured device"; |
618 qWarning() << "QAudioInput: Unable to use configured device"; |
615 return false; |
619 return false; |
616 } |
620 } |
617 |
621 |
618 // Set format |
622 // Set format |
|
623 // Wanted |
619 streamFormat = toAudioStreamBasicDescription(audioFormat); |
624 streamFormat = toAudioStreamBasicDescription(audioFormat); |
620 |
625 |
621 size = sizeof(deviceFormat); |
626 // Required on unit |
622 if (AudioUnitGetProperty(audioUnit, |
627 if (audioFormat == audioDeviceInfo->preferredFormat()) { |
623 kAudioUnitProperty_StreamFormat, |
628 deviceFormat = streamFormat; |
624 kAudioUnitScope_Input, |
629 AudioUnitSetProperty(audioUnit, |
625 1, |
|
626 &deviceFormat, |
|
627 &size) != noErr) { |
|
628 qWarning() << "QAudioInput: Unable to retrieve device format"; |
|
629 return false; |
|
630 } |
|
631 |
|
632 // If the device frequency is different to the requested use a converter |
|
633 if (deviceFormat.mSampleRate != streamFormat.mSampleRate) { |
|
634 AudioUnitSetProperty(audioUnit, |
|
635 kAudioUnitProperty_StreamFormat, |
630 kAudioUnitProperty_StreamFormat, |
636 kAudioUnitScope_Output, |
631 kAudioUnitScope_Output, |
637 1, |
632 1, |
638 &deviceFormat, |
633 &deviceFormat, |
639 sizeof(streamFormat)); |
634 sizeof(deviceFormat)); |
640 } |
635 } |
641 else { |
636 else { |
642 AudioUnitSetProperty(audioUnit, |
637 size = sizeof(deviceFormat); |
643 kAudioUnitProperty_StreamFormat, |
638 if (AudioUnitGetProperty(audioUnit, |
644 kAudioUnitScope_Output, |
639 kAudioUnitProperty_StreamFormat, |
645 1, |
640 kAudioUnitScope_Input, |
646 &streamFormat, |
641 1, |
647 sizeof(streamFormat)); |
642 &deviceFormat, |
|
643 &size) != noErr) { |
|
644 qWarning() << "QAudioInput: Unable to retrieve device format"; |
|
645 return false; |
|
646 } |
|
647 |
|
648 if (AudioUnitSetProperty(audioUnit, |
|
649 kAudioUnitProperty_StreamFormat, |
|
650 kAudioUnitScope_Output, |
|
651 1, |
|
652 &deviceFormat, |
|
653 sizeof(deviceFormat)) != noErr) { |
|
654 qWarning() << "QAudioInput: Unable to set device format"; |
|
655 return false; |
|
656 } |
648 } |
657 } |
649 |
658 |
650 // Setup buffers |
659 // Setup buffers |
651 UInt32 numberOfFrames; |
660 UInt32 numberOfFrames; |
652 size = sizeof(UInt32); |
661 size = sizeof(UInt32); |
659 qWarning() << "QAudioInput: Failed to get audio period size"; |
668 qWarning() << "QAudioInput: Failed to get audio period size"; |
660 return false; |
669 return false; |
661 } |
670 } |
662 |
671 |
663 // Allocate buffer |
672 // Allocate buffer |
664 periodSizeBytes = (numberOfFrames * streamFormat.mSampleRate / deviceFormat.mSampleRate) * |
673 periodSizeBytes = numberOfFrames * streamFormat.mBytesPerFrame; |
665 streamFormat.mBytesPerFrame; |
674 |
666 if (internalBufferSize < periodSizeBytes * 2) |
675 if (internalBufferSize < periodSizeBytes * 2) |
667 internalBufferSize = periodSizeBytes * 2; |
676 internalBufferSize = periodSizeBytes * 2; |
668 else |
677 else |
669 internalBufferSize -= internalBufferSize % streamFormat.mBytesPerFrame; |
678 internalBufferSize -= internalBufferSize % streamFormat.mBytesPerFrame; |
670 |
679 |
671 audioBuffer = new QAudioInputBuffer(internalBufferSize, |
680 audioBuffer = new QtMultimediaInternal::QAudioInputBuffer(internalBufferSize, |
672 periodSizeBytes, |
681 periodSizeBytes, |
673 deviceFormat, |
682 deviceFormat, |
674 streamFormat, |
683 streamFormat, |
675 this); |
684 this); |
676 |
685 |
677 audioIO = new MacInputDevice(audioBuffer, this); |
686 audioIO = new QtMultimediaInternal::MacInputDevice(audioBuffer, this); |
678 |
687 |
679 // Init |
688 // Init |
680 if (AudioUnitInitialize(audioUnit) != noErr) { |
689 if (AudioUnitInitialize(audioUnit) != noErr) { |
681 qWarning() << "QAudioInput: Failed to initialize AudioUnit"; |
690 qWarning() << "QAudioInput: Failed to initialize AudioUnit"; |
682 return false; |
691 return false; |
802 return internalBufferSize; |
811 return internalBufferSize; |
803 } |
812 } |
804 |
813 |
805 void QAudioInputPrivate::setNotifyInterval(int milliSeconds) |
814 void QAudioInputPrivate::setNotifyInterval(int milliSeconds) |
806 { |
815 { |
|
816 if (intervalTimer->interval() == milliSeconds) |
|
817 return; |
|
818 |
|
819 if (milliSeconds <= 0) |
|
820 milliSeconds = 0; |
|
821 |
807 intervalTimer->setInterval(milliSeconds); |
822 intervalTimer->setInterval(milliSeconds); |
808 } |
823 } |
809 |
824 |
810 int QAudioInputPrivate::notifyInterval() const |
825 int QAudioInputPrivate::notifyInterval() const |
811 { |
826 { |
881 } |
896 } |
882 |
897 |
883 void QAudioInputPrivate::startTimers() |
898 void QAudioInputPrivate::startTimers() |
884 { |
899 { |
885 audioBuffer->startFlushTimer(); |
900 audioBuffer->startFlushTimer(); |
886 intervalTimer->start(); |
901 if (intervalTimer->interval() > 0) |
|
902 intervalTimer->start(); |
887 } |
903 } |
888 |
904 |
889 void QAudioInputPrivate::stopTimers() |
905 void QAudioInputPrivate::stopTimers() |
890 { |
906 { |
891 audioBuffer->stopFlushTimer(); |
907 audioBuffer->stopFlushTimer(); |