This commit is contained in:
Brandon Taylor 2021-06-22 23:11:12 -04:00
parent 8c9b7da5a4
commit 36f85795cd
2 changed files with 36 additions and 12 deletions

View file

@ -348,9 +348,16 @@ function get_default_latency(input_channels, input_device, output_channels, outp
)
end
function combine_default_sample_rates(input_sample_rate, output_sample_rate)
if input_sample_rate != output_sample_rate
throw(ArgumentError("Default input and output sample rates disagree"))
end
input_sample_rate
end
# we can only have one sample rate
# so if the default sample rates differ, throw an error
function combine_default_sample_rates(
function get_default_sample_rates(
input_channels,
input_device,
output_channels,
@ -359,16 +366,12 @@ function combine_default_sample_rates(
input_channels_filled, output_channels_filled =
fill_both_channels(input_channels, input_device, output_channels, output_device)
input_output_or_both(
combine_default_sample_rates,
input_channels_filled,
output_channels_filled,
input_device.default_sample_rate,
output_device.default_sample_rate,
) do input_sample_rate, output_sample_rate
if input_sample_rate != output_sample_rate
throw(ArgumentError("Default input and output sample rates disagree"))
end
input_sample_rate
end
)
end
# we will spawn a thread to either read or write to port audio
@ -520,7 +523,7 @@ function PortAudioStream(
input_channels = 2,
output_channels = 2;
Sample = Float32,
sample_rate = combine_default_sample_rates(
sample_rate = get_default_sample_rates(
input_channels,
input_device,
output_channels,
@ -608,11 +611,10 @@ function PortAudioStream(
)
end
# if one device is given, use it for input and output, but set input_channels=0 so we
# end up with an output-only stream
# if one device is given, use it for input and output
function PortAudioStream(
device::Union{PortAudioDevice, AbstractString},
input_channels = 0,
input_channels = 2,
output_channels = 2;
keywords...,
)
@ -646,7 +648,9 @@ function close(stream::PortAudioStream)
close(stream.sink_messanger)
close(stream.source_messanger)
pointer_to = stream.pointer_to
handle_status(Pa_StopStream(pointer_to))
if !Bool(handle_status(Pa_IsStreamStopped(pointer_to)))
handle_status(Pa_StopStream(pointer_to))
end
handle_status(Pa_CloseStream(pointer_to))
end

View file

@ -27,7 +27,9 @@ using PortAudio.LibPortAudio:
Pa_GetSampleSize,
Pa_GetStreamCpuLoad,
Pa_GetStreamInfo,
Pa_GetStreamReadAvailable,
Pa_GetStreamTime,
Pa_GetStreamWriteAvailable,
Pa_HostApiDeviceIndexToDeviceIndex,
paHostApiNotFound,
Pa_HostApiTypeIdToHostApiIndex,
@ -43,6 +45,7 @@ using PortAudio.LibPortAudio:
paOutputUnderflowed,
Pa_SetStreamFinishedCallback,
Pa_Sleep,
Pa_StopStream,
PaStream,
PaStreamInfo,
PaStreamParameters
@ -74,7 +77,10 @@ using Test: @test, @test_logs, @test_nowarn, @testset, @test_throws
end
@testset "Errors without sound" begin
@test_throws ArgumentError("Default input and output sample rates disagree") combine_default_sample_rates(0, 1)
wrong = "foobarbaz"
@test sprint(showerror, PortAudioException(paNotInitialized)) ==
"PortAudioException: PortAudio not initialized"
@test_throws KeyError(wrong) get_device_info(wrong)
@test_throws BoundsError(Pa_GetDeviceInfo, -1) get_device_info(-1)
@test_throws ArgumentError("Could not find ALSA config") seek_alsa_conf([])
@ -125,6 +131,8 @@ if !isempty(devices())
@test sprint(show, sink) == "2 channel sink: $(repr(default_input_device))"
@test sprint(show, source) == "2 channel source: $(repr(default_output_device))"
write(stream, stream, 5s)
@test PaErrorCode(handle_status(Pa_StopStream(stream.pointer_to))) == paNoError
@test isopen(stream)
close(stream)
@test !isopen(stream)
@test !isopen(sink)
@ -175,6 +183,14 @@ if !isempty(devices())
@test fetch(frame_count_2) == 48000
end
end
@testset "Constructors" begin
PortAudioStream(2, max; call_back = C_NULL) do stream
@test isopen(stream)
end
PortAudioStream(default_input_device) do stream
@test isopen(stream)
end
end
@testset "Errors with sound" begin
@test_throws DomainError(typemax(Int), "max channels exceeded") PortAudioStream(typemax(Int), 0)
@test_throws ArgumentError("Input or output must have at least 1 channel") PortAudioStream(0, 0)
@ -185,6 +201,8 @@ if !isempty(devices())
@test Pa_HostApiDeviceIndexToDeviceIndex(paInDevelopment, 0) == 0
stream = PortAudioStream(2, 2)
pointer_to = stream.pointer_to
@test handle_status(Pa_GetStreamReadAvailable(pointer_to)) >= 0
@test handle_status(Pa_GetStreamWriteAvailable(pointer_to)) >= 0
@test Bool(handle_status(Pa_IsStreamActive(pointer_to)))
@test safe_load(Pa_GetStreamInfo(pointer_to), ErrorException("no info")) isa
PaStreamInfo
@ -197,3 +215,5 @@ if !isempty(devices())
end
end
end
# sample rates disagree