PortAudio.jl/test/runtests.jl

258 lines
9.3 KiB
Julia
Raw Normal View History

2014-06-30 21:24:29 -04:00
#!/usr/bin/env julia
2021-06-22 23:49:16 -04:00
using Base.Sys: iswindows
2021-06-01 13:44:23 -04:00
using PortAudio:
combine_default_sample_rates,
2021-06-17 14:28:55 -04:00
devices,
2021-06-26 12:27:31 -04:00
get_default_input_index,
get_default_output_index,
2021-06-17 13:49:33 -04:00
get_device_info,
2021-06-30 12:11:42 -04:00
get_input_type,
get_output_type,
handle_status,
2021-06-17 14:28:55 -04:00
initialize,
2021-06-22 20:31:23 -04:00
PortAudioException,
2021-06-17 14:28:55 -04:00
PortAudio,
PortAudioDevice,
2021-06-17 14:28:55 -04:00
PortAudioStream,
2021-06-17 16:52:54 -04:00
safe_load,
seek_alsa_conf,
2021-06-17 14:28:55 -04:00
terminate
2021-06-17 16:52:54 -04:00
using PortAudio.LibPortAudio:
Pa_AbortStream,
2021-06-21 09:31:53 -04:00
PaError,
2021-06-17 16:52:54 -04:00
PaErrorCode,
paFloat32,
Pa_GetDefaultHostApi,
2021-06-22 20:31:23 -04:00
Pa_GetDeviceInfo,
2021-06-17 16:52:54 -04:00
Pa_GetHostApiCount,
Pa_GetLastHostErrorInfo,
Pa_GetSampleSize,
Pa_GetStreamCpuLoad,
Pa_GetStreamInfo,
2021-06-22 23:11:12 -04:00
Pa_GetStreamReadAvailable,
2021-06-17 16:52:54 -04:00
Pa_GetStreamTime,
2021-06-22 23:11:12 -04:00
Pa_GetStreamWriteAvailable,
2021-06-22 23:36:56 -04:00
Pa_GetVersionInfo,
2021-06-17 16:52:54 -04:00
Pa_HostApiDeviceIndexToDeviceIndex,
2021-06-21 09:31:53 -04:00
paHostApiNotFound,
2021-06-17 16:52:54 -04:00
Pa_HostApiTypeIdToHostApiIndex,
PaHostErrorInfo,
paInDevelopment,
paInvalidDevice,
Pa_IsFormatSupported,
Pa_IsStreamActive,
paNoError,
paNoFlag,
paNotInitialized,
Pa_OpenDefaultStream,
2021-06-22 16:01:55 -04:00
paOutputUnderflowed,
2021-06-17 16:52:54 -04:00
Pa_SetStreamFinishedCallback,
Pa_Sleep,
2021-06-22 23:11:12 -04:00
Pa_StopStream,
2021-06-17 16:52:54 -04:00
PaStream,
PaStreamInfo,
2021-06-22 23:36:56 -04:00
PaStreamParameters,
PaVersionInfo
2021-06-23 00:23:47 -04:00
using SampledSignals: nchannels, s, SampleBuf, samplerate, SinSource
2021-06-17 14:28:55 -04:00
using Test: @test, @test_logs, @test_nowarn, @testset, @test_throws
2021-06-22 20:31:23 -04:00
@testset "Tests without sound" begin
@testset "Reports version" begin
io = IOBuffer()
PortAudio.versioninfo(io)
result = split(String(take!((io))), "\n")
# make sure this is the same version I tested with
@test startswith(result[1], "PortAudio V19")
end
@testset "Can list devices without crashing" begin
2021-06-26 12:27:31 -04:00
display(devices())
println()
end
2021-05-13 13:59:25 -04:00
2021-06-22 20:31:23 -04:00
@testset "libortaudio without sound" begin
2021-06-21 09:31:53 -04:00
@test handle_status(Pa_GetHostApiCount()) >= 0
@test handle_status(Pa_GetDefaultHostApi()) >= 0
2021-06-22 23:49:16 -04:00
# version info not available on windows?
if !Sys.iswindows()
2021-06-23 00:23:47 -04:00
@test safe_load(Pa_GetVersionInfo(), ErrorException("no info")) isa
PaVersionInfo
2021-06-22 23:49:16 -04:00
end
2021-06-22 16:01:55 -04:00
@test safe_load(Pa_GetLastHostErrorInfo(), ErrorException("no info")) isa
PaHostErrorInfo
2021-06-21 09:31:53 -04:00
@test PaErrorCode(Pa_IsFormatSupported(C_NULL, C_NULL, 0.0)) == paInvalidDevice
2021-06-17 16:52:54 -04:00
@test PaErrorCode(
2021-06-21 09:31:53 -04:00
Pa_OpenDefaultStream(Ref(C_NULL), 0, 0, paFloat32, 0.0, 0, C_NULL, C_NULL),
2021-06-17 16:52:54 -04:00
) == paInvalidDevice
2021-06-22 20:31:23 -04:00
end
@testset "Errors without sound" begin
2021-06-23 00:23:47 -04:00
@test sprint(showerror, PortAudioException(paNotInitialized)) ==
"PortAudioException: PortAudio not initialized"
2021-06-30 12:11:42 -04:00
@test_throws KeyError("foobarbaz") get_device_info("foobarbaz")
2021-06-26 12:27:31 -04:00
@test_throws KeyError(-1) get_device_info(-1)
2021-06-30 12:11:42 -04:00
@test_throws ArgumentError("Could not find alsa.conf in ()") seek_alsa_conf(())
2021-06-22 20:31:23 -04:00
@test_logs (:warn, "libportaudio: Output underflowed") handle_status(
PaError(paOutputUnderflowed),
)
@test_throws PortAudioException(paNotInitialized) handle_status(
2021-06-23 00:23:47 -04:00
PaError(paNotInitialized),
2021-06-22 20:31:23 -04:00
)
2021-06-17 16:52:54 -04:00
Pa_Sleep(1)
@test Pa_GetSampleSize(paFloat32) == 4
2021-06-30 12:11:42 -04:00
@test_throws MethodError(get_input_type, (Any,)) get_input_type(Any)
@test_throws MethodError(get_output_type, (Any,)) get_output_type(Any)
2021-06-17 16:52:54 -04:00
end
2021-06-22 20:31:23 -04:00
end
if !isempty(devices())
# make sure we can terminate, then reinitialize
terminate()
initialize()
2021-06-17 16:52:54 -04:00
2021-06-23 00:23:47 -04:00
# these default values are specific to local machines
2021-06-26 12:27:31 -04:00
input_index = get_default_input_index()
2021-06-30 12:11:42 -04:00
default_input_device = get_device_info(input_index)
default_input_device_name = default_input_device.name
2021-06-26 12:27:31 -04:00
output_index = get_default_output_index()
2021-06-30 12:11:42 -04:00
default_output_device = get_device_info(output_index)
default_output_device_name = default_output_device.name
2021-06-22 20:31:23 -04:00
@testset "Tests with sound" begin
@testset "Interactive tests" begin
println("Recording...")
stream = PortAudioStream(2, 0)
2021-06-22 20:31:23 -04:00
buffer = read(stream, 5s)
2021-06-30 13:14:41 -04:00
sleep(1)
2021-06-22 20:31:23 -04:00
@test size(buffer) ==
2021-06-01 13:44:23 -04:00
(round(Int, 5 * samplerate(stream)), nchannels(stream.source))
2021-06-22 20:31:23 -04:00
close(stream)
println("Playing back recording...")
PortAudioStream(0, 2) do stream
2021-06-22 20:31:23 -04:00
write(stream, buffer)
end
2021-06-30 13:14:41 -04:00
sleep(1)
println("Testing pass-through")
stream = PortAudioStream(2, 2)
sink = stream.sink
source = stream.source
2021-06-22 20:31:23 -04:00
@test sprint(show, stream) == """
PortAudioStream{Float32}
Samplerate: 44100.0Hz
2021-06-30 12:11:42 -04:00
2 channel sink: $(repr(default_output_device_name))
2 channel source: $(repr(default_input_device_name))"""
@test sprint(show, sink) == "2 channel sink: $(repr(default_input_device_name))"
@test sprint(show, source) ==
"2 channel source: $(repr(default_output_device_name))"
write(stream, stream, 5s)
2021-06-30 13:14:41 -04:00
sleep(1)
2021-06-22 23:11:12 -04:00
@test PaErrorCode(handle_status(Pa_StopStream(stream.pointer_to))) == paNoError
@test isopen(stream)
close(stream)
@test !isopen(stream)
@test !isopen(sink)
@test !isopen(source)
println("done")
end
@testset "Samplerate-converting writing" begin
2021-06-22 20:31:23 -04:00
PortAudioStream(0, 2) do stream
write(
stream,
SinSource(eltype(stream), samplerate(stream) * 0.8, [220, 330]),
3s,
)
2021-06-30 13:14:41 -04:00
sleep(1)
2021-06-22 20:31:23 -04:00
write(
stream,
SinSource(eltype(stream), samplerate(stream) * 1.2, [220, 330]),
3s,
)
2021-06-30 13:14:41 -04:00
sleep(1)
2021-06-22 20:31:23 -04:00
end
end
@testset "Open Device by name" begin
2021-06-30 12:11:42 -04:00
PortAudioStream(default_input_device_name, default_output_device_name) do stream
2021-06-22 20:31:23 -04:00
end
end
# no way to check that the right data is actually getting read or written here,
# but at least it's not crashing.
@testset "Queued Writing" begin
2021-06-22 20:31:23 -04:00
PortAudioStream(0, 2) do stream
buffer = SampleBuf(
rand(eltype(stream), 48000, nchannels(stream.sink)) * 0.1,
samplerate(stream),
)
frame_count_1 = @async write(stream, buffer)
frame_count_2 = @async write(stream, buffer)
@test fetch(frame_count_1) == 48000
2021-06-30 13:14:41 -04:00
sleep(1)
2021-06-22 20:31:23 -04:00
@test fetch(frame_count_2) == 48000
2021-06-30 13:14:41 -04:00
sleep(1)
2021-06-22 20:31:23 -04:00
end
end
@testset "Queued Reading" begin
2021-06-22 20:31:23 -04:00
PortAudioStream(2, 0) do stream
buffer = SampleBuf(
rand(eltype(stream), 48000, nchannels(stream.source)) * 0.1,
samplerate(stream),
)
frame_count_1 = @async read!(stream, buffer)
frame_count_2 = @async read!(stream, buffer)
@test fetch(frame_count_1) == 48000
2021-06-30 13:14:41 -04:00
sleep(1)
2021-06-22 20:31:23 -04:00
@test fetch(frame_count_2) == 48000
2021-06-30 13:14:41 -04:00
sleep(1)
2021-06-22 20:31:23 -04:00
end
end
2021-06-22 23:11:12 -04:00
@testset "Constructors" begin
PortAudioStream(2, max; call_back = C_NULL) do stream
@test isopen(stream)
end
2021-06-30 12:11:42 -04:00
PortAudioStream(default_input_device_name) do stream
2021-06-22 23:11:12 -04:00
@test isopen(stream)
end
end
2021-06-22 20:31:23 -04:00
@testset "Errors with sound" begin
2021-06-30 12:11:42 -04:00
big = typemax(Int)
@test_throws DomainError(
2021-06-23 00:23:47 -04:00
typemax(Int),
2021-06-30 12:11:42 -04:00
"$big exceeds max input channels for $default_input_device_name",
) PortAudioStream(big, 0)
2021-06-23 00:23:47 -04:00
@test_throws ArgumentError("Input or output must have at least 1 channel") PortAudioStream(
0,
0,
)
2021-06-30 12:11:42 -04:00
@test_throws ArgumentError("""
Default sample rate 0 for input $default_input_device_name disagrees with
default sample rate 1 for output $default_output_device_name.
Please specify a sample rate.
""") combine_default_sample_rates(
default_input_device,
0,
default_output_device,
1,
)
2021-06-22 20:31:23 -04:00
end
@testset "libportaudio with sound" begin
2021-06-22 20:40:26 -04:00
@test PaErrorCode(Pa_HostApiTypeIdToHostApiIndex(paInDevelopment)) ==
2021-06-23 00:23:47 -04:00
paHostApiNotFound
2021-06-22 20:48:01 -04:00
@test Pa_HostApiDeviceIndexToDeviceIndex(paInDevelopment, 0) == 0
2021-06-22 20:31:23 -04:00
stream = PortAudioStream(2, 2)
pointer_to = stream.pointer_to
2021-06-22 23:11:12 -04:00
@test handle_status(Pa_GetStreamReadAvailable(pointer_to)) >= 0
@test handle_status(Pa_GetStreamWriteAvailable(pointer_to)) >= 0
2021-06-22 20:31:23 -04:00
@test Bool(handle_status(Pa_IsStreamActive(pointer_to)))
@test safe_load(Pa_GetStreamInfo(pointer_to), ErrorException("no info")) isa
PaStreamInfo
@test Pa_GetStreamTime(pointer_to) >= 0
@test Pa_GetStreamCpuLoad(pointer_to) >= 0
@test PaErrorCode(handle_status(Pa_AbortStream(pointer_to))) == paNoError
@test PaErrorCode(
handle_status(Pa_SetStreamFinishedCallback(pointer_to, C_NULL)),
) == paNoError
end
end
end
2021-06-22 23:11:12 -04:00
2021-06-23 00:23:47 -04:00
# sample rates disagree