src/multimedia/audio/qaudio_symbian_p.cpp
changeset 19 fcece45ef507
child 14 c0432d11811c
equal deleted inserted replaced
18:2f34d5167611 19:fcece45ef507
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
       
     4 ** All rights reserved.
       
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
       
     6 **
       
     7 ** This file is part of the QtMultimedia module of the Qt Toolkit.
       
     8 **
       
     9 ** $QT_BEGIN_LICENSE:LGPL$
       
    10 ** No Commercial Usage
       
    11 ** This file contains pre-release code and may not be distributed.
       
    12 ** You may use this file in accordance with the terms and conditions
       
    13 ** contained in the Technology Preview License Agreement accompanying
       
    14 ** this package.
       
    15 **
       
    16 ** GNU Lesser General Public License Usage
       
    17 ** Alternatively, this file may be used under the terms of the GNU Lesser
       
    18 ** General Public License version 2.1 as published by the Free Software
       
    19 ** Foundation and appearing in the file LICENSE.LGPL included in the
       
    20 ** packaging of this file.  Please review the following information to
       
    21 ** ensure the GNU Lesser General Public License version 2.1 requirements
       
    22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
       
    23 **
       
    24 ** In addition, as a special exception, Nokia gives you certain additional
       
    25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
       
    26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
       
    27 **
       
    28 ** If you have questions regarding the use of this file, please contact
       
    29 ** Nokia at qt-info@nokia.com.
       
    30 **
       
    31 **
       
    32 **
       
    33 **
       
    34 **
       
    35 **
       
    36 **
       
    37 **
       
    38 ** $QT_END_LICENSE$
       
    39 **
       
    40 ****************************************************************************/
       
    41 
       
    42 #include "qaudio_symbian_p.h"
       
    43 #include <mmffourcc.h>
       
    44 
       
    45 QT_BEGIN_NAMESPACE
       
    46 
       
    47 namespace SymbianAudio {
       
    48 
       
    49 DevSoundCapabilities::DevSoundCapabilities(CMMFDevSound &devsound,
       
    50                                            QAudio::Mode mode)
       
    51 {
       
    52     QT_TRAP_THROWING(constructL(devsound, mode));
       
    53 }
       
    54 
       
    55 DevSoundCapabilities::~DevSoundCapabilities()
       
    56 {
       
    57     m_fourCC.Close();
       
    58 }
       
    59 
       
    60 void DevSoundCapabilities::constructL(CMMFDevSound &devsound,
       
    61                                       QAudio::Mode mode)
       
    62 {
       
    63     m_caps = devsound.Capabilities();
       
    64 
       
    65     TMMFPrioritySettings settings;
       
    66 
       
    67     switch (mode) {
       
    68     case QAudio::AudioOutput:
       
    69         settings.iState = EMMFStatePlaying;
       
    70         devsound.GetSupportedInputDataTypesL(m_fourCC, settings);
       
    71         break;
       
    72 
       
    73     case QAudio::AudioInput:
       
    74         settings.iState = EMMFStateRecording;
       
    75         devsound.GetSupportedInputDataTypesL(m_fourCC, settings);
       
    76         break;
       
    77 
       
    78     default:
       
    79         Q_ASSERT_X(false, Q_FUNC_INFO, "Invalid mode");
       
    80     }
       
    81 }
       
    82 
       
    83 namespace Utils {
       
    84 
       
    85 //-----------------------------------------------------------------------------
       
    86 // Static data
       
    87 //-----------------------------------------------------------------------------
       
    88 
       
    89 // Sample rate / frequency
       
    90 
       
    91 typedef TMMFSampleRate SampleRateNative;
       
    92 typedef int SampleRateQt;
       
    93 
       
    94 const int SampleRateCount = 12;
       
    95 
       
    96 const SampleRateNative SampleRateListNative[SampleRateCount] = {
       
    97         EMMFSampleRate8000Hz
       
    98     ,   EMMFSampleRate11025Hz
       
    99     ,   EMMFSampleRate12000Hz
       
   100     ,   EMMFSampleRate16000Hz
       
   101     ,   EMMFSampleRate22050Hz
       
   102     ,   EMMFSampleRate24000Hz
       
   103     ,   EMMFSampleRate32000Hz
       
   104     ,   EMMFSampleRate44100Hz
       
   105     ,   EMMFSampleRate48000Hz
       
   106     ,   EMMFSampleRate64000Hz
       
   107     ,   EMMFSampleRate88200Hz
       
   108     ,   EMMFSampleRate96000Hz
       
   109 };
       
   110 
       
   111 const SampleRateQt SampleRateListQt[SampleRateCount] = {
       
   112         8000
       
   113     ,   11025
       
   114     ,   12000
       
   115     ,   16000
       
   116     ,   22050
       
   117     ,   24000
       
   118     ,   32000
       
   119     ,   44100
       
   120     ,   48000
       
   121     ,   64000
       
   122     ,   88200
       
   123     ,   96000
       
   124 };
       
   125 
       
   126 // Channels
       
   127 
       
   128 typedef TMMFMonoStereo ChannelsNative;
       
   129 typedef int ChannelsQt;
       
   130 
       
   131 const int ChannelsCount = 2;
       
   132 
       
   133 const ChannelsNative ChannelsListNative[ChannelsCount] = {
       
   134         EMMFMono
       
   135     ,   EMMFStereo
       
   136 };
       
   137 
       
   138 const ChannelsQt ChannelsListQt[ChannelsCount] = {
       
   139         1
       
   140     ,   2
       
   141 };
       
   142 
       
   143 // Encoding
       
   144 
       
   145 const int EncodingCount = 6;
       
   146 
       
   147 const TUint32 EncodingFourCC[EncodingCount] = {
       
   148         KMMFFourCCCodePCM8              // 0
       
   149     ,   KMMFFourCCCodePCMU8             // 1
       
   150     ,   KMMFFourCCCodePCM16             // 2
       
   151     ,   KMMFFourCCCodePCMU16            // 3
       
   152     ,   KMMFFourCCCodePCM16B            // 4
       
   153     ,   KMMFFourCCCodePCMU16B           // 5
       
   154 };
       
   155 
       
   156 // The characterised DevSound API specification states that the iEncoding
       
   157 // field in TMMFCapabilities is ignored, and that the FourCC should be used
       
   158 // to specify the PCM encoding.
       
   159 // See "SGL.GT0287.102 Multimedia DevSound Baseline Compatibility.doc" in the
       
   160 // mm_info/mm_docs repository.
       
   161 const TMMFSoundEncoding EncodingNative[EncodingCount] = {
       
   162         EMMFSoundEncoding16BitPCM       // 0
       
   163     ,   EMMFSoundEncoding16BitPCM       // 1
       
   164     ,   EMMFSoundEncoding16BitPCM       // 2
       
   165     ,   EMMFSoundEncoding16BitPCM       // 3
       
   166     ,   EMMFSoundEncoding16BitPCM       // 4
       
   167     ,   EMMFSoundEncoding16BitPCM       // 5
       
   168 };
       
   169 
       
   170 
       
   171 const int EncodingSampleSize[EncodingCount] = {
       
   172         8                               // 0
       
   173     ,   8                               // 1
       
   174     ,   16                              // 2
       
   175     ,   16                              // 3
       
   176     ,   16                              // 4
       
   177     ,   16                              // 5
       
   178 };
       
   179 
       
   180 const QAudioFormat::Endian EncodingByteOrder[EncodingCount] = {
       
   181         QAudioFormat::LittleEndian      // 0
       
   182     ,   QAudioFormat::LittleEndian      // 1
       
   183     ,   QAudioFormat::LittleEndian      // 2
       
   184     ,   QAudioFormat::LittleEndian      // 3
       
   185     ,   QAudioFormat::BigEndian         // 4
       
   186     ,   QAudioFormat::BigEndian         // 5
       
   187 };
       
   188 
       
   189 const QAudioFormat::SampleType EncodingSampleType[EncodingCount] = {
       
   190         QAudioFormat::SignedInt         // 0
       
   191     ,   QAudioFormat::UnSignedInt       // 1
       
   192     ,   QAudioFormat::SignedInt         // 2
       
   193     ,   QAudioFormat::UnSignedInt       // 3
       
   194     ,   QAudioFormat::SignedInt         // 4
       
   195     ,   QAudioFormat::UnSignedInt       // 5
       
   196 };
       
   197 
       
   198 
       
   199 //-----------------------------------------------------------------------------
       
   200 // Private functions
       
   201 //-----------------------------------------------------------------------------
       
   202 
       
   203 // Helper functions for implementing parameter conversions
       
   204 
       
   205 template<typename Input>
       
   206 bool findValue(const Input *inputArray, int length, Input input, int &index) {
       
   207     bool result = false;
       
   208     for (int i=0; !result && i<length; ++i)
       
   209         if (inputArray[i] == input) {
       
   210             index = i;
       
   211             result = true;
       
   212         }
       
   213     return result;
       
   214 }
       
   215 
       
   216 template<typename Input, typename Output>
       
   217 bool convertValue(const Input *inputArray, const Output *outputArray,
       
   218     int length, Input input, Output &output) {
       
   219     int index;
       
   220     const bool result = findValue<Input>(inputArray, length, input, index);
       
   221     if (result)
       
   222         output = outputArray[index];
       
   223     return result;
       
   224 }
       
   225 
       
   226 /**
       
   227  * Macro which is used to generate the implementation of the conversion
       
   228  * functions.  The implementation is just a wrapper around the templated
       
   229  * convertValue function, e.g.
       
   230  *
       
   231  * CONVERSION_FUNCTION_IMPL(SampleRate, Qt, Native)
       
   232  *
       
   233  * expands to
       
   234  *
       
   235  * bool SampleRateQtToNative(int input, TMMFSampleRate &output) {
       
   236  *      return convertValue<SampleRateQt, SampleRateNative>
       
   237  *          (SampleRateListQt, SampleRateListNative, SampleRateCount,
       
   238  *          input, output);
       
   239  * }
       
   240  */
       
   241 #define CONVERSION_FUNCTION_IMPL(FieldLc, Field, Input, Output)               \
       
   242 bool FieldLc##Input##To##Output(Field##Input input, Field##Output &output) {  \
       
   243     return convertValue<Field##Input, Field##Output>(Field##List##Input,      \
       
   244         Field##List##Output, Field##Count, input, output);                    \
       
   245 }
       
   246 
       
   247 //-----------------------------------------------------------------------------
       
   248 // Local helper functions
       
   249 //-----------------------------------------------------------------------------
       
   250 
       
   251 CONVERSION_FUNCTION_IMPL(sampleRate, SampleRate, Qt, Native)
       
   252 CONVERSION_FUNCTION_IMPL(sampleRate, SampleRate, Native, Qt)
       
   253 CONVERSION_FUNCTION_IMPL(channels, Channels, Qt, Native)
       
   254 CONVERSION_FUNCTION_IMPL(channels, Channels, Native, Qt)
       
   255 
       
   256 bool sampleInfoQtToNative(int inputSampleSize,
       
   257                           QAudioFormat::Endian inputByteOrder,
       
   258                           QAudioFormat::SampleType inputSampleType,
       
   259                           TUint32 &outputFourCC,
       
   260                           TMMFSoundEncoding &outputEncoding) {
       
   261 
       
   262     bool found = false;
       
   263 
       
   264     for (int i=0; i<EncodingCount && !found; ++i) {
       
   265         if (    EncodingSampleSize[i] == inputSampleSize
       
   266             &&  EncodingByteOrder[i] == inputByteOrder
       
   267             &&  EncodingSampleType[i] == inputSampleType) {
       
   268             outputFourCC = EncodingFourCC[i];
       
   269             outputEncoding = EncodingNative[i]; // EMMFSoundEncoding16BitPCM
       
   270             found = true;
       
   271         }
       
   272     }
       
   273 
       
   274     return found;
       
   275 }
       
   276 
       
   277 //-----------------------------------------------------------------------------
       
   278 // Public functions
       
   279 //-----------------------------------------------------------------------------
       
   280 
       
   281 void capabilitiesNativeToQt(const DevSoundCapabilities &caps,
       
   282                             QList<int> &frequencies,
       
   283                             QList<int> &channels,
       
   284                             QList<int> &sampleSizes,
       
   285                             QList<QAudioFormat::Endian> &byteOrders,
       
   286                             QList<QAudioFormat::SampleType> &sampleTypes) {
       
   287 
       
   288     frequencies.clear();
       
   289     sampleSizes.clear();
       
   290     byteOrders.clear();
       
   291     sampleTypes.clear();
       
   292     channels.clear();
       
   293 
       
   294     for (int i=0; i<SampleRateCount; ++i)
       
   295         if (caps.caps().iRate & SampleRateListNative[i])
       
   296             frequencies += SampleRateListQt[i];
       
   297 
       
   298     for (int i=0; i<ChannelsCount; ++i)
       
   299         if (caps.caps().iChannels & ChannelsListNative[i])
       
   300             channels += ChannelsListQt[i];
       
   301 
       
   302     for (int i=0; i<EncodingCount; ++i) {
       
   303         if (caps.fourCC().Find(EncodingFourCC[i]) != KErrNotFound) {
       
   304             sampleSizes += EncodingSampleSize[i];
       
   305             byteOrders += EncodingByteOrder[i];
       
   306             sampleTypes += EncodingSampleType[i];
       
   307         }
       
   308     }
       
   309 
       
   310 }
       
   311 
       
   312 bool isFormatSupported(const QAudioFormat &formatQt,
       
   313                        const DevSoundCapabilities &caps) {
       
   314     TMMFCapabilities formatNative;
       
   315     TUint32 fourCC;
       
   316 
       
   317     bool result = false;
       
   318     if (formatQt.codec() == "audio/pcm" &&
       
   319         formatQtToNative(formatQt, fourCC, formatNative)) {
       
   320         result =
       
   321                 (formatNative.iRate & caps.caps().iRate)
       
   322             &&  (formatNative.iChannels & caps.caps().iChannels)
       
   323             &&  (caps.fourCC().Find(fourCC) != KErrNotFound);
       
   324     }
       
   325     return result;
       
   326 }
       
   327 
       
   328 bool formatQtToNative(const QAudioFormat &inputFormat,
       
   329                       TUint32 &outputFourCC,
       
   330                       TMMFCapabilities &outputFormat) {
       
   331 
       
   332     bool result = false;
       
   333 
       
   334     // Need to use temporary variables because TMMFCapabilities fields are all
       
   335     // TInt, rather than MMF enumerated types.
       
   336     TMMFSampleRate outputSampleRate;
       
   337     TMMFMonoStereo outputChannels;
       
   338     TMMFSoundEncoding outputEncoding;
       
   339 
       
   340     if (inputFormat.codec() == "audio/pcm") {
       
   341         result =
       
   342                 sampleRateQtToNative(inputFormat.frequency(), outputSampleRate)
       
   343             &&  channelsQtToNative(inputFormat.channels(), outputChannels)
       
   344             &&  sampleInfoQtToNative(inputFormat.sampleSize(),
       
   345                                      inputFormat.byteOrder(),
       
   346                                      inputFormat.sampleType(),
       
   347                                      outputFourCC,
       
   348                                      outputEncoding);
       
   349     }
       
   350 
       
   351     if (result) {
       
   352         outputFormat.iRate = outputSampleRate;
       
   353         outputFormat.iChannels = outputChannels;
       
   354         outputFormat.iEncoding = outputEncoding;
       
   355     }
       
   356 
       
   357     return result;
       
   358 }
       
   359 
       
   360 QAudio::State stateNativeToQt(State nativeState,
       
   361                               QAudio::State initializingState)
       
   362 {
       
   363     switch (nativeState) {
       
   364     case ClosedState:
       
   365         return QAudio::StoppedState;
       
   366     case InitializingState:
       
   367         return initializingState;
       
   368     case ActiveState:
       
   369         return QAudio::ActiveState;
       
   370     case IdleState:
       
   371         return QAudio::IdleState;
       
   372     case SuspendedState:
       
   373         return QAudio::SuspendedState;
       
   374     default:
       
   375         Q_ASSERT_X(false, Q_FUNC_INFO, "Invalid state");
       
   376         return QAudio::StoppedState; // suppress compiler warning
       
   377     }
       
   378 }
       
   379 
       
   380 qint64 bytesToSamples(const QAudioFormat &format, qint64 length)
       
   381 {
       
   382     return length / ((format.sampleSize() / 8) * format.channels());
       
   383 }
       
   384 
       
   385 qint64 samplesToBytes(const QAudioFormat &format, qint64 samples)
       
   386 {
       
   387     return samples * (format.sampleSize() / 8) * format.channels();
       
   388 }
       
   389 
       
   390 } // namespace Utils
       
   391 } // namespace SymbianAudio
       
   392 
       
   393 QT_END_NAMESPACE
       
   394 
       
   395