JuliaAudio / PortAudio.jl

PortAudio wrapper for the Julia programming language, compatible with the JuliaAudio family of packages
Other
114 stars 20 forks source link

{under,over}flow errors #124

Open bjarthur opened 5 months ago

bjarthur commented 5 months ago

i get an error when trying to simultaneously read and write as described here:

julia> using PortAudio

julia> N = 48000*5
240000

julia> output = randn(N) * 0.1;

julia> input = PortAudioStream(1,1) do str
           @async write(str, output)
           read(str, N)
       end
┌ Warning: libportaudio: Output underflowed
└ @ PortAudio ~/.julia/packages/PortAudio/HNBv4/src/PortAudio.jl:99
┌ Warning: libportaudio: Input overflowed
└ @ PortAudio ~/.julia/packages/PortAudio/HNBv4/src/PortAudio.jl:99
^CERROR: TaskFailedException
Stacktrace Stacktrace: [1] wait @ ./task.jl:352 [inlined] [2] fetch_messenger(messenger::PortAudio.Messenger{Float32, PortAudio.SampledSignalsReader, Tuple{…}, Int64}, task::Task) @ PortAudio ~/.julia/packages/PortAudio/HNBv4/src/PortAudio.jl:525 [3] close(stream::PortAudioStream{PortAudio.Messenger{…}, PortAudio.Messenger{…}}) @ PortAudio ~/.julia/packages/PortAudio/HNBv4/src/PortAudio.jl:896 [4] PortAudioStream(::var"#1#3", ::Int64, ::Vararg{Int64}; keywords::@Kwargs{}) @ PortAudio ~/.julia/packages/PortAudio/HNBv4/src/PortAudio.jl:888 [5] PortAudioStream(::Function, ::Int64, ::Vararg{Int64}) @ PortAudio ~/.julia/packages/PortAudio/HNBv4/src/PortAudio.jl:883 [6] top-level scope @ REPL[8]:1 nested task error: InterruptException: Stacktrace: [1] (::Base.var"#_unlock#648")(rl::ReentrantLock) @ Base ./lock.jl:177 [2] unlock @ ./lock.jl:177 [inlined] [3] lock(f::PortAudio.var"#7#8"{typeof(PortAudio.LibPortAudio.Pa_ReadStream), Ptr{…}, Matrix{…}, Int64}, l::ReentrantLock) @ Base ./lock.jl:231 [4] #read_or_write#6 @ ~/.julia/packages/PortAudio/HNBv4/src/PortAudio.jl:245 [inlined] [5] read_or_write @ ~/.julia/packages/PortAudio/HNBv4/src/PortAudio.jl:233 [inlined] [6] #read_buffer!#13 @ ~/.julia/packages/PortAudio/HNBv4/src/PortAudio.jl:434 [inlined] [7] read_buffer! @ ~/.julia/packages/PortAudio/HNBv4/src/PortAudio.jl:433 [inlined] [8] full_read! @ ~/.julia/packages/PortAudio/HNBv4/src/PortAudio.jl:365 [inlined] [9] #9 @ ~/.julia/packages/PortAudio/HNBv4/src/PortAudio.jl:329 [inlined] [10] foreach(f::PortAudio.var"#9#10"{…}, itr::StepRange{…}) @ Base ./abstractarray.jl:3097 [11] split_up(buffer::PortAudio.Buffer{…}, julia_buffer::Matrix{…}, already::Int64, frame_count::Int64, whole_function::Function, partial_function::typeof(PortAudio.partial_read!)) @ PortAudio ~/.julia/packages/PortAudio/HNBv4/src/PortAudio.jl:329 [12] SampledSignalsReader @ ~/.julia/packages/PortAudio/HNBv4/src/PortAudio.jl:375 [inlined] [13] send(messenger::PortAudio.Messenger{Float32, PortAudio.SampledSignalsReader, Tuple{Matrix{…}, Int64, Int64}, Int64}) @ PortAudio ~/.julia/packages/PortAudio/HNBv4/src/PortAudio.jl:470 [14] (::PortAudio.var"#14#15"{PortAudio.Messenger{Float32, PortAudio.SampledSignalsReader, Tuple{…}, Int64}})() @ PortAudio ~/.julia/packages/PortAudio/HNBv4/src/PortAudio.jl:505 caused by: TaskFailedException Stacktrace: [1] try_yieldto(undo::typeof(Base.ensure_rescheduled)) @ Base ./task.jl:931 [2] wait() @ Base ./task.jl:995 [3] wait(c::Base.GenericCondition{ReentrantLock}; first::Bool) @ Base ./condition.jl:130 [4] wait @ ./condition.jl:125 [inlined] [5] take_unbuffered(c::Channel{Int64}) @ Base ./channels.jl:494 [6] take! @ ./channels.jl:471 [inlined] [7] exchange @ ~/.julia/packages/PortAudio/HNBv4/src/PortAudio.jl:1031 [inlined] [8] unsafe_read! @ ~/.julia/packages/PortAudio/HNBv4/src/PortAudio.jl:1053 [inlined] [9] read!(source::PortAudio.PortAudioSource{…}, buf::SampledSignals.SampleBuf{…}, n::Int64) @ SampledSignals ~/.julia/packages/SampledSignals/KYg5Q/src/SampleStream.jl:184 [10] read! @ ~/.julia/packages/SampledSignals/KYg5Q/src/SampleStream.jl:222 [inlined] [11] read @ ~/.julia/packages/SampledSignals/KYg5Q/src/SampleStream.jl:63 [inlined] [12] read(stream::PortAudioStream{PortAudio.Messenger{…}, PortAudio.Messenger{…}}, arguments::Int64) @ PortAudio ~/.julia/packages/PortAudio/HNBv4/src/PortAudio.jl:928 [13] (::var"#1#3")(str::PortAudioStream{PortAudio.Messenger{…}, PortAudio.Messenger{…}}) @ Main ./REPL[8]:3 [14] PortAudioStream(::var"#1#3", ::Int64, ::Vararg{Int64}; keywords::@Kwargs{}) @ PortAudio ~/.julia/packages/PortAudio/HNBv4/src/PortAudio.jl:886 [15] PortAudioStream(::Function, ::Int64, ::Vararg{Int64}) @ PortAudio ~/.julia/packages/PortAudio/HNBv4/src/PortAudio.jl:883 [16] top-level scope @ REPL[8]:1 nested task error: InterruptException: Stacktrace: [1] (::Base.var"#_unlock#648")(rl::ReentrantLock) @ Base ./lock.jl:177 [2] unlock @ ./lock.jl:177 [inlined] [3] lock(f::PortAudio.var"#7#8"{typeof(PortAudio.LibPortAudio.Pa_ReadStream), Ptr{…}, Matrix{…}, Int64}, l::ReentrantLock) @ Base ./lock.jl:231 [4] #read_or_write#6 @ ~/.julia/packages/PortAudio/HNBv4/src/PortAudio.jl:245 [inlined] [5] read_or_write @ ~/.julia/packages/PortAudio/HNBv4/src/PortAudio.jl:233 [inlined] [6] #read_buffer!#13 @ ~/.julia/packages/PortAudio/HNBv4/src/PortAudio.jl:434 [inlined] [7] read_buffer! @ ~/.julia/packages/PortAudio/HNBv4/src/PortAudio.jl:433 [inlined] [8] full_read! @ ~/.julia/packages/PortAudio/HNBv4/src/PortAudio.jl:365 [inlined] [9] #9 @ ~/.julia/packages/PortAudio/HNBv4/src/PortAudio.jl:329 [inlined] [10] foreach(f::PortAudio.var"#9#10"{…}, itr::StepRange{…}) @ Base ./abstractarray.jl:3097 [11] split_up(buffer::PortAudio.Buffer{…}, julia_buffer::Matrix{…}, already::Int64, frame_count::Int64, whole_function::Function, partial_function::typeof(PortAudio.partial_read!)) @ PortAudio ~/.julia/packages/PortAudio/HNBv4/src/PortAudio.jl:329 [12] SampledSignalsReader @ ~/.julia/packages/PortAudio/HNBv4/src/PortAudio.jl:375 [inlined] [13] send(messenger::PortAudio.Messenger{Float32, PortAudio.SampledSignalsReader, Tuple{Matrix{…}, Int64, Int64}, Int64}) @ PortAudio ~/.julia/packages/PortAudio/HNBv4/src/PortAudio.jl:470 [14] (::PortAudio.var"#14#15"{PortAudio.Messenger{Float32, PortAudio.SampledSignalsReader, Tuple{…}, Int64}})() @ PortAudio ~/.julia/packages/PortAudio/HNBv4/src/PortAudio.jl:505 Some type information was truncated. Use `show(err)` to see complete types.

