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:
andrew@webrtc.org 2012-04-24 19:47:00 +00:00
parent 369166a179
commit 02d7174722
7 changed files with 86 additions and 31 deletions

View File

@ -206,6 +206,16 @@ public:
int reportingThreshold,
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:
VoEAudioProcessing() {}
virtual ~VoEAudioProcessing() {}

View File

@ -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
* that can be found in the LICENSE file in the root of the source
@ -15,7 +15,7 @@ namespace webrtc {
namespace voe {
WebRtc_Word32
WebRtc_Word32
AudioFrameOperations::MonoToStereo(AudioFrame& audioFrame)
{
if (audioFrame._audioChannel != 1)
@ -29,10 +29,9 @@ AudioFrameOperations::MonoToStereo(AudioFrame& audioFrame)
return -1;
}
WebRtc_Word16* payloadCopy =
new WebRtc_Word16[audioFrame._payloadDataLengthInSamples];
int16_t payloadCopy[AudioFrame::kMaxAudioFrameSizeSamples];
memcpy(payloadCopy, audioFrame._payloadData,
sizeof(WebRtc_Word16)*audioFrame._payloadDataLengthInSamples);
sizeof(int16_t) * audioFrame._payloadDataLengthInSamples);
for (int i = 0; i < audioFrame._payloadDataLengthInSamples; i++)
{
@ -42,11 +41,10 @@ AudioFrameOperations::MonoToStereo(AudioFrame& audioFrame)
audioFrame._audioChannel = 2;
delete [] payloadCopy;
return 0;
}
WebRtc_Word32
WebRtc_Word32
AudioFrameOperations::StereoToMono(AudioFrame& audioFrame)
{
if (audioFrame._audioChannel != 2)
@ -65,7 +63,15 @@ AudioFrameOperations::StereoToMono(AudioFrame& audioFrame)
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)
{
const int sizeInBytes = sizeof(WebRtc_Word16) *
@ -75,7 +81,7 @@ AudioFrameOperations::Mute(AudioFrame& audioFrame)
return 0;
}
WebRtc_Word32
WebRtc_Word32
AudioFrameOperations::Scale(const float left,
const float right,
AudioFrame& audioFrame)
@ -96,7 +102,7 @@ AudioFrameOperations::Scale(const float left,
return 0;
}
WebRtc_Word32
WebRtc_Word32
AudioFrameOperations::ScaleWithSat(const float scale, AudioFrame& audioFrame)
{
WebRtc_Word32 tmp(0);

View File

@ -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
* 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);
// 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 Scale(const float left,

View File

@ -201,12 +201,13 @@ TransmitMixer::TransmitMixer(const WebRtc_UWord32 instanceId) :
_mute(false),
_remainingMuteMicTimeMs(0),
_mixingFrequency(0),
_includeAudioLevelIndication(false)
_includeAudioLevelIndication(false),
swap_stereo_channels_(false)
{
WEBRTC_TRACE(kTraceMemory, kTraceVoice, VoEId(_instanceId, -1),
"TransmitMixer::TransmitMixer() - ctor");
}
TransmitMixer::~TransmitMixer()
{
WEBRTC_TRACE(kTraceMemory, kTraceVoice, VoEId(_instanceId, -1),
@ -324,19 +325,18 @@ TransmitMixer::PrepareDemux(const void* audioSamples,
void* iterator(NULL);
Channel* channelPtr = sc.GetFirstChannel(iterator);
_mixingFrequency = 8000;
while (channelPtr != NULL)
{
if (channelPtr->Sending())
{
CodecInst tmpCdc;
channelPtr->GetSendCodec(tmpCdc);
if (tmpCdc.plfreq > _mixingFrequency)
_mixingFrequency = tmpCdc.plfreq;
}
channelPtr = sc.GetNextChannel(iterator);
bool stereo_codec = false; // Used for stereo swapping.
while (channelPtr != NULL) {
if (channelPtr->Sending()) {
CodecInst temp_codec;
channelPtr->GetSendCodec(temp_codec);
stereo_codec = temp_codec.channels == 2;
if (temp_codec.plfreq > _mixingFrequency)
_mixingFrequency = temp_codec.plfreq;
}
channelPtr = sc.GetNextChannel(iterator);
}
// --- Resample input audio and create/store the initial audio frame
if (GenerateAudioFrame((const WebRtc_Word16*) audioSamples,
@ -352,6 +352,10 @@ TransmitMixer::PrepareDemux(const void* audioSamples,
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)
#ifdef WEBRTC_VOICE_ENGINE_TYPING_DETECTION
@ -1465,6 +1469,14 @@ int TransmitMixer::SetTypingDetectionParameters(int timeWindow,
}
#endif
void TransmitMixer::EnableStereoChannelSwapping(bool enable) {
swap_stereo_channels_ = enable;
}
bool TransmitMixer::IsStereoChannelSwappingEnabled() {
return swap_stereo_channels_;
}
} // namespace voe
} // namespace webrtc

View File

@ -133,11 +133,11 @@ public:
virtual ~TransmitMixer();
public: // MonitorObserver
// MonitorObserver
void OnPeriodicProcess();
public: // FileCallback
// FileCallback
void PlayNotification(const WebRtc_Word32 id,
const WebRtc_UWord32 durationMs);
@ -149,7 +149,7 @@ public: // FileCallback
void RecordFileEnded(const WebRtc_Word32 id);
#ifdef WEBRTC_VOICE_ENGINE_TYPING_DETECTION
public: // Typing detection
// Typing detection
int TimeSinceLastTyping(int &seconds);
int SetTypingDetectionParameters(int timeWindow,
int costPerTyping,
@ -157,10 +157,12 @@ public: // Typing detection
int penaltyDecay);
#endif
void EnableStereoChannelSwapping(bool enable);
bool IsStereoChannelSwappingEnabled();
private:
TransmitMixer(const WebRtc_UWord32 instanceId);
private:
WebRtc_Word32 GenerateAudioFrame(const WebRtc_Word16 audioSamples[],
const WebRtc_UWord32 nSamples,
const WebRtc_UWord8 nChannels,
@ -179,14 +181,14 @@ private:
int TypingDetection();
#endif
private: // uses
// uses
Statistics* _engineStatisticsPtr;
ChannelManager* _channelManagerPtr;
AudioProcessing* _audioProcessingModulePtr;
VoiceEngineObserver* _voiceEngineObserverPtr;
ProcessThread* _processThreadPtr;
private: // owns
// owns
MonitorModule _monitorModule;
AudioFrame _audioFrame;
Resampler _audioResampler; // ADM sample rate -> mixing rate
@ -220,7 +222,6 @@ private: // owns
WebRtc_UWord32 _saturationWarning;
WebRtc_UWord32 _noiseWarning;
private:
int _instanceId;
bool _mixFileWithMicrophone;
WebRtc_UWord32 _captureLevel;
@ -230,6 +231,7 @@ private:
WebRtc_Word32 _remainingMuteMicTimeMs;
int _mixingFrequency;
bool _includeAudioLevelIndication;
bool swap_stereo_channels_;
};
#endif // WEBRTC_VOICE_ENGINE_TRANSMIT_MIXER_H

View File

@ -18,6 +18,13 @@
#include "voe_errors.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 {
#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

View File

@ -98,6 +98,9 @@ class VoEAudioProcessingImpl
int reportingThreshold,
int penaltyDecay);
virtual void EnableStereoChannelSwapping(bool enable);
virtual bool IsStereoChannelSwappingEnabled();
protected:
VoEAudioProcessingImpl(voe::SharedData* shared);
virtual ~VoEAudioProcessingImpl();