1
0
mirror of https://github.com/danog/libtgvoip.git synced 2025-01-22 13:01:21 +01:00

2.1.1: a bunch of fixes

- Enabled delay-agnostic AEC on Windows & Linux, it seems to make a difference after all (telegramdesktop/tdesktop#4881)
- Fixed PulseAudio crashes, at least I hope so (closes #42)
- Fixed parsing of floating-point server config values in some locales in Linux
This commit is contained in:
Grishka 2018-07-02 00:42:49 +03:00
parent a541f8faf0
commit 697eea96aa
6 changed files with 55 additions and 61 deletions

6
EchoCanceller.cpp Normal file → Executable file
View File

@ -66,7 +66,7 @@ EchoCanceller::EchoCanceller(bool enableAEC, bool enableNS, bool enableAGC){
#else
aec=webrtc::WebRtcAec_Create();
webrtc::WebRtcAec_Init(aec, 48000, 48000);
//webrtc::WebRtcAec_enable_delay_agnostic(webrtc::WebRtcAec_aec_core(aec), 1);
webrtc::WebRtcAec_enable_delay_agnostic(webrtc::WebRtcAec_aec_core(aec), 1);
webrtc::AecConfig config;
config.metricsMode=webrtc::kAecFalse;
config.nlpMode=webrtc::kAecNlpAggressive;
@ -183,6 +183,8 @@ void EchoCanceller::RunBufferFarendThread(void* arg){
farendBufferPool->Reuse((unsigned char *) samplesIn);
((webrtc::SplittingFilter*)splittingFilterFarend)->Analysis(bufIn, bufOut);
aecMutex.Lock();
//outstandingFarendFrames++;
//LOGV("BufferFarend: %d frames", outstandingFarendFrames);
#ifndef TGVOIP_USE_DESKTOP_DSP
WebRtcAecm_BufferFarend(aec, bufOut->ibuf_const()->bands(0)[0], 160);
WebRtcAecm_BufferFarend(aec, bufOut->ibuf_const()->bands(0)[0]+160, 160);
@ -318,6 +320,8 @@ void EchoCanceller::ProcessInput(unsigned char* data, unsigned char* out, size_t
aecIn[i]+=160;
}
webrtc::WebRtcAec_Process(aec, aecIn, 3, aecOut, AEC_FRAME_SIZE, audio::AudioOutput::GetEstimatedDelay()+audio::AudioInput::GetEstimatedDelay(), 0);
//outstandingFarendFrames--;
//LOGV("Process: %d frames", outstandingFarendFrames);
memcpy(bufOut->fbuf()->bands(0)[0], _aecOut[0], 320*4);
memcpy(bufOut->fbuf()->bands(0)[1], _aecOut[1], 320*4);

1
EchoCanceller.h Normal file → Executable file
View File

@ -48,6 +48,7 @@ private:
void* ns; // NsxHandle
void* agc;
int32_t agcMicLevel;
//int32_t outstandingFarendFrames=0;
#endif
};

View File

@ -32,7 +32,7 @@
#include "Buffers.h"
#include "PacketReassembler.h"
#define LIBTGVOIP_VERSION "2.1"
#define LIBTGVOIP_VERSION "2.1.1"
#ifdef _WIN32
#undef GetCurrentTime

View File

@ -7,6 +7,8 @@
#include "VoIPServerConfig.h"
#include <stdlib.h>
#include "logging.h"
#include <sstream>
#include <locale>
using namespace tgvoip;
@ -40,12 +42,12 @@ double ServerConfig::GetDouble(std::string name, double fallback){
MutexGuard sync(mutex);
if(ContainsKey(name)){
std::string val=config[name];
char* end;
const char* start=val.c_str();
double d=strtod(start, &end);
if(end!=start){
return d;
}
std::istringstream stm(val);
double rval=fallback;
stm.imbue(std::locale("C"));
stm >> rval;
if(!stm.fail())
return rval;
}
return fallback;
}

View File

@ -65,8 +65,8 @@ AudioInputPulse::AudioInputPulse(std::string devID){
return;
}
pa_context_set_state_callback(context, AudioInputPulse::ContextStateCallback, this);
pa_threaded_mainloop_lock(mainloop);
isLocked=true;
pa_threaded_mainloop_lock(mainloop);
int err=pa_threaded_mainloop_start(mainloop);
CHECK_ERROR(err, "pa_threaded_mainloop_start");
didStart=true;
@ -75,9 +75,7 @@ AudioInputPulse::AudioInputPulse(std::string devID){
CHECK_ERROR(err, "pa_context_connect");
while(true){
pa_threaded_mainloop_lock(mainloop);
pa_context_state_t contextState=pa_context_get_state(context);
pa_threaded_mainloop_unlock(mainloop);
if(!PA_CONTEXT_IS_GOOD(contextState)){
LOGE("Error initializing PulseAudio (PA_CONTEXT_IS_GOOD)");
failed=true;
@ -147,8 +145,10 @@ void AudioInputPulse::Start(){
if(failed || isRecording)
return;
pa_threaded_mainloop_lock(mainloop);
isRecording=true;
pa_operation_unref(pa_stream_cork(stream, 0, AudioInputPulse::StreamSuccessCallback, mainloop));
pa_operation_unref(pa_stream_cork(stream, 0, AudioInputPulse::StreamSuccessCallback, NULL));
pa_threaded_mainloop_unlock(mainloop);
}
void AudioInputPulse::Stop(){
@ -156,7 +156,9 @@ void AudioInputPulse::Stop(){
return;
isRecording=false;
pa_operation_unref(pa_stream_cork(stream, 1, AudioInputPulse::StreamSuccessCallback, mainloop));
pa_threaded_mainloop_lock(mainloop);
pa_operation_unref(pa_stream_cork(stream, 1, AudioInputPulse::StreamSuccessCallback, NULL));
pa_threaded_mainloop_unlock(mainloop);
}
bool AudioInputPulse::IsRecording(){
@ -164,6 +166,7 @@ bool AudioInputPulse::IsRecording(){
}
void AudioInputPulse::SetCurrentDevice(std::string devID){
pa_threaded_mainloop_lock(mainloop);
currentDevice=devID;
if(isRecording && isConnected){
pa_stream_disconnect(stream);
@ -171,13 +174,13 @@ void AudioInputPulse::SetCurrentDevice(std::string devID){
}
pa_buffer_attr bufferAttr={
.maxlength=960*6,
.tlength=960*6,
.prebuf=0,
.minreq=960*2
.maxlength=(uint32_t)-1,
.tlength=(uint32_t)-1,
.prebuf=(uint32_t)-1,
.minreq=(uint32_t)-1,
.fragsize=960*2
};
int streamFlags=PA_STREAM_START_CORKED | PA_STREAM_INTERPOLATE_TIMING |
PA_STREAM_NOT_MONOTONIC | PA_STREAM_AUTO_TIMING_UPDATE | PA_STREAM_ADJUST_LATENCY;
int streamFlags=PA_STREAM_START_CORKED | PA_STREAM_INTERPOLATE_TIMING | PA_STREAM_AUTO_TIMING_UPDATE | PA_STREAM_ADJUST_LATENCY;
int err=pa_stream_connect_record(stream, devID=="default" ? NULL : devID.c_str(), &bufferAttr, (pa_stream_flags_t)streamFlags);
if(err!=0 && devID!="default"){
@ -187,9 +190,7 @@ void AudioInputPulse::SetCurrentDevice(std::string devID){
CHECK_ERROR(err, "pa_stream_connect_record");
while(true){
pa_threaded_mainloop_lock(mainloop);
pa_stream_state_t streamState=pa_stream_get_state(stream);
pa_threaded_mainloop_unlock(mainloop);
if(!PA_STREAM_IS_GOOD(streamState)){
LOGE("Error connecting to audio device '%s'", devID.c_str());
failed=true;
@ -205,6 +206,7 @@ void AudioInputPulse::SetCurrentDevice(std::string devID){
if(isRecording){
pa_operation_unref(pa_stream_cork(stream, 0, AudioInputPulse::StreamSuccessCallback, mainloop));
}
pa_threaded_mainloop_unlock(mainloop);
}
bool AudioInputPulse::EnumerateDevices(std::vector<AudioInputDevice>& devs){

View File

@ -150,7 +150,9 @@ void AudioOutputPulse::Start(){
return;
isPlaying=true;
pa_operation_unref(pa_stream_cork(stream, 0, AudioOutputPulse::StreamSuccessCallback, mainloop));
pa_threaded_mainloop_lock(mainloop);
pa_operation_unref(pa_stream_cork(stream, 0, AudioOutputPulse::StreamSuccessCallback, NULL));
pa_threaded_mainloop_unlock(mainloop);
}
void AudioOutputPulse::Stop(){
@ -158,7 +160,9 @@ void AudioOutputPulse::Stop(){
return;
isPlaying=false;
pa_operation_unref(pa_stream_cork(stream, 1, AudioOutputPulse::StreamSuccessCallback, mainloop));
pa_threaded_mainloop_lock(mainloop);
pa_operation_unref(pa_stream_cork(stream, 1, AudioOutputPulse::StreamSuccessCallback, NULL));
pa_threaded_mainloop_unlock(mainloop);
}
bool AudioOutputPulse::IsPlaying(){
@ -166,6 +170,7 @@ bool AudioOutputPulse::IsPlaying(){
}
void AudioOutputPulse::SetCurrentDevice(std::string devID){
pa_threaded_mainloop_lock(mainloop);
currentDevice=devID;
if(isPlaying && isConnected){
pa_stream_disconnect(stream);
@ -173,13 +178,13 @@ void AudioOutputPulse::SetCurrentDevice(std::string devID){
}
pa_buffer_attr bufferAttr={
.maxlength=960*6,
.tlength=960*6,
.prebuf=0,
.minreq=960*2
.maxlength=(uint32_t)-1,
.tlength=960*2,
.prebuf=(uint32_t)-1,
.minreq=(uint32_t)-1,
.fragsize=(uint32_t)-1
};
int streamFlags=PA_STREAM_START_CORKED | PA_STREAM_INTERPOLATE_TIMING |
PA_STREAM_NOT_MONOTONIC | PA_STREAM_AUTO_TIMING_UPDATE | PA_STREAM_ADJUST_LATENCY;
int streamFlags=PA_STREAM_START_CORKED | PA_STREAM_INTERPOLATE_TIMING | PA_STREAM_AUTO_TIMING_UPDATE | PA_STREAM_ADJUST_LATENCY;
int err=pa_stream_connect_playback(stream, devID=="default" ? NULL : devID.c_str(), &bufferAttr, (pa_stream_flags_t)streamFlags, NULL, NULL);
if(err!=0 && devID!="default"){
@ -189,9 +194,7 @@ void AudioOutputPulse::SetCurrentDevice(std::string devID){
CHECK_ERROR(err, "pa_stream_connect_playback");
while(true){
pa_threaded_mainloop_lock(mainloop);
pa_stream_state_t streamState=pa_stream_get_state(stream);
pa_threaded_mainloop_unlock(mainloop);
if(!PA_STREAM_IS_GOOD(streamState)){
LOGE("Error connecting to audio device '%s'", devID.c_str());
failed=true;
@ -207,6 +210,7 @@ void AudioOutputPulse::SetCurrentDevice(std::string devID){
if(isPlaying){
pa_operation_unref(pa_stream_cork(stream, 0, AudioOutputPulse::StreamSuccessCallback, mainloop));
}
pa_threaded_mainloop_unlock(mainloop);
}
bool AudioOutputPulse::EnumerateDevices(std::vector<AudioOutputDevice>& devs){
@ -270,40 +274,21 @@ void AudioOutputPulse::StreamWriteCallback(pa_stream *stream, size_t requestedBy
}
void AudioOutputPulse::StreamWriteCallback(pa_stream *stream, size_t requestedBytes) {
int bytesRemaining = requestedBytes;
uint8_t *buffer = NULL;
while (bytesRemaining > 0) {
size_t bytesToFill = 102400;
size_t i;
if (bytesToFill > bytesRemaining) bytesToFill = bytesRemaining;
int err=pa_stream_begin_write(stream, (void**) &buffer, &bytesToFill);
CHECK_ERROR(err, "pa_stream_begin_write");
assert(requestedBytes<=sizeof(remainingData));
while(requestedBytes>remainingDataSize){
if(isPlaying){
while(remainingDataSize<bytesToFill){
if(remainingDataSize+960*2>=sizeof(remainingData)){
LOGE("Can't provide %d bytes of audio data at a time", (int)bytesToFill);
failed=true;
pa_threaded_mainloop_unlock(mainloop);
return;
}
InvokeCallback(remainingData+remainingDataSize, 960*2);
remainingDataSize+=960*2;
}
memcpy(buffer, remainingData, bytesToFill);
memmove(remainingData, remainingData+bytesToFill, remainingDataSize-bytesToFill);
remainingDataSize-=bytesToFill;
InvokeCallback(remainingData+remainingDataSize, 960*2);
remainingDataSize+=960*2;
}else{
memset(buffer, 0, bytesToFill);
memset(remainingData+remainingDataSize, 0, requestedBytes-remainingDataSize);
remainingDataSize=requestedBytes;
}
err=pa_stream_write(stream, buffer, bytesToFill, NULL, 0LL, PA_SEEK_RELATIVE);
CHECK_ERROR(err, "pa_stream_write");
bytesRemaining -= bytesToFill;
}
int err=pa_stream_write(stream, remainingData, requestedBytes, NULL, 0, PA_SEEK_RELATIVE);
CHECK_ERROR(err, "pa_stream_write");
remainingDataSize-=requestedBytes;
if(remainingDataSize>0)
memmove(remainingData, remainingData+requestedBytes, remainingDataSize);
}
void AudioOutputPulse::StreamSuccessCallback(pa_stream *stream, int success, void *userdata) {