------------------------------------------------------------------------------- Technical Note #2730 Product: LanScape VOIP Media Engine, v5.10 (also includes previous versions). Date: 11-16-04 Rev: 03 LanScape Corporation. ------------------------------------------------------------------------------- Topic: How to implement transmit and receive dynamic mute functions using the LanScape VOIP Media Engine. Overview: Using the instruction in this tech note, software developers will be able to implement simple audio transmit and receive mute functions in thier applications. By following the instruction in this tech note, you will be able to mute your microphone so the far end person(s) will not be able to hear you talk. Also, you will be able to mute the far end person(s) so you will not be able to hear them. We will be using the undocumented SetPlaybackMixerCallback() and SetAudioRecordCallback() API procedures. Note: Because these instruction depend on capabilities that have not officially been released, the API additions described here may change slightly when a new VOIP Media Engine versions become available. Also, application developers should only use this capability after determining that they can not use the normal HoldLine() API procedure to mute phone call audio. ------------------------------------------------------------------------------- Step 1) Add new include file definitions: Add the following structure definitions, typedefs and function prototypes to your SipTelephonyApi.h header file: // data struct passed to a user registered playback mixer complete callback proc. // typedef struct { AUDIO_BANDWIDTH AudioBandwidth; // represents the format and rate of the sampled data. void *pSampleBuffer; // address of the sample buffer. unsigned long BufferLengthInBytes; // the number of bytes in the sample buffer. void *pUserData; // the user supplied callback data. this will be // set to the same value that was specified when // the SetPlaybackMixerCallback() proc was called. }PLAYBACK_MIXER_DATA; // data struct passed to a user registered callback proc. It allows application // software to access raw recorded audio buffers. // typedef struct { AUDIO_BANDWIDTH AudioBandwidth; // represents the format and rate of the sampled data. void *pSampleBuffer; // address of the sample buffer. unsigned long BufferLengthInBytes; // the number of bytes in the sample buffer. void *pUserData; // the user supplied callback data. this will // be set to the same value that was specified // when SetAudioRecordCallback() proc was called. }AUDIO_RECORD_DATA; typedef BOOL (*PLAYBACK_MIXER_CALLBACK_PROC)(PLAYBACK_MIXER_DATA *pPlaybackMixerData); typedef BOOL (*AUDIO_RECORD_CALLBACK_PROC)(AUDIO_RECORD_DATA *pAudioRecordData); // These two function prototypes must be placed inside the extern "C" block inside // the header file. If you do not put these inside the extern "C" block, you will // get "unresolved external symbol" link errors. // TELEPHONY_RETURN_VALUE SetPlaybackMixerCallback( SIPHANDLE hStateMachine, AUDIO_BANDWIDTH DesiredBandwidth, PLAYBACK_MIXER_CALLBACK_PROC pMixerReadyCallback, void *pUserData); TELEPHONY_RETURN_VALUE SetAudioRecordCallback( SIPHANDLE hStateMachine, AUDIO_BANDWIDTH DesiredBandwidth, AUDIO_RECORD_CALLBACK_PROC pAudioRecordCallback, void *pUserData); Step 2) Define callback procedures: Define 2 new callback procedures like the following: //////////////////////////////////////////////////////////////////////// // // The telephony engine's master playback mixer is sending us mixed // audio data. This proc is called directly by the telephony engine. // Return the following: // // TRUE - If you return TRUE to the telephony engine, he will // playback the sample buffer as normal. // // FALSE - If you return FALSE to the telephony engine, he will // not play back the specified sample buffer using the host's // multimedia hardware. // //////////////////////////////////////////////////////////////////////// BOOL MediaEngineMasterPlaybackMixerComplete(PLAYBACK_MIXER_DATA *pPlaybackMixerData) { BOOL PlaySamplesOnHost = TRUE; // This is where your application would determine if it wants to // "mute" all received audio from all of the phone lines and aux // audio outputs. Your application should perform a simple // check to see if muting is required. Do not perform GUI or other // blocking operations in this callback. return(PlaySamplesOnHost); } //////////////////////////////////////////////////////////////////////// // // The telephony engine's audio record function is informing us that he has // recorded audio data. This proc is called directly by the telephony engine. // Return the following: // // TRUE - If you return TRUE to the telephony engine, he will // ignore the current recoreded audio buffer. It can be // used to "mute" recorded audio that is normally played // to the phone lines. Good for muting the local microphone // input. // // FALSE - If you return FALSE to the telephony engine, he will // continue to process the recorded audio data as normal. // //////////////////////////////////////////////////////////////////////// BOOL MediaEngineRecordComplete(AUDIO_RECORD_DATA *pAudioRecordData) { BOOL MuteRecordedAudio = FALSE; // This is where your application would determine if it wants to // "mute" recorded audio that is sent to all phone lines. // Your application should perform a simple // check to see if muting is required. Do not perform GUI or other // blocking operations in this callback. return(MuteRecordedAudio); } Step 3) Register the previous callback procs with the VOIP Media Engine. This can be done anytime after your application calls the StartSipTelephony() API procedure. Note: When you call the SetPlaybackMixerCallback() and SetAudioRecordCallback() APIs, make sure the values you specify for the "pUserData" parameters are not NULL. If you do not need instance data specified, just set the "pUserData" parameter values to (void *)1. // allow the telephony engine's master playback mixer to call // us whenever it has audio data. status = SetPlaybackMixerCallback( hSipEngine, // handle to telephony engine. AUDIO_BW_PCM_22K, // desired data type. MediaEngineMasterPlaybackMixerComplete, // our callback handler. (void *)1 // callback instance data. ); if(status != SipSuccess) { // handle the error. } // allow the telephony engine's audio record function to call // us whenever it has audio data recorded. status = SetAudioRecordCallback( hSipEngine, // handle to telephony engine. AUDIO_BW_PCM_22K, // desired data type. MediaEngineRecordComplete, // our callback handler. (void *)1 // callback instance data. ); if(status != SipSuccess) { // handle the error. } ------------------------------------------------------------------------------- End Technical Note #2730. -------------------------------------------------------------------------------