From 4e9e5c36f01f41acb88ec27a9cf5db6b5a19c86e Mon Sep 17 00:00:00 2001 From: Volker Fischer Date: Fri, 5 Mar 2010 20:19:12 +0000 Subject: [PATCH] first try implementing CoreAudio interface --- linux/sound.h | 8 +- llcon.pro | 17 +++- mac/sound.cpp | 180 ++++++++++++++++++++++++++++++++++++++++- mac/sound.h | 23 ++++-- src/client.h | 12 ++- src/llconclientdlg.cpp | 2 +- src/llconclientdlg.h | 2 +- 7 files changed, 223 insertions(+), 21 deletions(-) diff --git a/linux/sound.h b/linux/sound.h index 7039f422..d277c533 100755 --- a/linux/sound.h +++ b/linux/sound.h @@ -67,10 +67,10 @@ public: virtual void Stop(); // not implemented yet, always return one device and default string - int GetNumDev() { return 1; } - QString GetDeviceName ( const int iDiD ) { return "wave mapper"; } - QString SetDev ( const int iNewDev ) { return ""; } // dummy - int GetDev() { return 0; } + int GetNumDev() { return 1; } + QString GetDeviceName ( const int ) { return "wave mapper"; } + QString SetDev ( const int ) { return ""; } // dummy + int GetDev() { return 0; } // these variables should be protected but cannot since we want // to access them from the callback function diff --git a/llcon.pro b/llcon.pro index 4c8575a5..b0bac42d 100755 --- a/llcon.pro +++ b/llcon.pro @@ -11,6 +11,17 @@ INCLUDEPATH += src \ DEFINES += USE_ALLOCA \ _REENTRANT +macx { + HEADERS += mac/sound.h + SOURCES += mac/sound.cpp + + LIBS += -framework CoreFoundation \ + -framework CoreServices \ + -framework CoreAudio \ + -framework AudioToolbox \ + -framework AudioUnit +} + RCC_DIR = src/res RESOURCES += src/resources.qrc @@ -20,8 +31,7 @@ FORMS += src/llconclientdlgbase.ui \ src/chatdlgbase.ui \ src/aboutdlgbase.ui -HEADERS += linux/sound.h \ - src/buffer.h \ +HEADERS += src/buffer.h \ src/global.h \ src/socket.h \ src/channel.h \ @@ -73,8 +83,7 @@ HEADERS += linux/sound.h \ libs/celt/stack_alloc.h \ libs/celt/vq.h -SOURCES += linux/sound.cpp \ - src/buffer.cpp \ +SOURCES += src/buffer.cpp \ src/main.cpp \ src/socket.cpp \ src/channel.cpp \ diff --git a/mac/sound.cpp b/mac/sound.cpp index 4df8e66d..bc7047ca 100755 --- a/mac/sound.cpp +++ b/mac/sound.cpp @@ -24,4 +24,182 @@ #include "sound.h" -// TODO implementation (use Jack interface as a reference) + +/* Implementation *************************************************************/ +void CSound::OpenCoreAudio() +{ + // open the default output unit + AudioComponentDescription desc; + desc.componentType = kAudioUnitType_Output; + desc.componentSubType = kAudioUnitSubType_DefaultOutput; + desc.componentFlags = 0; + desc.componentFlagsMask = 0; + desc.componentManufacturer = 0; + + AudioComponent comp = AudioComponentFindNext ( NULL, &desc ); + if ( comp == NULL ) + { + throw CGenErr ( tr ( "No CoreAudio next component found" ) ); + } + + if ( AudioComponentInstanceNew ( comp, &gOutputUnit ) ) + { + throw CGenErr ( tr ( "CoreAudio creating component instance failed" ) ); + } + + // set up a callback function to generate output to the output unit + AURenderCallbackStruct input; + input.inputProc = process; + input.inputProcRefCon = this; + + if ( AudioUnitSetProperty ( gOutputUnit, + kAudioUnitProperty_SetRenderCallback, + kAudioUnitScope_Input, + 0, + &input, + sizeof(input) ) ) + { + throw CGenErr ( tr ( "CoreAudio audio unit set property failed" ) ); + } + + // set up stream format + AudioStreamBasicDescription streamFormat; + streamFormat.mSampleRate = SYSTEM_SAMPLE_RATE; + streamFormat.mFormatID = kAudioFormatLinearPCM; + streamFormat.mFormatFlags = kAudioFormatFlagIsSignedInteger; + streamFormat.mFramesPerPacket = 1; + streamFormat.mChannelsPerFrame = 1; + streamFormat.mBitsPerChannel = 16; + streamFormat.mBytesPerPacket = 2; + streamFormat.mBytesPerFrame = 2; + + if ( AudioUnitSetProperty ( gOutputUnit, + kAudioUnitProperty_StreamFormat, + kAudioUnitScope_Input, + 0, + &streamFormat, + sizeof(streamFormat) ) ) + { + throw CGenErr ( tr ( "CoreAudio stream format set property failed" ) ); + } + + // initialize unit + if ( AudioUnitInitialize ( gOutputUnit ) ) + { + throw CGenErr ( tr ( "Initialization of CoreAudio failed" ) ); + } +} + +void CSound::CloseCoreAudio() +{ + // clean up "gOutputUnit" + AudioUnitUninitialize ( gOutputUnit ); + CloseComponent ( gOutputUnit ); +} + +void CSound::Start() +{ + // start the rendering + if ( AudioOutputUnitStart ( gOutputUnit ) ) + { + throw CGenErr ( tr ( "CoreAudio starting failed" ) ); + } +} + +void CSound::Stop() +{ + // stop the audio stream + if ( AudioOutputUnitStop ( gOutputUnit ) ) + { + throw CGenErr ( tr ( "CoreAudio stopping failed" ) ); + } +} + +int CSound::Init ( const int iNewPrefMonoBufferSize ) +{ + +/* +// try setting buffer size +// TODO seems not to work! -> no audio after this operation! +//jack_set_buffer_size ( pJackClient, iNewPrefMonoBufferSize ); + + // get actual buffer size + iJACKBufferSizeMono = jack_get_buffer_size ( pJackClient ); + + // init base clasee + CSoundBase::Init ( iJACKBufferSizeMono ); + + // set internal buffer size value and calculate stereo buffer size + iJACKBufferSizeStero = 2 * iJACKBufferSizeMono; + + // create memory for intermediate audio buffer + vecsTmpAudioSndCrdStereo.Init ( iJACKBufferSizeStero ); + + return iJACKBufferSizeMono; +*/ + + +// TEST +return 256; + +} + +OSStatus CSound::process ( void* inRefCon, + AudioUnitRenderActionFlags* ioActionFlags, + const AudioTimeStamp* inTimeStamp, + UInt32 inBusNumber, + UInt32 inNumberFrames, + AudioBufferList* ioData ) +{ + CSound* pSound = reinterpret_cast ( inRefCon ); + +/* + // get input data pointer + jack_default_audio_sample_t* in_left = + (jack_default_audio_sample_t*) jack_port_get_buffer ( + pSound->input_port_left, nframes ); + + jack_default_audio_sample_t* in_right = + (jack_default_audio_sample_t*) jack_port_get_buffer ( + pSound->input_port_right, nframes ); + + // copy input data + for ( i = 0; i < pSound->iJACKBufferSizeMono; i++ ) + { + pSound->vecsTmpAudioSndCrdStereo[2 * i] = (short) ( in_left[i] * _MAXSHORT ); + pSound->vecsTmpAudioSndCrdStereo[2 * i + 1] = (short) ( in_right[i] * _MAXSHORT ); + } + + // call processing callback function + pSound->ProcessCallback ( pSound->vecsTmpAudioSndCrdStereo ); + + // get output data pointer + jack_default_audio_sample_t* out_left = + (jack_default_audio_sample_t*) jack_port_get_buffer ( + pSound->output_port_left, nframes ); + + jack_default_audio_sample_t* out_right = + (jack_default_audio_sample_t*) jack_port_get_buffer ( + pSound->output_port_right, nframes ); + + // copy output data + for ( i = 0; i < pSound->iJACKBufferSizeMono; i++ ) + { + out_left[i] = (jack_default_audio_sample_t) + pSound->vecsTmpAudioSndCrdStereo[2 * i] / _MAXSHORT; + + out_right[i] = (jack_default_audio_sample_t) + pSound->vecsTmpAudioSndCrdStereo[2 * i + 1] / _MAXSHORT; + } +*/ +/* + ioData->mBuffers[0].mDataByteSize = 2048; + ioData->mBuffers[0].mData = lbuf; + ioData->mBuffers[0].mNumberChannels = 1; +*/ + +// TEST +printf ( "processing Core Audio\n" ); + + return noErr; +} diff --git a/mac/sound.h b/mac/sound.h index 2eab049e..0b2e01fc 100755 --- a/mac/sound.h +++ b/mac/sound.h @@ -25,6 +25,8 @@ #if !defined(_SOUND_H__9518A621345F78_363456876UZGSDF82CF549__INCLUDED_) #define _SOUND_H__9518A621345F78_363456876UZGSDF82CF549__INCLUDED_ +#include +#include #include "util.h" #include "soundbase.h" #include "global.h" @@ -35,20 +37,29 @@ class CSound : public CSoundBase { public: CSound ( void (*fpNewProcessCallback) ( CVector& psData, void* arg ), void* arg ) : - CSoundBase ( true, fpNewProcessCallback, arg ) { OpenJack(); } - virtual ~CSound() {} + CSoundBase ( true, fpNewProcessCallback, arg ) { OpenCoreAudio(); } + virtual ~CSound() { CloseCoreAudio(); } virtual int Init ( const int iNewPrefMonoBufferSize ); virtual void Start(); virtual void Stop(); // not implemented yet, always return one device and default string - int GetNumDev() { return 1; } - QString GetDeviceName ( const int iDiD ) { return "CoreAudio"; } - QString SetDev ( const int iNewDev ) { return ""; } // dummy - int GetDev() { return 0; } + int GetNumDev() { return 1; } + QString GetDeviceName ( const int ) { return "CoreAudio"; } + QString SetDev ( const int ) { return ""; } // dummy + int GetDev() { return 0; } protected: + void OpenCoreAudio(); + void CloseCoreAudio(); + + // callbacks + static OSStatus process ( void* inRefCon,AudioUnitRenderActionFlags* ioActionFlags, + const AudioTimeStamp* inTimeStamp, UInt32 inBusNumber, UInt32 inNumberFrames, + AudioBufferList* ioData ); + + AudioUnit gOutputUnit; }; #endif // !defined(_SOUND_H__9518A621345F78_363456876UZGSDF82CF549__INCLUDED_) diff --git a/src/client.h b/src/client.h index 944b73f6..7d958ee4 100755 --- a/src/client.h +++ b/src/client.h @@ -43,10 +43,14 @@ # ifdef _WIN32 # include "../windows/sound.h" # else -# include "../linux/sound.h" -# include -# include -# include +# if defined ( __APPLE__ ) || defined ( __MACOSX ) +# include "../mac/sound.h" +# else +# include "../linux/sound.h" +# include +# include +# include +# endif # endif #endif diff --git a/src/llconclientdlg.cpp b/src/llconclientdlg.cpp index 13141f07..7246d1ee 100755 --- a/src/llconclientdlg.cpp +++ b/src/llconclientdlg.cpp @@ -442,7 +442,7 @@ void CLlconClientDlg::OnSliderAudInFader ( int value ) UpdateAudioFaderSlider(); } -void CLlconClientDlg::OnLineEditServerAddrTextChanged ( const QString sNewText ) +void CLlconClientDlg::OnLineEditServerAddrTextChanged ( const QString ) { // if the maximum number of items in the combo box is reached, // delete the last item so that the new item can be added (first diff --git a/src/llconclientdlg.h b/src/llconclientdlg.h index 1b9f7359..de7535d3 100755 --- a/src/llconclientdlg.h +++ b/src/llconclientdlg.h @@ -114,7 +114,7 @@ public slots: void OnChatTextReceived ( QString strChatText ); void OnNewLocalInputText ( QString strChatText ) { pClient->SendTextMess ( strChatText ); } - void OnLineEditServerAddrTextChanged ( const QString sNewText ); + void OnLineEditServerAddrTextChanged ( const QString ); void OnLineEditServerAddrActivated ( int index ); void OnDisconnected(); void OnStopped();