Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in / Register
Toggle navigation
Menu
Open sidebar
savoirfairelinux
jami-daemon
Commits
11b168e7
Commit
11b168e7
authored
Aug 31, 2011
by
Rafaël Carré
Browse files
* #6229 : remove malloc/free from pulse audio loop
use pa_stream_begin_write() when writing to speakers
parent
fa186c4d
Changes
4
Hide whitespace changes
Inline
Side-by-side
daemon/src/audio/dcblocker.cpp
View file @
11b168e7
...
...
@@ -51,20 +51,7 @@ int DcBlocker::getData (SFLDataFormat *outputData UNUSED)
void
DcBlocker
::
process
(
SFLDataFormat
*
data
,
int
nbBytes
)
{
// y(n) = x(n) - x(n-1) + R y(n-1) , R = 0.9999
int
nbSamples
=
nbBytes
/
sizeof
(
SFLDataFormat
);
for
(
int
i
=
0
;
i
<
nbSamples
;
i
++
)
{
_x
=
data
[
i
];
_y
=
(
SFLDataFormat
)
(
(
float
)
_x
-
(
float
)
_xm1
+
0.995
*
(
float
)
_ym1
);
_xm1
=
_x
;
_ym1
=
_y
;
data
[
i
]
=
_y
;
}
abort
();
// use the 3 args prototype with input == output
}
int
DcBlocker
::
process
(
SFLDataFormat
*
inputData
,
SFLDataFormat
*
outputData
,
int
nbBytes
)
...
...
daemon/src/audio/dcblocker.h
View file @
11b168e7
...
...
@@ -57,16 +57,7 @@ class DcBlocker : public Algorithm
*/
virtual
int
getData
(
SFLDataFormat
*
outputData
);
/**
* Perform dc blocking given the input data
*/
virtual
void
process
(
SFLDataFormat
*
data
,
int
nbBytes
);
/**
* Perform echo cancellation using internal buffers
* \param inputData containing mixed echo and voice data
* \param outputData containing
*/
virtual
void
process
(
SFLDataFormat
*
inputData
,
int
nbBytes
);
virtual
int
process
(
SFLDataFormat
*
inputData
,
SFLDataFormat
*
outputData
,
int
nbBytes
);
private:
...
...
daemon/src/audio/pulseaudio/pulselayer.cpp
View file @
11b168e7
...
...
@@ -197,6 +197,8 @@ PulseLayer::PulseLayer ()
,
playback_
(
0
)
,
record_
(
0
)
,
ringtone_
(
0
)
,
mic_buffer_
(
NULL
)
,
mic_buf_size_
(
0
)
{
setenv
(
"PULSE_PROP_media.role"
,
"phone"
,
1
);
...
...
@@ -241,6 +243,8 @@ PulseLayer::~PulseLayer (void)
if
(
mainloop_
)
pa_threaded_mainloop_free
(
mainloop_
);
delete
[]
mic_buffer_
;
}
void
PulseLayer
::
context_state_callback
(
pa_context
*
c
,
void
*
user_data
)
...
...
@@ -314,19 +318,19 @@ void PulseLayer::createStreams (pa_context* c)
_debug
(
"PulseAudio: Devices: playback %s , record %s , ringtone %s"
,
playbackDevice
.
c_str
(),
recordDevice
.
c_str
(),
ringtoneDevice
.
c_str
());
playback_
=
new
AudioStream
(
c
,
mainloop_
,
PLAYBACK_STREAM_NAME
,
PLAYBACK_STREAM
,
audioSampleRate_
,
playback_
=
new
AudioStream
(
c
,
mainloop_
,
"SFLphone playback"
,
PLAYBACK_STREAM
,
audioSampleRate_
,
inSinkList
(
playbackDevice
)
?
&
playbackDevice
:
NULL
);
pa_stream_set_write_callback
(
playback_
->
pulseStream
(),
playback_callback
,
this
);
pa_stream_set_moved_callback
(
playback_
->
pulseStream
(),
stream_moved_callback
,
this
);
record_
=
new
AudioStream
(
c
,
mainloop_
,
CAPTURE_STREAM_NAME
,
CAPTURE_STREAM
,
audioSampleRate_
,
record_
=
new
AudioStream
(
c
,
mainloop_
,
"SFLphone capture"
,
CAPTURE_STREAM
,
audioSampleRate_
,
inSourceList
(
recordDevice
)
?
&
recordDevice
:
NULL
);
pa_stream_set_read_callback
(
record_
->
pulseStream
()
,
capture_callback
,
this
);
pa_stream_set_moved_callback
(
record_
->
pulseStream
(),
stream_moved_callback
,
this
);
ringtone_
=
new
AudioStream
(
c
,
mainloop_
,
RINGTONE_STREAM_NAME
,
RINGTONE_STREAM
,
audioSampleRate_
,
ringtone_
=
new
AudioStream
(
c
,
mainloop_
,
"SFLphone ringtone"
,
RINGTONE_STREAM
,
audioSampleRate_
,
inSourceList
(
ringtoneDevice
)
?
&
ringtoneDevice
:
NULL
);
pa_stream_set_write_callback
(
ringtone_
->
pulseStream
(),
ringtone_callback
,
this
);
...
...
@@ -410,24 +414,26 @@ void PulseLayer::writeToSpeaker (void)
if
(
!
playback_
or
!
playback_
->
isReady
())
return
;
pa_stream
*
s
=
playback_
->
pulseStream
();
// available bytes to be written in pulseaudio internal buffer
int
writ
e
able
SizeBytes
=
pa_stream_writable_size
(
playback_
->
pulseStream
()
);
if
(
writ
e
able
SizeBytes
<
0
)
_error
(
"Pulse: playback error : %s"
,
pa_strerror
(
writ
e
able
SizeBytes
));
if
(
writ
e
able
SizeBytes
<=
0
)
int
writable
=
pa_stream_writable_size
(
s
);
if
(
writable
<
0
)
_error
(
"Pulse: playback error : %s"
,
pa_strerror
(
writable
));
if
(
writable
<=
0
)
return
;
size_t
bytes
=
writable
;
void
*
data
;
notifyincomingCall
();
int
urgentBytes
=
urgentRingBuffer_
.
AvailForGet
();
if
(
urgentBytes
>
writeableSizeBytes
)
urgentBytes
=
writeableSizeBytes
;
size_t
urgentBytes
=
urgentRingBuffer_
.
AvailForGet
();
if
(
urgentBytes
>
bytes
)
urgentBytes
=
bytes
;
if
(
urgentBytes
)
{
SFLDataFormat
*
out
=
(
SFLDataFormat
*
)
pa_xmalloc
(
urgentBytes
);
urgentRingBuffer_
.
Get
(
out
,
urgentBytes
);
pa_stream_write
(
playback_
->
pulseStream
(),
out
,
urgentBytes
,
NULL
,
0
,
PA_SEEK_RELATIVE
);
pa_xfree
(
out
);
pa_stream_begin_write
(
s
,
&
data
,
&
urgentBytes
);
urgentRingBuffer_
.
Get
(
data
,
urgentBytes
);
pa_stream_write
(
s
,
data
,
urgentBytes
,
NULL
,
0
,
PA_SEEK_RELATIVE
);
// Consume the regular one as well (same amount of bytes)
getMainBuffer
()
->
discard
(
urgentBytes
);
return
;
...
...
@@ -436,22 +442,20 @@ void PulseLayer::writeToSpeaker (void)
AudioLoop
*
toneToPlay
=
Manager
::
instance
().
getTelephoneTone
();
if
(
toneToPlay
)
{
if
(
playback_
->
isReady
())
{
SFLDataFormat
*
out
=
(
SFLDataFormat
*
)
pa_xmalloc
(
writeableSizeBytes
);
toneToPlay
->
getNext
(
out
,
writeableSizeBytes
/
sizeof
(
SFLDataFormat
),
100
);
pa_stream_write
(
playback_
->
pulseStream
(),
out
,
writeableSizeBytes
,
NULL
,
0
,
PA_SEEK_RELATIVE
);
pa_xfree
(
out
);
pa_stream_begin_write
(
s
,
&
data
,
&
bytes
);
toneToPlay
->
getNext
((
SFLDataFormat
*
)
data
,
bytes
/
sizeof
(
SFLDataFormat
),
100
);
pa_stream_write
(
s
,
data
,
bytes
,
NULL
,
0
,
PA_SEEK_RELATIVE
);
}
return
;
}
flushUrgent
();
// flush remaining samples in _urgentRingBuffer
in
t
availSamples
=
getMainBuffer
()
->
availForGet
()
/
sizeof
(
SFLDataFormat
);
size_
t
availSamples
=
getMainBuffer
()
->
availForGet
()
/
sizeof
(
SFLDataFormat
);
if
(
availSamples
==
0
)
{
// play silence
SFLDataFormat
*
zeros
=
(
SFLDataFormat
*
)
pa_xmalloc0
(
writeableSizeBytes
);
pa_stream_write
(
playback_
->
pulseStream
(),
zeros
,
writeableSizeBytes
,
NULL
,
0
,
PA_SEEK_RELATIVE
);
pa_xfree
(
zeros
);
pa_stream_begin_write
(
s
,
&
data
,
&
bytes
);
memset
(
data
,
0
,
bytes
);
pa_stream_write
(
s
,
data
,
bytes
,
NULL
,
0
,
PA_SEEK_RELATIVE
);
return
;
}
...
...
@@ -459,10 +463,10 @@ void PulseLayer::writeToSpeaker (void)
bool
resample
=
audioSampleRate_
!=
mainBufferSampleRate
;
// how much samples we can write in the output
in
t
outSamples
=
writeableSizeB
ytes
/
sizeof
(
SFLDataFormat
);
size_
t
outSamples
=
b
ytes
/
sizeof
(
SFLDataFormat
);
// how much samples we want to read from the buffer
in
t
inSamples
=
outSamples
;
size_
t
inSamples
=
outSamples
;
double
resampleFactor
=
1.
;
if
(
resample
)
{
...
...
@@ -472,21 +476,19 @@ void PulseLayer::writeToSpeaker (void)
if
(
inSamples
>
availSamples
)
inSamples
=
availSamples
;
in
t
outBytes
=
(
double
)
inSamples
*
resampleFactor
*
sizeof
(
SFLDataFormat
);
size_
t
outBytes
=
(
double
)
inSamples
*
resampleFactor
*
sizeof
(
SFLDataFormat
);
in
t
inBytes
=
inSamples
*
sizeof
(
SFLDataFormat
);
SFLDataFormat
*
out
=
(
SFLDataFormat
*
)
pa_xmalloc
(
inBytes
);
getMainBuffer
()
->
getData
(
out
,
inBytes
);
size_
t
inBytes
=
inSamples
*
sizeof
(
SFLDataFormat
);
pa_stream_begin_write
(
s
,
&
data
,
&
inBytes
);
getMainBuffer
()
->
getData
(
data
,
inBytes
);
if
(
resample
)
{
SFLDataFormat
*
rsmpl_out
=
(
SFLDataFormat
*
)
pa_xmalloc
(
outBytes
);
converter_
->
resample
(
out
,
rsmpl_out
,
mainBufferSampleRate
,
audioSampleRate_
,
inSamples
);
pa_stream_write
(
playback_
->
pulseStream
()
,
rsmpl_out
,
outBytes
,
NULL
,
0
,
PA_SEEK_RELATIVE
);
converter_
->
resample
((
SFLDataFormat
*
)
data
,
rsmpl_out
,
mainBufferSampleRate
,
audioSampleRate_
,
inSamples
);
pa_stream_write
(
s
,
rsmpl_out
,
outBytes
,
NULL
,
0
,
PA_SEEK_RELATIVE
);
pa_xfree
(
rsmpl_out
);
}
else
pa_stream_write
(
playback_
->
pulseStream
(),
out
,
inBytes
,
NULL
,
0
,
PA_SEEK_RELATIVE
);
pa_xfree
(
out
);
pa_stream_write
(
s
,
data
,
inBytes
,
NULL
,
0
,
PA_SEEK_RELATIVE
);
}
void
PulseLayer
::
readFromMic
(
void
)
...
...
@@ -495,33 +497,34 @@ void PulseLayer::readFromMic (void)
return
;
const
char
*
data
=
NULL
;
size_t
r
;
SFLDataFormat
*
out
;
size_t
bytes
;
size_t
samples
;
unsigned
int
mainBufferSampleRate
=
getMainBuffer
()
->
getInternalSamplingRate
();
bool
resample
=
audioSampleRate_
!=
mainBufferSampleRate
;
if
(
pa_stream_peek
(
record_
->
pulseStream
()
,
(
const
void
**
)
&
data
,
&
r
)
<
0
or
!
data
)
{
if
(
pa_stream_peek
(
record_
->
pulseStream
()
,
(
const
void
**
)
&
data
,
&
bytes
)
<
0
or
!
data
)
{
_error
(
"Audio: Error capture stream peek failed: %s"
,
pa_strerror
(
pa_context_errno
(
context_
)));
goto
end
;
}
if
(
resample
)
{
double
resampleFactor
=
(
double
)
audioSampleRate_
/
mainBufferSampleRate
;
r
=
(
double
)
r
*
resampleFactor
;
bytes
=
(
double
)
bytes
*
resampleFactor
;
}
out
=
(
SFLDataFormat
*
)
pa_xmalloc
(
r
);
if
(
resample
)
{
converter_
->
resample
(
(
SFLDataFormat
*
)
data
,
out
,
mainBufferSampleRate
,
audioSampleRate_
,
r
/
sizeof
(
SFLDataFormat
));
dcblocker_
.
process
(
out
,
r
);
}
else
{
dcblocker_
.
process
(
(
SFLDataFormat
*
)
data
,
out
,
r
);
samples
=
bytes
/
sizeof
(
SFLDataFormat
);
if
(
bytes
>
mic_buf_size_
)
{
mic_buf_size_
=
bytes
;
delete
[]
mic_buffer_
;
mic_buffer_
=
new
SFLDataFormat
[
samples
];
}
getMainBuffer
()
->
putData
(
out
,
r
);
pa_xfree
(
out
);
if
(
resample
)
converter_
->
resample
((
SFLDataFormat
*
)
data
,
mic_buffer_
,
mainBufferSampleRate
,
audioSampleRate_
,
samples
);
dcblocker_
.
process
(
resample
?
mic_buffer_
:
(
SFLDataFormat
*
)
data
,
mic_buffer_
,
bytes
);
getMainBuffer
()
->
putData
(
mic_buffer_
,
bytes
);
end:
if
(
pa_stream_drop
(
record_
->
pulseStream
())
<
0
)
...
...
@@ -532,22 +535,25 @@ end:
void
PulseLayer
::
ringtoneToSpeaker
(
void
)
{
if
(
!
ringtone_
or
!
ringtone_
->
isReady
())
return
;
return
;
pa_stream
*
s
=
ringtone_
->
pulseStream
();
int
writable
Size
=
pa_stream_writable_size
(
ringtone_
->
pulseStream
()
);
if
(
writable
Size
<
0
)
_error
(
"Pulse: ringtone error : %s"
,
pa_strerror
(
writable
Size
));
if
(
writable
Size
<=
0
)
int
writable
=
pa_stream_writable_size
(
s
);
if
(
writable
<
0
)
_error
(
"Pulse: ringtone error : %s"
,
pa_strerror
(
writable
));
if
(
writable
<=
0
)
return
;
SFLDataFormat
*
out
=
(
SFLDataFormat
*
)
pa_xmalloc
(
writableSize
);
size_t
bytes
=
writable
;
void
*
data
;
pa_stream_begin_write
(
s
,
&
data
,
&
bytes
);
AudioLoop
*
fileToPlay
=
Manager
::
instance
().
getTelephoneFile
();
if
(
fileToPlay
)
fileToPlay
->
getNext
(
out
,
writableSize
/
sizeof
(
SFLDataFormat
),
100
);
fileToPlay
->
getNext
((
SFLDataFormat
*
)
data
,
bytes
/
sizeof
(
SFLDataFormat
),
100
);
else
memset
(
out
,
0
,
writableSize
);
memset
(
data
,
0
,
bytes
);
pa_stream_write
(
ringtone_
->
pulseStream
(),
out
,
writableSize
,
NULL
,
0
,
PA_SEEK_RELATIVE
);
pa_xfree
(
out
);
pa_stream_write
(
s
,
data
,
bytes
,
NULL
,
0
,
PA_SEEK_RELATIVE
);
}
daemon/src/audio/pulseaudio/pulselayer.h
View file @
11b168e7
...
...
@@ -39,17 +39,7 @@
#include
<list>
#include
<string>
#define PLAYBACK_STREAM_NAME "SFLphone playback"
#define CAPTURE_STREAM_NAME "SFLphone capture"
#define RINGTONE_STREAM_NAME "SFLphone ringtone"
class
RingBuffer
;
class
ManagerImpl
;
class
AudioStream
;
class
DcBlocker
;
class
SamplerateConverter
;
typedef
std
::
list
<
std
::
string
>
DeviceList
;
class
PulseLayer
:
public
AudioLayer
{
...
...
@@ -57,11 +47,11 @@ class PulseLayer : public AudioLayer
PulseLayer
();
~
PulseLayer
(
void
);
DeviceList
*
getSinkList
(
void
)
{
std
::
list
<
std
::
string
>
*
getSinkList
(
void
)
{
return
&
sinkList_
;
}
DeviceList
*
getSourceList
(
void
)
{
std
::
list
<
std
::
string
>
*
getSourceList
(
void
)
{
return
&
sourceList_
;
}
...
...
@@ -124,8 +114,14 @@ class PulseLayer : public AudioLayer
*/
AudioStream
*
ringtone_
;
DeviceList
sinkList_
;
DeviceList
sourceList_
;
std
::
list
<
std
::
string
>
sinkList_
;
std
::
list
<
std
::
string
>
sourceList_
;
/*
* Buffers used to avoid doing malloc/free in the audio thread
*/
SFLDataFormat
*
mic_buffer_
;
size_t
mic_buf_size_
;
public:
friend
class
AudioLayerTest
;
...
...
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment