first working version of CoreAudio interface, still a lot to do...
This commit is contained in:
parent
07be35a465
commit
b6ee741e2c
2 changed files with 128 additions and 83 deletions
176
mac/sound.cpp
176
mac/sound.cpp
|
@ -71,14 +71,19 @@ void CSound::OpenCoreAudio()
|
||||||
throw CGenErr ( tr ( "No CoreAudio next component found" ) );
|
throw CGenErr ( tr ( "No CoreAudio next component found" ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( OpenAComponent ( comp, &audioUnit ) )
|
if ( OpenAComponent ( comp, &audioInputUnit ) )
|
||||||
{
|
{
|
||||||
throw CGenErr ( tr ( "CoreAudio creating component instance failed" ) );
|
throw CGenErr ( tr ( "CoreAudio creating input component instance failed" ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
// we enable input and disable output
|
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;
|
UInt32 enableIO = 1;
|
||||||
err = AudioUnitSetProperty ( audioUnit,
|
err = AudioUnitSetProperty ( audioInputUnit,
|
||||||
kAudioOutputUnitProperty_EnableIO,
|
kAudioOutputUnitProperty_EnableIO,
|
||||||
kAudioUnitScope_Input,
|
kAudioUnitScope_Input,
|
||||||
1, // input element
|
1, // input element
|
||||||
|
@ -86,28 +91,13 @@ void CSound::OpenCoreAudio()
|
||||||
sizeof ( enableIO ) );
|
sizeof ( enableIO ) );
|
||||||
|
|
||||||
enableIO = 0;
|
enableIO = 0;
|
||||||
err = AudioUnitSetProperty ( audioUnit,
|
err = AudioUnitSetProperty ( audioInputUnit,
|
||||||
kAudioOutputUnitProperty_EnableIO,
|
kAudioOutputUnitProperty_EnableIO,
|
||||||
kAudioUnitScope_Output,
|
kAudioUnitScope_Output,
|
||||||
0, // output element
|
0, // output element
|
||||||
&enableIO,
|
&enableIO,
|
||||||
sizeof ( enableIO ) );
|
sizeof ( enableIO ) );
|
||||||
|
|
||||||
// set up a callback function for new input data
|
|
||||||
AURenderCallbackStruct input;
|
|
||||||
input.inputProc = process;
|
|
||||||
input.inputProcRefCon = this;
|
|
||||||
|
|
||||||
if ( AudioUnitSetProperty ( audioUnit,
|
|
||||||
kAudioOutputUnitProperty_SetInputCallback,
|
|
||||||
kAudioUnitScope_Global,
|
|
||||||
0,
|
|
||||||
&input,
|
|
||||||
sizeof ( input ) ) )
|
|
||||||
{
|
|
||||||
throw CGenErr ( tr ( "CoreAudio audio unit set property failed" ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
// set input device
|
// set input device
|
||||||
size = sizeof ( AudioDeviceID );
|
size = sizeof ( AudioDeviceID );
|
||||||
AudioDeviceID inputDevice;
|
AudioDeviceID inputDevice;
|
||||||
|
@ -115,19 +105,69 @@ void CSound::OpenCoreAudio()
|
||||||
&size,
|
&size,
|
||||||
&inputDevice ) )
|
&inputDevice ) )
|
||||||
{
|
{
|
||||||
throw CGenErr ( tr ( "CoreAudio AudioHardwareGetProperty call failed" ) );
|
throw CGenErr ( tr ( "CoreAudio input AudioHardwareGetProperty call failed" ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( AudioUnitSetProperty ( audioUnit,
|
if ( AudioUnitSetProperty ( audioInputUnit,
|
||||||
kAudioOutputUnitProperty_CurrentDevice,
|
kAudioOutputUnitProperty_CurrentDevice,
|
||||||
kAudioUnitScope_Global,
|
kAudioUnitScope_Global,
|
||||||
0,
|
1,
|
||||||
&inputDevice,
|
&inputDevice,
|
||||||
sizeof ( inputDevice ) ) )
|
sizeof ( inputDevice ) ) )
|
||||||
{
|
{
|
||||||
throw CGenErr ( tr ( "CoreAudio input AudioUnitSetProperty call failed" ) );
|
throw CGenErr ( tr ( "CoreAudio input AudioUnitSetProperty call failed" ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// set up a callback function for new input data
|
||||||
|
AURenderCallbackStruct input;
|
||||||
|
input.inputProc = processInput;
|
||||||
|
input.inputProcRefCon = this;
|
||||||
|
|
||||||
|
if ( AudioUnitSetProperty ( audioInputUnit,
|
||||||
|
kAudioOutputUnitProperty_SetInputCallback,//kAudioUnitProperty_SetRenderCallback,//
|
||||||
|
kAudioUnitScope_Global,
|
||||||
|
0,
|
||||||
|
&input,
|
||||||
|
sizeof ( input ) ) )
|
||||||
|
{
|
||||||
|
throw CGenErr ( tr ( "CoreAudio audio unit set property failed" ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
// set output device
|
||||||
|
size = sizeof ( AudioDeviceID );
|
||||||
|
AudioDeviceID outputDevice;
|
||||||
|
if ( AudioHardwareGetProperty ( kAudioHardwarePropertyDefaultOutputDevice,
|
||||||
|
&size,
|
||||||
|
&outputDevice ) )
|
||||||
|
{
|
||||||
|
throw CGenErr ( tr ( "CoreAudio output AudioHardwareGetProperty call failed" ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( AudioUnitSetProperty ( audioOutputUnit,
|
||||||
|
kAudioOutputUnitProperty_CurrentDevice,
|
||||||
|
kAudioUnitScope_Global,
|
||||||
|
0,
|
||||||
|
&outputDevice,
|
||||||
|
sizeof ( outputDevice ) ) )
|
||||||
|
{
|
||||||
|
throw CGenErr ( tr ( "CoreAudio output AudioUnitSetProperty call failed" ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
// set up a callback function for new output data
|
||||||
|
AURenderCallbackStruct output;
|
||||||
|
output.inputProc = processOutput;
|
||||||
|
output.inputProcRefCon = this;
|
||||||
|
|
||||||
|
if ( AudioUnitSetProperty ( audioOutputUnit,
|
||||||
|
kAudioUnitProperty_SetRenderCallback,//kAudioOutputUnitProperty_SetInputCallback,//
|
||||||
|
kAudioUnitScope_Global,
|
||||||
|
0,
|
||||||
|
&output,
|
||||||
|
sizeof ( output ) ) )
|
||||||
|
{
|
||||||
|
throw CGenErr ( tr ( "CoreAudio audio unit set property failed" ) );
|
||||||
|
}
|
||||||
|
|
||||||
// set up stream format
|
// set up stream format
|
||||||
AudioStreamBasicDescription streamFormat;
|
AudioStreamBasicDescription streamFormat;
|
||||||
streamFormat.mSampleRate = SYSTEM_SAMPLE_RATE;
|
streamFormat.mSampleRate = SYSTEM_SAMPLE_RATE;
|
||||||
|
@ -140,7 +180,7 @@ void CSound::OpenCoreAudio()
|
||||||
streamFormat.mBitsPerChannel = 16;
|
streamFormat.mBitsPerChannel = 16;
|
||||||
|
|
||||||
// our output
|
// our output
|
||||||
if ( AudioUnitSetProperty ( audioUnit,
|
if ( AudioUnitSetProperty ( audioOutputUnit,
|
||||||
kAudioUnitProperty_StreamFormat,
|
kAudioUnitProperty_StreamFormat,
|
||||||
kAudioUnitScope_Input,
|
kAudioUnitScope_Input,
|
||||||
0,
|
0,
|
||||||
|
@ -151,7 +191,7 @@ void CSound::OpenCoreAudio()
|
||||||
}
|
}
|
||||||
|
|
||||||
// our input
|
// our input
|
||||||
if ( AudioUnitSetProperty ( audioUnit,
|
if ( AudioUnitSetProperty ( audioInputUnit,
|
||||||
kAudioUnitProperty_StreamFormat,
|
kAudioUnitProperty_StreamFormat,
|
||||||
kAudioUnitScope_Output,
|
kAudioUnitScope_Output,
|
||||||
1,
|
1,
|
||||||
|
@ -167,7 +207,8 @@ void CSound::OpenCoreAudio()
|
||||||
|
|
||||||
|
|
||||||
// TEST
|
// TEST
|
||||||
StoreInOutStreamProps ( audioUnit );
|
StoreInOutStreamProps ( audioInputUnit );
|
||||||
|
StoreInOutStreamProps ( audioOutputUnit );
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -175,17 +216,17 @@ StoreInOutStreamProps ( audioUnit );
|
||||||
void CSound::CloseCoreAudio()
|
void CSound::CloseCoreAudio()
|
||||||
{
|
{
|
||||||
// clean up "gOutputUnit"
|
// clean up "gOutputUnit"
|
||||||
AudioUnitUninitialize ( audioUnit );
|
AudioUnitUninitialize ( audioInputUnit );
|
||||||
CloseComponent ( audioUnit );
|
AudioUnitUninitialize ( audioOutputUnit );
|
||||||
|
CloseComponent ( audioInputUnit );
|
||||||
|
CloseComponent ( audioOutputUnit );
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSound::Start()
|
void CSound::Start()
|
||||||
{
|
{
|
||||||
// start the rendering
|
// start the rendering
|
||||||
if ( AudioOutputUnitStart ( audioUnit ) )
|
AudioOutputUnitStart ( audioInputUnit );
|
||||||
{
|
AudioOutputUnitStart ( audioOutputUnit );
|
||||||
throw CGenErr ( tr ( "CoreAudio starting failed" ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
// call base class
|
// call base class
|
||||||
CSoundBase::Start();
|
CSoundBase::Start();
|
||||||
|
@ -194,10 +235,8 @@ void CSound::Start()
|
||||||
void CSound::Stop()
|
void CSound::Stop()
|
||||||
{
|
{
|
||||||
// stop the audio stream
|
// stop the audio stream
|
||||||
if ( AudioOutputUnitStop ( audioUnit ) )
|
AudioOutputUnitStop ( audioInputUnit );
|
||||||
{
|
AudioOutputUnitStop ( audioOutputUnit );
|
||||||
throw CGenErr ( tr ( "CoreAudio stopping failed" ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
// call base class
|
// call base class
|
||||||
CSoundBase::Stop();
|
CSoundBase::Stop();
|
||||||
|
@ -211,7 +250,14 @@ int CSound::Init ( const int iNewPrefMonoBufferSize )
|
||||||
// get the audio unit buffer size
|
// get the audio unit buffer size
|
||||||
UInt32 bufferSizeFrames;
|
UInt32 bufferSizeFrames;
|
||||||
UInt32 propertySize = sizeof(UInt32);
|
UInt32 propertySize = sizeof(UInt32);
|
||||||
AudioUnitGetProperty ( audioUnit, kAudioDevicePropertyBufferFrameSize,
|
|
||||||
|
|
||||||
|
// TEST
|
||||||
|
AudioUnitGetProperty ( audioOutputUnit, kAudioDevicePropertyBufferFrameSize,
|
||||||
|
kAudioUnitScope_Global, 1, &bufferSizeFrames, &propertySize );
|
||||||
|
printf("out buf size: %d\n",bufferSizeFrames);
|
||||||
|
|
||||||
|
AudioUnitGetProperty ( audioInputUnit, kAudioDevicePropertyBufferFrameSize,
|
||||||
kAudioUnitScope_Global, 1, &bufferSizeFrames, &propertySize );
|
kAudioUnitScope_Global, 1, &bufferSizeFrames, &propertySize );
|
||||||
|
|
||||||
// store buffer size
|
// store buffer size
|
||||||
|
@ -236,15 +282,21 @@ printf ( "Buffer_Size: %d", (int) bufferSizeFrames );
|
||||||
theBufferList = (AudioBufferList*) malloc ( offsetof ( AudioBufferList,
|
theBufferList = (AudioBufferList*) malloc ( offsetof ( AudioBufferList,
|
||||||
mBuffers[0] ) + sizeof(AudioBuffer) );
|
mBuffers[0] ) + sizeof(AudioBuffer) );
|
||||||
|
|
||||||
|
//(sizeof(AudioBufferList) + (numChannels-1)) * sizeof(AudioBuffer)
|
||||||
|
|
||||||
|
|
||||||
theBufferList->mNumberBuffers = 1;
|
theBufferList->mNumberBuffers = 1;
|
||||||
theBufferList->mBuffers[0].mNumberChannels = 2; // stereo
|
theBufferList->mBuffers[0].mNumberChannels = 2; // stereo
|
||||||
theBufferList->mBuffers[0].mDataByteSize = bufferSizeFrames * 4; // 2 bytes, 2 channels
|
theBufferList->mBuffers[0].mDataByteSize = bufferSizeFrames * 4; // 2 bytes, 2 channels
|
||||||
theBufferList->mBuffers[0].mData = &vecsTmpAudioSndCrdStereo[0];
|
theBufferList->mBuffers[0].mData = &vecsTmpAudioSndCrdStereo[0];
|
||||||
//theBufferList->mBuffers[0].mData = malloc(bufferSizeBytes);
|
|
||||||
|
|
||||||
// initialize unit
|
// initialize unit
|
||||||
if ( AudioUnitInitialize ( audioUnit ) )
|
if ( AudioUnitInitialize ( audioInputUnit ) )
|
||||||
|
{
|
||||||
|
throw CGenErr ( tr ( "Initialization of CoreAudio failed" ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( AudioUnitInitialize ( audioOutputUnit ) )
|
||||||
{
|
{
|
||||||
throw CGenErr ( tr ( "Initialization of CoreAudio failed" ) );
|
throw CGenErr ( tr ( "Initialization of CoreAudio failed" ) );
|
||||||
}
|
}
|
||||||
|
@ -252,7 +304,7 @@ theBufferList = (AudioBufferList*) malloc ( offsetof ( AudioBufferList,
|
||||||
return iCoreAudioBufferSizeMono;
|
return iCoreAudioBufferSizeMono;
|
||||||
}
|
}
|
||||||
|
|
||||||
OSStatus CSound::process ( void* inRefCon,
|
OSStatus CSound::processInput ( void* inRefCon,
|
||||||
AudioUnitRenderActionFlags* ioActionFlags,
|
AudioUnitRenderActionFlags* ioActionFlags,
|
||||||
const AudioTimeStamp* inTimeStamp,
|
const AudioTimeStamp* inTimeStamp,
|
||||||
UInt32 inBusNumber,
|
UInt32 inBusNumber,
|
||||||
|
@ -263,51 +315,39 @@ OSStatus CSound::process ( void* inRefCon,
|
||||||
|
|
||||||
// get the new audio data
|
// get the new audio data
|
||||||
ComponentResult err =
|
ComponentResult err =
|
||||||
AudioUnitRender ( pSound->audioUnit,
|
AudioUnitRender ( pSound->audioInputUnit,
|
||||||
ioActionFlags,
|
ioActionFlags,
|
||||||
inTimeStamp,
|
inTimeStamp,
|
||||||
inBusNumber,
|
inBusNumber,
|
||||||
inNumberFrames,
|
inNumberFrames,
|
||||||
theBufferList );
|
theBufferList );
|
||||||
|
|
||||||
/*
|
|
||||||
// TEST
|
|
||||||
//static FILE* pFile = fopen ( "test.dat", "w" );
|
|
||||||
for ( int test = 0; test < theBufferList->mBuffers[0].mDataByteSize / 4; test++ )
|
|
||||||
{
|
|
||||||
fprintf ( pFile, "%e\n", static_cast<float*>(theBufferList->mBuffers[0].mData)[test]);
|
|
||||||
}
|
|
||||||
fflush ( pFile );
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
// TEST output seems to work!!!
|
|
||||||
for ( UInt32 i = 1; i < theBufferList->mBuffers[0].mDataByteSize / 2; i++)
|
|
||||||
{
|
|
||||||
static_cast<short*> ( theBufferList->mBuffers[0].mData)[i] = (short) ( (double) rand() / RAND_MAX * 10000 );
|
|
||||||
}
|
|
||||||
ioData = theBufferList;
|
|
||||||
*/
|
|
||||||
|
|
||||||
// TEST
|
|
||||||
printf ( "buffersize: %d, inBus: %d, ioActionFlags: %d, err: %d\n",
|
|
||||||
(int) inNumberFrames, (int) inBusNumber, (int) ioActionFlags, (int) err );
|
|
||||||
|
|
||||||
|
|
||||||
// call processing callback function
|
// call processing callback function
|
||||||
pSound->ProcessCallback ( pSound->vecsTmpAudioSndCrdStereo );
|
pSound->ProcessCallback ( pSound->vecsTmpAudioSndCrdStereo );
|
||||||
|
|
||||||
|
return noErr;
|
||||||
|
}
|
||||||
|
|
||||||
|
OSStatus CSound::processOutput ( void* inRefCon,
|
||||||
|
AudioUnitRenderActionFlags* ioActionFlags,
|
||||||
|
const AudioTimeStamp* inTimeStamp,
|
||||||
|
UInt32 inBusNumber,
|
||||||
|
UInt32 inNumberFrames,
|
||||||
|
AudioBufferList* ioData )
|
||||||
|
{
|
||||||
|
CSound* pSound = reinterpret_cast<CSound*> ( inRefCon );
|
||||||
|
|
||||||
// TODO take care of outputting processed data
|
memcpy ( ioData->mBuffers[0].mData,
|
||||||
|
&pSound->vecsTmpAudioSndCrdStereo[0],
|
||||||
|
theBufferList->mBuffers[0].mDataByteSize);
|
||||||
|
|
||||||
return noErr;
|
return noErr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||||
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||||
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||||
|
|
|
@ -61,11 +61,16 @@ protected:
|
||||||
void CloseCoreAudio();
|
void CloseCoreAudio();
|
||||||
|
|
||||||
// callbacks
|
// callbacks
|
||||||
static OSStatus process ( void* inRefCon,AudioUnitRenderActionFlags* ioActionFlags,
|
static OSStatus processInput ( void* inRefCon,AudioUnitRenderActionFlags* ioActionFlags,
|
||||||
const AudioTimeStamp* inTimeStamp, UInt32 inBusNumber, UInt32 inNumberFrames,
|
const AudioTimeStamp* inTimeStamp, UInt32 inBusNumber, UInt32 inNumberFrames,
|
||||||
AudioBufferList* ioData );
|
AudioBufferList* ioData );
|
||||||
|
|
||||||
ComponentInstance audioUnit;
|
static OSStatus processOutput ( void* inRefCon,AudioUnitRenderActionFlags* ioActionFlags,
|
||||||
|
const AudioTimeStamp* inTimeStamp, UInt32 inBusNumber, UInt32 inNumberFrames,
|
||||||
|
AudioBufferList* ioData );
|
||||||
|
|
||||||
|
ComponentInstance audioInputUnit;
|
||||||
|
ComponentInstance audioOutputUnit;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // !defined(_SOUND_H__9518A621345F78_363456876UZGSDF82CF549__INCLUDED_)
|
#endif // !defined(_SOUND_H__9518A621345F78_363456876UZGSDF82CF549__INCLUDED_)
|
||||||
|
|
Loading…
Reference in a new issue