diff --git a/.appveyor.yml b/.appveyor.yml new file mode 100644 index 0000000..440f448 --- /dev/null +++ b/.appveyor.yml @@ -0,0 +1,32 @@ +# Documentation: https://github.com/JuliaCI/Appveyor.jl +environment: + matrix: + - julia_version: 1.0 + - julia_version: 1 + - julia_version: nightly +platform: + - x86 + - x64 +matrix: + allow_failures: + - julia_version: nightly +branches: + only: + - master + - /release-.*/ +notifications: + - provider: Email + on_build_success: false + on_build_failure: false + on_build_status_changed: true +install: + - ps: iex ((new-object net.webclient).DownloadString("https://raw.githubusercontent.com/JuliaCI/Appveyor.jl/version-1/bin/install.ps1")) +build_script: + - echo "%JL_BUILD_SCRIPT%" + - C:\julia\bin\julia -e "%JL_BUILD_SCRIPT%" +test_script: + - echo "%JL_TEST_SCRIPT%" + - C:\julia\bin\julia -e "%JL_TEST_SCRIPT%" +on_success: + - echo "%JL_CODECOV_SCRIPT%" + - C:\julia\bin\julia -e "%JL_CODECOV_SCRIPT%" diff --git a/.gitignore b/.gitignore index 331ca43..afe9806 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,5 @@ *.jl.mem coverage *~ +Manifest.toml +test/Manifest.toml diff --git a/.travis.yml b/.travis.yml index 75b54f6..4d0b5f8 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,26 +4,14 @@ os: - linux - osx julia: - - 0.6 - - 0.7 - 1.0 + - 1 - nightly matrix: allow_failures: - julia: nightly fast_finish: true -branches: - only: - master notifications: - email: false -script: - - if [[ -a .git/shallow ]]; then git fetch --unshallow; fi - - julia --color=yes ci_setup.jl - - julia --color=yes --code-coverage test/runtests.jl + email: true after_success: - - julia -e 'VERSION >= v"0.7.0-" && using Pkg; - VERSION < v"0.7.0-" && cd(Pkg.dir("SampledSignals")); - Pkg.add("Coverage"); - using Coverage; - Codecov.submit(process_folder())' + - julia -e 'using Pkg; Pkg.add("Coverage"); using Coverage; Codecov.submit(process_folder())' diff --git a/Project.toml b/Project.toml new file mode 100644 index 0000000..0b81088 --- /dev/null +++ b/Project.toml @@ -0,0 +1,43 @@ +name = "SampledSignals" +uuid = "bd7594eb-a658-542f-9e75-4c4d8908c167" + +[deps] +Compat = "34da2185-b29b-5c13-b0c7-acf172513d20" +DSP = "717857b8-e6f2-59f4-9121-6e50c889abd2" +FFTW = "7a1cc6ca-52ef-59f5-83cd-3a7055c09341" +FixedPointNumbers = "53c48c17-4a7d-5ca2-90c5-79b7896eea93" +IntervalSets = "8197267c-284f-5f27-9208-e0e47529a953" +LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" +TreeViews = "a2a6695c-b41b-5b7d-aed9-dbfdeacea5d7" +Unitful = "1986cc42-f94f-5a68-af5c-568840ba703d" + +[compat] +Compat = "2" +DSP = "0.6.1" +FFTW = "1.1.0" +FixedPointNumbers = "0.6.1" +IntervalSets = "0.3.2" +Unitful = "0.17.0" +julia = "1" + +[extras] +DSP = "717857b8-e6f2-59f4-9121-6e50c889abd2" +FileIO = "5789e2e9-d7fb-5bc7-8068-2c6fae9b9549" +FixedPointNumbers = "53c48c17-4a7d-5ca2-90c5-79b7896eea93" +# LibSndFile = "b13ce0c6-77b0-50c6-a2db-140568b8d1a5" +Unitful = "1986cc42-f94f-5a68-af5c-568840ba703d" +Compat = "34da2185-b29b-5c13-b0c7-acf172513d20" +SampledSignals = "bd7594eb-a658-542f-9e75-4c4d8908c167" +TreeViews = "a2a6695c-b41b-5b7d-aed9-dbfdeacea5d7" +IntervalSets = "8197267c-284f-5f27-9208-e0e47529a953" + +[targets] +test = ["DSP", + "FileIO", + "FixedPointNumbers", + # "LibSndFile", + "Unitful", + "Compat", + "SampledSignals", + "TreeViews", + "IntervalSets"] diff --git a/REQUIRE b/REQUIRE deleted file mode 100644 index 9731afd..0000000 --- a/REQUIRE +++ /dev/null @@ -1,7 +0,0 @@ -julia 0.6 -Unitful 0.8.0 -FixedPointNumbers 0.4.6 -DSP 0.4.0 -FFTW 0.0.4 -IntervalSets 0.2.0 -Compat 0.59.0 diff --git a/appveyor.yml b/appveyor.yml deleted file mode 100644 index eec2e82..0000000 --- a/appveyor.yml +++ /dev/null @@ -1,43 +0,0 @@ -environment: - matrix: -# disable win32 testing until LibSndFile is fixed on 32-bit -# - JULIA_URL: "https://julialang-s3.julialang.org/bin/winnt/x86/0.6/julia-0.6-latest-win32.exe" - - JULIA_URL: "https://julialang-s3.julialang.org/bin/winnt/x64/0.6/julia-0.6-latest-win64.exe" -# - JULIA_URL: "https://julialang-s3.julialang.org/bin/winnt/x86/0.7/julia-0.7-latest-win32.exe" - - JULIA_URL: "https://julialang-s3.julialang.org/bin/winnt/x64/0.7/julia-0.7-latest-win64.exe" -# - JULIA_URL: "https://julialang-s3.julialang.org/bin/winnt/x86/1.0/julia-1.0-latest-win32.exe" - - JULIA_URL: "https://julialang-s3.julialang.org/bin/winnt/x64/1.0/julia-1.0-latest-win64.exe" - -notifications: - - provider: Email - on_build_success: false - on_build_failure: false - on_build_status_changed: false - -matrix: - allow_failures: - # currently failing on 1.0 until https://github.com/JuliaLang/METADATA.jl/pull/16370 is merged - - JULIA_URL: "https://julialang-s3.julialang.org/bin/winnt/x64/1.0/julia-1.0-latest-win64.exe" - -# only build master and PRs -branches: - only: - - master - -install: - - ps: "[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.SecurityProtocolType]::Tls12" -# Download most recent Julia Windows binary - - ps: (new-object net.webclient).DownloadFile( - $env:JULIA_URL, - "C:\projects\julia-binary.exe") -# Run installer silently, output to C:\projects\julia - - C:\projects\julia-binary.exe /S /D=C:\projects\julia - -build_script: -# Need to convert from shallow to complete for Pkg.clone to work - - IF EXIST .git\shallow (git fetch --unshallow) - - C:\projects\julia\bin\julia --color=yes ci_setup.jl - -test_script: - # - C:\projects\julia\bin\julia --check-bounds=yes -e "Pkg.test(\"SampledSignals\")" - - C:\projects\julia\bin\julia --color=yes --code-coverage --check-bounds=yes test/runtests.jl diff --git a/src/SampleBuf.jl b/src/SampleBuf.jl index 6e499c7..85f22a3 100644 --- a/src/SampleBuf.jl +++ b/src/SampleBuf.jl @@ -278,11 +278,11 @@ function toindex end toindex(buf::SampleBuf, t::Number) = t toindex(buf::SampleBuf, t::FrameQuant) = inframes(Int, t) + 1 toindex(buf::SampleBuf, t::Unitful.Time) = inframes(Int, t, samplerate(buf)) + 1 -toindex(buf::SampleBuf, t::Quantity) = throw(Unitful.DimensionError(t, s)) +toindex(buf::SampleBuf, t::Unitful.AbstractQuantity) = throw(Unitful.DimensionError(t, s)) toindex(buf::SpectrumBuf, f::Number) = f toindex(buf::SpectrumBuf, f::FrameQuant) = inframes(Int, f) + 1 toindex(buf::SpectrumBuf, f::Unitful.Frequency) = inframes(Int, f, samplerate(buf)) + 1 -toindex(buf::SpectrumBuf, f::Quantity) = throw(Unitful.DimensionError(f, Hz)) +toindex(buf::SpectrumBuf, f::Unitful.AbstractQuantity) = throw(Unitful.DimensionError(f, Hz)) # indexing by vectors of Quantities not yet supported toindex(buf::AbstractSampleBuf, I::ClosedInterval{Int}) = diff --git a/src/SampleStream.jl b/src/SampleStream.jl index 6fed407..db6a838 100644 --- a/src/SampleStream.jl +++ b/src/SampleStream.jl @@ -71,7 +71,7 @@ const DEFAULT_BLOCKSIZE=4096 function Base.write(sink::SampleSink, source::SampleSource, duration::Quantity; blocksize=-1) sr = samplerate(sink) - frames = trunc(Int, inseconds(duration) * sr) + frames = trunc(Int, inseconds(duration, sr) * sr) n = write(sink, source, frames; blocksize=blocksize) # if we completed the operation return back the original duration so the diff --git a/src/SampledSignals.jl b/src/SampledSignals.jl index 6d14de2..a8a88a6 100644 --- a/src/SampledSignals.jl +++ b/src/SampledSignals.jl @@ -29,6 +29,8 @@ using Compat using Compat: AbstractRange, undef, range using Compat.Random: randstring using Compat.Base64: base64encode +using TreeViews: TreeViews + if VERSION >= v"0.7.0-DEV" using LinearAlgebra: mul! import FFTW @@ -53,12 +55,6 @@ include("SignalGen/SinSource.jl") include("WAVDisplay.jl") include("deprecated.jl") -function __init__() - if isdefined(Main, :IJulia) && Main.IJulia.inited - embed_javascript() - end -end - """ metadata(x, key::Symbol) metadata(x, key::Symbol, idx) diff --git a/src/WAVDisplay.jl b/src/WAVDisplay.jl index b38487c..8bae681 100644 --- a/src/WAVDisplay.jl +++ b/src/WAVDisplay.jl @@ -2,117 +2,25 @@ # WAV.jl package. Rather than full WAV support here we just want to support # enough for simple HTML display of SampleBufs -# notebook init code heavily inspired by PlotlyJS - thanks @sglyon! -function embed_javascript() - js_path = joinpath(dirname(dirname(@__FILE__)), "deps", "wavesurfer.min.js") - js_text = open(js_path) do io - read(io, String) - end - # the javascript file contains the code to add itself to the require module - # cache under the name 'wavesurfer' - display("text/html", """ - - """) -end - # need to specify that T <: Number to avoid a method ambiguity with AbstractArray{Method} on 0.4 function show(io::IO, ::MIME"text/html", buf::SampleBuf{T, N}) where {T <: Number, N} tempio = IOBuffer() wavwrite(tempio, buf) data = base64encode(take!(tempio)) - # we want the divID to start with a letter - divid = string("a", randstring(10)) - # include an error message that will get cleared if javascript loads correctly - # they won't be able to re-run this cell without importing SampledSignals, - # which will run the initialization code above. I can't think of a way to - # get in the state where the javascript isn't initialized but the module is - # loaded, but if it comes up we'll want to add an instruction to run - # `SampledSignals.embed_javascript()`. - println(io, """ -
-

