add libsndfile bindings
This commit is contained in:
parent
1fe3e123c1
commit
5afba7136b
4 changed files with 98 additions and 0 deletions
|
@ -27,6 +27,7 @@ end
|
|||
|
||||
include("nodes.jl")
|
||||
include("portaudio.jl")
|
||||
include("sndfile.jl")
|
||||
|
||||
############ Exported Functions #############
|
||||
|
||||
|
|
84
src/sndfile.jl
Normal file
84
src/sndfile.jl
Normal file
|
@ -0,0 +1,84 @@
|
|||
export openAudio, closeAudio, readFrames
|
||||
|
||||
const sndfile = "libsndfile"
|
||||
|
||||
|
||||
const SFM_READ = int32(0x10)
|
||||
const SFM_WRITE = int32(0x20)
|
||||
|
||||
type SF_INFO
|
||||
frames::Int64
|
||||
samplerate::Int32
|
||||
channels::Int32
|
||||
format::Int32
|
||||
sections::Int32
|
||||
seekable::Int32
|
||||
end
|
||||
|
||||
type Sndfile
|
||||
filePtr::Ptr{Void}
|
||||
sfinfo::SF_INFO
|
||||
end
|
||||
|
||||
function openAudio(path::String)
|
||||
sfinfo = SF_INFO(0, 0, 0, 0, 0, 0)
|
||||
filePtr = ccall((:sf_open, sndfile), Ptr{Void},
|
||||
(Ptr{Uint8}, Int32, Ptr{SF_INFO}),
|
||||
path, SFM_READ, &sfinfo)
|
||||
if filePtr == C_NULL
|
||||
errmsg = ccall((:sf_strerror, sndfile), Ptr{Uint8}, (Ptr{Void},), filePtr)
|
||||
error(bytestring(errmsg))
|
||||
end
|
||||
|
||||
return Sndfile(filePtr, sfinfo)
|
||||
end
|
||||
|
||||
function closeAudio(file::Sndfile)
|
||||
err = ccall((:sf_close, sndfile), Int32, (Ptr{Void},), file.filePtr)
|
||||
if err != 0
|
||||
error("Failed to close file")
|
||||
end
|
||||
end
|
||||
|
||||
function openAudio(f::Function, path::String)
|
||||
file = openAudio(path)
|
||||
f(file)
|
||||
closeAudio(file)
|
||||
end
|
||||
|
||||
function readFrames(file::Sndfile, nframes::Integer, dtype::Type = Int16)
|
||||
arr = []
|
||||
if file.sfinfo.channels == 2
|
||||
arr = Array(dtype, 2, nframes)
|
||||
else
|
||||
arr = Array(dtype, nframes)
|
||||
end
|
||||
|
||||
if dtype == Int16
|
||||
nread = ccall((:sf_readf_short, sndfile), Int64,
|
||||
(Ptr{Void}, Ptr{Int16}, Int64),
|
||||
file.filePtr, arr, nframes)
|
||||
elseif dtype == Int32
|
||||
nread = ccall((:sf_readf_int, sndfile), Int64,
|
||||
(Ptr{Void}, Ptr{Int32}, Int64),
|
||||
file.filePtr, arr, nframes)
|
||||
elseif dtype == Float32
|
||||
nread = ccall((:sf_readf_float, sndfile), Int64,
|
||||
(Ptr{Void}, Ptr{Float32}, Int64),
|
||||
file.filePtr, arr, nframes)
|
||||
elseif dtype == Float64
|
||||
nread = ccall((:sf_readf_double, sndfile), Int64,
|
||||
(Ptr{Void}, Ptr{Float64}, Int64),
|
||||
file.filePtr, arr, nframes)
|
||||
end
|
||||
|
||||
if nread == 0
|
||||
return []
|
||||
end
|
||||
|
||||
if file.sfinfo.channels == 2
|
||||
return arr[:, 1:nread]
|
||||
end
|
||||
|
||||
return arr[1:nread]
|
||||
end
|
BIN
test/sinwave.flac
Normal file
BIN
test/sinwave.flac
Normal file
Binary file not shown.
|
@ -72,3 +72,16 @@ stop(node)
|
|||
# give the render task a chance to clean up
|
||||
process(test_stream)
|
||||
@test process(test_stream) == zeros(AudioIO.AudioSample, TEST_BUF_SIZE)
|
||||
|
||||
info("Testing libsndfile read")
|
||||
samplerate = 44100
|
||||
freq = 440
|
||||
t = linspace(0, 2, 2 * samplerate)
|
||||
phase = 2 * pi * freq * t
|
||||
reference = int16((2 ^ 15 - 1) * sin(phase))
|
||||
|
||||
f = openAudio("test/sinwave.flac")
|
||||
@test f.sfinfo.channels == 1
|
||||
@test f.sfinfo.frames == 2 * samplerate
|
||||
actual = readFrames(f, 2 * samplerate)
|
||||
@test_approx_eq(reference, actual)
|
||||
|
|
Loading…
Reference in a new issue