same story when just trying to read as described in the docs:

julia> using PortAudio

julia> stream = PortAudioStream(1,0)
PortAudioStream{Float32}
  Samplerate: 48000Hz
  1 channel source: "MacBook Pro Microphone"

julia> buf = read(stream, 10)
┌ Warning: libportaudio: Input overflowed
└ @ PortAudio ~/.julia/packages/PortAudio/HNBv4/src/PortAudio.jl:99
10-frame, 1-channel SampleBuf{Float32, 2}
0.00020833333333333335s sampled at 48000.0Hz
▂▃▃▃▃▃▃▃▃▃

ditto for just playing, though it actually did play something:

julia> using PortAudio, SampledSignals

julia> S = 8192 # sampling rate (samples / second)
8192

julia> x = cos.(2pi*(1:2S)*440/S) # A440 tone for 2 seconds
16384-element Vector{Float64}:

julia> PortAudioStream(0, 2; samplerate=S) do stream
           write(stream, x)
       end
┌ Warning: libportaudio: Output underflowed
└ @ PortAudio ~/.julia/packages/PortAudio/HNBv4/src/PortAudio.jl:99
16384
julia> versioninfo()
Julia Version 1.10.2
Commit bd47eca2c8a (2024-03-01 10:14 UTC)
Build Info:
  Official https://julialang.org/ release
Platform Info:
  OS: macOS (arm64-apple-darwin22.4.0)
  CPU: 12 × Apple M2 Max
  WORD_SIZE: 64
  LIBM: libopenlibm
  LLVM: libLLVM-15.0.7 (ORCJIT, apple-m1)
Threads: 1 default, 0 interactive, 1 GC (on 8 virtual cores)
Environment:
  JULIA_PROJECT = @.
  JULIA_EDITOR = vi

(jl_0map0x) pkg> st
Status `/private/var/folders/s5/8d629n5d7nsf37f60_91wzr40000gq/T/jl_0map0x/Project.toml`
  [80ea8bcb] PortAudio v1.3.0
mashu commented 1 month ago

I was getting the very same warning, when I played audio like this

stream = PortAudioStream(0, 1)
write(stream, SampleBuf(audio, 44100))
close(stream)

and when audio was Vector{Float64} after changing that input to Vector{Float32} the underflow warning is gone. Hopefully this helps to narrow down and fix the issue?