diff --git a/android/AndroidManifest.xml b/android/AndroidManifest.xml index 74a43c5c..051ea8e9 100644 --- a/android/AndroidManifest.xml +++ b/android/AndroidManifest.xml @@ -1,38 +1,38 @@ - - - + + + - - - - - + + + + + - - - + + + - - - - - + + + + + - - - + + + - + - - + + diff --git a/android/sound.cpp b/android/sound.cpp index 032d1d3a..15f9729a 100644 --- a/android/sound.cpp +++ b/android/sound.cpp @@ -29,12 +29,15 @@ CSound::CSound ( void (*fpNewProcessCallback) ( CVector& psData, void* arg ), void* arg ) : CSoundBase ( "OpenSL", true, fpNewProcessCallback, arg ) { - SLObjectItf engineObject; - SLEngineItf engine; - SLObjectItf outputMixObject; - SLObjectItf playerObject; - SLPlayItf player; - SLAndroidSimpleBufferQueueItf playerSimpleBufQueue; + // set up stream format + SLDataFormat_PCM streamFormat; + streamFormat.formatType = SL_DATAFORMAT_PCM; + streamFormat.numChannels = 2; + streamFormat.samplesPerSec = SYSTEM_SAMPLE_RATE_HZ * 1000; // unit is mHz + streamFormat.bitsPerSample = SL_PCMSAMPLEFORMAT_FIXED_16; + streamFormat.containerSize = 16; + streamFormat.channelMask = SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT; + streamFormat.endianness = SL_BYTEORDER_LITTLEENDIAN; // create the OpenSL root engine object slCreateEngine ( &engineObject, @@ -54,36 +57,24 @@ CSound::CSound ( void (*fpNewProcessCallback) ( CVector& psData, void* ar &engine ); // create the main output mix - const SLInterfaceID engineIds[] = { SL_IID_VOLUME }; - const SLboolean engineReq[] = { SL_BOOLEAN_FALSE }; - (*engine)->CreateOutputMix ( engine, &outputMixObject, - 1, - engineIds, - engineReq ); + 0, + nullptr, + nullptr ); + (*outputMixObject)->Realize ( outputMixObject, SL_BOOLEAN_FALSE ); - // configure the buffer queue. - SLDataLocator_AndroidSimpleBufferQueue bufferQueue; - bufferQueue.locatorType = SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE; - bufferQueue.numBuffers = 1; - - // set up stream format - SLDataFormat_PCM streamFormat; - streamFormat.formatType = SL_DATAFORMAT_PCM; - streamFormat.numChannels = 1; - streamFormat.samplesPerSec = SYSTEM_SAMPLE_RATE_HZ * 1000; // unit is mHz - streamFormat.bitsPerSample = SL_PCMSAMPLEFORMAT_FIXED_16; - streamFormat.containerSize = 16; - streamFormat.channelMask = SL_SPEAKER_FRONT_CENTER; - streamFormat.endianness = SL_BYTEORDER_LITTLEENDIAN; + // configure the output buffer queue. + SLDataLocator_AndroidSimpleBufferQueue outBufferQueue; + outBufferQueue.locatorType = SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE; + outBufferQueue.numBuffers = 1; // max number of buffers in queue // configure the audio (data) source SLDataSource dataSource; - dataSource.pLocator = &bufferQueue; + dataSource.pLocator = &outBufferQueue; dataSource.pFormat = &streamFormat; // configure the output mix @@ -122,363 +113,24 @@ CSound::CSound ( void (*fpNewProcessCallback) ( CVector& psData, void* ar SL_IID_ANDROIDSIMPLEBUFFERQUEUE, &playerSimpleBufQueue ); - - - -/* - - // set up a callback struct for new input data - inputCallbackStruct.inputProc = processInput; - inputCallbackStruct.inputProcRefCon = this; - - // set up a callback struct for new output data - outputCallbackStruct.inputProc = processOutput; - outputCallbackStruct.inputProcRefCon = this; - - // allocate memory for buffer struct - pBufferList = (AudioBufferList*) malloc ( offsetof ( AudioBufferList, - mBuffers[0] ) + sizeof ( AudioBuffer ) ); - - // open the default unit - ComponentDescription desc; - desc.componentType = kAudioUnitType_Output; - desc.componentSubType = kAudioUnitSubType_HALOutput; - desc.componentManufacturer = kAudioUnitManufacturer_Apple; - desc.componentFlags = 0; - desc.componentFlagsMask = 0; - - Component comp = FindNextComponent ( NULL, &desc ); - if ( comp == NULL ) - { - throw CGenErr ( tr ( "No CoreAudio next component found" ) ); - } - - if ( OpenAComponent ( comp, &audioInputUnit ) ) - { - throw CGenErr ( tr ( "CoreAudio creating input component instance failed" ) ); - } - - if ( OpenAComponent ( comp, &audioOutputUnit ) ) - { - throw CGenErr ( tr ( "CoreAudio creating output component instance failed" ) ); - } - - // we enable input and disable output for input component - UInt32 enableIO = 1; - AudioUnitSetProperty ( audioInputUnit, - kAudioOutputUnitProperty_EnableIO, - kAudioUnitScope_Input, - 1, // input element - &enableIO, - sizeof ( enableIO ) ); - - enableIO = 0; - AudioUnitSetProperty ( audioInputUnit, - kAudioOutputUnitProperty_EnableIO, - kAudioUnitScope_Output, - 0, // output element - &enableIO, - sizeof ( enableIO ) ); - - // set up a callback function for new input data - if ( AudioUnitSetProperty ( audioInputUnit, - kAudioOutputUnitProperty_SetInputCallback, - kAudioUnitScope_Global, - 0, - &inputCallbackStruct, - sizeof ( inputCallbackStruct ) ) ) - { - throw CGenErr ( tr ( "CoreAudio audio unit set property failed" ) ); - } - - // set input stream format - if ( AudioUnitSetProperty ( audioInputUnit, - kAudioUnitProperty_StreamFormat, - kAudioUnitScope_Output, - 1, - &streamFormat, - sizeof ( streamFormat ) ) ) - { - throw CGenErr ( tr ( "CoreAudio stream format set property failed" ) ); - } - - - // set up a callback function for new output data - if ( AudioUnitSetProperty ( audioOutputUnit, - kAudioUnitProperty_SetRenderCallback, - kAudioUnitScope_Global, - 0, - &outputCallbackStruct, - sizeof ( outputCallbackStruct ) ) ) - { - throw CGenErr ( tr ( "CoreAudio audio unit set property failed" ) ); - } - - // ste output stream format - if ( AudioUnitSetProperty ( audioOutputUnit, - kAudioUnitProperty_StreamFormat, - kAudioUnitScope_Input, - 0, - &streamFormat, - sizeof ( streamFormat ) ) ) - { - throw CGenErr ( tr ( "CoreAudio stream format set property failed" ) ); - } - - - // Get available input/output devices -------------------------------------- - UInt32 iPropertySize; - - // first get property size of devices array and allocate memory - AudioHardwareGetPropertyInfo ( kAudioHardwarePropertyDevices, - &iPropertySize, - NULL ); - - AudioDeviceID* audioDevices = (AudioDeviceID*) malloc ( iPropertySize ); - - // now actually query all devices present in the system - AudioHardwareGetProperty ( kAudioHardwarePropertyDevices, - &iPropertySize, - audioDevices ); - - // calculate device count based on size of returned data array - const UInt32 deviceCount = ( iPropertySize / sizeof ( AudioDeviceID ) ); - - // always add system default devices for input and output as first entry - lNumDevs = 0; - strDriverNames[lNumDevs] = "System Default In/Out Devices"; - - iPropertySize = sizeof ( AudioDeviceID ); - if ( AudioHardwareGetProperty ( kAudioHardwarePropertyDefaultInputDevice, - &iPropertySize, - &audioInputDevice[lNumDevs] ) ) - { - throw CGenErr ( tr ( "CoreAudio input AudioHardwareGetProperty call failed. " - "It seems that no sound card is available in the system." ) ); - } - - iPropertySize = sizeof ( AudioDeviceID ); - if ( AudioHardwareGetProperty ( kAudioHardwarePropertyDefaultOutputDevice, - &iPropertySize, - &audioOutputDevice[lNumDevs] ) ) - { - throw CGenErr ( tr ( "CoreAudio output AudioHardwareGetProperty call failed. " - "It seems that no sound card is available in the system." ) ); - } - - lNumDevs++; // next device - - // add detected devices (also check for maximum allowed sound cards!) - // - // we add combined entries for input and output for each device so that we - // do not need two combo boxes in the GUI for input and output (therefore - // all possible combinations are required) - for ( UInt32 i = 0; ( i < deviceCount ) && ( i < MAX_NUMBER_SOUND_CARDS - 1 ); i++ ) - { - for ( UInt32 j = 0; ( j < deviceCount ) && ( j < MAX_NUMBER_SOUND_CARDS - 1 ); j++ ) - { - // get device infos for both current devices - QString strDeviceName_i; - QString strDeviceName_j; - bool bIsInput_i; - bool bIsInput_j; - bool bIsOutput_i; - bool bIsOutput_j; - - GetAudioDeviceInfos ( audioDevices[i], - strDeviceName_i, - bIsInput_i, - bIsOutput_i ); - - GetAudioDeviceInfos ( audioDevices[j], - strDeviceName_j, - bIsInput_j, - bIsOutput_j ); - - // check if i device is input and j device is output - if ( bIsInput_i && bIsOutput_j ) - { - strDriverNames[lNumDevs] = "in: " + - strDeviceName_i + "/out: " + - strDeviceName_j; - - // store audio device IDs - audioInputDevice[lNumDevs] = audioDevices[i]; - audioOutputDevice[lNumDevs] = audioDevices[j]; - - lNumDevs++; // next device - } - } - } - - // init device index as not initialized (invalid) - lCurDev = INVALID_SNC_CARD_DEVICE; -*/ + // register the audio output callback + (*playerSimpleBufQueue)->RegisterCallback ( playerSimpleBufQueue, + processOutput, + this ); } -/* -void CSound::GetAudioDeviceInfos ( const AudioDeviceID DeviceID, - QString& strDeviceName, - bool& bIsInput, - bool& bIsOutput ) -{ - // get property name - UInt32 iPropertySize = sizeof ( CFStringRef ); - CFStringRef sPropertyStringValue; - - AudioDeviceGetProperty ( DeviceID, - 0, - false, - kAudioObjectPropertyName, - &iPropertySize, - &sPropertyStringValue ); - - // convert CFString in c-string (quick hack!) and then in QString - char* sC_strPropValue = - (char*) malloc ( CFStringGetLength ( sPropertyStringValue ) + 1 ); - - CFStringGetCString ( sPropertyStringValue, - sC_strPropValue, - CFStringGetLength ( sPropertyStringValue ) + 1, - kCFStringEncodingISOLatin1 ); - - strDeviceName = sC_strPropValue; - - // check if device is input or output or both (is that possible?) - // we do this by trying to set the current device for the audio unit - // with the parameter input and output and then we simply check the - // error/ok result - bIsInput = !AudioUnitSetProperty ( audioInputUnit, - kAudioOutputUnitProperty_CurrentDevice, - kAudioUnitScope_Global, - 1, - &DeviceID, - sizeof ( AudioDeviceID ) ); - - bIsOutput = !AudioUnitSetProperty ( audioOutputUnit, - kAudioOutputUnitProperty_CurrentDevice, - kAudioUnitScope_Global, - 0, - &DeviceID, - sizeof ( AudioDeviceID ) ); -} -*/ - -/* -QString CSound::LoadAndInitializeDriver ( int iDriverIdx ) -{ - // set input device - if ( AudioUnitSetProperty ( audioInputUnit, - kAudioOutputUnitProperty_CurrentDevice, - kAudioUnitScope_Global, - 1, - &audioInputDevice[iDriverIdx], - sizeof ( AudioDeviceID ) ) ) - { - throw CGenErr ( tr ( "CoreAudio input AudioUnitSetProperty call failed" ) ); - } - - // set output device - if ( AudioUnitSetProperty ( audioOutputUnit, - kAudioOutputUnitProperty_CurrentDevice, - kAudioUnitScope_Global, - 0, - &audioOutputDevice[iDriverIdx], - sizeof ( AudioDeviceID ) ) ) - { - throw CGenErr ( tr ( "CoreAudio output AudioUnitSetProperty call failed" ) ); - } - - // check device capabilities if it fullfills our requirements - const QString strStat = - CheckDeviceCapabilities ( audioInputUnit, audioOutputUnit ); - - // check if device is capable - if ( strStat.isEmpty() ) - { - // store ID of selected driver if initialization was successful - lCurDev = iDriverIdx; - - // setup callback for xruns (only for input is enough) - AudioDeviceAddPropertyListener ( audioInputDevice[lCurDev], - 0, - true, - kAudioDeviceProcessorOverload, - deviceNotification, - this ); - } - - return strStat; -} -*/ - -/* -QString CSound::CheckDeviceCapabilities ( ComponentInstance& NewAudioInputUnit, - ComponentInstance& NewAudioOutputUnit ) -{ - UInt32 size; - - // check input device sample rate - size = sizeof ( Float64 ); - Float64 inputSampleRate; - AudioUnitGetProperty ( NewAudioInputUnit, - kAudioUnitProperty_SampleRate, - kAudioUnitScope_Input, - 1, - &inputSampleRate, - &size ); - - if ( static_cast ( inputSampleRate ) != SYSTEM_SAMPLE_RATE_HZ ) - { - return QString ( tr ( "Current system audio input device sample " - "rate of %1 Hz is not supported. Please open the Audio-MIDI-Setup in " - "Applications->Utilities and try to set a sample rate of %2 Hz." ) ).arg ( - static_cast ( inputSampleRate ) ).arg ( SYSTEM_SAMPLE_RATE_HZ ); - } - - // check output device sample rate - size = sizeof ( Float64 ); - Float64 outputSampleRate; - AudioUnitGetProperty ( NewAudioOutputUnit, - kAudioUnitProperty_SampleRate, - kAudioUnitScope_Output, - 0, - &outputSampleRate, - &size ); - - if ( static_cast ( outputSampleRate ) != SYSTEM_SAMPLE_RATE_HZ ) - { - return QString ( tr ( "Current system audio output device sample " - "rate of %1 Hz is not supported. Please open the Audio-MIDI-Setup in " - "Applications->Utilities and try to set a sample rate of %2 Hz." ) ).arg ( - static_cast ( outputSampleRate ) ).arg ( SYSTEM_SAMPLE_RATE_HZ ); - } - - // everything is ok, return empty string for "no error" case - return ""; -} -*/ - void CSound::CloseOpenSL() { - -/* // clean up - AudioUnitUninitialize ( audioInputUnit ); - AudioUnitUninitialize ( audioOutputUnit ); - CloseComponent ( audioInputUnit ); - CloseComponent ( audioOutputUnit ); -*/ + (*playerObject)->Destroy ( playerObject ); + (*outputMixObject)->Destroy ( outputMixObject ); + (*engineObject)->Destroy ( engineObject ); } void CSound::Start() { - -/* // start the rendering - AudioOutputUnitStart ( audioInputUnit ); - AudioOutputUnitStart ( audioOutputUnit ); -*/ + (*player)->SetPlayState ( player, SL_PLAYSTATE_PLAYING ); // call base class CSoundBase::Start(); @@ -486,12 +138,11 @@ void CSound::Start() void CSound::Stop() { - -/* // stop the audio stream - AudioOutputUnitStop ( audioInputUnit ); - AudioOutputUnitStop ( audioOutputUnit ); -*/ + (*player)->SetPlayState ( player, SL_PLAYSTATE_STOPPED ); + + // clear the buffers + (*playerSimpleBufQueue)->Clear ( playerSimpleBufQueue ); // call base class CSoundBase::Stop(); @@ -499,7 +150,6 @@ void CSound::Stop() int CSound::Init ( const int iNewPrefMonoBufferSize ) { - /* UInt32 iActualMonoBufferSize; @@ -532,19 +182,27 @@ int CSound::Init ( const int iNewPrefMonoBufferSize ) throw CGenErr ( strErrBufSize ); } } +*/ + +/* +// TEST +int iActualMonoBufferSize = iNewPrefMonoBufferSize; + // store buffer size - iCoreAudioBufferSizeMono = iActualMonoBufferSize; + iOpenSLBufferSizeMono = iActualMonoBufferSize; // init base class - CSoundBase::Init ( iCoreAudioBufferSizeMono ); + CSoundBase::Init ( iOpenSLBufferSizeMono ); // set internal buffer size value and calculate stereo buffer size - iCoreAudioBufferSizeStero = 2 * iCoreAudioBufferSizeMono; + iOpenSLBufferSizeStero = 2 * iOpenSLBufferSizeMono; // create memory for intermediate audio buffer - vecsTmpAudioSndCrdStereo.Init ( iCoreAudioBufferSizeStero ); + vecsTmpAudioSndCrdStereo.Init ( iOpenSLBufferSizeStero ); +*/ +/* // fill audio unit buffer struct pBufferList->mNumberBuffers = 1; pBufferList->mBuffers[0].mNumberChannels = 2; // stereo @@ -567,53 +225,6 @@ int CSound::Init ( const int iNewPrefMonoBufferSize ) } /* -UInt32 CSound::SetBufferSize ( AudioDeviceID& audioDeviceID, - const bool bIsInput, - UInt32 iPrefBufferSize ) -{ - // first set the value - UInt32 iSizeBufValue = sizeof ( UInt32 ); - AudioDeviceSetProperty ( audioDeviceID, - NULL, - 0, - bIsInput, - kAudioDevicePropertyBufferFrameSize, - iSizeBufValue, - &iPrefBufferSize ); - - // read back which value is actually used - UInt32 iActualMonoBufferSize; - AudioDeviceGetProperty ( audioDeviceID, - 0, - bIsInput, - kAudioDevicePropertyBufferFrameSize, - &iSizeBufValue, - &iActualMonoBufferSize ); - - return iActualMonoBufferSize; -} -*/ - -/* -OSStatus CSound::deviceNotification ( AudioDeviceID, - UInt32, - Boolean, - AudioDevicePropertyID inPropertyID, - void* inRefCon ) -{ - CSound* pSound = reinterpret_cast ( inRefCon ); - - if ( inPropertyID == kAudioDeviceProcessorOverload ) - { - // xrun handling (it is important to act on xruns under CoreAudio - // since it seems that the xrun situation stays stable for a - // while and would give you a long time bad audio - pSound->EmitReinitRequestSignal ( RS_ONLY_RESTART ); - } - - return noErr; -} - OSStatus CSound::processInput ( void* inRefCon, AudioUnitRenderActionFlags* ioActionFlags, const AudioTimeStamp* inTimeStamp, @@ -638,22 +249,17 @@ OSStatus CSound::processInput ( void* inRefCon, return noErr; } +*/ -OSStatus CSound::processOutput ( void* inRefCon, - AudioUnitRenderActionFlags*, - const AudioTimeStamp*, - UInt32, - UInt32, - AudioBufferList* ioData ) +void CSound::processOutput ( SLAndroidSimpleBufferQueueItf bufferQueue, + void* instance) { - CSound* pSound = reinterpret_cast ( inRefCon ); + CSound* pSound = reinterpret_cast ( instance ); QMutexLocker locker ( &pSound->Mutex ); - memcpy ( ioData->mBuffers[0].mData, - &pSound->vecsTmpAudioSndCrdStereo[0], - pSound->pBufferList->mBuffers[0].mDataByteSize); - - return noErr; + // enqueue the buffer for playback. + (*bufferQueue)->Enqueue ( bufferQueue, + &pSound->vecsTmpAudioSndCrdStereo[0], + pSound->iOpenSLBufferSizeStero ); } -*/ diff --git a/android/sound.h b/android/sound.h index 4189ada3..49595900 100644 --- a/android/sound.h +++ b/android/sound.h @@ -27,6 +27,7 @@ #include #include +#include #include "soundbase.h" #include "global.h" @@ -49,64 +50,31 @@ public: int iOpenSLBufferSizeStero; protected: -/* - virtual QString LoadAndInitializeDriver ( int iIdx ); - - QString CheckDeviceCapabilities ( ComponentInstance& NewAudioInputUnit, - ComponentInstance& NewAudioOutputUnit ); -*/ void CloseOpenSL(); -/* - UInt32 SetBufferSize ( AudioDeviceID& audioDeviceID, - const bool bIsInput, - UInt32 iPrefBufferSize ); - - void GetAudioDeviceInfos ( const AudioDeviceID DeviceID, - QString& strDeviceName, - bool& bIsInput, - bool& bIsOutput ); -*/ - /* // callbacks - static OSStatus deviceNotification ( AudioDeviceID, - UInt32, - Boolean, - AudioDevicePropertyID inPropertyID, - void* inRefCon ); - static OSStatus processInput ( void* inRefCon, AudioUnitRenderActionFlags* ioActionFlags, const AudioTimeStamp* inTimeStamp, UInt32 inBusNumber, UInt32 inNumberFrames, AudioBufferList* ); - - static OSStatus processOutput ( void* inRefCon, - AudioUnitRenderActionFlags*, - const AudioTimeStamp*, - UInt32, - UInt32, - AudioBufferList* ioData ); */ -/* - AudioStreamBasicDescription streamFormat; + static void processOutput ( SLAndroidSimpleBufferQueueItf bufferQueue, + void* instance); - AURenderCallbackStruct inputCallbackStruct; - AURenderCallbackStruct outputCallbackStruct; + SLObjectItf engineObject; + SLEngineItf engine; + SLObjectItf outputMixObject; + SLObjectItf playerObject; + SLPlayItf player; + SLAndroidSimpleBufferQueueItf playerSimpleBufQueue; - ComponentInstance audioInputUnit; - AudioDeviceID audioInputDevice[MAX_NUMBER_SOUND_CARDS]; - ComponentInstance audioOutputUnit; - AudioDeviceID audioOutputDevice[MAX_NUMBER_SOUND_CARDS]; + QMutex Mutex; - AudioBufferList* pBufferList; - - QMutex Mutex; -*/ }; #endif // !defined(_SOUND_H__9518A621345F78_3638457H73245GUIG9__INCLUDED_)