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:
parent
a541f8faf0
commit
697eea96aa
6
EchoCanceller.cpp
Normal file → Executable file
6
EchoCanceller.cpp
Normal file → Executable 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
1
EchoCanceller.h
Normal file → Executable file
@ -48,6 +48,7 @@ private:
|
||||
void* ns; // NsxHandle
|
||||
void* agc;
|
||||
int32_t agcMicLevel;
|
||||
//int32_t outstandingFarendFrames=0;
|
||||
#endif
|
||||
};
|
||||
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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){
|
||||
|
@ -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) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user