parent
3cd4551d81
commit
44d4ca38f8
2 changed files with 35 additions and 35 deletions
|
@ -1,7 +1,7 @@
|
||||||
name = "PortAudio"
|
name = "PortAudio"
|
||||||
uuid = "80ea8bcb-4634-5cb3-8ee8-a132660d1d2d"
|
uuid = "80ea8bcb-4634-5cb3-8ee8-a132660d1d2d"
|
||||||
repo = "https://github.com/JuliaAudio/PortAudio.jl.git"
|
repo = "https://github.com/JuliaAudio/PortAudio.jl.git"
|
||||||
version = "1.1.2"
|
version = "1.2.0"
|
||||||
|
|
||||||
[deps]
|
[deps]
|
||||||
alsa_plugins_jll = "5ac2f6bb-493e-5871-9171-112d4c21a6e7"
|
alsa_plugins_jll = "5ac2f6bb-493e-5871-9171-112d4c21a6e7"
|
||||||
|
|
|
@ -424,9 +424,9 @@ function read_buffer!(buffer, use_frames = buffer.frames_per_buffer)
|
||||||
read_or_write(Pa_ReadStream, buffer, use_frames)
|
read_or_write(Pa_ReadStream, buffer, use_frames)
|
||||||
end
|
end
|
||||||
|
|
||||||
# the messanger will send tasks to the scribe
|
# the messenger will send tasks to the scribe
|
||||||
# the scribe will read/write from the buffer
|
# the scribe will read/write from the buffer
|
||||||
struct Messanger{Sample, Scribe, Input, Output}
|
struct Messenger{Sample, Scribe, Input, Output}
|
||||||
device_name::String
|
device_name::String
|
||||||
buffer::Buffer{Sample}
|
buffer::Buffer{Sample}
|
||||||
scribe::Scribe
|
scribe::Scribe
|
||||||
|
@ -434,18 +434,18 @@ struct Messanger{Sample, Scribe, Input, Output}
|
||||||
output_channel::Channel{Output}
|
output_channel::Channel{Output}
|
||||||
end
|
end
|
||||||
|
|
||||||
eltype(::Type{Messanger{Sample}}) where {Sample} = Sample
|
eltype(::Type{Messenger{Sample}}) where {Sample} = Sample
|
||||||
name(messanger::Messanger) = messanger.device_name
|
name(messenger::Messenger) = messenger.device_name
|
||||||
nchannels(messanger::Messanger) = nchannels(messanger.buffer)
|
nchannels(messenger::Messenger) = nchannels(messenger.buffer)
|
||||||
|
|
||||||
# the scribe will be running on a separate thread in the background
|
# the scribe will be running on a separate thread in the background
|
||||||
# alternating transposing and
|
# alternating transposing and
|
||||||
# waiting to pass inputs and outputs back and forth to PortAudio
|
# waiting to pass inputs and outputs back and forth to PortAudio
|
||||||
function send(messanger)
|
function send(messenger)
|
||||||
buffer = messanger.buffer
|
buffer = messenger.buffer
|
||||||
scribe = messanger.scribe
|
scribe = messenger.scribe
|
||||||
input_channel = messanger.input_channel
|
input_channel = messenger.input_channel
|
||||||
output_channel = messanger.output_channel
|
output_channel = messenger.output_channel
|
||||||
while true
|
while true
|
||||||
input = try
|
input = try
|
||||||
take!(input_channel)
|
take!(input_channel)
|
||||||
|
@ -464,8 +464,8 @@ end
|
||||||
# convenience method
|
# convenience method
|
||||||
has_channels(something) = nchannels(something) > 0
|
has_channels(something) = nchannels(something) > 0
|
||||||
|
|
||||||
# create the messanger, and start the scribe on a separate task
|
# create the messenger, and start the scribe on a separate task
|
||||||
function messanger_task(
|
function messenger_task(
|
||||||
device_name,
|
device_name,
|
||||||
buffer::Buffer{Sample},
|
buffer::Buffer{Sample},
|
||||||
scribe::Scribe
|
scribe::Scribe
|
||||||
|
@ -475,7 +475,7 @@ function messanger_task(
|
||||||
input_channel = Channel{Input}(0)
|
input_channel = Channel{Input}(0)
|
||||||
output_channel = Channel{Output}(0)
|
output_channel = Channel{Output}(0)
|
||||||
# unbuffered channels so putting and taking will block till everyone's ready
|
# unbuffered channels so putting and taking will block till everyone's ready
|
||||||
messanger = Messanger{Sample, Scribe, Input, Output}(
|
messenger = Messenger{Sample, Scribe, Input, Output}(
|
||||||
device_name,
|
device_name,
|
||||||
buffer,
|
buffer,
|
||||||
scribe,
|
scribe,
|
||||||
|
@ -487,12 +487,12 @@ function messanger_task(
|
||||||
# start the scribe thread when its created
|
# start the scribe thread when its created
|
||||||
# if there's channels at all
|
# if there's channels at all
|
||||||
# we can't make the task a field of the buffer, because the task uses the buffer
|
# we can't make the task a field of the buffer, because the task uses the buffer
|
||||||
task = Task(let messanger = messanger
|
task = Task(let messenger = messenger
|
||||||
() -> begin
|
() -> begin
|
||||||
# xruns will return an error code and send a duplicate warning to stderr
|
# xruns will return an error code and send a duplicate warning to stderr
|
||||||
# since we handle the error codes, we don't need the duplicate warnings
|
# since we handle the error codes, we don't need the duplicate warnings
|
||||||
# so we send them to a debug log
|
# so we send them to a debug log
|
||||||
log = @capture_err send(messanger)
|
log = @capture_err send(messenger)
|
||||||
if !isempty(log)
|
if !isempty(log)
|
||||||
@debug log
|
@debug log
|
||||||
end
|
end
|
||||||
|
@ -508,13 +508,13 @@ function messanger_task(
|
||||||
close(input_channel)
|
close(input_channel)
|
||||||
close(output_channel)
|
close(output_channel)
|
||||||
end
|
end
|
||||||
messanger, task
|
messenger, task
|
||||||
end
|
end
|
||||||
|
|
||||||
function fetch_messanger(messanger, task)
|
function fetch_messanger(messenger, task)
|
||||||
if has_channels(messanger)
|
if has_channels(messenger)
|
||||||
# this will shut down the channels, which will shut down the thread
|
# this will shut down the channels, which will shut down the thread
|
||||||
close(messanger.input_channel)
|
close(messenger.input_channel)
|
||||||
# wait for tasks to finish to make sure any errors get caught
|
# wait for tasks to finish to make sure any errors get caught
|
||||||
wait(task)
|
wait(task)
|
||||||
# output channel will close because it is bound to the task
|
# output channel will close because it is bound to the task
|
||||||
|
@ -527,13 +527,13 @@ end
|
||||||
# PortAudioStream
|
# PortAudioStream
|
||||||
#
|
#
|
||||||
|
|
||||||
struct PortAudioStream{SinkMessanger, SourceMessanger}
|
struct PortAudioStream{SinkMessenger, SourceMessenger}
|
||||||
sample_rate::Float64
|
sample_rate::Float64
|
||||||
# pointer to the c object
|
# pointer to the c object
|
||||||
pointer_to::Ptr{PaStream}
|
pointer_to::Ptr{PaStream}
|
||||||
sink_messanger::SinkMessanger
|
sink_messanger::SinkMessenger
|
||||||
sink_task::Task
|
sink_task::Task
|
||||||
source_messanger::SourceMessanger
|
source_messanger::SourceMessenger
|
||||||
source_task::Task
|
source_task::Task
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -803,7 +803,7 @@ function PortAudioStream(
|
||||||
samplerate,
|
samplerate,
|
||||||
pointer_to,
|
pointer_to,
|
||||||
# we need to keep track of the tasks so we can wait for them to finish and catch errors
|
# we need to keep track of the tasks so we can wait for them to finish and catch errors
|
||||||
messanger_task(
|
messenger_task(
|
||||||
output_device.name,
|
output_device.name,
|
||||||
Buffer(
|
Buffer(
|
||||||
stream_lock,
|
stream_lock,
|
||||||
|
@ -815,7 +815,7 @@ function PortAudioStream(
|
||||||
),
|
),
|
||||||
writer,
|
writer,
|
||||||
)...,
|
)...,
|
||||||
messanger_task(
|
messenger_task(
|
||||||
input_device.name,
|
input_device.name,
|
||||||
Buffer(
|
Buffer(
|
||||||
stream_lock,
|
stream_lock,
|
||||||
|
@ -906,7 +906,7 @@ isopen(stream::PortAudioStream) = isopen(stream.pointer_to)
|
||||||
|
|
||||||
samplerate(stream::PortAudioStream) = stream.sample_rate
|
samplerate(stream::PortAudioStream) = stream.sample_rate
|
||||||
function eltype(
|
function eltype(
|
||||||
::Type{<:PortAudioStream{<:Messanger{Sample}, <:Messanger{Sample}}},
|
::Type{<:PortAudioStream{<:Messenger{Sample}, <:Messenger{Sample}}},
|
||||||
) where {Sample}
|
) where {Sample}
|
||||||
Sample
|
Sample
|
||||||
end
|
end
|
||||||
|
@ -956,8 +956,8 @@ end
|
||||||
# only defined for SampledSignals scribes
|
# only defined for SampledSignals scribes
|
||||||
function getproperty(
|
function getproperty(
|
||||||
stream::PortAudioStream{
|
stream::PortAudioStream{
|
||||||
<:Messanger{<:Any, <:SampledSignalsWriter},
|
<:Messenger{<:Any, <:SampledSignalsWriter},
|
||||||
<:Messanger{<:Any, <:SampledSignalsReader},
|
<:Messenger{<:Any, <:SampledSignalsReader},
|
||||||
},
|
},
|
||||||
property::Symbol,
|
property::Symbol,
|
||||||
)
|
)
|
||||||
|
@ -982,8 +982,8 @@ end
|
||||||
function eltype(
|
function eltype(
|
||||||
::Type{
|
::Type{
|
||||||
<:Union{
|
<:Union{
|
||||||
<:PortAudioSink{<:Messanger{Sample}, <:Messanger{Sample}},
|
<:PortAudioSink{<:Messenger{Sample}, <:Messenger{Sample}},
|
||||||
<:PortAudioSource{<:Messanger{Sample}, <:Messanger{Sample}},
|
<:PortAudioSource{<:Messenger{Sample}, <:Messenger{Sample}},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
) where {Sample}
|
) where {Sample}
|
||||||
|
@ -1014,14 +1014,14 @@ end
|
||||||
# both reading and writing will outsource to the readers or writers
|
# both reading and writing will outsource to the readers or writers
|
||||||
# so we just need to pass inputs in and take outputs out
|
# so we just need to pass inputs in and take outputs out
|
||||||
# SampledSignals can take care of this feeding for us
|
# SampledSignals can take care of this feeding for us
|
||||||
function exchange(messanger, arguments...)
|
function exchange(messenger, arguments...)
|
||||||
put!(messanger.input_channel, arguments)
|
put!(messenger.input_channel, arguments)
|
||||||
take!(messanger.output_channel)
|
take!(messenger.output_channel)
|
||||||
end
|
end
|
||||||
|
|
||||||
# these will only work with sampledsignals scribes
|
# these will only work with sampledsignals scribes
|
||||||
function unsafe_write(
|
function unsafe_write(
|
||||||
sink::PortAudioSink{<:Messanger{<:Any, <:SampledSignalsWriter}},
|
sink::PortAudioSink{<:Messenger{<:Any, <:SampledSignalsWriter}},
|
||||||
julia_buffer::Array,
|
julia_buffer::Array,
|
||||||
already,
|
already,
|
||||||
frame_count,
|
frame_count,
|
||||||
|
@ -1030,7 +1030,7 @@ function unsafe_write(
|
||||||
end
|
end
|
||||||
|
|
||||||
function unsafe_read!(
|
function unsafe_read!(
|
||||||
source::PortAudioSource{<:Any, <:Messanger{<:Any, <:SampledSignalsReader}},
|
source::PortAudioSource{<:Any, <:Messenger{<:Any, <:SampledSignalsReader}},
|
||||||
julia_buffer::Array,
|
julia_buffer::Array,
|
||||||
already,
|
already,
|
||||||
frame_count,
|
frame_count,
|
||||||
|
|
Loading…
Reference in a new issue