SampleBuf display requires javascript

-

To enable for the whole notebook select "Trust Notebook" from the - "File" menu. You can also trust this cell by re-running it. You may - also need to re-run `using SampledSignals` if the module is not yet - loaded in the Julia kernel, or `SampledSignals.embed_javascript()` - if the Julia module is loaded but the javascript isn't initialized.

-
""") - # only show playback controls for real-valued SampleBufs. We also initialize - # them hidden and they get displayed if javascript is enabled. if isa(buf, SampleBuf) && eltype(buf) <: Real println(io, """ - - - - """) + """) + else + show(io, MIME"text/plain"(), buf) end - println(io, """ - - """) +TreeViews.hastreeview(::SampleBuf) = true +TreeViews.numberofnodes(::SampleBuf) = 0 +function TreeViews.treelabel(io::IO, buf::SampleBuf, ::MIME"text/html") + show(io, MIME"text/html"(), buf) end # Required WAV Chunk; The format chunk describes how the waveform data is stored diff --git a/src/units.jl b/src/units.jl index 0e7e954..d265c9b 100644 --- a/src/units.jl +++ b/src/units.jl @@ -29,8 +29,8 @@ inframes(time::Unitful.Time, rate) = inseconds(time)*inHz(rate) inframes(::Type{T}, freq::Unitful.Frequency, rate) where T <: Integer = round(T, inHz(freq)*inseconds(rate)) inframes(freq::Unitful.Frequency, rate) = inHz(freq)*inseconds(rate) -inframes(::Type, frame::Quantity) = error("Unknown sample rate") -inframes(frame::Quantity) = error("Unknown sample rate") +inframes(::Type, frame::Unitful.AbstractQuantity) = error("Unknown sample rate") +inframes(frame::Unitful.AbstractQuantity) = error("Unknown sample rate") inframes(::Type{T}, frame::Real) where T = T(frame) inframes(frame::Real) = frame diff --git a/test/REQUIRE b/test/REQUIRE deleted file mode 100644 index 95b73da..0000000 --- a/test/REQUIRE +++ /dev/null @@ -1,7 +0,0 @@ -FixedPointNumbers -LibSndFile -DSP -FileIO -Gumbo -Unitful -FFTW diff --git a/test/WAVDisplay.jl b/test/WAVDisplay.jl index b2d741e..f69bd56 100644 --- a/test/WAVDisplay.jl +++ b/test/WAVDisplay.jl @@ -1,73 +1,7 @@ @inline loadwav(fname::String, args...) = LibSndFile.load(File(format"WAV", fname), args...) @inline loadwav(io::IO, args...) = LibSndFile.load(Stream(format"WAV", io), args...) -function parsehtmldisplay(buf) - outputbuf = IOBuffer() - display(TextDisplay(outputbuf), "text/html", buf) - fragment = String(take!(outputbuf)) - - fullhtml = """ - - - - $fragment - - """ - - doc = parsehtml(fullhtml, strict=true) - body = doc.root[2] - @assert tag(body) == :body - - # return the body of the parsed HTML doc - body -end - -# looks for a button child with a span child that has the given class, which is -# how font-awesome displays icons -function hasiconbtn(doc, css_class) - for maybebutton in children(doc) - if tag(maybebutton) == :button - for maybespan in children(maybebutton) - if tag(maybespan) == :span - classes = split(getattr(maybespan, "class")) - css_class in classes && return true - end - end - end - end - return false -end - @testset "WAVDisplay Tests" begin - @testset "SampleBuf display Generates valid HTML" begin - buf = SampleBuf(rand(16, 2), 48000) - parsehtmldisplay(buf) - end - - @testset "SampleBuf display has the right buttons" begin - buf = SampleBuf(rand(16, 2), 48000) - output = parsehtmldisplay(buf) - @test hasiconbtn(output, "fa-step-backward") - @test hasiconbtn(output, "fa-step-forward") - @test hasiconbtn(output, "fa-play") - @test hasiconbtn(output, "fa-stop") - end - - # @testset "SpectrumBuf display Generates valid HTML" begin - # buf = SpectrumBuf(rand(16, 2), 48000) - # parsehtmldisplay(buf) - # end - - # @testset "SpectrumBuf display doesn't show buttons" begin - # buf = SpectrumBuf(rand(16, 2), 48000) - # output = parsehtmldisplay(buf) - # @test !hasiconbtn(output, "fa-step-backward") - # @test !hasiconbtn(output, "fa-step-forward") - # @test !hasiconbtn(output, "fa-play") - # @test !hasiconbtn(output, "fa-stop") - # end - @testset "wavwrite Generates valid WAV file with raw Int16" begin buf = SampleBuf(rand(Int16, 4, 2), 48000) io = IOBuffer() @@ -113,20 +47,4 @@ end @test samplerate(readbuf) == 48000 @test eltype(readbuf) == Fixed{Int16, 15} end - - # this is used to display spectrum magnitudes using the same infrastructure - # as displaying/playing time-domain buffers - # @testset "wavwrite converts complex float values to 16-bit int wav" begin - # complexbuf = SpectrumBuf(rand(Complex{Float32}, 16, 2), 48000) - # floatbuf = map(abs, complexbuf) - # complexio = IOBuffer() - # floatio = IOBuffer() - # SampledSignals.wavwrite(complexio, complexbuf) - # SampledSignals.wavwrite(floatio, floatbuf) - # complexsamples, fs, nbits, opt = wavread(IOBuffer(take!(complexio)), format="native") - # floatsamples, _, _, _ = wavread(IOBuffer(take!(floatio)), format="native") - # @test isapprox(complexsamples, floatsamples) - # @test fs == 48000 - # @test nbits == 16 - # end end diff --git a/test/runtests.jl b/test/runtests.jl index 4da7b99..ac11e00 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -2,9 +2,11 @@ using SampledSignals using Compat.Test using DSP using FixedPointNumbers -using Gumbo using FileIO: File, Stream, @format_str -import LibSndFile +# for now we're disabling the wav display tests so we don't need to include +# LibSndFile in our test dependencies. We can re-enable it once all the +# BinaryBuilder stuff is worked out +# import LibSndFile include("support/util.jl") @@ -13,5 +15,6 @@ include("support/util.jl") "SampleBuf.jl", "SampleStream.jl", "SinSource.jl", - "WAVDisplay.jl"]) + # "WAVDisplay.jl" + ]) end