Skip to content

Commit e665a4a

Browse files
committed
Improved audio processing by basic channel up-mixing to avoid additional audio converter
1 parent 071cbe9 commit e665a4a

File tree

2 files changed

+95
-2
lines changed

2 files changed

+95
-2
lines changed

webrtc-jni/src/main/cpp/src/JNI_AudioProcessing.cpp

+59-2
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
#include "media/audio/AudioProcessing.h"
2828
#include "media/audio/AudioProcessingConfig.h"
2929
#include "media/audio/AudioProcessingStreamConfig.h"
30+
#include "api/audio/audio_frame.h"
3031
#include "api/scoped_refptr.h"
3132
#include "modules/audio_processing/include/audio_processing.h"
3233
#include "rtc_base/logging.h"
@@ -72,7 +73,35 @@ JNIEXPORT jint JNICALL Java_dev_onvoid_webrtc_media_audio_AudioProcessing_proces
7273
jbyte * srcPtr = env->GetByteArrayElements(src, nullptr);
7374
jbyte * dstPtr = env->GetByteArrayElements(dest, &isDstCopy);
7475

75-
int result = apm->ProcessStream(reinterpret_cast<const int16_t *>(srcPtr), srcConfig, dstConfig, reinterpret_cast<int16_t *>(dstPtr));
76+
int result;
77+
78+
if (srcConfig.num_channels() == 1 && dstConfig.num_channels() == 2) {
79+
// Up-mixing, only mono to stereo.
80+
// For complex channel layouts an audio converter is required.
81+
82+
const size_t srcNumSamples = srcConfig.num_samples();
83+
const size_t dstNumChannels = dstConfig.num_channels();
84+
const size_t frameSize = srcNumSamples * dstNumChannels;
85+
86+
if (frameSize > webrtc::AudioFrame::kMaxDataSizeSamples) {
87+
return -9;
88+
}
89+
90+
const int16_t * srcFrame = reinterpret_cast<const int16_t *>(srcPtr);
91+
int16_t * dstFrame = reinterpret_cast<int16_t*>(dstPtr);
92+
93+
for (int i = srcNumSamples - 1; i >= 0; i--) {
94+
for (size_t j = 0; j < dstNumChannels; ++j) {
95+
dstFrame[dstNumChannels * i + j] = srcFrame[i];
96+
}
97+
}
98+
99+
result = apm->ProcessStream(dstFrame, srcConfig, dstConfig, dstFrame);
100+
}
101+
else {
102+
// Will also down-mix if required, e.g. from stereo to mono.
103+
result = apm->ProcessStream(reinterpret_cast<const int16_t *>(srcPtr), srcConfig, dstConfig, reinterpret_cast<int16_t *>(dstPtr));
104+
}
76105

77106
if (isDstCopy == JNI_TRUE) {
78107
jsize dstLength = env->GetArrayLength(dest);
@@ -100,7 +129,35 @@ JNIEXPORT jint JNICALL Java_dev_onvoid_webrtc_media_audio_AudioProcessing_proces
100129
jbyte * srcPtr = env->GetByteArrayElements(src, nullptr);
101130
jbyte * dstPtr = env->GetByteArrayElements(dest, &isDstCopy);
102131

103-
int result = apm->ProcessReverseStream(reinterpret_cast<int16_t *>(srcPtr), srcConfig, dstConfig, reinterpret_cast<int16_t *>(dstPtr));
132+
int result;
133+
134+
if (srcConfig.num_channels() == 1 && dstConfig.num_channels() == 2) {
135+
// Up-mixing, only mono to stereo.
136+
// For complex channel layouts an audio converter is required.
137+
138+
const size_t srcNumSamples = srcConfig.num_samples();
139+
const size_t dstNumChannels = dstConfig.num_channels();
140+
const size_t frameSize = srcNumSamples * dstNumChannels;
141+
142+
if (frameSize > webrtc::AudioFrame::kMaxDataSizeSamples) {
143+
return -9;
144+
}
145+
146+
const int16_t * srcFrame = reinterpret_cast<const int16_t *>(srcPtr);
147+
int16_t * dstFrame = reinterpret_cast<int16_t *>(dstPtr);
148+
149+
for (int i = srcNumSamples - 1; i >= 0; i--) {
150+
for (size_t j = 0; j < dstNumChannels; ++j) {
151+
dstFrame[dstNumChannels * i + j] = srcFrame[i];
152+
}
153+
}
154+
155+
result = apm->ProcessStream(dstFrame, srcConfig, dstConfig, dstFrame);
156+
}
157+
else {
158+
// Will also down-mix if required, e.g. from stereo to mono.
159+
result = apm->ProcessStream(reinterpret_cast<const int16_t *>(srcPtr), srcConfig, dstConfig, reinterpret_cast<int16_t *>(dstPtr));
160+
}
104161

105162
if (isDstCopy == JNI_TRUE) {
106163
jsize dstLength = env->GetArrayLength(dest);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
/*
2+
* Copyright 2021 Alex Andres
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package dev.onvoid.webrtc.media.audio;
18+
19+
import dev.onvoid.webrtc.internal.DisposableNativeObject;
20+
21+
public class AudioConverter extends DisposableNativeObject {
22+
23+
public AudioConverter(int srcSampleRate, int srcChannels, int dstSampleRate,
24+
int dstChannels) {
25+
initialize(srcSampleRate, srcChannels, dstSampleRate, dstChannels);
26+
}
27+
28+
public native int convert(byte[] src, int nSrcSamples, byte[] dst, int nDstSamples);
29+
30+
@Override
31+
public native void dispose();
32+
33+
private native void initialize(int srcSampleRate, int srcChannels,
34+
int dstSampleRate, int dstChannels);
35+
36+
}

0 commit comments

Comments
 (0)