send xrun messages to debug

This commit is contained in:
Brandon Taylor 2021-05-18 18:48:01 -04:00
parent 3233af2277
commit d47abb9072
2 changed files with 16 additions and 25 deletions

View file

@ -77,7 +77,6 @@ mutable struct PortAudioStream{T}
samplerate::Float64
latency::Float64
stream::PaStream
warn_xruns::Bool
recover_xruns::Bool
sink # untyped because of circular type definition
source # untyped because of circular type definition
@ -91,7 +90,7 @@ mutable struct PortAudioStream{T}
# TODO: figure out whether we can get deterministic latency...
function PortAudioStream{T}(indev::PortAudioDevice, outdev::PortAudioDevice,
inchans, outchans, sr,
latency, warn_xruns, recover_xruns) where {T}
latency, recover_xruns) where {T}
inchans = inchans == -1 ? indev.maxinchans : inchans
outchans = outchans == -1 ? outdev.maxoutchans : outchans
inparams = (inchans == 0) ?
@ -100,7 +99,7 @@ mutable struct PortAudioStream{T}
outparams = (outchans == 0) ?
Ptr{Pa_StreamParameters}(0) :
Ref(Pa_StreamParameters(outdev.idx, outchans, type_to_fmt[T], latency, C_NULL))
this = new(sr, latency, C_NULL, warn_xruns, recover_xruns)
this = new(sr, latency, C_NULL, recover_xruns)
# finalizer(close, this)
this.sink = PortAudioSink{T}(outdev.name, this, outchans)
this.source = PortAudioSource{T}(indev.name, this, inchans)
@ -144,7 +143,7 @@ Audio devices can either be `PortAudioDevice` instances as returned
by `PortAudio.devices()`, or strings with the device name as reported by the
operating system. If a single `duplexdevice` is given it will be used for both
input and output. If no devices are given the system default devices will be
used.
used. Over- and under-run messages will be sent to the debug log.
Options:
@ -152,9 +151,6 @@ Options:
* `samplerate`: Sample rate (defaults to device sample rate)
* `latency`: Requested latency. Stream could underrun when too low, consider
using provided device defaults
* `warn_xruns`: Display a warning if there is a stream overrun or underrun, which
often happens when Julia is compiling, or with a particularly large
GC run. This can be quite verbose so is false by default.
* `recover_xruns`: Attempt to recover from overruns and underruns by emptying and
filling the input and output buffers, respectively. Should result in
fewer xruns but could make each xrun more audible. True by default.
@ -162,7 +158,7 @@ Options:
"""
function PortAudioStream(indev::PortAudioDevice, outdev::PortAudioDevice,
inchans=2, outchans=2; eltype=Float32, samplerate=-1,
latency=defaultlatency(indev, outdev), warn_xruns=false, recover_xruns=true)
latency=defaultlatency(indev, outdev), recover_xruns=true)
if samplerate == -1
sampleratein = indev.defaultsamplerate
samplerateout = outdev.defaultsamplerate
@ -178,7 +174,7 @@ function PortAudioStream(indev::PortAudioDevice, outdev::PortAudioDevice,
end
end
PortAudioStream{eltype}(indev, outdev, inchans, outchans, samplerate,
latency, warn_xruns, recover_xruns)
latency, recover_xruns)
end
# handle device names given as streams
@ -315,8 +311,7 @@ function SampledSignals.unsafe_write(sink::PortAudioSink, buf::Array, frameoffse
view(buf, (1:n) .+ nwritten .+ frameoffset, :))
# TODO: if the stream is closed we just want to return a
# shorter-than-requested frame count instead of throwing an error
err = Pa_WriteStream(sink.stream.stream, sink.chunkbuf, n,
sink.stream.warn_xruns)
err = Pa_WriteStream(sink.stream.stream, sink.chunkbuf, n)
if err (PA_OUTPUT_UNDERFLOWED, PA_INPUT_OVERFLOWED) && sink.stream.recover_xruns
recover_xrun(sink.stream)
end
@ -332,8 +327,7 @@ function SampledSignals.unsafe_read!(source::PortAudioSource, buf::Array, frameo
n = min(framecount-nread, CHUNKFRAMES)
# TODO: if the stream is closed we just want to return a
# shorter-than-requested frame count instead of throwing an error
err = Pa_ReadStream(source.stream.stream, source.chunkbuf, n,
source.stream.warn_xruns)
err = Pa_ReadStream(source.stream.stream, source.chunkbuf, n)
if err (PA_OUTPUT_UNDERFLOWED, PA_INPUT_OVERFLOWED) && source.stream.recover_xruns
recover_xrun(source.stream)
end

View file

@ -242,8 +242,7 @@ function Pa_GetStreamWriteAvailable(stream::PaStream)
avail
end
function Pa_ReadStream(stream::PaStream, buf::Array, frames::Integer,
show_warnings=true)
function Pa_ReadStream(stream::PaStream, buf::Array, frames::Integer)
# without disable_sigint I get a segfault with the error:
# "error thrown and no exception handler available."
# if the user tries to ctrl-C. Note I've still had some crash problems with
@ -254,18 +253,17 @@ function Pa_ReadStream(stream::PaStream, buf::Array, frames::Integer,
(PaStream, Ptr{Cvoid}, Culong),
stream, buf, frames)
end
handle_status(err, show_warnings)
handle_status(err)
err
end
function Pa_WriteStream(stream::PaStream, buf::Array, frames::Integer,
show_warnings=true)
function Pa_WriteStream(stream::PaStream, buf::Array, frames::Integer)
err = disable_sigint() do
@tcall @locked ccall((:Pa_WriteStream, libportaudio), PaError,
(PaStream, Ptr{Cvoid}, Culong),
stream, buf, frames)
end
handle_status(err, show_warnings)
handle_status(err)
err
end
@ -279,13 +277,12 @@ end
# end
#
# General utility function to handle the status from the Pa_* functions
function handle_status(err::PaError, show_warnings::Bool=true)
function handle_status(err::PaError)
if err == PA_OUTPUT_UNDERFLOWED || err == PA_INPUT_OVERFLOWED
if show_warnings
msg = @locked ccall((:Pa_GetErrorText, libportaudio),
Ptr{Cchar}, (PaError,), err)
@warn("libportaudio: " * unsafe_string(msg))
end
@debug unsafe_string(
@locked ccall((:Pa_GetErrorText, libportaudio),
Ptr{Cchar}, (PaError,), err)
)
elseif err != PA_NO_ERROR
msg = @locked ccall((:Pa_GetErrorText, libportaudio),
Ptr{Cchar}, (PaError,), err)