some more Android code, not yet working...
This commit is contained in:
parent
ac388f0c1c
commit
ee4fedc689
3 changed files with 82 additions and 508 deletions
|
@ -1,38 +1,38 @@
|
||||||
<?xml version='1.0' encoding='utf-8'?>
|
<?xml version='1.0' encoding='utf-8'?>
|
||||||
<manifest android:versionCode="1" package="org.qtproject.example" android:installLocation="auto" android:versionName="1.0" xmlns:android="http://schemas.android.com/apk/res/android">
|
<manifest android:versionName="1.0" package="org.qtproject.example" xmlns:android="http://schemas.android.com/apk/res/android" android:versionCode="1" android:installLocation="auto">
|
||||||
<application android:label="@string/app_name" android:name="org.qtproject.qt5.android.bindings.QtApplication">
|
<application android:name="org.qtproject.qt5.android.bindings.QtApplication" android:label="@string/app_name">
|
||||||
<activity android:screenOrientation="unspecified" android:configChanges="orientation|uiMode|screenLayout|screenSize|smallestScreenSize|locale|fontScale|keyboard|keyboardHidden|navigation" android:label="@string/app_name" android:name="org.qtproject.qt5.android.bindings.QtActivity">
|
<activity android:name="org.qtproject.qt5.android.bindings.QtActivity" android:label="@string/app_name" android:screenOrientation="landscape" android:configChanges="orientation|uiMode|screenLayout|screenSize|smallestScreenSize|locale|fontScale|keyboard|keyboardHidden|navigation">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.intent.action.MAIN"/>
|
<action android:name="android.intent.action.MAIN"/>
|
||||||
<category android:name="android.intent.category.LAUNCHER"/>
|
<category android:name="android.intent.category.LAUNCHER"/>
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
<meta-data android:value="-- %%INSERT_APP_LIB_NAME%% --" android:name="android.app.lib_name"/>
|
<meta-data android:name="android.app.lib_name" android:value="-- %%INSERT_APP_LIB_NAME%% --"/>
|
||||||
<meta-data android:resource="@array/qt_sources" android:name="android.app.qt_sources_resource_id"/>
|
<meta-data android:name="android.app.qt_sources_resource_id" android:resource="@array/qt_sources"/>
|
||||||
<meta-data android:value="default" android:name="android.app.repository"/>
|
<meta-data android:name="android.app.repository" android:value="default"/>
|
||||||
<meta-data android:resource="@array/qt_libs" android:name="android.app.qt_libs_resource_id"/>
|
<meta-data android:name="android.app.qt_libs_resource_id" android:resource="@array/qt_libs"/>
|
||||||
<meta-data android:resource="@array/bundled_libs" android:name="android.app.bundled_libs_resource_id"/>
|
<meta-data android:name="android.app.bundled_libs_resource_id" android:resource="@array/bundled_libs"/>
|
||||||
<!-- Deploy Qt libs as part of package -->
|
<!-- Deploy Qt libs as part of package -->
|
||||||
<meta-data android:value="-- %%BUNDLE_LOCAL_QT_LIBS%% --" android:name="android.app.bundle_local_qt_libs"/>
|
<meta-data android:name="android.app.bundle_local_qt_libs" android:value="-- %%BUNDLE_LOCAL_QT_LIBS%% --"/>
|
||||||
<meta-data android:resource="@array/bundled_in_lib" android:name="android.app.bundled_in_lib_resource_id"/>
|
<meta-data android:name="android.app.bundled_in_lib_resource_id" android:resource="@array/bundled_in_lib"/>
|
||||||
<meta-data android:resource="@array/bundled_in_assets" android:name="android.app.bundled_in_assets_resource_id"/>
|
<meta-data android:name="android.app.bundled_in_assets_resource_id" android:resource="@array/bundled_in_assets"/>
|
||||||
<!-- Run with local libs -->
|
<!-- Run with local libs -->
|
||||||
<meta-data android:value="-- %%USE_LOCAL_QT_LIBS%% --" android:name="android.app.use_local_qt_libs"/>
|
<meta-data android:name="android.app.use_local_qt_libs" android:value="-- %%USE_LOCAL_QT_LIBS%% --"/>
|
||||||
<meta-data android:value="/data/local/tmp/qt/" android:name="android.app.libs_prefix"/>
|
<meta-data android:name="android.app.libs_prefix" android:value="/data/local/tmp/qt/"/>
|
||||||
<meta-data android:value="-- %%INSERT_LOCAL_LIBS%% --" android:name="android.app.load_local_libs"/>
|
<meta-data android:name="android.app.load_local_libs" android:value="-- %%INSERT_LOCAL_LIBS%% --"/>
|
||||||
<meta-data android:value="-- %%INSERT_LOCAL_JARS%% --" android:name="android.app.load_local_jars"/>
|
<meta-data android:name="android.app.load_local_jars" android:value="-- %%INSERT_LOCAL_JARS%% --"/>
|
||||||
<meta-data android:value="-- %%INSERT_INIT_CLASSES%% --" android:name="android.app.static_init_classes"/>
|
<meta-data android:name="android.app.static_init_classes" android:value="-- %%INSERT_INIT_CLASSES%% --"/>
|
||||||
<!-- Messages maps -->
|
<!-- Messages maps -->
|
||||||
<meta-data android:value="@string/ministro_not_found_msg" android:name="android.app.ministro_not_found_msg"/>
|
<meta-data android:name="android.app.ministro_not_found_msg" android:value="@string/ministro_not_found_msg"/>
|
||||||
<meta-data android:value="@string/ministro_needed_msg" android:name="android.app.ministro_needed_msg"/>
|
<meta-data android:name="android.app.ministro_needed_msg" android:value="@string/ministro_needed_msg"/>
|
||||||
<meta-data android:value="@string/fatal_error_msg" android:name="android.app.fatal_error_msg"/>
|
<meta-data android:name="android.app.fatal_error_msg" android:value="@string/fatal_error_msg"/>
|
||||||
<!-- Messages maps -->
|
<!-- Messages maps -->
|
||||||
<!-- Splash screen -->
|
<!-- Splash screen -->
|
||||||
<meta-data android:resource="@layout/splash" android:name="android.app.splash_screen"/>
|
<meta-data android:name="android.app.splash_screen" android:resource="@layout/splash"/>
|
||||||
<!-- Splash screen -->
|
<!-- Splash screen -->
|
||||||
</activity>
|
</activity>
|
||||||
</application>
|
</application>
|
||||||
<uses-sdk android:targetSdkVersion="19" android:minSdkVersion="9"/>
|
<uses-sdk android:minSdkVersion="9" android:targetSdkVersion="19"/>
|
||||||
<supports-screens android:largeScreens="true" android:anyDensity="true" android:normalScreens="true" android:smallScreens="true"/>
|
<supports-screens android:largeScreens="true" android:normalScreens="true" android:anyDensity="true" android:smallScreens="true"/>
|
||||||
<!-- %%INSERT_PERMISSIONS -->
|
<!-- %%INSERT_PERMISSIONS -->
|
||||||
<!-- %%INSERT_FEATURES -->
|
<!-- %%INSERT_FEATURES -->
|
||||||
<uses-permission android:name="android.permission.INTERNET"/>
|
<uses-permission android:name="android.permission.INTERNET"/>
|
||||||
|
|
|
@ -29,12 +29,15 @@
|
||||||
CSound::CSound ( void (*fpNewProcessCallback) ( CVector<short>& psData, void* arg ), void* arg ) :
|
CSound::CSound ( void (*fpNewProcessCallback) ( CVector<short>& psData, void* arg ), void* arg ) :
|
||||||
CSoundBase ( "OpenSL", true, fpNewProcessCallback, arg )
|
CSoundBase ( "OpenSL", true, fpNewProcessCallback, arg )
|
||||||
{
|
{
|
||||||
SLObjectItf engineObject;
|
// set up stream format
|
||||||
SLEngineItf engine;
|
SLDataFormat_PCM streamFormat;
|
||||||
SLObjectItf outputMixObject;
|
streamFormat.formatType = SL_DATAFORMAT_PCM;
|
||||||
SLObjectItf playerObject;
|
streamFormat.numChannels = 2;
|
||||||
SLPlayItf player;
|
streamFormat.samplesPerSec = SYSTEM_SAMPLE_RATE_HZ * 1000; // unit is mHz
|
||||||
SLAndroidSimpleBufferQueueItf playerSimpleBufQueue;
|
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
|
// create the OpenSL root engine object
|
||||||
slCreateEngine ( &engineObject,
|
slCreateEngine ( &engineObject,
|
||||||
|
@ -54,36 +57,24 @@ CSound::CSound ( void (*fpNewProcessCallback) ( CVector<short>& psData, void* ar
|
||||||
&engine );
|
&engine );
|
||||||
|
|
||||||
// create the main output mix
|
// create the main output mix
|
||||||
const SLInterfaceID engineIds[] = { SL_IID_VOLUME };
|
|
||||||
const SLboolean engineReq[] = { SL_BOOLEAN_FALSE };
|
|
||||||
|
|
||||||
(*engine)->CreateOutputMix ( engine,
|
(*engine)->CreateOutputMix ( engine,
|
||||||
&outputMixObject,
|
&outputMixObject,
|
||||||
1,
|
0,
|
||||||
engineIds,
|
nullptr,
|
||||||
engineReq );
|
nullptr );
|
||||||
|
|
||||||
|
|
||||||
(*outputMixObject)->Realize ( outputMixObject,
|
(*outputMixObject)->Realize ( outputMixObject,
|
||||||
SL_BOOLEAN_FALSE );
|
SL_BOOLEAN_FALSE );
|
||||||
|
|
||||||
// configure the buffer queue.
|
// configure the output buffer queue.
|
||||||
SLDataLocator_AndroidSimpleBufferQueue bufferQueue;
|
SLDataLocator_AndroidSimpleBufferQueue outBufferQueue;
|
||||||
bufferQueue.locatorType = SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE;
|
outBufferQueue.locatorType = SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE;
|
||||||
bufferQueue.numBuffers = 1;
|
outBufferQueue.numBuffers = 1; // max number of buffers in queue
|
||||||
|
|
||||||
// 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 audio (data) source
|
// configure the audio (data) source
|
||||||
SLDataSource dataSource;
|
SLDataSource dataSource;
|
||||||
dataSource.pLocator = &bufferQueue;
|
dataSource.pLocator = &outBufferQueue;
|
||||||
dataSource.pFormat = &streamFormat;
|
dataSource.pFormat = &streamFormat;
|
||||||
|
|
||||||
// configure the output mix
|
// configure the output mix
|
||||||
|
@ -122,363 +113,24 @@ CSound::CSound ( void (*fpNewProcessCallback) ( CVector<short>& psData, void* ar
|
||||||
SL_IID_ANDROIDSIMPLEBUFFERQUEUE,
|
SL_IID_ANDROIDSIMPLEBUFFERQUEUE,
|
||||||
&playerSimpleBufQueue );
|
&playerSimpleBufQueue );
|
||||||
|
|
||||||
|
// register the audio output callback
|
||||||
|
(*playerSimpleBufQueue)->RegisterCallback ( playerSimpleBufQueue,
|
||||||
|
processOutput,
|
||||||
/*
|
this );
|
||||||
|
|
||||||
// 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;
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
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<int> ( 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<int> ( 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<int> ( 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<int> ( outputSampleRate ) ).arg ( SYSTEM_SAMPLE_RATE_HZ );
|
|
||||||
}
|
|
||||||
|
|
||||||
// everything is ok, return empty string for "no error" case
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
void CSound::CloseOpenSL()
|
void CSound::CloseOpenSL()
|
||||||
{
|
{
|
||||||
|
|
||||||
/*
|
|
||||||
// clean up
|
// clean up
|
||||||
AudioUnitUninitialize ( audioInputUnit );
|
(*playerObject)->Destroy ( playerObject );
|
||||||
AudioUnitUninitialize ( audioOutputUnit );
|
(*outputMixObject)->Destroy ( outputMixObject );
|
||||||
CloseComponent ( audioInputUnit );
|
(*engineObject)->Destroy ( engineObject );
|
||||||
CloseComponent ( audioOutputUnit );
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSound::Start()
|
void CSound::Start()
|
||||||
{
|
{
|
||||||
|
|
||||||
/*
|
|
||||||
// start the rendering
|
// start the rendering
|
||||||
AudioOutputUnitStart ( audioInputUnit );
|
(*player)->SetPlayState ( player, SL_PLAYSTATE_PLAYING );
|
||||||
AudioOutputUnitStart ( audioOutputUnit );
|
|
||||||
*/
|
|
||||||
|
|
||||||
// call base class
|
// call base class
|
||||||
CSoundBase::Start();
|
CSoundBase::Start();
|
||||||
|
@ -486,12 +138,11 @@ void CSound::Start()
|
||||||
|
|
||||||
void CSound::Stop()
|
void CSound::Stop()
|
||||||
{
|
{
|
||||||
|
|
||||||
/*
|
|
||||||
// stop the audio stream
|
// stop the audio stream
|
||||||
AudioOutputUnitStop ( audioInputUnit );
|
(*player)->SetPlayState ( player, SL_PLAYSTATE_STOPPED );
|
||||||
AudioOutputUnitStop ( audioOutputUnit );
|
|
||||||
*/
|
// clear the buffers
|
||||||
|
(*playerSimpleBufQueue)->Clear ( playerSimpleBufQueue );
|
||||||
|
|
||||||
// call base class
|
// call base class
|
||||||
CSoundBase::Stop();
|
CSoundBase::Stop();
|
||||||
|
@ -499,7 +150,6 @@ void CSound::Stop()
|
||||||
|
|
||||||
int CSound::Init ( const int iNewPrefMonoBufferSize )
|
int CSound::Init ( const int iNewPrefMonoBufferSize )
|
||||||
{
|
{
|
||||||
|
|
||||||
/*
|
/*
|
||||||
UInt32 iActualMonoBufferSize;
|
UInt32 iActualMonoBufferSize;
|
||||||
|
|
||||||
|
@ -532,19 +182,27 @@ int CSound::Init ( const int iNewPrefMonoBufferSize )
|
||||||
throw CGenErr ( strErrBufSize );
|
throw CGenErr ( strErrBufSize );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
// TEST
|
||||||
|
int iActualMonoBufferSize = iNewPrefMonoBufferSize;
|
||||||
|
|
||||||
|
|
||||||
// store buffer size
|
// store buffer size
|
||||||
iCoreAudioBufferSizeMono = iActualMonoBufferSize;
|
iOpenSLBufferSizeMono = iActualMonoBufferSize;
|
||||||
|
|
||||||
// init base class
|
// init base class
|
||||||
CSoundBase::Init ( iCoreAudioBufferSizeMono );
|
CSoundBase::Init ( iOpenSLBufferSizeMono );
|
||||||
|
|
||||||
// set internal buffer size value and calculate stereo buffer size
|
// set internal buffer size value and calculate stereo buffer size
|
||||||
iCoreAudioBufferSizeStero = 2 * iCoreAudioBufferSizeMono;
|
iOpenSLBufferSizeStero = 2 * iOpenSLBufferSizeMono;
|
||||||
|
|
||||||
// create memory for intermediate audio buffer
|
// create memory for intermediate audio buffer
|
||||||
vecsTmpAudioSndCrdStereo.Init ( iCoreAudioBufferSizeStero );
|
vecsTmpAudioSndCrdStereo.Init ( iOpenSLBufferSizeStero );
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
// fill audio unit buffer struct
|
// fill audio unit buffer struct
|
||||||
pBufferList->mNumberBuffers = 1;
|
pBufferList->mNumberBuffers = 1;
|
||||||
pBufferList->mBuffers[0].mNumberChannels = 2; // stereo
|
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<CSound*> ( 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,
|
OSStatus CSound::processInput ( void* inRefCon,
|
||||||
AudioUnitRenderActionFlags* ioActionFlags,
|
AudioUnitRenderActionFlags* ioActionFlags,
|
||||||
const AudioTimeStamp* inTimeStamp,
|
const AudioTimeStamp* inTimeStamp,
|
||||||
|
@ -638,22 +249,17 @@ OSStatus CSound::processInput ( void* inRefCon,
|
||||||
|
|
||||||
return noErr;
|
return noErr;
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
OSStatus CSound::processOutput ( void* inRefCon,
|
void CSound::processOutput ( SLAndroidSimpleBufferQueueItf bufferQueue,
|
||||||
AudioUnitRenderActionFlags*,
|
void* instance)
|
||||||
const AudioTimeStamp*,
|
|
||||||
UInt32,
|
|
||||||
UInt32,
|
|
||||||
AudioBufferList* ioData )
|
|
||||||
{
|
{
|
||||||
CSound* pSound = reinterpret_cast<CSound*> ( inRefCon );
|
CSound* pSound = reinterpret_cast<CSound*> ( instance );
|
||||||
|
|
||||||
QMutexLocker locker ( &pSound->Mutex );
|
QMutexLocker locker ( &pSound->Mutex );
|
||||||
|
|
||||||
memcpy ( ioData->mBuffers[0].mData,
|
// enqueue the buffer for playback.
|
||||||
&pSound->vecsTmpAudioSndCrdStereo[0],
|
(*bufferQueue)->Enqueue ( bufferQueue,
|
||||||
pSound->pBufferList->mBuffers[0].mDataByteSize);
|
&pSound->vecsTmpAudioSndCrdStereo[0],
|
||||||
|
pSound->iOpenSLBufferSizeStero );
|
||||||
return noErr;
|
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
|
|
|
@ -27,6 +27,7 @@
|
||||||
|
|
||||||
#include <SLES/OpenSLES.h>
|
#include <SLES/OpenSLES.h>
|
||||||
#include <SLES/OpenSLES_Android.h>
|
#include <SLES/OpenSLES_Android.h>
|
||||||
|
#include <QMutex>
|
||||||
#include "soundbase.h"
|
#include "soundbase.h"
|
||||||
#include "global.h"
|
#include "global.h"
|
||||||
|
|
||||||
|
@ -49,64 +50,31 @@ public:
|
||||||
int iOpenSLBufferSizeStero;
|
int iOpenSLBufferSizeStero;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
/*
|
|
||||||
virtual QString LoadAndInitializeDriver ( int iIdx );
|
|
||||||
|
|
||||||
QString CheckDeviceCapabilities ( ComponentInstance& NewAudioInputUnit,
|
|
||||||
ComponentInstance& NewAudioOutputUnit );
|
|
||||||
*/
|
|
||||||
|
|
||||||
void CloseOpenSL();
|
void CloseOpenSL();
|
||||||
|
|
||||||
/*
|
|
||||||
UInt32 SetBufferSize ( AudioDeviceID& audioDeviceID,
|
|
||||||
const bool bIsInput,
|
|
||||||
UInt32 iPrefBufferSize );
|
|
||||||
|
|
||||||
void GetAudioDeviceInfos ( const AudioDeviceID DeviceID,
|
|
||||||
QString& strDeviceName,
|
|
||||||
bool& bIsInput,
|
|
||||||
bool& bIsOutput );
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
// callbacks
|
// callbacks
|
||||||
static OSStatus deviceNotification ( AudioDeviceID,
|
|
||||||
UInt32,
|
|
||||||
Boolean,
|
|
||||||
AudioDevicePropertyID inPropertyID,
|
|
||||||
void* inRefCon );
|
|
||||||
|
|
||||||
static OSStatus processInput ( void* inRefCon,
|
static OSStatus processInput ( void* inRefCon,
|
||||||
AudioUnitRenderActionFlags* ioActionFlags,
|
AudioUnitRenderActionFlags* ioActionFlags,
|
||||||
const AudioTimeStamp* inTimeStamp,
|
const AudioTimeStamp* inTimeStamp,
|
||||||
UInt32 inBusNumber,
|
UInt32 inBusNumber,
|
||||||
UInt32 inNumberFrames,
|
UInt32 inNumberFrames,
|
||||||
AudioBufferList* );
|
AudioBufferList* );
|
||||||
|
|
||||||
static OSStatus processOutput ( void* inRefCon,
|
|
||||||
AudioUnitRenderActionFlags*,
|
|
||||||
const AudioTimeStamp*,
|
|
||||||
UInt32,
|
|
||||||
UInt32,
|
|
||||||
AudioBufferList* ioData );
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
static void processOutput ( SLAndroidSimpleBufferQueueItf bufferQueue,
|
||||||
AudioStreamBasicDescription streamFormat;
|
void* instance);
|
||||||
|
|
||||||
AURenderCallbackStruct inputCallbackStruct;
|
SLObjectItf engineObject;
|
||||||
AURenderCallbackStruct outputCallbackStruct;
|
SLEngineItf engine;
|
||||||
|
SLObjectItf outputMixObject;
|
||||||
|
SLObjectItf playerObject;
|
||||||
|
SLPlayItf player;
|
||||||
|
SLAndroidSimpleBufferQueueItf playerSimpleBufQueue;
|
||||||
|
|
||||||
ComponentInstance audioInputUnit;
|
QMutex Mutex;
|
||||||
AudioDeviceID audioInputDevice[MAX_NUMBER_SOUND_CARDS];
|
|
||||||
ComponentInstance audioOutputUnit;
|
|
||||||
AudioDeviceID audioOutputDevice[MAX_NUMBER_SOUND_CARDS];
|
|
||||||
|
|
||||||
AudioBufferList* pBufferList;
|
|
||||||
|
|
||||||
QMutex Mutex;
|
|
||||||
*/
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // !defined(_SOUND_H__9518A621345F78_3638457H73245GUIG9__INCLUDED_)
|
#endif // !defined(_SOUND_H__9518A621345F78_3638457H73245GUIG9__INCLUDED_)
|
||||||
|
|
Loading…
Reference in a new issue