140ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org/*
240ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
340ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org *
440ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org *  Use of this source code is governed by a BSD-style license
540ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org *  that can be found in the LICENSE file in the root of the source
640ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org *  tree. An additional intellectual property rights grant can be found
740ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org *  in the file PATENTS.  All contributing project authors may
840ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org *  be found in the AUTHORS file in the root of the source tree.
940ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org */
1040ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org
1140ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org#include "webrtc/voice_engine/transmit_mixer.h"
1240ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org
13dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting#include "webrtc/base/format_macros.h"
14ad856229a796a8efa1126ef8aa8d238f2b0a2b21pbos#include "webrtc/base/logging.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/event_wrapper.h"
1898f53510b222f71fdd8b799b2f33737ceeb28c61Henrik Kjellander#include "webrtc/system_wrappers/include/trace.h"
1940ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org#include "webrtc/voice_engine/channel.h"
2040ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org#include "webrtc/voice_engine/channel_manager.h"
2140ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org#include "webrtc/voice_engine/include/voe_external_media.h"
2240ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org#include "webrtc/voice_engine/statistics.h"
2340ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org#include "webrtc/voice_engine/utility.h"
2440ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org#include "webrtc/voice_engine/voe_base_impl.h"
2540ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org
2640ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.orgnamespace webrtc {
2740ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.orgnamespace voe {
2840ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org
2940ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org// TODO(ajm): The thread safety of this is dubious...
3040ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.orgvoid
3140ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.orgTransmitMixer::OnPeriodicProcess()
3240ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org{
3340ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId, -1),
3440ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org                 "TransmitMixer::OnPeriodicProcess()");
3540ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org
3640ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org#if defined(WEBRTC_VOICE_ENGINE_TYPING_DETECTION)
37302c978c921c2c63e1ab2414f0db03d19d5bfc60solenberg    bool send_typing_noise_warning = false;
38302c978c921c2c63e1ab2414f0db03d19d5bfc60solenberg    bool typing_noise_detected = false;
3940ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    {
40302c978c921c2c63e1ab2414f0db03d19d5bfc60solenberg      CriticalSectionScoped cs(&_critSect);
41302c978c921c2c63e1ab2414f0db03d19d5bfc60solenberg      if (_typingNoiseWarningPending) {
42302c978c921c2c63e1ab2414f0db03d19d5bfc60solenberg        send_typing_noise_warning = true;
43302c978c921c2c63e1ab2414f0db03d19d5bfc60solenberg        typing_noise_detected = _typingNoiseDetected;
44302c978c921c2c63e1ab2414f0db03d19d5bfc60solenberg        _typingNoiseWarningPending = false;
45302c978c921c2c63e1ab2414f0db03d19d5bfc60solenberg      }
46302c978c921c2c63e1ab2414f0db03d19d5bfc60solenberg    }
47302c978c921c2c63e1ab2414f0db03d19d5bfc60solenberg    if (send_typing_noise_warning) {
4840ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org        CriticalSectionScoped cs(&_callbackCritSect);
49302c978c921c2c63e1ab2414f0db03d19d5bfc60solenberg        if (_voiceEngineObserverPtr) {
50302c978c921c2c63e1ab2414f0db03d19d5bfc60solenberg            if (typing_noise_detected) {
5140ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org                WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, -1),
5240ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org                             "TransmitMixer::OnPeriodicProcess() => "
5340ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org                             "CallbackOnError(VE_TYPING_NOISE_WARNING)");
5440ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org                _voiceEngineObserverPtr->CallbackOnError(
5540ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org                    -1,
5640ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org                    VE_TYPING_NOISE_WARNING);
5740ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org            } else {
5840ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org                WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, -1),
5940ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org                             "TransmitMixer::OnPeriodicProcess() => "
6040ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org                             "CallbackOnError(VE_TYPING_NOISE_OFF_WARNING)");
6140ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org                _voiceEngineObserverPtr->CallbackOnError(
6240ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org                    -1,
6340ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org                    VE_TYPING_NOISE_OFF_WARNING);
6440ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org            }
6540ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org        }
6640ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    }
6740ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org#endif
6840ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org
6940ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    bool saturationWarning = false;
7040ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    {
7140ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org      // Modify |_saturationWarning| under lock to avoid conflict with write op
7240ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org      // in ProcessAudio and also ensure that we don't hold the lock during the
7340ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org      // callback.
7440ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org      CriticalSectionScoped cs(&_critSect);
7540ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org      saturationWarning = _saturationWarning;
7640ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org      if (_saturationWarning)
7740ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org        _saturationWarning = false;
7840ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    }
7940ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org
8040ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    if (saturationWarning)
8140ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    {
8240ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org        CriticalSectionScoped cs(&_callbackCritSect);
8340ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org        if (_voiceEngineObserverPtr)
8440ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org        {
8540ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org            WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, -1),
8640ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org                         "TransmitMixer::OnPeriodicProcess() =>"
8740ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org                         " CallbackOnError(VE_SATURATION_WARNING)");
8840ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org            _voiceEngineObserverPtr->CallbackOnError(-1, VE_SATURATION_WARNING);
8940ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org        }
9040ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    }
9140ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org}
9240ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org
9340ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org
9440ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.orgvoid TransmitMixer::PlayNotification(int32_t id,
9540ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org                                     uint32_t durationMs)
9640ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org{
9740ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId, -1),
9840ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org                 "TransmitMixer::PlayNotification(id=%d, durationMs=%d)",
9940ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org                 id, durationMs);
10040ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org
10140ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    // Not implement yet
10240ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org}
10340ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org
10440ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.orgvoid TransmitMixer::RecordNotification(int32_t id,
10540ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org                                       uint32_t durationMs)
10640ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org{
10740ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,-1),
10840ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org                 "TransmitMixer::RecordNotification(id=%d, durationMs=%d)",
10940ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org                 id, durationMs);
11040ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org
11140ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    // Not implement yet
11240ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org}
11340ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org
11440ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.orgvoid TransmitMixer::PlayFileEnded(int32_t id)
11540ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org{
11640ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId, -1),
11740ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org                 "TransmitMixer::PlayFileEnded(id=%d)", id);
11840ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org
11940ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    assert(id == _filePlayerId);
12040ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org
12140ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    CriticalSectionScoped cs(&_critSect);
12240ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org
12340ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    _filePlaying = false;
12440ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    WEBRTC_TRACE(kTraceStateInfo, kTraceVoice, VoEId(_instanceId, -1),
12540ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org                 "TransmitMixer::PlayFileEnded() =>"
12640ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org                 "file player module is shutdown");
12740ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org}
12840ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org
12940ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.orgvoid
13040ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.orgTransmitMixer::RecordFileEnded(int32_t id)
13140ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org{
13240ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId, -1),
13340ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org                 "TransmitMixer::RecordFileEnded(id=%d)", id);
13440ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org
13540ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    if (id == _fileRecorderId)
13640ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    {
13740ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org        CriticalSectionScoped cs(&_critSect);
13840ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org        _fileRecording = false;
13940ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org        WEBRTC_TRACE(kTraceStateInfo, kTraceVoice, VoEId(_instanceId, -1),
14040ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org                     "TransmitMixer::RecordFileEnded() => fileRecorder module"
14140ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org                     "is shutdown");
14240ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    } else if (id == _fileCallRecorderId)
14340ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    {
14440ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org        CriticalSectionScoped cs(&_critSect);
14540ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org        _fileCallRecording = false;
14640ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org        WEBRTC_TRACE(kTraceStateInfo, kTraceVoice, VoEId(_instanceId, -1),
14740ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org                     "TransmitMixer::RecordFileEnded() => fileCallRecorder"
14840ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org                     "module is shutdown");
14940ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    }
15040ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org}
15140ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org
15240ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.orgint32_t
15340ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.orgTransmitMixer::Create(TransmitMixer*& mixer, uint32_t instanceId)
15440ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org{
15540ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    WEBRTC_TRACE(kTraceMemory, kTraceVoice, VoEId(instanceId, -1),
15640ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org                 "TransmitMixer::Create(instanceId=%d)", instanceId);
15740ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    mixer = new TransmitMixer(instanceId);
15840ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    if (mixer == NULL)
15940ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    {
16040ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org        WEBRTC_TRACE(kTraceMemory, kTraceVoice, VoEId(instanceId, -1),
16140ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org                     "TransmitMixer::Create() unable to allocate memory"
16240ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org                     "for mixer");
16340ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org        return -1;
16440ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    }
16540ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    return 0;
16640ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org}
16740ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org
16840ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.orgvoid
16940ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.orgTransmitMixer::Destroy(TransmitMixer*& mixer)
17040ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org{
17140ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    if (mixer)
17240ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    {
17340ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org        delete mixer;
17440ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org        mixer = NULL;
17540ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    }
17640ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org}
17740ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org
17840ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.orgTransmitMixer::TransmitMixer(uint32_t instanceId) :
17940ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    _engineStatisticsPtr(NULL),
18040ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    _channelManagerPtr(NULL),
18140ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    audioproc_(NULL),
18240ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    _voiceEngineObserverPtr(NULL),
18340ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    _processThreadPtr(NULL),
18440ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    _filePlayerPtr(NULL),
18540ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    _fileRecorderPtr(NULL),
18640ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    _fileCallRecorderPtr(NULL),
18740ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    // Avoid conflict with other channels by adding 1024 - 1026,
18840ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    // won't use as much as 1024 channels.
18940ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    _filePlayerId(instanceId + 1024),
19040ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    _fileRecorderId(instanceId + 1025),
19140ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    _fileCallRecorderId(instanceId + 1026),
19240ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    _filePlaying(false),
19340ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    _fileRecording(false),
19440ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    _fileCallRecording(false),
19540ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    _audioLevel(),
19640ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    _critSect(*CriticalSectionWrapper::CreateCriticalSection()),
19740ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    _callbackCritSect(*CriticalSectionWrapper::CreateCriticalSection()),
19840ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org#ifdef WEBRTC_VOICE_ENGINE_TYPING_DETECTION
19940ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    _typingNoiseWarningPending(false),
20040ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    _typingNoiseDetected(false),
20140ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org#endif
20240ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    _saturationWarning(false),
20340ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    _instanceId(instanceId),
20440ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    _mixFileWithMicrophone(false),
20540ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    _captureLevel(0),
20640ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    external_postproc_ptr_(NULL),
20740ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    external_preproc_ptr_(NULL),
20840ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    _mute(false),
20940ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    _remainingMuteMicTimeMs(0),
21040ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    stereo_codec_(false),
21140ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    swap_stereo_channels_(false)
21240ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org{
21340ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    WEBRTC_TRACE(kTraceMemory, kTraceVoice, VoEId(_instanceId, -1),
21440ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org                 "TransmitMixer::TransmitMixer() - ctor");
21540ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org}
21640ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org
21740ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.orgTransmitMixer::~TransmitMixer()
21840ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org{
21940ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    WEBRTC_TRACE(kTraceMemory, kTraceVoice, VoEId(_instanceId, -1),
22040ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org                 "TransmitMixer::~TransmitMixer() - dtor");
22140ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    _monitorModule.DeRegisterObserver();
22240ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    if (_processThreadPtr)
22340ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    {
22440ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org        _processThreadPtr->DeRegisterModule(&_monitorModule);
22540ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    }
22640ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    DeRegisterExternalMediaProcessing(kRecordingAllChannelsMixed);
22740ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    DeRegisterExternalMediaProcessing(kRecordingPreprocessing);
22840ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    {
22940ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org        CriticalSectionScoped cs(&_critSect);
23040ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org        if (_fileRecorderPtr)
23140ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org        {
23240ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org            _fileRecorderPtr->RegisterModuleFileCallback(NULL);
23340ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org            _fileRecorderPtr->StopRecording();
23440ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org            FileRecorder::DestroyFileRecorder(_fileRecorderPtr);
23540ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org            _fileRecorderPtr = NULL;
23640ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org        }
23740ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org        if (_fileCallRecorderPtr)
23840ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org        {
23940ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org            _fileCallRecorderPtr->RegisterModuleFileCallback(NULL);
24040ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org            _fileCallRecorderPtr->StopRecording();
24140ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org            FileRecorder::DestroyFileRecorder(_fileCallRecorderPtr);
24240ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org            _fileCallRecorderPtr = NULL;
24340ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org        }
24440ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org        if (_filePlayerPtr)
24540ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org        {
24640ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org            _filePlayerPtr->RegisterModuleFileCallback(NULL);
24740ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org            _filePlayerPtr->StopPlayingFile();
24840ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org            FilePlayer::DestroyFilePlayer(_filePlayerPtr);
24940ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org            _filePlayerPtr = NULL;
25040ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org        }
25140ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    }
25240ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    delete &_critSect;
25340ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    delete &_callbackCritSect;
25440ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org}
25540ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org
25640ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.orgint32_t
25740ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.orgTransmitMixer::SetEngineInformation(ProcessThread& processThread,
25840ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org                                    Statistics& engineStatistics,
25940ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org                                    ChannelManager& channelManager)
26040ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org{
26140ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, -1),
26240ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org                 "TransmitMixer::SetEngineInformation()");
26340ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org
26440ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    _processThreadPtr = &processThread;
26540ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    _engineStatisticsPtr = &engineStatistics;
26640ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    _channelManagerPtr = &channelManager;
26740ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org
2683985f0151aff9b91418733795a98140079c19a73tommi@webrtc.org    _processThreadPtr->RegisterModule(&_monitorModule);
2693985f0151aff9b91418733795a98140079c19a73tommi@webrtc.org    _monitorModule.RegisterObserver(*this);
27040ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org
27140ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    return 0;
27240ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org}
27340ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org
27440ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.orgint32_t
27540ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.orgTransmitMixer::RegisterVoiceEngineObserver(VoiceEngineObserver& observer)
27640ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org{
27740ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, -1),
27840ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org                 "TransmitMixer::RegisterVoiceEngineObserver()");
27940ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    CriticalSectionScoped cs(&_callbackCritSect);
28040ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org
28140ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    if (_voiceEngineObserverPtr)
28240ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    {
28340ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org        _engineStatisticsPtr->SetLastError(
28440ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org            VE_INVALID_OPERATION, kTraceError,
28540ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org            "RegisterVoiceEngineObserver() observer already enabled");
28640ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org        return -1;
28740ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    }
28840ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    _voiceEngineObserverPtr = &observer;
28940ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    return 0;
29040ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org}
29140ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org
29240ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.orgint32_t
29340ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.orgTransmitMixer::SetAudioProcessingModule(AudioProcessing* audioProcessingModule)
29440ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org{
29540ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, -1),
29640ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org                 "TransmitMixer::SetAudioProcessingModule("
29740ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org                 "audioProcessingModule=0x%x)",
29840ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org                 audioProcessingModule);
29940ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    audioproc_ = audioProcessingModule;
30040ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    return 0;
30140ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org}
30240ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org
3036955870806624479723addfae6dcf5d13968796cPeter Kastingvoid TransmitMixer::GetSendCodecInfo(int* max_sample_rate,
3046955870806624479723addfae6dcf5d13968796cPeter Kasting                                     size_t* max_channels) {
30540ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org  *max_sample_rate = 8000;
30640ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org  *max_channels = 1;
30740ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org  for (ChannelManager::Iterator it(_channelManagerPtr); it.IsValid();
30840ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org       it.Increment()) {
30940ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    Channel* channel = it.GetChannel();
31040ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    if (channel->Sending()) {
31140ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org      CodecInst codec;
31240ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org      channel->GetSendCodec(codec);
31340ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org      *max_sample_rate = std::max(*max_sample_rate, codec.plfreq);
31440ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org      *max_channels = std::max(*max_channels, codec.channels);
31540ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    }
31640ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org  }
31740ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org}
31840ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org
31940ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.orgint32_t
32040ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.orgTransmitMixer::PrepareDemux(const void* audioSamples,
321dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting                            size_t nSamples,
3226955870806624479723addfae6dcf5d13968796cPeter Kasting                            size_t nChannels,
32340ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org                            uint32_t samplesPerSec,
32440ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org                            uint16_t totalDelayMS,
32540ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org                            int32_t clockDrift,
32640ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org                            uint16_t currentMicLevel,
32740ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org                            bool keyPressed)
32840ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org{
32940ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId, -1),
330dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting                 "TransmitMixer::PrepareDemux(nSamples=%" PRIuS ", "
3316955870806624479723addfae6dcf5d13968796cPeter Kasting                 "nChannels=%" PRIuS ", samplesPerSec=%u, totalDelayMS=%u, "
332dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting                 "clockDrift=%d, currentMicLevel=%u)",
333dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting                 nSamples, nChannels, samplesPerSec, totalDelayMS, clockDrift,
334dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting                 currentMicLevel);
33540ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org
33640ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    // --- Resample input audio and create/store the initial audio frame
33740ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    GenerateAudioFrame(static_cast<const int16_t*>(audioSamples),
33840ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org                       nSamples,
33940ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org                       nChannels,
34040ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org                       samplesPerSec);
34140ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org
34240ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    {
34340ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org      CriticalSectionScoped cs(&_callbackCritSect);
34440ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org      if (external_preproc_ptr_) {
34540ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org        external_preproc_ptr_->Process(-1, kRecordingPreprocessing,
34640ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org                                       _audioFrame.data_,
34740ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org                                       _audioFrame.samples_per_channel_,
34840ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org                                       _audioFrame.sample_rate_hz_,
34940ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org                                       _audioFrame.num_channels_ == 2);
35040ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org      }
35140ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    }
35240ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org
35340ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    // --- Near-end audio processing.
35440ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    ProcessAudio(totalDelayMS, clockDrift, currentMicLevel, keyPressed);
35540ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org
35640ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    if (swap_stereo_channels_ && stereo_codec_)
35740ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org      // Only bother swapping if we're using a stereo codec.
35840ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org      AudioFrameOperations::SwapStereoChannels(&_audioFrame);
35940ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org
36040ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    // --- Annoying typing detection (utilizes the APM/VAD decision)
36140ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org#ifdef WEBRTC_VOICE_ENGINE_TYPING_DETECTION
36240ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    TypingDetection(keyPressed);
36340ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org#endif
36440ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org
36540ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    // --- Mute during DTMF tone if direct feedback is enabled
36640ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    if (_remainingMuteMicTimeMs > 0)
36740ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    {
36840ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org        AudioFrameOperations::Mute(_audioFrame);
36940ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org        _remainingMuteMicTimeMs -= 10;
37040ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org        if (_remainingMuteMicTimeMs < 0)
37140ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org        {
37240ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org            _remainingMuteMicTimeMs = 0;
37340ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org        }
37440ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    }
37540ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org
37640ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    // --- Mute signal
37740ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    if (_mute)
37840ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    {
37940ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org        AudioFrameOperations::Mute(_audioFrame);
38040ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    }
38140ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org
38240ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    // --- Mix with file (does not affect the mixing frequency)
38340ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    if (_filePlaying)
38440ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    {
38540ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org        MixOrReplaceAudioWithFile(_audioFrame.sample_rate_hz_);
38640ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    }
38740ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org
38840ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    // --- Record to file
38940ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    bool file_recording = false;
39040ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    {
39140ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org        CriticalSectionScoped cs(&_critSect);
39240ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org        file_recording =  _fileRecording;
39340ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    }
39440ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    if (file_recording)
39540ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    {
39640ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org        RecordAudioToFile(_audioFrame.sample_rate_hz_);
39740ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    }
39840ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org
39940ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    {
40040ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org      CriticalSectionScoped cs(&_callbackCritSect);
40140ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org      if (external_postproc_ptr_) {
40240ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org        external_postproc_ptr_->Process(-1, kRecordingAllChannelsMixed,
40340ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org                                        _audioFrame.data_,
40440ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org                                        _audioFrame.samples_per_channel_,
40540ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org                                        _audioFrame.sample_rate_hz_,
40640ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org                                        _audioFrame.num_channels_ == 2);
40740ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org      }
40840ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    }
40940ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org
41040ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    // --- Measure audio level of speech after all processing.
41140ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    _audioLevel.ComputeLevel(_audioFrame);
41240ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    return 0;
41340ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org}
41440ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org
41540ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.orgint32_t
41640ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.orgTransmitMixer::DemuxAndMix()
41740ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org{
41840ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId, -1),
41940ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org                 "TransmitMixer::DemuxAndMix()");
42040ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org
42140ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    for (ChannelManager::Iterator it(_channelManagerPtr); it.IsValid();
42240ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org         it.Increment())
42340ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    {
42440ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org        Channel* channelPtr = it.GetChannel();
42566803489f9694cb7c7c0dd3ba07b63e2b6b71779henrika@webrtc.org        if (channelPtr->Sending())
42640ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org        {
42740ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org            // Demultiplex makes a copy of its input.
42840ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org            channelPtr->Demultiplex(_audioFrame);
42940ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org            channelPtr->PrepareEncodeAndSend(_audioFrame.sample_rate_hz_);
43040ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org        }
43140ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    }
43240ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    return 0;
43340ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org}
43440ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org
43540ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.orgvoid TransmitMixer::DemuxAndMix(const int voe_channels[],
4366955870806624479723addfae6dcf5d13968796cPeter Kasting                                size_t number_of_voe_channels) {
4376955870806624479723addfae6dcf5d13968796cPeter Kasting  for (size_t i = 0; i < number_of_voe_channels; ++i) {
43840ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    voe::ChannelOwner ch = _channelManagerPtr->GetChannel(voe_channels[i]);
43940ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    voe::Channel* channel_ptr = ch.channel();
44040ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    if (channel_ptr) {
44166803489f9694cb7c7c0dd3ba07b63e2b6b71779henrika@webrtc.org      if (channel_ptr->Sending()) {
44240ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org        // Demultiplex makes a copy of its input.
44340ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org        channel_ptr->Demultiplex(_audioFrame);
44440ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org        channel_ptr->PrepareEncodeAndSend(_audioFrame.sample_rate_hz_);
44540ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org      }
44640ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    }
44740ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org  }
44840ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org}
44940ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org
45040ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.orgint32_t
45140ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.orgTransmitMixer::EncodeAndSend()
45240ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org{
45340ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId, -1),
45440ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org                 "TransmitMixer::EncodeAndSend()");
45540ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org
45640ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    for (ChannelManager::Iterator it(_channelManagerPtr); it.IsValid();
45740ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org         it.Increment())
45840ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    {
45940ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org        Channel* channelPtr = it.GetChannel();
46066803489f9694cb7c7c0dd3ba07b63e2b6b71779henrika@webrtc.org        if (channelPtr->Sending())
46140ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org        {
46240ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org            channelPtr->EncodeAndSend();
46340ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org        }
46440ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    }
46540ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    return 0;
46640ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org}
46740ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org
46840ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.orgvoid TransmitMixer::EncodeAndSend(const int voe_channels[],
4696955870806624479723addfae6dcf5d13968796cPeter Kasting                                  size_t number_of_voe_channels) {
4706955870806624479723addfae6dcf5d13968796cPeter Kasting  for (size_t i = 0; i < number_of_voe_channels; ++i) {
47140ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    voe::ChannelOwner ch = _channelManagerPtr->GetChannel(voe_channels[i]);
47240ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    voe::Channel* channel_ptr = ch.channel();
47366803489f9694cb7c7c0dd3ba07b63e2b6b71779henrika@webrtc.org    if (channel_ptr && channel_ptr->Sending())
47440ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org      channel_ptr->EncodeAndSend();
47540ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org  }
47640ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org}
47740ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org
47840ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.orguint32_t TransmitMixer::CaptureLevel() const
47940ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org{
48040ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    return _captureLevel;
48140ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org}
48240ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org
48340ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.orgvoid
48440ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.orgTransmitMixer::UpdateMuteMicrophoneTime(uint32_t lengthMs)
48540ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org{
48640ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, -1),
48740ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org               "TransmitMixer::UpdateMuteMicrophoneTime(lengthMs=%d)",
48840ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org               lengthMs);
48940ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    _remainingMuteMicTimeMs = lengthMs;
49040ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org}
49140ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org
49240ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.orgint32_t
49340ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.orgTransmitMixer::StopSend()
49440ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org{
49540ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, -1),
49640ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org               "TransmitMixer::StopSend()");
49740ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    _audioLevel.Clear();
49840ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    return 0;
49940ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org}
50040ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org
50140ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.orgint TransmitMixer::StartPlayingFileAsMicrophone(const char* fileName,
50240ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org                                                bool loop,
50340ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org                                                FileFormats format,
50440ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org                                                int startPosition,
50540ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org                                                float volumeScaling,
50640ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org                                                int stopPosition,
50740ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org                                                const CodecInst* codecInst)
50840ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org{
50940ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, -1),
51040ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org                 "TransmitMixer::StartPlayingFileAsMicrophone("
51140ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org                 "fileNameUTF8[]=%s,loop=%d, format=%d, volumeScaling=%5.3f,"
51240ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org                 " startPosition=%d, stopPosition=%d)", fileName, loop,
51340ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org                 format, volumeScaling, startPosition, stopPosition);
51440ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org
51540ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    if (_filePlaying)
51640ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    {
51740ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org        _engineStatisticsPtr->SetLastError(
51840ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org            VE_ALREADY_PLAYING, kTraceWarning,
51940ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org            "StartPlayingFileAsMicrophone() is already playing");
52040ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org        return 0;
52140ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    }
52240ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org
52340ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    CriticalSectionScoped cs(&_critSect);
52440ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org
52540ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    // Destroy the old instance
52640ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    if (_filePlayerPtr)
52740ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    {
52840ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org        _filePlayerPtr->RegisterModuleFileCallback(NULL);
52940ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org        FilePlayer::DestroyFilePlayer(_filePlayerPtr);
53040ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org        _filePlayerPtr = NULL;
53140ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    }
53240ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org
53340ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    // Dynamically create the instance
53440ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    _filePlayerPtr
53540ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org        = FilePlayer::CreateFilePlayer(_filePlayerId,
53640ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org                                       (const FileFormats) format);
53740ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org
53840ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    if (_filePlayerPtr == NULL)
53940ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    {
54040ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org        _engineStatisticsPtr->SetLastError(
54140ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org            VE_INVALID_ARGUMENT, kTraceError,
54240ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org            "StartPlayingFileAsMicrophone() filePlayer format isnot correct");
54340ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org        return -1;
54440ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    }
54540ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org
54640ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    const uint32_t notificationTime(0);
54740ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org
54840ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    if (_filePlayerPtr->StartPlayingFile(
54940ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org        fileName,
55040ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org        loop,
55140ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org        startPosition,
55240ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org        volumeScaling,
55340ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org        notificationTime,
55440ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org        stopPosition,
55540ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org        (const CodecInst*) codecInst) != 0)
55640ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    {
55740ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org        _engineStatisticsPtr->SetLastError(
55840ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org            VE_BAD_FILE, kTraceError,
55940ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org            "StartPlayingFile() failed to start file playout");
56040ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org        _filePlayerPtr->StopPlayingFile();
56140ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org        FilePlayer::DestroyFilePlayer(_filePlayerPtr);
56240ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org        _filePlayerPtr = NULL;
56340ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org        return -1;
56440ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    }
56540ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org
56640ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    _filePlayerPtr->RegisterModuleFileCallback(this);
56740ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    _filePlaying = true;
56840ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org
56940ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    return 0;
57040ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org}
57140ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org
57240ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.orgint TransmitMixer::StartPlayingFileAsMicrophone(InStream* stream,
57340ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org                                                FileFormats format,
57440ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org                                                int startPosition,
57540ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org                                                float volumeScaling,
57640ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org                                                int stopPosition,
57740ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org                                                const CodecInst* codecInst)
57840ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org{
57940ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,-1),
58040ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org                 "TransmitMixer::StartPlayingFileAsMicrophone(format=%d,"
58140ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org                 " volumeScaling=%5.3f, startPosition=%d, stopPosition=%d)",
58240ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org                 format, volumeScaling, startPosition, stopPosition);
58340ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org
58440ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    if (stream == NULL)
58540ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    {
58640ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org        _engineStatisticsPtr->SetLastError(
58740ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org            VE_BAD_FILE, kTraceError,
58840ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org            "StartPlayingFileAsMicrophone() NULL as input stream");
58940ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org        return -1;
59040ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    }
59140ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org
59240ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    if (_filePlaying)
59340ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    {
59440ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org        _engineStatisticsPtr->SetLastError(
59540ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org            VE_ALREADY_PLAYING, kTraceWarning,
59640ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org            "StartPlayingFileAsMicrophone() is already playing");
59740ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org        return 0;
59840ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    }
59940ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org
60040ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    CriticalSectionScoped cs(&_critSect);
60140ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org
60240ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    // Destroy the old instance
60340ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    if (_filePlayerPtr)
60440ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    {
60540ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org        _filePlayerPtr->RegisterModuleFileCallback(NULL);
60640ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org        FilePlayer::DestroyFilePlayer(_filePlayerPtr);
60740ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org        _filePlayerPtr = NULL;
60840ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    }
60940ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org
61040ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    // Dynamically create the instance
61140ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    _filePlayerPtr
61240ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org        = FilePlayer::CreateFilePlayer(_filePlayerId,
61340ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org                                       (const FileFormats) format);
61440ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org
61540ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    if (_filePlayerPtr == NULL)
61640ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    {
61740ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org        _engineStatisticsPtr->SetLastError(
61840ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org            VE_INVALID_ARGUMENT, kTraceWarning,
61940ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org            "StartPlayingFileAsMicrophone() filePlayer format isnot correct");
62040ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org        return -1;
62140ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    }
62240ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org
62340ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    const uint32_t notificationTime(0);
62440ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org
62540ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    if (_filePlayerPtr->StartPlayingFile(
62640ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org        (InStream&) *stream,
62740ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org        startPosition,
62840ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org        volumeScaling,
62940ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org        notificationTime,
63040ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org        stopPosition,
63140ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org        (const CodecInst*) codecInst) != 0)
63240ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    {
63340ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org        _engineStatisticsPtr->SetLastError(
63440ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org            VE_BAD_FILE, kTraceError,
63540ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org            "StartPlayingFile() failed to start file playout");
63640ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org        _filePlayerPtr->StopPlayingFile();
63740ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org        FilePlayer::DestroyFilePlayer(_filePlayerPtr);
63840ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org        _filePlayerPtr = NULL;
63940ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org        return -1;
64040ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    }
64140ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    _filePlayerPtr->RegisterModuleFileCallback(this);
64240ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    _filePlaying = true;
64340ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org
64440ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    return 0;
64540ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org}
64640ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org
64740ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.orgint TransmitMixer::StopPlayingFileAsMicrophone()
64840ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org{
64940ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,-1),
65040ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org                 "TransmitMixer::StopPlayingFileAsMicrophone()");
65140ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org
65240ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    if (!_filePlaying)
65340ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    {
65440ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org        return 0;
65540ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    }
65640ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org
65740ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    CriticalSectionScoped cs(&_critSect);
65840ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org
65940ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    if (_filePlayerPtr->StopPlayingFile() != 0)
66040ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    {
66140ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org        _engineStatisticsPtr->SetLastError(
66240ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org            VE_CANNOT_STOP_PLAYOUT, kTraceError,
66340ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org            "StopPlayingFile() couldnot stop playing file");
66440ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org        return -1;
66540ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    }
66640ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org
66740ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    _filePlayerPtr->RegisterModuleFileCallback(NULL);
66840ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    FilePlayer::DestroyFilePlayer(_filePlayerPtr);
66940ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    _filePlayerPtr = NULL;
67040ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    _filePlaying = false;
67140ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org
67240ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    return 0;
67340ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org}
67440ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org
67540ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.orgint TransmitMixer::IsPlayingFileAsMicrophone() const
67640ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org{
67740ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, -1),
67840ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org                 "TransmitMixer::IsPlayingFileAsMicrophone()");
67940ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    return _filePlaying;
68040ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org}
68140ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org
68240ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.orgint TransmitMixer::StartRecordingMicrophone(const char* fileName,
68340ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org                                            const CodecInst* codecInst)
68440ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org{
68540ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, -1),
68640ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org                 "TransmitMixer::StartRecordingMicrophone(fileName=%s)",
68740ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org                 fileName);
68840ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org
68940ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    CriticalSectionScoped cs(&_critSect);
69040ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org
69140ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    if (_fileRecording)
69240ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    {
69340ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org        WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId, -1),
69440ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org                     "StartRecordingMicrophone() is already recording");
69540ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org        return 0;
69640ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    }
69740ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org
69840ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    FileFormats format;
69940ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    const uint32_t notificationTime(0); // Not supported in VoE
70040ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    CodecInst dummyCodec = { 100, "L16", 16000, 320, 1, 320000 };
70140ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org
7026955870806624479723addfae6dcf5d13968796cPeter Kasting    if (codecInst != NULL && codecInst->channels > 2)
70340ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    {
70440ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org        _engineStatisticsPtr->SetLastError(
70540ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org            VE_BAD_ARGUMENT, kTraceError,
70640ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org            "StartRecordingMicrophone() invalid compression");
70740ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org        return (-1);
70840ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    }
70940ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    if (codecInst == NULL)
71040ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    {
71140ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org        format = kFileFormatPcm16kHzFile;
71240ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org        codecInst = &dummyCodec;
71340ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    } else if ((STR_CASE_CMP(codecInst->plname,"L16") == 0) ||
71440ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org        (STR_CASE_CMP(codecInst->plname,"PCMU") == 0) ||
71540ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org        (STR_CASE_CMP(codecInst->plname,"PCMA") == 0))
71640ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    {
71740ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org        format = kFileFormatWavFile;
71840ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    } else
71940ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    {
72040ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org        format = kFileFormatCompressedFile;
72140ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    }
72240ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org
72340ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    // Destroy the old instance
72440ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    if (_fileRecorderPtr)
72540ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    {
72640ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org        _fileRecorderPtr->RegisterModuleFileCallback(NULL);
72740ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org        FileRecorder::DestroyFileRecorder(_fileRecorderPtr);
72840ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org        _fileRecorderPtr = NULL;
72940ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    }
73040ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org
73140ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    _fileRecorderPtr =
73240ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org        FileRecorder::CreateFileRecorder(_fileRecorderId,
73340ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org                                         (const FileFormats) format);
73440ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    if (_fileRecorderPtr == NULL)
73540ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    {
73640ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org        _engineStatisticsPtr->SetLastError(
73740ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org            VE_INVALID_ARGUMENT, kTraceError,
73840ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org            "StartRecordingMicrophone() fileRecorder format isnot correct");
73940ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org        return -1;
74040ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    }
74140ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org
74240ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    if (_fileRecorderPtr->StartRecordingAudioFile(
74340ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org        fileName,
74440ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org        (const CodecInst&) *codecInst,
74540ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org        notificationTime) != 0)
74640ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    {
74740ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org        _engineStatisticsPtr->SetLastError(
74840ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org            VE_BAD_FILE, kTraceError,
74940ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org            "StartRecordingAudioFile() failed to start file recording");
75040ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org        _fileRecorderPtr->StopRecording();
75140ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org        FileRecorder::DestroyFileRecorder(_fileRecorderPtr);
75240ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org        _fileRecorderPtr = NULL;
75340ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org        return -1;
75440ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    }
75540ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    _fileRecorderPtr->RegisterModuleFileCallback(this);
75640ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    _fileRecording = true;
75740ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org
75840ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    return 0;
75940ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org}
76040ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org
76140ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.orgint TransmitMixer::StartRecordingMicrophone(OutStream* stream,
76240ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org                                            const CodecInst* codecInst)
76340ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org{
76440ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, -1),
76540ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org               "TransmitMixer::StartRecordingMicrophone()");
76640ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org
76740ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    CriticalSectionScoped cs(&_critSect);
76840ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org
76940ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    if (_fileRecording)
77040ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    {
77140ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org        WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId, -1),
77240ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org                   "StartRecordingMicrophone() is already recording");
77340ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org        return 0;
77440ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    }
77540ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org
77640ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    FileFormats format;
77740ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    const uint32_t notificationTime(0); // Not supported in VoE
77840ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    CodecInst dummyCodec = { 100, "L16", 16000, 320, 1, 320000 };
77940ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org
78040ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    if (codecInst != NULL && codecInst->channels != 1)
78140ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    {
78240ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org        _engineStatisticsPtr->SetLastError(
78340ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org            VE_BAD_ARGUMENT, kTraceError,
78440ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org            "StartRecordingMicrophone() invalid compression");
78540ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org        return (-1);
78640ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    }
78740ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    if (codecInst == NULL)
78840ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    {
78940ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org        format = kFileFormatPcm16kHzFile;
79040ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org        codecInst = &dummyCodec;
79140ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    } else if ((STR_CASE_CMP(codecInst->plname,"L16") == 0) ||
79240ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org        (STR_CASE_CMP(codecInst->plname,"PCMU") == 0) ||
79340ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org        (STR_CASE_CMP(codecInst->plname,"PCMA") == 0))
79440ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    {
79540ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org        format = kFileFormatWavFile;
79640ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    } else
79740ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    {
79840ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org        format = kFileFormatCompressedFile;
79940ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    }
80040ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org
80140ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    // Destroy the old instance
80240ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    if (_fileRecorderPtr)
80340ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    {
80440ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org        _fileRecorderPtr->RegisterModuleFileCallback(NULL);
80540ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org        FileRecorder::DestroyFileRecorder(_fileRecorderPtr);
80640ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org        _fileRecorderPtr = NULL;
80740ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    }
80840ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org
80940ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    _fileRecorderPtr =
81040ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org        FileRecorder::CreateFileRecorder(_fileRecorderId,
81140ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org                                         (const FileFormats) format);
81240ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    if (_fileRecorderPtr == NULL)
81340ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    {
81440ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org        _engineStatisticsPtr->SetLastError(
81540ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org            VE_INVALID_ARGUMENT, kTraceError,
81640ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org            "StartRecordingMicrophone() fileRecorder format isnot correct");
81740ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org        return -1;
81840ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    }
81940ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org
82040ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    if (_fileRecorderPtr->StartRecordingAudioFile(*stream,
82140ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org                                                  *codecInst,
82240ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org                                                  notificationTime) != 0)
82340ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    {
82440ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    _engineStatisticsPtr->SetLastError(VE_BAD_FILE, kTraceError,
82540ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org      "StartRecordingAudioFile() failed to start file recording");
82640ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    _fileRecorderPtr->StopRecording();
82740ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    FileRecorder::DestroyFileRecorder(_fileRecorderPtr);
82840ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    _fileRecorderPtr = NULL;
82940ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    return -1;
83040ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    }
83140ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org
83240ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    _fileRecorderPtr->RegisterModuleFileCallback(this);
83340ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    _fileRecording = true;
83440ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org
83540ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    return 0;
83640ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org}
83740ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org
83840ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org
83940ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.orgint TransmitMixer::StopRecordingMicrophone()
84040ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org{
84140ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, -1),
84240ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org                 "TransmitMixer::StopRecordingMicrophone()");
84340ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org
84440ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    CriticalSectionScoped cs(&_critSect);
84540ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org
84640ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    if (!_fileRecording)
84740ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    {
84840ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org        WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId, -1),
84940ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org                   "StopRecordingMicrophone() isnot recording");
85040ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org        return 0;
85140ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    }
85240ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org
85340ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    if (_fileRecorderPtr->StopRecording() != 0)
85440ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    {
85540ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org        _engineStatisticsPtr->SetLastError(
85640ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org            VE_STOP_RECORDING_FAILED, kTraceError,
85740ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org            "StopRecording(), could not stop recording");
85840ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org        return -1;
85940ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    }
86040ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    _fileRecorderPtr->RegisterModuleFileCallback(NULL);
86140ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    FileRecorder::DestroyFileRecorder(_fileRecorderPtr);
86240ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    _fileRecorderPtr = NULL;
86340ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    _fileRecording = false;
86440ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org
86540ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    return 0;
86640ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org}
86740ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org
86840ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.orgint TransmitMixer::StartRecordingCall(const char* fileName,
86940ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org                                      const CodecInst* codecInst)
87040ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org{
87140ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, -1),
87240ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org                 "TransmitMixer::StartRecordingCall(fileName=%s)", fileName);
87340ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org
87440ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    if (_fileCallRecording)
87540ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    {
87640ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org        WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId, -1),
87740ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org                     "StartRecordingCall() is already recording");
87840ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org        return 0;
87940ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    }
88040ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org
88140ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    FileFormats format;
88240ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    const uint32_t notificationTime(0); // Not supported in VoE
88340ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    CodecInst dummyCodec = { 100, "L16", 16000, 320, 1, 320000 };
88440ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org
88540ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    if (codecInst != NULL && codecInst->channels != 1)
88640ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    {
88740ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org        _engineStatisticsPtr->SetLastError(
88840ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org            VE_BAD_ARGUMENT, kTraceError,
88940ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org            "StartRecordingCall() invalid compression");
89040ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org        return (-1);
89140ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    }
89240ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    if (codecInst == NULL)
89340ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    {
89440ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org        format = kFileFormatPcm16kHzFile;
89540ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org        codecInst = &dummyCodec;
89640ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    } else if ((STR_CASE_CMP(codecInst->plname,"L16") == 0) ||
89740ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org        (STR_CASE_CMP(codecInst->plname,"PCMU") == 0) ||
89840ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org        (STR_CASE_CMP(codecInst->plname,"PCMA") == 0))
89940ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    {
90040ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org        format = kFileFormatWavFile;
90140ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    } else
90240ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    {
90340ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org        format = kFileFormatCompressedFile;
90440ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    }
90540ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org
90640ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    CriticalSectionScoped cs(&_critSect);
90740ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org
90840ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    // Destroy the old instance
90940ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    if (_fileCallRecorderPtr)
91040ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    {
91140ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org        _fileCallRecorderPtr->RegisterModuleFileCallback(NULL);
91240ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org        FileRecorder::DestroyFileRecorder(_fileCallRecorderPtr);
91340ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org        _fileCallRecorderPtr = NULL;
91440ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    }
91540ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org
91640ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    _fileCallRecorderPtr
91740ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org        = FileRecorder::CreateFileRecorder(_fileCallRecorderId,
91840ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org                                           (const FileFormats) format);
91940ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    if (_fileCallRecorderPtr == NULL)
92040ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    {
92140ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org        _engineStatisticsPtr->SetLastError(
92240ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org            VE_INVALID_ARGUMENT, kTraceError,
92340ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org            "StartRecordingCall() fileRecorder format isnot correct");
92440ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org        return -1;
92540ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    }
92640ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org
92740ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    if (_fileCallRecorderPtr->StartRecordingAudioFile(
92840ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org        fileName,
92940ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org        (const CodecInst&) *codecInst,
93040ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org        notificationTime) != 0)
93140ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    {
93240ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org        _engineStatisticsPtr->SetLastError(
93340ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org            VE_BAD_FILE, kTraceError,
93440ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org            "StartRecordingAudioFile() failed to start file recording");
93540ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org        _fileCallRecorderPtr->StopRecording();
93640ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org        FileRecorder::DestroyFileRecorder(_fileCallRecorderPtr);
93740ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org        _fileCallRecorderPtr = NULL;
93840ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org        return -1;
93940ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    }
94040ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    _fileCallRecorderPtr->RegisterModuleFileCallback(this);
94140ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    _fileCallRecording = true;
94240ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org
94340ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    return 0;
94440ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org}
94540ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org
94640ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.orgint TransmitMixer::StartRecordingCall(OutStream* stream,
94740ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org                                      const  CodecInst* codecInst)
94840ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org{
94940ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, -1),
95040ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org                 "TransmitMixer::StartRecordingCall()");
95140ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org
95240ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    if (_fileCallRecording)
95340ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    {
95440ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org        WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId, -1),
95540ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org                     "StartRecordingCall() is already recording");
95640ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org        return 0;
95740ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    }
95840ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org
95940ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    FileFormats format;
96040ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    const uint32_t notificationTime(0); // Not supported in VoE
96140ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    CodecInst dummyCodec = { 100, "L16", 16000, 320, 1, 320000 };
96240ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org
96340ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    if (codecInst != NULL && codecInst->channels != 1)
96440ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    {
96540ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org        _engineStatisticsPtr->SetLastError(
96640ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org            VE_BAD_ARGUMENT, kTraceError,
96740ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org            "StartRecordingCall() invalid compression");
96840ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org        return (-1);
96940ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    }
97040ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    if (codecInst == NULL)
97140ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    {
97240ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org        format = kFileFormatPcm16kHzFile;
97340ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org        codecInst = &dummyCodec;
97440ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    } else if ((STR_CASE_CMP(codecInst->plname,"L16") == 0) ||
97540ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org        (STR_CASE_CMP(codecInst->plname,"PCMU") == 0) ||
97640ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org        (STR_CASE_CMP(codecInst->plname,"PCMA") == 0))
97740ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    {
97840ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org        format = kFileFormatWavFile;
97940ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    } else
98040ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    {
98140ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org        format = kFileFormatCompressedFile;
98240ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    }
98340ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org
98440ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    CriticalSectionScoped cs(&_critSect);
98540ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org
98640ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    // Destroy the old instance
98740ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    if (_fileCallRecorderPtr)
98840ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    {
98940ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org        _fileCallRecorderPtr->RegisterModuleFileCallback(NULL);
99040ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org        FileRecorder::DestroyFileRecorder(_fileCallRecorderPtr);
99140ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org        _fileCallRecorderPtr = NULL;
99240ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    }
99340ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org
99440ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    _fileCallRecorderPtr =
99540ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org        FileRecorder::CreateFileRecorder(_fileCallRecorderId,
99640ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org                                         (const FileFormats) format);
99740ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    if (_fileCallRecorderPtr == NULL)
99840ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    {
99940ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org        _engineStatisticsPtr->SetLastError(
100040ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org            VE_INVALID_ARGUMENT, kTraceError,
100140ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org            "StartRecordingCall() fileRecorder format isnot correct");
100240ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org        return -1;
100340ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    }
100440ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org
100540ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    if (_fileCallRecorderPtr->StartRecordingAudioFile(*stream,
100640ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org                                                      *codecInst,
100740ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org                                                      notificationTime) != 0)
100840ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    {
100940ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    _engineStatisticsPtr->SetLastError(VE_BAD_FILE, kTraceError,
101040ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org     "StartRecordingAudioFile() failed to start file recording");
101140ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    _fileCallRecorderPtr->StopRecording();
101240ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    FileRecorder::DestroyFileRecorder(_fileCallRecorderPtr);
101340ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    _fileCallRecorderPtr = NULL;
101440ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    return -1;
101540ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    }
101640ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org
101740ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    _fileCallRecorderPtr->RegisterModuleFileCallback(this);
101840ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    _fileCallRecording = true;
101940ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org
102040ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    return 0;
102140ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org}
102240ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org
102340ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.orgint TransmitMixer::StopRecordingCall()
102440ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org{
102540ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, -1),
102640ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org                 "TransmitMixer::StopRecordingCall()");
102740ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org
102840ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    if (!_fileCallRecording)
102940ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    {
103040ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org        WEBRTC_TRACE(kTraceError, kTraceVoice, VoEId(_instanceId, -1),
103140ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org                     "StopRecordingCall() file isnot recording");
103240ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org        return -1;
103340ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    }
103440ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org
103540ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    CriticalSectionScoped cs(&_critSect);
103640ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org
103740ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    if (_fileCallRecorderPtr->StopRecording() != 0)
103840ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    {
103940ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org        _engineStatisticsPtr->SetLastError(
104040ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org            VE_STOP_RECORDING_FAILED, kTraceError,
104140ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org            "StopRecording(), could not stop recording");
104240ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org        return -1;
104340ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    }
104440ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org
104540ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    _fileCallRecorderPtr->RegisterModuleFileCallback(NULL);
104640ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    FileRecorder::DestroyFileRecorder(_fileCallRecorderPtr);
104740ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    _fileCallRecorderPtr = NULL;
104840ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    _fileCallRecording = false;
104940ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org
105040ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    return 0;
105140ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org}
105240ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org
105340ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.orgvoid
105440ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.orgTransmitMixer::SetMixWithMicStatus(bool mix)
105540ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org{
105640ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    _mixFileWithMicrophone = mix;
105740ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org}
105840ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org
105940ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.orgint TransmitMixer::RegisterExternalMediaProcessing(
106040ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    VoEMediaProcess* object,
106140ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    ProcessingTypes type) {
106240ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org  WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, -1),
106340ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org               "TransmitMixer::RegisterExternalMediaProcessing()");
106440ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org
106540ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org  CriticalSectionScoped cs(&_callbackCritSect);
106640ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org  if (!object) {
106740ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    return -1;
106840ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org  }
106940ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org
107040ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org  // Store the callback object according to the processing type.
107140ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org  if (type == kRecordingAllChannelsMixed) {
107240ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    external_postproc_ptr_ = object;
107340ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org  } else if (type == kRecordingPreprocessing) {
107440ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    external_preproc_ptr_ = object;
107540ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org  } else {
107640ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    return -1;
107740ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org  }
107840ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org  return 0;
107940ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org}
108040ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org
108140ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.orgint TransmitMixer::DeRegisterExternalMediaProcessing(ProcessingTypes type) {
108240ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org  WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, -1),
108340ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org               "TransmitMixer::DeRegisterExternalMediaProcessing()");
108440ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org
108540ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org  CriticalSectionScoped cs(&_callbackCritSect);
108640ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org  if (type == kRecordingAllChannelsMixed) {
108740ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    external_postproc_ptr_ = NULL;
108840ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org  } else if (type == kRecordingPreprocessing) {
108940ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    external_preproc_ptr_ = NULL;
109040ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org  } else {
109140ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    return -1;
109240ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org  }
109340ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org  return 0;
109440ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org}
109540ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org
109640ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.orgint
109740ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.orgTransmitMixer::SetMute(bool enable)
109840ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org{
109940ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, -1),
110040ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org                 "TransmitMixer::SetMute(enable=%d)", enable);
110140ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    _mute = enable;
110240ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    return 0;
110340ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org}
110440ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org
110540ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.orgbool
110640ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.orgTransmitMixer::Mute() const
110740ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org{
110840ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    return _mute;
110940ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org}
111040ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org
111140ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.orgint8_t TransmitMixer::AudioLevel() const
111240ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org{
111340ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    // Speech + file level [0,9]
111440ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    return _audioLevel.Level();
111540ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org}
111640ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org
111740ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.orgint16_t TransmitMixer::AudioLevelFullRange() const
111840ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org{
111940ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    // Speech + file level [0,32767]
112040ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    return _audioLevel.LevelFullRange();
112140ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org}
112240ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org
112340ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.orgbool TransmitMixer::IsRecordingCall()
112440ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org{
112540ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    return _fileCallRecording;
112640ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org}
112740ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org
112840ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.orgbool TransmitMixer::IsRecordingMic()
112940ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org{
113040ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    CriticalSectionScoped cs(&_critSect);
113140ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    return _fileRecording;
113240ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org}
113340ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org
113440ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.orgvoid TransmitMixer::GenerateAudioFrame(const int16_t* audio,
1135dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting                                       size_t samples_per_channel,
11366955870806624479723addfae6dcf5d13968796cPeter Kasting                                       size_t num_channels,
113740ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org                                       int sample_rate_hz) {
113840ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org  int codec_rate;
11396955870806624479723addfae6dcf5d13968796cPeter Kasting  size_t num_codec_channels;
114040ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org  GetSendCodecInfo(&codec_rate, &num_codec_channels);
114140ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org  stereo_codec_ = num_codec_channels == 2;
114240ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org
1143cdfe20bfc1146030aa59eb37635fd2fbcecd6cdbAlejandro Luebs  // We want to process at the lowest rate possible without losing information.
1144cdfe20bfc1146030aa59eb37635fd2fbcecd6cdbAlejandro Luebs  // Choose the lowest native rate at least equal to the input and codec rates.
1145cdfe20bfc1146030aa59eb37635fd2fbcecd6cdbAlejandro Luebs  const int min_processing_rate = std::min(sample_rate_hz, codec_rate);
1146cdfe20bfc1146030aa59eb37635fd2fbcecd6cdbAlejandro Luebs  for (size_t i = 0; i < AudioProcessing::kNumNativeSampleRates; ++i) {
1147cdfe20bfc1146030aa59eb37635fd2fbcecd6cdbAlejandro Luebs    _audioFrame.sample_rate_hz_ = AudioProcessing::kNativeSampleRatesHz[i];
1148cdfe20bfc1146030aa59eb37635fd2fbcecd6cdbAlejandro Luebs    if (_audioFrame.sample_rate_hz_ >= min_processing_rate) {
1149cdfe20bfc1146030aa59eb37635fd2fbcecd6cdbAlejandro Luebs      break;
1150cdfe20bfc1146030aa59eb37635fd2fbcecd6cdbAlejandro Luebs    }
1151cdfe20bfc1146030aa59eb37635fd2fbcecd6cdbAlejandro Luebs  }
1152cdfe20bfc1146030aa59eb37635fd2fbcecd6cdbAlejandro Luebs  if (audioproc_->echo_control_mobile()->is_enabled()) {
1153cdfe20bfc1146030aa59eb37635fd2fbcecd6cdbAlejandro Luebs    // AECM only supports 8 and 16 kHz.
1154cdfe20bfc1146030aa59eb37635fd2fbcecd6cdbAlejandro Luebs    _audioFrame.sample_rate_hz_ = std::min(
1155cdfe20bfc1146030aa59eb37635fd2fbcecd6cdbAlejandro Luebs        _audioFrame.sample_rate_hz_, AudioProcessing::kMaxAECMSampleRateHz);
115640ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org  }
1157cdfe20bfc1146030aa59eb37635fd2fbcecd6cdbAlejandro Luebs  _audioFrame.num_channels_ = std::min(num_channels, num_codec_channels);
1158cdfe20bfc1146030aa59eb37635fd2fbcecd6cdbAlejandro Luebs  RemixAndResample(audio, samples_per_channel, num_channels, sample_rate_hz,
1159cdfe20bfc1146030aa59eb37635fd2fbcecd6cdbAlejandro Luebs                   &resampler_, &_audioFrame);
116040ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org}
116140ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org
116240ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.orgint32_t TransmitMixer::RecordAudioToFile(
116340ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    uint32_t mixingFrequency)
116440ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org{
116540ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    CriticalSectionScoped cs(&_critSect);
116640ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    if (_fileRecorderPtr == NULL)
116740ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    {
116840ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org        WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId, -1),
116940ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org                     "TransmitMixer::RecordAudioToFile() filerecorder doesnot"
117040ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org                     "exist");
117140ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org        return -1;
117240ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    }
117340ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org
117440ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    if (_fileRecorderPtr->RecordAudioToFile(_audioFrame) != 0)
117540ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    {
117640ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org        WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId, -1),
117740ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org                     "TransmitMixer::RecordAudioToFile() file recording"
117840ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org                     "failed");
117940ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org        return -1;
118040ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    }
118140ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org
118240ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    return 0;
118340ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org}
118440ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org
118540ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.orgint32_t TransmitMixer::MixOrReplaceAudioWithFile(
118640ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    int mixingFrequency)
118740ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org{
118800b8f6b3643332cce1ee711715f7fbb824d793cakwiberg@webrtc.org  rtc::scoped_ptr<int16_t[]> fileBuffer(new int16_t[640]);
118940ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org
1190dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting    size_t fileSamples(0);
119140ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    {
119240ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org        CriticalSectionScoped cs(&_critSect);
119340ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org        if (_filePlayerPtr == NULL)
119440ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org        {
119540ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org            WEBRTC_TRACE(kTraceWarning, kTraceVoice,
119640ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org                         VoEId(_instanceId, -1),
119740ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org                         "TransmitMixer::MixOrReplaceAudioWithFile()"
119840ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org                         "fileplayer doesnot exist");
119940ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org            return -1;
120040ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org        }
120140ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org
120240ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org        if (_filePlayerPtr->Get10msAudioFromFile(fileBuffer.get(),
120340ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org                                                 fileSamples,
120440ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org                                                 mixingFrequency) == -1)
120540ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org        {
120640ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org            WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId, -1),
120740ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org                         "TransmitMixer::MixOrReplaceAudioWithFile() file"
120840ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org                         " mixing failed");
120940ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org            return -1;
121040ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org        }
121140ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    }
121240ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org
121340ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    assert(_audioFrame.samples_per_channel_ == fileSamples);
121440ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org
121540ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    if (_mixFileWithMicrophone)
121640ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    {
121740ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org        // Currently file stream is always mono.
121840ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org        // TODO(xians): Change the code when FilePlayer supports real stereo.
121940ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org        MixWithSat(_audioFrame.data_,
122040ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org                   _audioFrame.num_channels_,
122140ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org                   fileBuffer.get(),
122240ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org                   1,
122340ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org                   fileSamples);
122440ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    } else
122540ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    {
122640ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org        // Replace ACM audio with file.
122740ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org        // Currently file stream is always mono.
122840ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org        // TODO(xians): Change the code when FilePlayer supports real stereo.
122940ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org        _audioFrame.UpdateFrame(-1,
1230eec6ecdb1e249871dd25d04b62fc9ddc03dc8a34tommi@webrtc.org                                0xFFFFFFFF,
123140ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org                                fileBuffer.get(),
123240ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org                                fileSamples,
123340ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org                                mixingFrequency,
123440ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org                                AudioFrame::kNormalSpeech,
123540ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org                                AudioFrame::kVadUnknown,
123640ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org                                1);
123740ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    }
123840ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    return 0;
123940ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org}
124040ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org
124140ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.orgvoid TransmitMixer::ProcessAudio(int delay_ms, int clock_drift,
124240ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org                                 int current_mic_level, bool key_pressed) {
124340ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org  if (audioproc_->set_stream_delay_ms(delay_ms) != 0) {
1244ad856229a796a8efa1126ef8aa8d238f2b0a2b21pbos    // Silently ignore this failure to avoid flooding the logs.
124540ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org  }
124640ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org
124740ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org  GainControl* agc = audioproc_->gain_control();
124840ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org  if (agc->set_stream_analog_level(current_mic_level) != 0) {
1249ad856229a796a8efa1126ef8aa8d238f2b0a2b21pbos    LOG(LS_ERROR) << "set_stream_analog_level failed: current_mic_level = "
1250ad856229a796a8efa1126ef8aa8d238f2b0a2b21pbos                  << current_mic_level;
125140ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    assert(false);
125240ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org  }
125340ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org
125440ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org  EchoCancellation* aec = audioproc_->echo_cancellation();
125540ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org  if (aec->is_drift_compensation_enabled()) {
125640ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    aec->set_stream_drift_samples(clock_drift);
125740ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org  }
125840ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org
125940ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org  audioproc_->set_stream_key_pressed(key_pressed);
126040ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org
126140ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org  int err = audioproc_->ProcessStream(&_audioFrame);
126240ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org  if (err != 0) {
126340ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    LOG(LS_ERROR) << "ProcessStream() error: " << err;
126440ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    assert(false);
126540ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org  }
126640ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org
126740ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org  // Store new capture level. Only updated when analog AGC is enabled.
126840ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org  _captureLevel = agc->stream_analog_level();
126940ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org
127040ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org  CriticalSectionScoped cs(&_critSect);
127140ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org  // Triggers a callback in OnPeriodicProcess().
127240ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org  _saturationWarning |= agc->stream_is_saturated();
127340ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org}
127440ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org
127540ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org#ifdef WEBRTC_VOICE_ENGINE_TYPING_DETECTION
127640ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.orgvoid TransmitMixer::TypingDetection(bool keyPressed)
127740ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org{
127840ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org  // We let the VAD determine if we're using this feature or not.
127940ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org  if (_audioFrame.vad_activity_ == AudioFrame::kVadUnknown) {
128040ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    return;
128140ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org  }
128240ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org
128340ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org  bool vadActive = _audioFrame.vad_activity_ == AudioFrame::kVadActive;
128440ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org  if (_typingDetection.Process(keyPressed, vadActive)) {
1285302c978c921c2c63e1ab2414f0db03d19d5bfc60solenberg    CriticalSectionScoped cs(&_critSect);
128640ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    _typingNoiseWarningPending = true;
128740ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    _typingNoiseDetected = true;
128840ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org  } else {
1289302c978c921c2c63e1ab2414f0db03d19d5bfc60solenberg    CriticalSectionScoped cs(&_critSect);
129040ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    // If there is already a warning pending, do not change the state.
129140ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    // Otherwise set a warning pending if last callback was for noise detected.
129240ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    if (!_typingNoiseWarningPending && _typingNoiseDetected) {
129340ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org      _typingNoiseWarningPending = true;
129440ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org      _typingNoiseDetected = false;
129540ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    }
129640ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org  }
129740ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org}
129840ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org#endif
129940ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org
130040ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.orgint TransmitMixer::GetMixingFrequency()
130140ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org{
130240ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    assert(_audioFrame.sample_rate_hz_ != 0);
130340ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    return _audioFrame.sample_rate_hz_;
130440ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org}
130540ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org
130640ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org#ifdef WEBRTC_VOICE_ENGINE_TYPING_DETECTION
130740ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.orgint TransmitMixer::TimeSinceLastTyping(int &seconds)
130840ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org{
130940ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    // We check in VoEAudioProcessingImpl that this is only called when
131040ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    // typing detection is active.
131140ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    seconds = _typingDetection.TimeSinceLastDetectionInSeconds();
131240ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    return 0;
131340ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org}
131440ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org#endif
131540ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org
131640ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org#ifdef WEBRTC_VOICE_ENGINE_TYPING_DETECTION
131740ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.orgint TransmitMixer::SetTypingDetectionParameters(int timeWindow,
131840ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org                                                int costPerTyping,
131940ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org                                                int reportingThreshold,
132040ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org                                                int penaltyDecay,
132140ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org                                                int typeEventDelay)
132240ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org{
132340ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    _typingDetection.SetParameters(timeWindow,
132440ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org                                   costPerTyping,
132540ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org                                   reportingThreshold,
132640ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org                                   penaltyDecay,
132740ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org                                   typeEventDelay,
132840ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org                                   0);
132940ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    return 0;
133040ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org}
133140ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org#endif
133240ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org
133340ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.orgvoid TransmitMixer::EnableStereoChannelSwapping(bool enable) {
133440ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org  swap_stereo_channels_ = enable;
133540ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org}
133640ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org
133740ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.orgbool TransmitMixer::IsStereoChannelSwappingEnabled() {
133840ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org  return swap_stereo_channels_;
133940ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org}
134040ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org
134140ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org}  // namespace voe
134240ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org}  // namespace webrtc
1343