1470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com/* 29a065d1eae9ed296e1e2eaaad73d7ca1223bfe79mflodman@webrtc.org * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. 3470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com * 4470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com * Use of this source code is governed by a BSD-style license 5470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com * that can be found in the LICENSE file in the root of the source 6470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com * tree. An additional intellectual property rights grant can be found 7470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com * in the file PATENTS. All contributing project authors may 8470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com * be found in the AUTHORS file in the root of the source tree. 9470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com */ 10470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 1150b2efef6ecb51a9d5818345c58533c5d236ec29andrew@webrtc.org#include "webrtc/voice_engine/output_mixer.h" 12470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 136955870806624479723addfae6dcf5d13968796cPeter Kasting#include "webrtc/base/format_macros.h" 1450b2efef6ecb51a9d5818345c58533c5d236ec29andrew@webrtc.org#include "webrtc/modules/audio_processing/include/audio_processing.h" 15ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander#include "webrtc/modules/utility/include/audio_frame_operations.h" 1698f53510b222f71fdd8b799b2f33737ceeb28c61Henrik Kjellander#include "webrtc/system_wrappers/include/critical_section_wrapper.h" 1798f53510b222f71fdd8b799b2f33737ceeb28c61Henrik Kjellander#include "webrtc/system_wrappers/include/file_wrapper.h" 1898f53510b222f71fdd8b799b2f33737ceeb28c61Henrik Kjellander#include "webrtc/system_wrappers/include/trace.h" 1950b2efef6ecb51a9d5818345c58533c5d236ec29andrew@webrtc.org#include "webrtc/voice_engine/include/voe_external_media.h" 2050b2efef6ecb51a9d5818345c58533c5d236ec29andrew@webrtc.org#include "webrtc/voice_engine/statistics.h" 2140ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org#include "webrtc/voice_engine/utility.h" 22470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 23470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comnamespace webrtc { 24470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comnamespace voe { 25470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 26470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comvoid 279213521ea98b0977c7cdabd2853060835af226f3pbos@webrtc.orgOutputMixer::NewMixedAudio(int32_t id, 28470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com const AudioFrame& generalAudioFrame, 29470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com const AudioFrame** uniqueAudioFrames, 309213521ea98b0977c7cdabd2853060835af226f3pbos@webrtc.org uint32_t size) 31470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{ 32470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,-1), 33470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "OutputMixer::NewMixedAudio(id=%d, size=%u)", id, size); 34470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 35ae1a58bba4f926d149a5f39243269c3f6625f494andrew@webrtc.org _audioFrame.CopyFrom(generalAudioFrame); 3663a509858d3988299726640c664b699d6229a1d4andrew@webrtc.org _audioFrame.id_ = id; 37470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com} 38470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 399213521ea98b0977c7cdabd2853060835af226f3pbos@webrtc.orgvoid OutputMixer::PlayNotification(int32_t id, uint32_t durationMs) 40470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{ 41470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,-1), 42470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "OutputMixer::PlayNotification(id=%d, durationMs=%d)", 43470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com id, durationMs); 44470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com // Not implement yet 45470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com} 46470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 479213521ea98b0977c7cdabd2853060835af226f3pbos@webrtc.orgvoid OutputMixer::RecordNotification(int32_t id, 489213521ea98b0977c7cdabd2853060835af226f3pbos@webrtc.org uint32_t durationMs) 49470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{ 50470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,-1), 51470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "OutputMixer::RecordNotification(id=%d, durationMs=%d)", 52470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com id, durationMs); 53470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 54470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com // Not implement yet 55470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com} 56470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 579213521ea98b0977c7cdabd2853060835af226f3pbos@webrtc.orgvoid OutputMixer::PlayFileEnded(int32_t id) 58470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{ 59470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,-1), 60470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "OutputMixer::PlayFileEnded(id=%d)", id); 61470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 62470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com // not needed 63470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com} 64470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 659213521ea98b0977c7cdabd2853060835af226f3pbos@webrtc.orgvoid OutputMixer::RecordFileEnded(int32_t id) 66470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{ 67470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,-1), 68470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "OutputMixer::RecordFileEnded(id=%d)", id); 69470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com assert(id == _instanceId); 70470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 719a065d1eae9ed296e1e2eaaad73d7ca1223bfe79mflodman@webrtc.org CriticalSectionScoped cs(&_fileCritSect); 72470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _outputFileRecording = false; 73470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com WEBRTC_TRACE(kTraceStateInfo, kTraceVoice, VoEId(_instanceId,-1), 74470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "OutputMixer::RecordFileEnded() =>" 75470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "output file recorder module is shutdown"); 76470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com} 77470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 786141e13873d0fdea626de08dfec2efa2c9171c76pbos@webrtc.orgint32_t 799213521ea98b0977c7cdabd2853060835af226f3pbos@webrtc.orgOutputMixer::Create(OutputMixer*& mixer, uint32_t instanceId) 80470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{ 81470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com WEBRTC_TRACE(kTraceMemory, kTraceVoice, instanceId, 82470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "OutputMixer::Create(instanceId=%d)", instanceId); 83470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com mixer = new OutputMixer(instanceId); 84470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com if (mixer == NULL) 85470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 86470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com WEBRTC_TRACE(kTraceMemory, kTraceVoice, instanceId, 87470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "OutputMixer::Create() unable to allocate memory for" 88470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "mixer"); 89470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return -1; 90470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 91470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return 0; 92470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com} 93470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 949213521ea98b0977c7cdabd2853060835af226f3pbos@webrtc.orgOutputMixer::OutputMixer(uint32_t instanceId) : 95470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _callbackCritSect(*CriticalSectionWrapper::CreateCriticalSection()), 96470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _fileCritSect(*CriticalSectionWrapper::CreateCriticalSection()), 97c4f129f97c6e285ba9f82cacafdb1281996150a4andrew@webrtc.org _mixerModule(*AudioConferenceMixer::Create(instanceId)), 98470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _audioLevel(), 9922963abffe4179e75f18a2e7be1d1c58c9518089xians@google.com _dtmfGenerator(instanceId), 10022963abffe4179e75f18a2e7be1d1c58c9518089xians@google.com _instanceId(instanceId), 10122963abffe4179e75f18a2e7be1d1c58c9518089xians@google.com _externalMediaCallbackPtr(NULL), 102470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _externalMedia(false), 103470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _panLeft(1.0f), 104470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _panRight(1.0f), 10522963abffe4179e75f18a2e7be1d1c58c9518089xians@google.com _mixingFrequencyHz(8000), 10622963abffe4179e75f18a2e7be1d1c58c9518089xians@google.com _outputFileRecorderPtr(NULL), 10722963abffe4179e75f18a2e7be1d1c58c9518089xians@google.com _outputFileRecording(false) 108470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{ 109470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com WEBRTC_TRACE(kTraceMemory, kTraceVoice, VoEId(_instanceId,-1), 110470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "OutputMixer::OutputMixer() - ctor"); 111ae1a58bba4f926d149a5f39243269c3f6625f494andrew@webrtc.org 1120f4b3731c34e796da92572380855dbc7321c8cfeminyuel if (_mixerModule.RegisterMixedStreamCallback(this) == -1) 113470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 114470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com WEBRTC_TRACE(kTraceError, kTraceVoice, VoEId(_instanceId,-1), 115470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "OutputMixer::OutputMixer() failed to register mixer" 116470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "callbacks"); 117470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 118ae1a58bba4f926d149a5f39243269c3f6625f494andrew@webrtc.org 119470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _dtmfGenerator.Init(); 120470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com} 121470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 122470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comvoid 123470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comOutputMixer::Destroy(OutputMixer*& mixer) 124470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{ 125470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com if (mixer) 126470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 127470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com delete mixer; 128470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com mixer = NULL; 129470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 130470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com} 131ae1a58bba4f926d149a5f39243269c3f6625f494andrew@webrtc.org 132470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comOutputMixer::~OutputMixer() 133470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{ 134470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com WEBRTC_TRACE(kTraceMemory, kTraceVoice, VoEId(_instanceId,-1), 135470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "OutputMixer::~OutputMixer() - dtor"); 136470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com if (_externalMedia) 137470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 138470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com DeRegisterExternalMediaProcessing(); 139470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 140470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 1419a065d1eae9ed296e1e2eaaad73d7ca1223bfe79mflodman@webrtc.org CriticalSectionScoped cs(&_fileCritSect); 142470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com if (_outputFileRecorderPtr) 143470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 144470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _outputFileRecorderPtr->RegisterModuleFileCallback(NULL); 145470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _outputFileRecorderPtr->StopRecording(); 146470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com FileRecorder::DestroyFileRecorder(_outputFileRecorderPtr); 147470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _outputFileRecorderPtr = NULL; 148470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 149470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 150470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _mixerModule.UnRegisterMixedStreamCallback(); 151470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com delete &_mixerModule; 152470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com delete &_callbackCritSect; 153470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com delete &_fileCritSect; 154470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com} 155470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 1566141e13873d0fdea626de08dfec2efa2c9171c76pbos@webrtc.orgint32_t 157470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comOutputMixer::SetEngineInformation(voe::Statistics& engineStatistics) 158470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{ 159470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,-1), 160470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "OutputMixer::SetEngineInformation()"); 161470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _engineStatisticsPtr = &engineStatistics; 162470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return 0; 163470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com} 164470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 1656141e13873d0fdea626de08dfec2efa2c9171c76pbos@webrtc.orgint32_t 1666141e13873d0fdea626de08dfec2efa2c9171c76pbos@webrtc.orgOutputMixer::SetAudioProcessingModule(AudioProcessing* audioProcessingModule) 167470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{ 168470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,-1), 169470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "OutputMixer::SetAudioProcessingModule(" 170470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "audioProcessingModule=0x%x)", audioProcessingModule); 171470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _audioProcessingModulePtr = audioProcessingModule; 172470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return 0; 173470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com} 174470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 175470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint OutputMixer::RegisterExternalMediaProcessing( 176470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com VoEMediaProcess& proccess_object) 177470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{ 178470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,-1), 179470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "OutputMixer::RegisterExternalMediaProcessing()"); 180470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 1819a065d1eae9ed296e1e2eaaad73d7ca1223bfe79mflodman@webrtc.org CriticalSectionScoped cs(&_callbackCritSect); 182470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _externalMediaCallbackPtr = &proccess_object; 183470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _externalMedia = true; 184470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 185470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return 0; 186470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com} 187470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 188470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint OutputMixer::DeRegisterExternalMediaProcessing() 189470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{ 190470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,-1), 191470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "OutputMixer::DeRegisterExternalMediaProcessing()"); 192470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 1939a065d1eae9ed296e1e2eaaad73d7ca1223bfe79mflodman@webrtc.org CriticalSectionScoped cs(&_callbackCritSect); 194470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _externalMedia = false; 195470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _externalMediaCallbackPtr = NULL; 196470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 197470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return 0; 198470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com} 199470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 2006141e13873d0fdea626de08dfec2efa2c9171c76pbos@webrtc.orgint OutputMixer::PlayDtmfTone(uint8_t eventCode, int lengthMs, 201470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com int attenuationDb) 202470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{ 203470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, -1), 204470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "OutputMixer::PlayDtmfTone()"); 205470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com if (_dtmfGenerator.AddTone(eventCode, lengthMs, attenuationDb) != 0) 206470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 207470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _engineStatisticsPtr->SetLastError(VE_STILL_PLAYING_PREV_DTMF, 208470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com kTraceError, 209470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "OutputMixer::PlayDtmfTone()"); 210470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return -1; 211470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 212470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return 0; 213470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com} 214470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 2156141e13873d0fdea626de08dfec2efa2c9171c76pbos@webrtc.orgint32_t 216470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comOutputMixer::SetMixabilityStatus(MixerParticipant& participant, 2179213521ea98b0977c7cdabd2853060835af226f3pbos@webrtc.org bool mixable) 218470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{ 2190f4b3731c34e796da92572380855dbc7321c8cfeminyuel return _mixerModule.SetMixabilityStatus(&participant, mixable); 220470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com} 221470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 2226141e13873d0fdea626de08dfec2efa2c9171c76pbos@webrtc.orgint32_t 223066f9e5a2fbb8e83ef88ceca0ab5a4ea057cc619henrike@webrtc.orgOutputMixer::SetAnonymousMixabilityStatus(MixerParticipant& participant, 2249213521ea98b0977c7cdabd2853060835af226f3pbos@webrtc.org bool mixable) 225066f9e5a2fbb8e83ef88ceca0ab5a4ea057cc619henrike@webrtc.org{ 2260f4b3731c34e796da92572380855dbc7321c8cfeminyuel return _mixerModule.SetAnonymousMixabilityStatus(&participant, mixable); 227066f9e5a2fbb8e83ef88ceca0ab5a4ea057cc619henrike@webrtc.org} 228066f9e5a2fbb8e83ef88ceca0ab5a4ea057cc619henrike@webrtc.org 2296141e13873d0fdea626de08dfec2efa2c9171c76pbos@webrtc.orgint32_t 230470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comOutputMixer::MixActiveChannels() 231470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{ 232470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return _mixerModule.Process(); 233470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com} 234470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 235470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint 2366141e13873d0fdea626de08dfec2efa2c9171c76pbos@webrtc.orgOutputMixer::GetSpeechOutputLevel(uint32_t& level) 237470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{ 2386141e13873d0fdea626de08dfec2efa2c9171c76pbos@webrtc.org int8_t currentLevel = _audioLevel.Level(); 2396141e13873d0fdea626de08dfec2efa2c9171c76pbos@webrtc.org level = static_cast<uint32_t> (currentLevel); 240470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com WEBRTC_TRACE(kTraceStateInfo, kTraceVoice, VoEId(_instanceId,-1), 241470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "GetSpeechOutputLevel() => level=%u", level); 242470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return 0; 243470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com} 244470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 245470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint 2466141e13873d0fdea626de08dfec2efa2c9171c76pbos@webrtc.orgOutputMixer::GetSpeechOutputLevelFullRange(uint32_t& level) 247470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{ 2486141e13873d0fdea626de08dfec2efa2c9171c76pbos@webrtc.org int16_t currentLevel = _audioLevel.LevelFullRange(); 2496141e13873d0fdea626de08dfec2efa2c9171c76pbos@webrtc.org level = static_cast<uint32_t> (currentLevel); 250470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com WEBRTC_TRACE(kTraceStateInfo, kTraceVoice, VoEId(_instanceId,-1), 251470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "GetSpeechOutputLevelFullRange() => level=%u", level); 252470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return 0; 253470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com} 254470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 255470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint 256470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comOutputMixer::SetOutputVolumePan(float left, float right) 257470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{ 258470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,-1), 259470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "OutputMixer::SetOutputVolumePan()"); 260470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _panLeft = left; 261470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _panRight = right; 262470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return 0; 263470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com} 264470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 265470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint 266470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comOutputMixer::GetOutputVolumePan(float& left, float& right) 267470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{ 268470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com left = _panLeft; 269470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com right = _panRight; 270470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com WEBRTC_TRACE(kTraceStateInfo, kTraceVoice, VoEId(_instanceId,-1), 271470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "GetOutputVolumePan() => left=%2.1f, right=%2.1f", 272470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com left, right); 273470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return 0; 274470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com} 275470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 276470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint OutputMixer::StartRecordingPlayout(const char* fileName, 277470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com const CodecInst* codecInst) 278470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{ 279470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,-1), 280470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "OutputMixer::StartRecordingPlayout(fileName=%s)", fileName); 281470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 282470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com if (_outputFileRecording) 283470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 284470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId,-1), 285470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "StartRecordingPlayout() is already recording"); 286470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return 0; 287470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 288470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 289470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com FileFormats format; 2906141e13873d0fdea626de08dfec2efa2c9171c76pbos@webrtc.org const uint32_t notificationTime(0); 291470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com CodecInst dummyCodec={100,"L16",16000,320,1,320000}; 292470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 29340197d7b3b347f05b299a930641dad131c853e01niklas.enbom@webrtc.org if ((codecInst != NULL) && 29440197d7b3b347f05b299a930641dad131c853e01niklas.enbom@webrtc.org ((codecInst->channels < 1) || (codecInst->channels > 2))) 295470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 296470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _engineStatisticsPtr->SetLastError( 297470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com VE_BAD_ARGUMENT, kTraceError, 298470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "StartRecordingPlayout() invalid compression"); 299470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return(-1); 300470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 301470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com if(codecInst == NULL) 302470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 303470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com format = kFileFormatPcm16kHzFile; 304470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com codecInst=&dummyCodec; 305470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 306470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com else if((STR_CASE_CMP(codecInst->plname,"L16") == 0) || 307470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com (STR_CASE_CMP(codecInst->plname,"PCMU") == 0) || 308470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com (STR_CASE_CMP(codecInst->plname,"PCMA") == 0)) 309470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 310470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com format = kFileFormatWavFile; 311470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 312470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com else 313470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 314470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com format = kFileFormatCompressedFile; 315470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 316470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 3179a065d1eae9ed296e1e2eaaad73d7ca1223bfe79mflodman@webrtc.org CriticalSectionScoped cs(&_fileCritSect); 318ae1a58bba4f926d149a5f39243269c3f6625f494andrew@webrtc.org 319470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com // Destroy the old instance 320470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com if (_outputFileRecorderPtr) 321470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 322470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _outputFileRecorderPtr->RegisterModuleFileCallback(NULL); 323470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com FileRecorder::DestroyFileRecorder(_outputFileRecorderPtr); 324470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _outputFileRecorderPtr = NULL; 325470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 326470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 327470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _outputFileRecorderPtr = FileRecorder::CreateFileRecorder( 328470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _instanceId, 329470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com (const FileFormats)format); 330470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com if (_outputFileRecorderPtr == NULL) 331470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 332470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _engineStatisticsPtr->SetLastError( 333470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com VE_INVALID_ARGUMENT, kTraceError, 334470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "StartRecordingPlayout() fileRecorder format isnot correct"); 335470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return -1; 336470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 337470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 338470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com if (_outputFileRecorderPtr->StartRecordingAudioFile( 339470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com fileName, 340470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com (const CodecInst&)*codecInst, 341470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com notificationTime) != 0) 342470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 343470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _engineStatisticsPtr->SetLastError( 344470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com VE_BAD_FILE, kTraceError, 345470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "StartRecordingAudioFile() failed to start file recording"); 346470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _outputFileRecorderPtr->StopRecording(); 347470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com FileRecorder::DestroyFileRecorder(_outputFileRecorderPtr); 348470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _outputFileRecorderPtr = NULL; 349470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return -1; 350470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 351470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _outputFileRecorderPtr->RegisterModuleFileCallback(this); 352470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _outputFileRecording = true; 353470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 354470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return 0; 355470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com} 356470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 357470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint OutputMixer::StartRecordingPlayout(OutStream* stream, 358470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com const CodecInst* codecInst) 359470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{ 360470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,-1), 361470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "OutputMixer::StartRecordingPlayout()"); 362470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 363470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com if (_outputFileRecording) 364470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 365470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId,-1), 366470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "StartRecordingPlayout() is already recording"); 367470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return 0; 368470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 369470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 370470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com FileFormats format; 3716141e13873d0fdea626de08dfec2efa2c9171c76pbos@webrtc.org const uint32_t notificationTime(0); 372470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com CodecInst dummyCodec={100,"L16",16000,320,1,320000}; 373470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 374470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com if (codecInst != NULL && codecInst->channels != 1) 375470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 376470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _engineStatisticsPtr->SetLastError( 377470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com VE_BAD_ARGUMENT, kTraceError, 378470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "StartRecordingPlayout() invalid compression"); 379470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return(-1); 380470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 381470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com if(codecInst == NULL) 382470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 383470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com format = kFileFormatPcm16kHzFile; 384470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com codecInst=&dummyCodec; 385470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 386470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com else if((STR_CASE_CMP(codecInst->plname,"L16") == 0) || 387470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com (STR_CASE_CMP(codecInst->plname,"PCMU") == 0) || 388470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com (STR_CASE_CMP(codecInst->plname,"PCMA") == 0)) 389470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 390470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com format = kFileFormatWavFile; 391470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 392470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com else 393470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 394470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com format = kFileFormatCompressedFile; 395470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 396470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 3979a065d1eae9ed296e1e2eaaad73d7ca1223bfe79mflodman@webrtc.org CriticalSectionScoped cs(&_fileCritSect); 398470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 399470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com // Destroy the old instance 400470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com if (_outputFileRecorderPtr) 401470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 402470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _outputFileRecorderPtr->RegisterModuleFileCallback(NULL); 403470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com FileRecorder::DestroyFileRecorder(_outputFileRecorderPtr); 404470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _outputFileRecorderPtr = NULL; 405470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 406470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 407470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _outputFileRecorderPtr = FileRecorder::CreateFileRecorder( 408470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _instanceId, 409470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com (const FileFormats)format); 410470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com if (_outputFileRecorderPtr == NULL) 411470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 412470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _engineStatisticsPtr->SetLastError( 413470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com VE_INVALID_ARGUMENT, kTraceError, 414470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "StartRecordingPlayout() fileRecorder format isnot correct"); 415470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return -1; 416470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 417470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 418470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com if (_outputFileRecorderPtr->StartRecordingAudioFile(*stream, 419470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com *codecInst, 420470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com notificationTime) != 0) 421470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 422470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _engineStatisticsPtr->SetLastError(VE_BAD_FILE, kTraceError, 4234ecea3e1057eebf846af9b93abf8faf8571bc576andrew@webrtc.org "StartRecordingAudioFile() failed to start file recording"); 424470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _outputFileRecorderPtr->StopRecording(); 425470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com FileRecorder::DestroyFileRecorder(_outputFileRecorderPtr); 426470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _outputFileRecorderPtr = NULL; 427470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return -1; 428470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 4294ecea3e1057eebf846af9b93abf8faf8571bc576andrew@webrtc.org 430470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _outputFileRecorderPtr->RegisterModuleFileCallback(this); 431470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _outputFileRecording = true; 432470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 433470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return 0; 434470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com} 435470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 436470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint OutputMixer::StopRecordingPlayout() 437470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{ 438470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,-1), 439470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "OutputMixer::StopRecordingPlayout()"); 440470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 441470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com if (!_outputFileRecording) 442470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 443470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com WEBRTC_TRACE(kTraceError, kTraceVoice, VoEId(_instanceId,-1), 444470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "StopRecordingPlayout() file isnot recording"); 445470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return -1; 446470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 447470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 4489a065d1eae9ed296e1e2eaaad73d7ca1223bfe79mflodman@webrtc.org CriticalSectionScoped cs(&_fileCritSect); 449470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 450470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com if (_outputFileRecorderPtr->StopRecording() != 0) 451470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 452470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _engineStatisticsPtr->SetLastError( 453470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com VE_STOP_RECORDING_FAILED, kTraceError, 454470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "StopRecording(), could not stop recording"); 455470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return -1; 456470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 457470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _outputFileRecorderPtr->RegisterModuleFileCallback(NULL); 458470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com FileRecorder::DestroyFileRecorder(_outputFileRecorderPtr); 459470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _outputFileRecorderPtr = NULL; 460470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _outputFileRecording = false; 461470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 462470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return 0; 463470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com} 464470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 4654ecea3e1057eebf846af9b93abf8faf8571bc576andrew@webrtc.orgint OutputMixer::GetMixedAudio(int sample_rate_hz, 4666955870806624479723addfae6dcf5d13968796cPeter Kasting size_t num_channels, 4674ecea3e1057eebf846af9b93abf8faf8571bc576andrew@webrtc.org AudioFrame* frame) { 4686955870806624479723addfae6dcf5d13968796cPeter Kasting WEBRTC_TRACE( 4696955870806624479723addfae6dcf5d13968796cPeter Kasting kTraceStream, kTraceVoice, VoEId(_instanceId,-1), 4706955870806624479723addfae6dcf5d13968796cPeter Kasting "OutputMixer::GetMixedAudio(sample_rate_hz=%d, num_channels=%" PRIuS ")", 4716955870806624479723addfae6dcf5d13968796cPeter Kasting sample_rate_hz, num_channels); 472470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 4734ecea3e1057eebf846af9b93abf8faf8571bc576andrew@webrtc.org // --- Record playout if enabled 4744ecea3e1057eebf846af9b93abf8faf8571bc576andrew@webrtc.org { 4754ecea3e1057eebf846af9b93abf8faf8571bc576andrew@webrtc.org CriticalSectionScoped cs(&_fileCritSect); 4764ecea3e1057eebf846af9b93abf8faf8571bc576andrew@webrtc.org if (_outputFileRecording && _outputFileRecorderPtr) 4774ecea3e1057eebf846af9b93abf8faf8571bc576andrew@webrtc.org _outputFileRecorderPtr->RecordAudioToFile(_audioFrame); 4784ecea3e1057eebf846af9b93abf8faf8571bc576andrew@webrtc.org } 479470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 4804ecea3e1057eebf846af9b93abf8faf8571bc576andrew@webrtc.org frame->num_channels_ = num_channels; 4814ecea3e1057eebf846af9b93abf8faf8571bc576andrew@webrtc.org frame->sample_rate_hz_ = sample_rate_hz; 4824ecea3e1057eebf846af9b93abf8faf8571bc576andrew@webrtc.org // TODO(andrew): Ideally the downmixing would occur much earlier, in 4834ecea3e1057eebf846af9b93abf8faf8571bc576andrew@webrtc.org // AudioCodingModule. 48440ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org RemixAndResample(_audioFrame, &resampler_, frame); 48540ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org return 0; 486470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com} 487470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 4886141e13873d0fdea626de08dfec2efa2c9171c76pbos@webrtc.orgint32_t 4895692531f18cae04d8a8107793dc74ae932bdf219xians@webrtc.orgOutputMixer::DoOperationsOnCombinedSignal(bool feed_data_to_apm) 490470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{ 49163a509858d3988299726640c664b699d6229a1d4andrew@webrtc.org if (_audioFrame.sample_rate_hz_ != _mixingFrequencyHz) 492470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 493470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,-1), 494470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "OutputMixer::DoOperationsOnCombinedSignal() => " 49563a509858d3988299726640c664b699d6229a1d4andrew@webrtc.org "mixing frequency = %d", _audioFrame.sample_rate_hz_); 49663a509858d3988299726640c664b699d6229a1d4andrew@webrtc.org _mixingFrequencyHz = _audioFrame.sample_rate_hz_; 497470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 498470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 499470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com // --- Insert inband Dtmf tone 500470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com if (_dtmfGenerator.IsAddingTone()) 501470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 502470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com InsertInbandDtmfTone(); 503470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 504470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 505470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com // Scale left and/or right channel(s) if balance is active 506470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com if (_panLeft != 1.0 || _panRight != 1.0) 507470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 50863a509858d3988299726640c664b699d6229a1d4andrew@webrtc.org if (_audioFrame.num_channels_ == 1) 509470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 5104ecea3e1057eebf846af9b93abf8faf8571bc576andrew@webrtc.org AudioFrameOperations::MonoToStereo(&_audioFrame); 511470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 512470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com else 513470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 514470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com // Pure stereo mode (we are receiving a stereo signal). 515470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 516470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 51763a509858d3988299726640c664b699d6229a1d4andrew@webrtc.org assert(_audioFrame.num_channels_ == 2); 518470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com AudioFrameOperations::Scale(_panLeft, _panRight, _audioFrame); 519470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 520470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 521470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com // --- Far-end Voice Quality Enhancement (AudioProcessing Module) 52266085beef83c790a69666b9be8a74bb2eee44fabpeah if (feed_data_to_apm) { 52366085beef83c790a69666b9be8a74bb2eee44fabpeah // Convert from mixing to AudioProcessing sample rate, similarly to how it 52466085beef83c790a69666b9be8a74bb2eee44fabpeah // is done on the send side. Downmix to mono. 52566085beef83c790a69666b9be8a74bb2eee44fabpeah AudioFrame frame; 52666085beef83c790a69666b9be8a74bb2eee44fabpeah frame.num_channels_ = 1; 52766085beef83c790a69666b9be8a74bb2eee44fabpeah frame.sample_rate_hz_ = _audioProcessingModulePtr->input_sample_rate_hz(); 52866085beef83c790a69666b9be8a74bb2eee44fabpeah RemixAndResample(_audioFrame, &audioproc_resampler_, &frame); 52966085beef83c790a69666b9be8a74bb2eee44fabpeah 53066085beef83c790a69666b9be8a74bb2eee44fabpeah if (_audioProcessingModulePtr->AnalyzeReverseStream(&frame) != 0) { 53166085beef83c790a69666b9be8a74bb2eee44fabpeah WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId, -1), 53266085beef83c790a69666b9be8a74bb2eee44fabpeah "AudioProcessingModule::AnalyzeReverseStream() => error"); 53366085beef83c790a69666b9be8a74bb2eee44fabpeah RTC_DCHECK(false); 53466085beef83c790a69666b9be8a74bb2eee44fabpeah } 53566085beef83c790a69666b9be8a74bb2eee44fabpeah } 536470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 537470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com // --- External media processing 538470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 5399a065d1eae9ed296e1e2eaaad73d7ca1223bfe79mflodman@webrtc.org CriticalSectionScoped cs(&_callbackCritSect); 540944cbeb2926feb86a687e5fda9e2ac88ea8e3001henrika@webrtc.org if (_externalMedia) 541470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 542944cbeb2926feb86a687e5fda9e2ac88ea8e3001henrika@webrtc.org const bool is_stereo = (_audioFrame.num_channels_ == 2); 543944cbeb2926feb86a687e5fda9e2ac88ea8e3001henrika@webrtc.org if (_externalMediaCallbackPtr) 544944cbeb2926feb86a687e5fda9e2ac88ea8e3001henrika@webrtc.org { 545944cbeb2926feb86a687e5fda9e2ac88ea8e3001henrika@webrtc.org _externalMediaCallbackPtr->Process( 546944cbeb2926feb86a687e5fda9e2ac88ea8e3001henrika@webrtc.org -1, 547944cbeb2926feb86a687e5fda9e2ac88ea8e3001henrika@webrtc.org kPlaybackAllChannelsMixed, 548944cbeb2926feb86a687e5fda9e2ac88ea8e3001henrika@webrtc.org (int16_t*)_audioFrame.data_, 549944cbeb2926feb86a687e5fda9e2ac88ea8e3001henrika@webrtc.org _audioFrame.samples_per_channel_, 550944cbeb2926feb86a687e5fda9e2ac88ea8e3001henrika@webrtc.org _audioFrame.sample_rate_hz_, 551944cbeb2926feb86a687e5fda9e2ac88ea8e3001henrika@webrtc.org is_stereo); 552944cbeb2926feb86a687e5fda9e2ac88ea8e3001henrika@webrtc.org } 553470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 554470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 555470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 556470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com // --- Measure audio level (0-9) for the combined signal 557470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _audioLevel.ComputeLevel(_audioFrame); 558470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 559470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return 0; 560470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com} 561470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 562470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com// ---------------------------------------------------------------------------- 5634ecea3e1057eebf846af9b93abf8faf8571bc576andrew@webrtc.org// Private methods 564470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com// ---------------------------------------------------------------------------- 565470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 566470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint 567470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comOutputMixer::InsertInbandDtmfTone() 568470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{ 5696141e13873d0fdea626de08dfec2efa2c9171c76pbos@webrtc.org uint16_t sampleRate(0); 570470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _dtmfGenerator.GetSampleRate(sampleRate); 57163a509858d3988299726640c664b699d6229a1d4andrew@webrtc.org if (sampleRate != _audioFrame.sample_rate_hz_) 572470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 573470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com // Update sample rate of Dtmf tone since the mixing frequency changed. 574470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _dtmfGenerator.SetSampleRate( 5756141e13873d0fdea626de08dfec2efa2c9171c76pbos@webrtc.org (uint16_t)(_audioFrame.sample_rate_hz_)); 576470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com // Reset the tone to be added taking the new sample rate into account. 577470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _dtmfGenerator.ResetTone(); 578470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 579470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 5806141e13873d0fdea626de08dfec2efa2c9171c76pbos@webrtc.org int16_t toneBuffer[320]; 5816141e13873d0fdea626de08dfec2efa2c9171c76pbos@webrtc.org uint16_t toneSamples(0); 582470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com if (_dtmfGenerator.Get10msTone(toneBuffer, toneSamples) == -1) 583470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 584470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId, -1), 585470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "OutputMixer::InsertInbandDtmfTone() inserting Dtmf" 586470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "tone failed"); 587470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return -1; 588470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 589470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 590470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com // replace mixed audio with Dtmf tone 59163a509858d3988299726640c664b699d6229a1d4andrew@webrtc.org if (_audioFrame.num_channels_ == 1) 592470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 593470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com // mono 5946141e13873d0fdea626de08dfec2efa2c9171c76pbos@webrtc.org memcpy(_audioFrame.data_, toneBuffer, sizeof(int16_t) 595470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com * toneSamples); 596470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } else 597470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 598470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com // stereo 599dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting for (size_t i = 0; i < _audioFrame.samples_per_channel_; i++) 600470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 60163a509858d3988299726640c664b699d6229a1d4andrew@webrtc.org _audioFrame.data_[2 * i] = toneBuffer[i]; 60263a509858d3988299726640c664b699d6229a1d4andrew@webrtc.org _audioFrame.data_[2 * i + 1] = 0; 603470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 604470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 60563a509858d3988299726640c664b699d6229a1d4andrew@webrtc.org assert(_audioFrame.samples_per_channel_ == toneSamples); 606470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 607470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return 0; 608470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com} 609470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 610d900e8bea84c474696bf0219aed1353ce65ffd8epbos@webrtc.org} // namespace voe 611d900e8bea84c474696bf0219aed1353ce65ffd8epbos@webrtc.org} // namespace webrtc 612