/**************************************************************************** ** ** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the Qt Mobility Components. ** ** $QT_BEGIN_LICENSE:LGPL$ ** GNU Lesser General Public License Usage ** This file may be used under the terms of the GNU Lesser General Public ** License version 2.1 as published by the Free Software Foundation and ** appearing in the file LICENSE.LGPL included in the packaging of this ** file. Please review the following information to ensure the GNU Lesser ** General Public License version 2.1 requirements will be met: ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, Nokia gives you certain additional ** rights. These rights are described in the Nokia Qt LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU General ** Public License version 3.0 as published by the Free Software Foundation ** and appearing in the file LICENSE.GPL included in the packaging of this ** file. Please review the following information to ensure the GNU General ** Public License version 3.0 requirements will be met: ** http://www.gnu.org/copyleft/gpl.html. ** ** Other Usage ** Alternatively, this file may be used in accordance with the terms and ** conditions contained in a signed written agreement between you and Nokia. ** ** ** ** ** ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "qaudio_symbian_p.h" #include QT_BEGIN_NAMESPACE namespace SymbianAudio { namespace Utils { //----------------------------------------------------------------------------- // Static data //----------------------------------------------------------------------------- // Sample rate / frequency typedef TMMFSampleRate SampleRateNative; typedef int SampleRateQt; const int SampleRateCount = 12; const SampleRateNative SampleRateListNative[SampleRateCount] = { EMMFSampleRate8000Hz , EMMFSampleRate11025Hz , EMMFSampleRate12000Hz , EMMFSampleRate16000Hz , EMMFSampleRate22050Hz , EMMFSampleRate24000Hz , EMMFSampleRate32000Hz , EMMFSampleRate44100Hz , EMMFSampleRate48000Hz , EMMFSampleRate64000Hz , EMMFSampleRate88200Hz , EMMFSampleRate96000Hz }; const SampleRateQt SampleRateListQt[SampleRateCount] = { 8000 , 11025 , 12000 , 16000 , 22050 , 24000 , 32000 , 44100 , 48000 , 64000 , 88200 , 96000 }; // Channels typedef TMMFMonoStereo ChannelsNative; typedef int ChannelsQt; const int ChannelsCount = 2; const ChannelsNative ChannelsListNative[ChannelsCount] = { EMMFMono , EMMFStereo }; const ChannelsQt ChannelsListQt[ChannelsCount] = { 1 , 2 }; // Encoding const int EncodingCount = 6; const TUint32 EncodingFourCC[EncodingCount] = { KMMFFourCCCodePCM8 // 0 , KMMFFourCCCodePCMU8 // 1 , KMMFFourCCCodePCM16 // 2 , KMMFFourCCCodePCMU16 // 3 , KMMFFourCCCodePCM16B // 4 , KMMFFourCCCodePCMU16B // 5 }; // The characterised DevSound API specification states that the iEncoding // field in TMMFCapabilities is ignored, and that the FourCC should be used // to specify the PCM encoding. // See "SGL.GT0287.102 Multimedia DevSound Baseline Compatibility.doc" in the // mm_info/mm_docs repository. const TMMFSoundEncoding EncodingNative[EncodingCount] = { EMMFSoundEncoding16BitPCM // 0 , EMMFSoundEncoding16BitPCM // 1 , EMMFSoundEncoding16BitPCM // 2 , EMMFSoundEncoding16BitPCM // 3 , EMMFSoundEncoding16BitPCM // 4 , EMMFSoundEncoding16BitPCM // 5 }; const int EncodingSampleSize[EncodingCount] = { 8 // 0 , 8 // 1 , 16 // 2 , 16 // 3 , 16 // 4 , 16 // 5 }; const QAudioFormat::Endian EncodingByteOrder[EncodingCount] = { QAudioFormat::LittleEndian // 0 , QAudioFormat::LittleEndian // 1 , QAudioFormat::LittleEndian // 2 , QAudioFormat::LittleEndian // 3 , QAudioFormat::BigEndian // 4 , QAudioFormat::BigEndian // 5 }; const QAudioFormat::SampleType EncodingSampleType[EncodingCount] = { QAudioFormat::SignedInt // 0 , QAudioFormat::UnSignedInt // 1 , QAudioFormat::SignedInt // 2 , QAudioFormat::UnSignedInt // 3 , QAudioFormat::SignedInt // 4 , QAudioFormat::UnSignedInt // 5 }; //----------------------------------------------------------------------------- // Private functions //----------------------------------------------------------------------------- // Helper functions for implementing parameter conversions template bool findValue(const Input *inputArray, int length, Input input, int &index) { bool result = false; for (int i=0; !result && i bool convertValue(const Input *inputArray, const Output *outputArray, int length, Input input, Output &output) { int index = -1; const bool result = findValue(inputArray, length, input, index); if (result) output = outputArray[index]; return result; } /** * Macro which is used to generate the implementation of the conversion * functions. The implementation is just a wrapper around the templated * convertValue function, e.g. * * CONVERSION_FUNCTION_IMPL(SampleRate, Qt, Native) * * expands to * * bool SampleRateQtToNative(int input, TMMFSampleRate &output) { * return convertValue * (SampleRateListQt, SampleRateListNative, SampleRateCount, * input, output); * } */ #define CONVERSION_FUNCTION_IMPL(FieldLc, Field, Input, Output) \ bool FieldLc##Input##To##Output(Field##Input input, Field##Output &output) { \ return convertValue(Field##List##Input, \ Field##List##Output, Field##Count, input, output); \ } //----------------------------------------------------------------------------- // Local helper functions //----------------------------------------------------------------------------- CONVERSION_FUNCTION_IMPL(sampleRate, SampleRate, Qt, Native) CONVERSION_FUNCTION_IMPL(sampleRate, SampleRate, Native, Qt) CONVERSION_FUNCTION_IMPL(channels, Channels, Qt, Native) CONVERSION_FUNCTION_IMPL(channels, Channels, Native, Qt) bool sampleInfoQtToNative(int inputSampleSize, QAudioFormat::Endian inputByteOrder, QAudioFormat::SampleType inputSampleType, TUint32 &outputFourCC, TMMFSoundEncoding &outputEncoding) { bool found = false; for (int i=0; i &frequencies, QList &channels, QList &sampleSizes, QList &byteOrders, QList &sampleTypes) { frequencies.clear(); sampleSizes.clear(); byteOrders.clear(); sampleTypes.clear(); channels.clear(); for (int i=0; i& DevSoundWrapper::supportedCodecs() const { return m_supportedCodecs; } void DevSoundWrapper::initialize(const QString& codec) { Q_ASSERT(StateInitializing != m_state); m_state = StateInitializing; if (QLatin1String("audio/pcm") == codec) { m_fourcc = KMMFFourCCCodePCM16; TRAPD(err, m_devsound->InitializeL(*this, m_fourcc, m_nativeMode)); if (KErrNone != err) { m_state = StateIdle; emit initializeComplete(err); } } else { emit initializeComplete(KErrNotSupported); } } const QList& DevSoundWrapper::supportedFrequencies() const { Q_ASSERT(StateInitialized == m_state); return m_supportedFrequencies; } const QList& DevSoundWrapper::supportedChannels() const { Q_ASSERT(StateInitialized == m_state); return m_supportedChannels; } const QList& DevSoundWrapper::supportedSampleSizes() const { Q_ASSERT(StateInitialized == m_state); return m_supportedSampleSizes; } const QList& DevSoundWrapper::supportedByteOrders() const { Q_ASSERT(StateInitialized == m_state); return m_supportedByteOrders; } const QList& DevSoundWrapper::supportedSampleTypes() const { Q_ASSERT(StateInitialized == m_state); return m_supportedSampleTypes; } bool DevSoundWrapper::isFormatSupported(const QAudioFormat &format) const { Q_ASSERT(StateInitialized == m_state); return m_supportedCodecs.contains(format.codec()) && m_supportedFrequencies.contains(format.frequency()) && m_supportedChannels.contains(format.channels()) && m_supportedSampleSizes.contains(format.sampleSize()) && m_supportedSampleTypes.contains(format.sampleType()) && m_supportedByteOrders.contains(format.byteOrder()); } int DevSoundWrapper::samplesProcessed() const { int result = 0; if (StateInitialized == m_state) { switch (m_mode) { case QAudio::AudioInput: result = m_devsound->SamplesRecorded(); break; case QAudio::AudioOutput: result = m_devsound->SamplesPlayed(); break; } } return result; } bool DevSoundWrapper::setFormat(const QAudioFormat &format) { Q_ASSERT(StateInitialized == m_state); bool result = false; TUint32 fourcc; TMMFCapabilities nativeFormat; if (Utils::formatQtToNative(format, fourcc, nativeFormat)) { TMMFCapabilities currentNativeFormat = m_devsound->Config(); nativeFormat.iBufferSize = currentNativeFormat.iBufferSize; TRAPD(err, m_devsound->SetConfigL(nativeFormat)); result = (KErrNone == err); } return result; } bool DevSoundWrapper::start() { Q_ASSERT(StateInitialized == m_state); int err = KErrArgument; switch (m_mode) { case QAudio::AudioInput: TRAP(err, m_devsound->RecordInitL()); break; case QAudio::AudioOutput: TRAP(err, m_devsound->PlayInitL()); break; } return (KErrNone == err); } bool DevSoundWrapper::pause() { Q_ASSERT(StateInitialized == m_state); #ifndef PRE_S60_52_PLATFORM if (m_mode == QAudio::AudioOutput ) { m_devsound->Pause(); return true; } else { const bool canPause = isResumeSupported(); if (canPause) m_devsound->Pause(); else stop(); return canPause; } #else const bool canPause = isResumeSupported(); if (canPause) m_devsound->Pause(); else stop(); return canPause; #endif } void DevSoundWrapper::resume() { Q_ASSERT(StateInitialized == m_state); Q_ASSERT(isResumeSupported()); // TODO: QTBUG-13625 } void DevSoundWrapper::stop() { m_devsound->Stop(); } void DevSoundWrapper::bufferProcessed() { Q_ASSERT(StateInitialized == m_state); switch (m_mode) { case QAudio::AudioInput: m_devsound->RecordData(); break; case QAudio::AudioOutput: m_devsound->PlayData(); break; } } void DevSoundWrapper::getSupportedCodecs() { /* * TODO: once we support formats other than PCM, this function should * convert the array of FourCC codes into MIME types for each codec. * RArray fourcc; QT_TRAP_THROWING(CleanupClosePushL(&fourcc)); TMMFPrioritySettings settings; switch (mode) { case QAudio::AudioOutput: settings.iState = EMMFStatePlaying; m_devsound->GetSupportedInputDataTypesL(fourcc, settings); break; case QAudio::AudioInput: settings.iState = EMMFStateRecording; m_devsound->GetSupportedInputDataTypesL(fourcc, settings); break; default: Q_ASSERT_X(false, Q_FUNC_INFO, "Invalid mode"); } CleanupStack::PopAndDestroy(); // fourcc */ m_supportedCodecs.append(QLatin1String("audio/pcm")); } void DevSoundWrapper::populateCapabilities() { m_supportedFrequencies.clear(); m_supportedChannels.clear(); m_supportedSampleSizes.clear(); m_supportedByteOrders.clear(); m_supportedSampleTypes.clear(); const TMMFCapabilities caps = m_devsound->Capabilities(); for (int i=0; iEmptyBuffers(); } #endif int DevSoundWrapper::volume() const { return m_volume; } void DevSoundWrapper::setVolume(int value) { value = qMax(0, value); value = qMin(100, value); if (value != m_volume) { m_volume = value; if (StateInitialized == m_state) applyVolume(); } } void DevSoundWrapper::applyVolume() { Q_ASSERT(StateInitialized == m_state); Q_ASSERT(m_volume >= 0); Q_ASSERT(m_volume <= 100); switch (m_mode) { case QAudio::AudioOutput: m_devsound->SetVolume(m_volume * m_devsound->MaxVolume() / 100); break; case QAudio::AudioInput: m_devsound->SetGain(m_volume * m_devsound->MaxGain() / 100); break; } } } // namespace SymbianAudio QT_END_NAMESPACE