Add API to swap stereo channels.
BUG=issue451 TEST=manually with voe_cmd_test, using stereo and mono codecs Review URL: https://webrtc-codereview.appspot.com/519001 git-svn-id: http://webrtc.googlecode.com/svn/trunk@2106 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
parent
369166a179
commit
02d7174722
@ -206,6 +206,16 @@ public:
|
|||||||
int reportingThreshold,
|
int reportingThreshold,
|
||||||
int penaltyDecay) = 0;
|
int penaltyDecay) = 0;
|
||||||
|
|
||||||
|
// Swaps the capture-side left and right audio channels when enabled. It
|
||||||
|
// only has an effect when using a stereo send codec. The setting is
|
||||||
|
// persistent; it will be applied whenever a stereo send codec is enabled.
|
||||||
|
//
|
||||||
|
// The swap is applied only to the captured audio, and not mixed files. The
|
||||||
|
// swap will appear in file recordings and when accessing audio through the
|
||||||
|
// external media interface.
|
||||||
|
virtual void EnableStereoChannelSwapping(bool enable) = 0;
|
||||||
|
virtual bool IsStereoChannelSwappingEnabled() = 0;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
VoEAudioProcessing() {}
|
VoEAudioProcessing() {}
|
||||||
virtual ~VoEAudioProcessing() {}
|
virtual ~VoEAudioProcessing() {}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
|
* Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
|
||||||
*
|
*
|
||||||
* Use of this source code is governed by a BSD-style license
|
* Use of this source code is governed by a BSD-style license
|
||||||
* that can be found in the LICENSE file in the root of the source
|
* that can be found in the LICENSE file in the root of the source
|
||||||
@ -15,7 +15,7 @@ namespace webrtc {
|
|||||||
|
|
||||||
namespace voe {
|
namespace voe {
|
||||||
|
|
||||||
WebRtc_Word32
|
WebRtc_Word32
|
||||||
AudioFrameOperations::MonoToStereo(AudioFrame& audioFrame)
|
AudioFrameOperations::MonoToStereo(AudioFrame& audioFrame)
|
||||||
{
|
{
|
||||||
if (audioFrame._audioChannel != 1)
|
if (audioFrame._audioChannel != 1)
|
||||||
@ -29,10 +29,9 @@ AudioFrameOperations::MonoToStereo(AudioFrame& audioFrame)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
WebRtc_Word16* payloadCopy =
|
int16_t payloadCopy[AudioFrame::kMaxAudioFrameSizeSamples];
|
||||||
new WebRtc_Word16[audioFrame._payloadDataLengthInSamples];
|
|
||||||
memcpy(payloadCopy, audioFrame._payloadData,
|
memcpy(payloadCopy, audioFrame._payloadData,
|
||||||
sizeof(WebRtc_Word16)*audioFrame._payloadDataLengthInSamples);
|
sizeof(int16_t) * audioFrame._payloadDataLengthInSamples);
|
||||||
|
|
||||||
for (int i = 0; i < audioFrame._payloadDataLengthInSamples; i++)
|
for (int i = 0; i < audioFrame._payloadDataLengthInSamples; i++)
|
||||||
{
|
{
|
||||||
@ -42,11 +41,10 @@ AudioFrameOperations::MonoToStereo(AudioFrame& audioFrame)
|
|||||||
|
|
||||||
audioFrame._audioChannel = 2;
|
audioFrame._audioChannel = 2;
|
||||||
|
|
||||||
delete [] payloadCopy;
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
WebRtc_Word32
|
WebRtc_Word32
|
||||||
AudioFrameOperations::StereoToMono(AudioFrame& audioFrame)
|
AudioFrameOperations::StereoToMono(AudioFrame& audioFrame)
|
||||||
{
|
{
|
||||||
if (audioFrame._audioChannel != 2)
|
if (audioFrame._audioChannel != 2)
|
||||||
@ -65,7 +63,15 @@ AudioFrameOperations::StereoToMono(AudioFrame& audioFrame)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
WebRtc_Word32
|
void AudioFrameOperations::SwapStereoChannels(AudioFrame* frame) {
|
||||||
|
for (int i = 0; i < frame->_payloadDataLengthInSamples * 2; i += 2) {
|
||||||
|
int16_t temp_data = frame->_payloadData[i];
|
||||||
|
frame->_payloadData[i] = frame->_payloadData[i + 1];
|
||||||
|
frame->_payloadData[i + 1] = temp_data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
WebRtc_Word32
|
||||||
AudioFrameOperations::Mute(AudioFrame& audioFrame)
|
AudioFrameOperations::Mute(AudioFrame& audioFrame)
|
||||||
{
|
{
|
||||||
const int sizeInBytes = sizeof(WebRtc_Word16) *
|
const int sizeInBytes = sizeof(WebRtc_Word16) *
|
||||||
@ -75,7 +81,7 @@ AudioFrameOperations::Mute(AudioFrame& audioFrame)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
WebRtc_Word32
|
WebRtc_Word32
|
||||||
AudioFrameOperations::Scale(const float left,
|
AudioFrameOperations::Scale(const float left,
|
||||||
const float right,
|
const float right,
|
||||||
AudioFrame& audioFrame)
|
AudioFrame& audioFrame)
|
||||||
@ -96,7 +102,7 @@ AudioFrameOperations::Scale(const float left,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
WebRtc_Word32
|
WebRtc_Word32
|
||||||
AudioFrameOperations::ScaleWithSat(const float scale, AudioFrame& audioFrame)
|
AudioFrameOperations::ScaleWithSat(const float scale, AudioFrame& audioFrame)
|
||||||
{
|
{
|
||||||
WebRtc_Word32 tmp(0);
|
WebRtc_Word32 tmp(0);
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
|
* Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
|
||||||
*
|
*
|
||||||
* Use of this source code is governed by a BSD-style license
|
* Use of this source code is governed by a BSD-style license
|
||||||
* that can be found in the LICENSE file in the root of the source
|
* that can be found in the LICENSE file in the root of the source
|
||||||
@ -26,6 +26,10 @@ public:
|
|||||||
|
|
||||||
static WebRtc_Word32 StereoToMono(AudioFrame& audioFrame);
|
static WebRtc_Word32 StereoToMono(AudioFrame& audioFrame);
|
||||||
|
|
||||||
|
// Swap the left and right channels of |frame|. Fails silently if |frame|
|
||||||
|
// is not stereo.
|
||||||
|
static void SwapStereoChannels(AudioFrame* frame);
|
||||||
|
|
||||||
static WebRtc_Word32 Mute(AudioFrame& audioFrame);
|
static WebRtc_Word32 Mute(AudioFrame& audioFrame);
|
||||||
|
|
||||||
static WebRtc_Word32 Scale(const float left,
|
static WebRtc_Word32 Scale(const float left,
|
||||||
|
@ -201,12 +201,13 @@ TransmitMixer::TransmitMixer(const WebRtc_UWord32 instanceId) :
|
|||||||
_mute(false),
|
_mute(false),
|
||||||
_remainingMuteMicTimeMs(0),
|
_remainingMuteMicTimeMs(0),
|
||||||
_mixingFrequency(0),
|
_mixingFrequency(0),
|
||||||
_includeAudioLevelIndication(false)
|
_includeAudioLevelIndication(false),
|
||||||
|
swap_stereo_channels_(false)
|
||||||
{
|
{
|
||||||
WEBRTC_TRACE(kTraceMemory, kTraceVoice, VoEId(_instanceId, -1),
|
WEBRTC_TRACE(kTraceMemory, kTraceVoice, VoEId(_instanceId, -1),
|
||||||
"TransmitMixer::TransmitMixer() - ctor");
|
"TransmitMixer::TransmitMixer() - ctor");
|
||||||
}
|
}
|
||||||
|
|
||||||
TransmitMixer::~TransmitMixer()
|
TransmitMixer::~TransmitMixer()
|
||||||
{
|
{
|
||||||
WEBRTC_TRACE(kTraceMemory, kTraceVoice, VoEId(_instanceId, -1),
|
WEBRTC_TRACE(kTraceMemory, kTraceVoice, VoEId(_instanceId, -1),
|
||||||
@ -324,19 +325,18 @@ TransmitMixer::PrepareDemux(const void* audioSamples,
|
|||||||
void* iterator(NULL);
|
void* iterator(NULL);
|
||||||
Channel* channelPtr = sc.GetFirstChannel(iterator);
|
Channel* channelPtr = sc.GetFirstChannel(iterator);
|
||||||
_mixingFrequency = 8000;
|
_mixingFrequency = 8000;
|
||||||
while (channelPtr != NULL)
|
bool stereo_codec = false; // Used for stereo swapping.
|
||||||
{
|
while (channelPtr != NULL) {
|
||||||
if (channelPtr->Sending())
|
if (channelPtr->Sending()) {
|
||||||
{
|
CodecInst temp_codec;
|
||||||
CodecInst tmpCdc;
|
channelPtr->GetSendCodec(temp_codec);
|
||||||
channelPtr->GetSendCodec(tmpCdc);
|
stereo_codec = temp_codec.channels == 2;
|
||||||
if (tmpCdc.plfreq > _mixingFrequency)
|
if (temp_codec.plfreq > _mixingFrequency)
|
||||||
_mixingFrequency = tmpCdc.plfreq;
|
_mixingFrequency = temp_codec.plfreq;
|
||||||
}
|
}
|
||||||
channelPtr = sc.GetNextChannel(iterator);
|
channelPtr = sc.GetNextChannel(iterator);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// --- Resample input audio and create/store the initial audio frame
|
// --- Resample input audio and create/store the initial audio frame
|
||||||
|
|
||||||
if (GenerateAudioFrame((const WebRtc_Word16*) audioSamples,
|
if (GenerateAudioFrame((const WebRtc_Word16*) audioSamples,
|
||||||
@ -352,6 +352,10 @@ TransmitMixer::PrepareDemux(const void* audioSamples,
|
|||||||
|
|
||||||
APMProcessStream(totalDelayMS, clockDrift, currentMicLevel);
|
APMProcessStream(totalDelayMS, clockDrift, currentMicLevel);
|
||||||
|
|
||||||
|
if (swap_stereo_channels_ && stereo_codec)
|
||||||
|
// Only bother swapping if we're using a stereo codec.
|
||||||
|
AudioFrameOperations::SwapStereoChannels(&_audioFrame);
|
||||||
|
|
||||||
// --- Annoying typing detection (utilizes the APM/VAD decision)
|
// --- Annoying typing detection (utilizes the APM/VAD decision)
|
||||||
|
|
||||||
#ifdef WEBRTC_VOICE_ENGINE_TYPING_DETECTION
|
#ifdef WEBRTC_VOICE_ENGINE_TYPING_DETECTION
|
||||||
@ -1465,6 +1469,14 @@ int TransmitMixer::SetTypingDetectionParameters(int timeWindow,
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
void TransmitMixer::EnableStereoChannelSwapping(bool enable) {
|
||||||
|
swap_stereo_channels_ = enable;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TransmitMixer::IsStereoChannelSwappingEnabled() {
|
||||||
|
return swap_stereo_channels_;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace voe
|
} // namespace voe
|
||||||
|
|
||||||
} // namespace webrtc
|
} // namespace webrtc
|
||||||
|
@ -133,11 +133,11 @@ public:
|
|||||||
|
|
||||||
virtual ~TransmitMixer();
|
virtual ~TransmitMixer();
|
||||||
|
|
||||||
public: // MonitorObserver
|
// MonitorObserver
|
||||||
void OnPeriodicProcess();
|
void OnPeriodicProcess();
|
||||||
|
|
||||||
|
|
||||||
public: // FileCallback
|
// FileCallback
|
||||||
void PlayNotification(const WebRtc_Word32 id,
|
void PlayNotification(const WebRtc_Word32 id,
|
||||||
const WebRtc_UWord32 durationMs);
|
const WebRtc_UWord32 durationMs);
|
||||||
|
|
||||||
@ -149,7 +149,7 @@ public: // FileCallback
|
|||||||
void RecordFileEnded(const WebRtc_Word32 id);
|
void RecordFileEnded(const WebRtc_Word32 id);
|
||||||
|
|
||||||
#ifdef WEBRTC_VOICE_ENGINE_TYPING_DETECTION
|
#ifdef WEBRTC_VOICE_ENGINE_TYPING_DETECTION
|
||||||
public: // Typing detection
|
// Typing detection
|
||||||
int TimeSinceLastTyping(int &seconds);
|
int TimeSinceLastTyping(int &seconds);
|
||||||
int SetTypingDetectionParameters(int timeWindow,
|
int SetTypingDetectionParameters(int timeWindow,
|
||||||
int costPerTyping,
|
int costPerTyping,
|
||||||
@ -157,10 +157,12 @@ public: // Typing detection
|
|||||||
int penaltyDecay);
|
int penaltyDecay);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
void EnableStereoChannelSwapping(bool enable);
|
||||||
|
bool IsStereoChannelSwappingEnabled();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
TransmitMixer(const WebRtc_UWord32 instanceId);
|
TransmitMixer(const WebRtc_UWord32 instanceId);
|
||||||
|
|
||||||
private:
|
|
||||||
WebRtc_Word32 GenerateAudioFrame(const WebRtc_Word16 audioSamples[],
|
WebRtc_Word32 GenerateAudioFrame(const WebRtc_Word16 audioSamples[],
|
||||||
const WebRtc_UWord32 nSamples,
|
const WebRtc_UWord32 nSamples,
|
||||||
const WebRtc_UWord8 nChannels,
|
const WebRtc_UWord8 nChannels,
|
||||||
@ -179,14 +181,14 @@ private:
|
|||||||
int TypingDetection();
|
int TypingDetection();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
private: // uses
|
// uses
|
||||||
Statistics* _engineStatisticsPtr;
|
Statistics* _engineStatisticsPtr;
|
||||||
ChannelManager* _channelManagerPtr;
|
ChannelManager* _channelManagerPtr;
|
||||||
AudioProcessing* _audioProcessingModulePtr;
|
AudioProcessing* _audioProcessingModulePtr;
|
||||||
VoiceEngineObserver* _voiceEngineObserverPtr;
|
VoiceEngineObserver* _voiceEngineObserverPtr;
|
||||||
ProcessThread* _processThreadPtr;
|
ProcessThread* _processThreadPtr;
|
||||||
|
|
||||||
private: // owns
|
// owns
|
||||||
MonitorModule _monitorModule;
|
MonitorModule _monitorModule;
|
||||||
AudioFrame _audioFrame;
|
AudioFrame _audioFrame;
|
||||||
Resampler _audioResampler; // ADM sample rate -> mixing rate
|
Resampler _audioResampler; // ADM sample rate -> mixing rate
|
||||||
@ -220,7 +222,6 @@ private: // owns
|
|||||||
WebRtc_UWord32 _saturationWarning;
|
WebRtc_UWord32 _saturationWarning;
|
||||||
WebRtc_UWord32 _noiseWarning;
|
WebRtc_UWord32 _noiseWarning;
|
||||||
|
|
||||||
private:
|
|
||||||
int _instanceId;
|
int _instanceId;
|
||||||
bool _mixFileWithMicrophone;
|
bool _mixFileWithMicrophone;
|
||||||
WebRtc_UWord32 _captureLevel;
|
WebRtc_UWord32 _captureLevel;
|
||||||
@ -230,6 +231,7 @@ private:
|
|||||||
WebRtc_Word32 _remainingMuteMicTimeMs;
|
WebRtc_Word32 _remainingMuteMicTimeMs;
|
||||||
int _mixingFrequency;
|
int _mixingFrequency;
|
||||||
bool _includeAudioLevelIndication;
|
bool _includeAudioLevelIndication;
|
||||||
|
bool swap_stereo_channels_;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // WEBRTC_VOICE_ENGINE_TRANSMIT_MIXER_H
|
#endif // WEBRTC_VOICE_ENGINE_TRANSMIT_MIXER_H
|
||||||
|
@ -18,6 +18,13 @@
|
|||||||
#include "voe_errors.h"
|
#include "voe_errors.h"
|
||||||
#include "voice_engine_impl.h"
|
#include "voice_engine_impl.h"
|
||||||
|
|
||||||
|
// TODO(andrew): move to a common place.
|
||||||
|
#define WEBRTC_TRACE_VOICE_API() \
|
||||||
|
do { \
|
||||||
|
WEBRTC_TRACE(kTraceApiCall, kTraceVoice, \
|
||||||
|
VoEId(_shared->instance_id(), -1), __FUNCTION__); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
namespace webrtc {
|
namespace webrtc {
|
||||||
|
|
||||||
#if defined(WEBRTC_ANDROID) || defined(MAC_IPHONE) || defined(MAC_IPHONE_SIM)
|
#if defined(WEBRTC_ANDROID) || defined(MAC_IPHONE) || defined(MAC_IPHONE_SIM)
|
||||||
@ -1108,6 +1115,17 @@ int VoEAudioProcessingImpl::SetTypingDetectionParameters(int timeWindow,
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void VoEAudioProcessingImpl::EnableStereoChannelSwapping(bool enable) {
|
||||||
|
WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
|
||||||
|
"EnableStereoChannelSwapping(enable=%d)", enable);
|
||||||
|
_shared->transmit_mixer()->EnableStereoChannelSwapping(enable);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool VoEAudioProcessingImpl::IsStereoChannelSwappingEnabled() {
|
||||||
|
WEBRTC_TRACE_VOICE_API();
|
||||||
|
return _shared->transmit_mixer()->IsStereoChannelSwappingEnabled();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#endif // #ifdef WEBRTC_VOICE_ENGINE_AUDIO_PROCESSING_API
|
#endif // #ifdef WEBRTC_VOICE_ENGINE_AUDIO_PROCESSING_API
|
||||||
|
@ -98,6 +98,9 @@ class VoEAudioProcessingImpl
|
|||||||
int reportingThreshold,
|
int reportingThreshold,
|
||||||
int penaltyDecay);
|
int penaltyDecay);
|
||||||
|
|
||||||
|
virtual void EnableStereoChannelSwapping(bool enable);
|
||||||
|
virtual bool IsStereoChannelSwappingEnabled();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
VoEAudioProcessingImpl(voe::SharedData* shared);
|
VoEAudioProcessingImpl(voe::SharedData* shared);
|
||||||
virtual ~VoEAudioProcessingImpl();
|
virtual ~VoEAudioProcessingImpl();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user