src/multimedia/audio/qaudioinput_mac_p.cpp
changeset 19 fcece45ef507
parent 18 2f34d5167611
child 33 3e2da88830cd
equal deleted inserted replaced
18:2f34d5167611 19:fcece45ef507
    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
   167         return sf.mBytesPerPacket;
   166         return sf.mBytesPerPacket;
   168     }
   167     }
   169 
   168 
   170     void reset()
   169     void reset()
   171     {
   170     {
   172         for (UInt32 i = 0; i < bfs->mNumberBuffers; ++i)
   171         for (UInt32 i = 0; i < bfs->mNumberBuffers; ++i) {
   173             bfs->mBuffers[i].mDataByteSize = dataSize;
   172             bfs->mBuffers[i].mDataByteSize = dataSize;
       
   173             bfs->mBuffers[i].mData = 0;
       
   174         }
   174     }
   175     }
   175 
   176 
   176 private:
   177 private:
   177     bool    owner;
   178     bool    owner;
   178     int     dataSize;
   179     int     dataSize;
   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);
   535 }
   538 }
   536 
   539 
   537 QAudioInputPrivate::~QAudioInputPrivate()
   540 QAudioInputPrivate::~QAudioInputPrivate()
   538 {
   541 {
   539     close();
   542     close();
       
   543     delete audioDeviceInfo;
   540 }
   544 }
   541 
   545 
   542 bool QAudioInputPrivate::open()
   546 bool QAudioInputPrivate::open()
   543 {
   547 {
   544     UInt32  size = 0;
   548     UInt32  size = 0;
   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;
   705 
   714 
   706 QIODevice* QAudioInputPrivate::start(QIODevice* device)
   715 QIODevice* QAudioInputPrivate::start(QIODevice* device)
   707 {
   716 {
   708     QIODevice*  op = device;
   717     QIODevice*  op = device;
   709 
   718 
   710     if (!open()) {
   719     if (!audioFormat.isValid() || !open()) {
   711         stateCode = QAudio::StoppedState;
   720         stateCode = QAudio::StoppedState;
   712         errorCode = QAudio::OpenError;
   721         errorCode = QAudio::OpenError;
   713         return audioIO;
   722         return audioIO;
   714     }
   723     }
   715 
   724 
   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();