diff --git a/README.md b/README.md index 428400c..0da5414 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,18 @@ PortAudio.jl -========== +============ [![Build Status](https://travis-ci.org/JuliaAudio/PortAudio.jl.svg?branch=master)](https://travis-ci.org/JuliaAudio/PortAudio.jl) [![codecov.io] (http://codecov.io/github/JuliaAudio/PortAudio.jl/coverage.svg?branch=master)] (http://codecov.io/github/JuliaAudio/PortAudio.jl?branch=master) -PortAudio.jl is a wrapper for [libportaudio](http://www.portaudio.com/), which gives cross-platform access to audio devices. It is compatible with the types defined in [SampleTypes.jl](https://github.com/JuliaAudio/SampleTypes.jl), so it provides `PASampleSink` and `PASampleSource` types, which can be read from and written to. +PortAudio.jl is a wrapper for [libportaudio](http://www.portaudio.com/), which gives cross-platform access to audio devices. It is compatible with the types defined in [SampleTypes.jl](https://github.com/JuliaAudio/SampleTypes.jl), so it provides `PortAudioSink` and `PortAudioSource` types, which can be read from and written to. + +## Examples + +### Set up an audio pass-through from microphone to speaker + +```julia +src = PortAudioSource() +sink = PortAudioSink() +write(sink, source) +end +``` diff --git a/src/PortAudio.jl b/src/PortAudio.jl index b5a3be4..3c37825 100644 --- a/src/PortAudio.jl +++ b/src/PortAudio.jl @@ -93,24 +93,28 @@ function SampleTypes.unsafe_write(sink::PortAudioSink, buf::SampleBuf) shift!(sink.waiters) end - sink.busy = true total = nframes(buf) written = 0 + try + sink.busy = true - while written < total - n = min(size(sink.pabuf, 2), total-written, Pa_GetStreamWriteAvailable(sink.stream)) - bufstart = 1+written - bufend = n+written - @devec sink.jlbuf[1:n, :] = buf[bufstart:bufend, :] - transpose!(sink.pabuf, sink.jlbuf) - Pa_WriteStream(sink.stream, sink.pabuf, n, false) - written += n - sleep(POLL_SECONDS) - end - sink.busy = false - if length(sink.waiters) > 0 - # let the next task in line go - notify(sink.waiters[1]) + while written < total + n = min(size(sink.pabuf, 2), total-written, Pa_GetStreamWriteAvailable(sink.stream)) + bufstart = 1+written + bufend = n+written + @devec sink.jlbuf[1:n, :] = buf[bufstart:bufend, :] + transpose!(sink.pabuf, sink.jlbuf) + Pa_WriteStream(sink.stream, sink.pabuf, n, false) + written += n + sleep(POLL_SECONDS) + end + finally + # make sure we release the busy flag even if the user ctrl-C'ed out + sink.busy = false + if length(sink.waiters) > 0 + # let the next task in line go + notify(sink.waiters[1]) + end end written @@ -124,26 +128,29 @@ function SampleTypes.unsafe_read!(source::PortAudioSource, buf::SampleBuf) shift!(source.waiters) end - source.busy = true - total = nframes(buf) read = 0 - while read < total - n = min(size(source.pabuf, 2), total-read, Pa_GetStreamReadAvailable(source.stream)) - Pa_ReadStream(source.stream, source.pabuf, n, false) - transpose!(source.jlbuf, source.pabuf) - bufstart = 1+read - bufend = n+read - @devec buf[bufstart:bufend, :] = source.jlbuf[1:n, :] - read += n - sleep(POLL_SECONDS) - end + try + source.busy = true - source.busy = false - if length(source.waiters) > 0 - # let the next task in line go - notify(source.waiters[1]) + while read < total + n = min(size(source.pabuf, 2), total-read, Pa_GetStreamReadAvailable(source.stream)) + Pa_ReadStream(source.stream, source.pabuf, n, false) + transpose!(source.jlbuf, source.pabuf) + bufstart = 1+read + bufend = n+read + @devec buf[bufstart:bufend, :] = source.jlbuf[1:n, :] + read += n + sleep(POLL_SECONDS) + end + + finally + source.busy = false + if length(source.waiters) > 0 + # let the next task in line go + notify(source.waiters[1]) + end end read