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 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() {}
|
||||
|
@ -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);
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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();
|
||||
|
Loading…
x
Reference in New Issue
Block a user