basic audio callback synchronization is working
This commit is contained in:
parent
ae77cd2260
commit
171b709708
2 changed files with 39 additions and 44 deletions
50
deps/src/shim.c
vendored
50
deps/src/shim.c
vendored
|
@ -1,29 +1,7 @@
|
|||
#include <portaudio.h>
|
||||
#include <semaphore.h>
|
||||
#include <julia/julia.h>
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
|
||||
// some defines we need to include until PR 4997 is merged
|
||||
STATIC_INLINE jl_function_t *jl_get_function(jl_module_t *m, const char *name)
|
||||
{
|
||||
return (jl_function_t*) jl_get_global(m, jl_symbol(name));
|
||||
}
|
||||
|
||||
DLLEXPORT jl_value_t *jl_call2(jl_function_t *f, jl_value_t *a, jl_value_t *b)
|
||||
{
|
||||
jl_value_t *v;
|
||||
JL_TRY {
|
||||
JL_GC_PUSH3(&f,&a,&b);
|
||||
jl_value_t *args[2] = {a,b};
|
||||
v = jl_apply(f, args, 2);
|
||||
JL_GC_POP();
|
||||
}
|
||||
JL_CATCH {
|
||||
v = NULL;
|
||||
}
|
||||
return v;
|
||||
}
|
||||
#include <unistd.h>
|
||||
|
||||
static int paCallback(const void *inputBuffer, void *outputBuffer,
|
||||
unsigned long framesPerBuffer,
|
||||
|
@ -32,12 +10,22 @@ static int paCallback(const void *inputBuffer, void *outputBuffer,
|
|||
void *userData);
|
||||
|
||||
static PaStream *AudioStream;
|
||||
static jl_value_t *JuliaRemote;
|
||||
static int JuliaPipeReadFD = 0;
|
||||
static int JuliaPipeWriteFD = 0;
|
||||
static sem_t CSemaphore;
|
||||
static void *OutData = NULL;
|
||||
static unsigned long OutFrames = 0;
|
||||
static jl_function_t *RemotePutFunc = NULL;
|
||||
static jl_value_t *RemotePutArg = NULL;
|
||||
|
||||
|
||||
int make_pipe(void)
|
||||
{
|
||||
int pipefd[2];
|
||||
pipe(pipefd);
|
||||
JuliaPipeReadFD = pipefd[0];
|
||||
JuliaPipeWriteFD = pipefd[1];
|
||||
sem_init(&CSemaphore, 0, 0);
|
||||
return JuliaPipeReadFD;
|
||||
}
|
||||
|
||||
|
||||
void wake_callback_thread(void *outData, unsigned int outFrames)
|
||||
|
@ -47,15 +35,10 @@ void wake_callback_thread(void *outData, unsigned int outFrames)
|
|||
sem_post(&CSemaphore);
|
||||
}
|
||||
|
||||
PaError open_stream(unsigned int sampleRate, unsigned int bufSize,
|
||||
jl_value_t *jlRemote)
|
||||
PaError open_stream(unsigned int sampleRate, unsigned int bufSize)
|
||||
{
|
||||
PaError err;
|
||||
|
||||
JuliaRemote = jlRemote;
|
||||
sem_init(&CSemaphore, 0, 0);
|
||||
RemotePutFunc = jl_get_function(jl_base_module, "put");
|
||||
RemotePutArg = jl_box_int32(0);
|
||||
|
||||
err = Pa_OpenDefaultStream(&AudioStream,
|
||||
0, /* no input channels */
|
||||
|
@ -114,6 +97,7 @@ static int paCallback(const void *inputBuffer, void *outputBuffer,
|
|||
void *userData)
|
||||
{
|
||||
unsigned int i;
|
||||
unsigned char fd_data = 0;
|
||||
|
||||
sem_wait(&CSemaphore);
|
||||
for(i=0; i<framesPerBuffer; i++)
|
||||
|
@ -121,6 +105,6 @@ static int paCallback(const void *inputBuffer, void *outputBuffer,
|
|||
((float *)outputBuffer)[i] = ((float *)OutData)[i];
|
||||
}
|
||||
// TODO: copy the input data somewhere
|
||||
jl_call2(RemotePutFunc, JuliaRemote, RemotePutArg);
|
||||
write(JuliaPipeWriteFD, &fd_data, 1);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -13,15 +13,22 @@ const PA_NO_ERROR = 0
|
|||
############ Exported Functions #############
|
||||
|
||||
function play_sin(sample_rate, buf_size)
|
||||
jl_remote = RemoteRef()
|
||||
precompile(process!, (Array{Float32}, Array{Float32}))
|
||||
|
||||
ccall((:open_stream, libportaudio_shim), PaError,
|
||||
(Cuint, Cuint, RemoteRef),
|
||||
sample_rate, buf_size, jl_remote)
|
||||
fd = ccall((:make_pipe, libportaudio_shim), Cint, ())
|
||||
|
||||
info("Launching Audio Task...")
|
||||
yieldto(Task(audio_task))
|
||||
info("Audio Task Yielded")
|
||||
function task_wrapper()
|
||||
audio_task(fd)
|
||||
end
|
||||
schedule(Task(task_wrapper))
|
||||
yield()
|
||||
info("Audio Task Yielded, starting the stream...")
|
||||
|
||||
ccall((:open_stream, libportaudio_shim), PaError,
|
||||
(Cuint, Cuint),
|
||||
sample_rate, buf_size)
|
||||
info("Portaudio stream started.")
|
||||
end
|
||||
|
||||
#function stop_sin()
|
||||
|
@ -32,7 +39,7 @@ end
|
|||
############ Internal Functions ############
|
||||
|
||||
const sample_rate = 44100
|
||||
const buf_size = 512
|
||||
const buf_size = 1024
|
||||
const freq = 100
|
||||
phase = 0.0
|
||||
|
||||
|
@ -54,10 +61,13 @@ function wake_callback_thread(out_array)
|
|||
out_array, size(out_array, 1))
|
||||
end
|
||||
|
||||
function audio_task()
|
||||
function audio_task(jl_filedesc)
|
||||
info("Audio Task Launched")
|
||||
in_array = zeros(buf_size)
|
||||
out_array = zeros(buf_size)
|
||||
in_array = convert(Array{Float32}, zeros(buf_size))
|
||||
out_array = convert(Array{Float32}, zeros(buf_size))
|
||||
desc_bytes = Cchar[0]
|
||||
jl_stream = fdio(jl_filedesc)
|
||||
jl_rawfd = RawFD(jl_filedesc)
|
||||
while true
|
||||
process!(out_array, in_array)
|
||||
# wake the C code so it knows we've given it some more data
|
||||
|
@ -65,7 +75,8 @@ function audio_task()
|
|||
# wait for new data to be available from the sound card (and for it to
|
||||
# have processed our last frame of data). At some point we should do
|
||||
# something with the data we get from the callback
|
||||
take(jl_remote)
|
||||
wait(jl_rawfd, readable=true)
|
||||
ccall((:read, ""), Clong, (Cint, Ptr{Void}, Culong), jl_filedesc, desc_bytes, 1)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
Loading…
Reference in a new issue