PortAudio.jl/src/sndfile.jl

109 lines
2.8 KiB
Julia
Raw Normal View History

2014-01-09 00:25:55 +01:00
export openAudio, closeAudio, readFrames, FileInput
2014-01-06 17:24:53 +01:00
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
2014-01-09 00:25:55 +01:00
arr = zeros(dtype, 2, nframes)
2014-01-06 17:24:53 +01:00
else
2014-01-09 00:25:55 +01:00
arr = zeros(dtype, nframes)
2014-01-06 17:24:53 +01:00
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
2014-01-09 00:25:55 +01:00
return Nothing
2014-01-06 17:24:53 +01:00
end
2014-01-09 00:25:55 +01:00
return arr
end
type FileInput <: AudioNode
active::Bool
file::Sndfile
function FileInput(path::String)
node = new(false, openAudio(path))
finalizer(node, node -> closeAudio(node.file))
return node
end
end
function render(node::FileInput, device_input::AudioBuf, info::DeviceInfo)
@assert node.file.sfinfo.samplerate == info.sample_rate
audio = readFrames(node.file, info.buf_size, AudioSample)
if audio == Nothing
return zeros(AudioSample, info.buf_size), false
end
# if the file is stereo, mix the two channels together
if node.file.sfinfo.channels == 2
return (audio[1, :] / 2) + (audio[2, :] / 2), node.active
2014-01-06 17:24:53 +01:00
end
2014-01-09 00:25:55 +01:00
return audio, node.active
2014-01-06 17:24:53 +01:00
end