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 <portaudio.h>
|
||||||
#include <semaphore.h>
|
#include <semaphore.h>
|
||||||
#include <julia/julia.h>
|
|
||||||
#include <math.h>
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <unistd.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;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int paCallback(const void *inputBuffer, void *outputBuffer,
|
static int paCallback(const void *inputBuffer, void *outputBuffer,
|
||||||
unsigned long framesPerBuffer,
|
unsigned long framesPerBuffer,
|
||||||
|
@ -32,12 +10,22 @@ static int paCallback(const void *inputBuffer, void *outputBuffer,
|
||||||
void *userData);
|
void *userData);
|
||||||
|
|
||||||
static PaStream *AudioStream;
|
static PaStream *AudioStream;
|
||||||
static jl_value_t *JuliaRemote;
|
static int JuliaPipeReadFD = 0;
|
||||||
|
static int JuliaPipeWriteFD = 0;
|
||||||
static sem_t CSemaphore;
|
static sem_t CSemaphore;
|
||||||
static void *OutData = NULL;
|
static void *OutData = NULL;
|
||||||
static unsigned long OutFrames = 0;
|
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)
|
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);
|
sem_post(&CSemaphore);
|
||||||
}
|
}
|
||||||
|
|
||||||
PaError open_stream(unsigned int sampleRate, unsigned int bufSize,
|
PaError open_stream(unsigned int sampleRate, unsigned int bufSize)
|
||||||
jl_value_t *jlRemote)
|
|
||||||
{
|
{
|
||||||
PaError err;
|
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,
|
err = Pa_OpenDefaultStream(&AudioStream,
|
||||||
0, /* no input channels */
|
0, /* no input channels */
|
||||||
|
@ -114,6 +97,7 @@ static int paCallback(const void *inputBuffer, void *outputBuffer,
|
||||||
void *userData)
|
void *userData)
|
||||||
{
|
{
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
|
unsigned char fd_data = 0;
|
||||||
|
|
||||||
sem_wait(&CSemaphore);
|
sem_wait(&CSemaphore);
|
||||||
for(i=0; i<framesPerBuffer; i++)
|
for(i=0; i<framesPerBuffer; i++)
|
||||||
|
@ -121,6 +105,6 @@ static int paCallback(const void *inputBuffer, void *outputBuffer,
|
||||||
((float *)outputBuffer)[i] = ((float *)OutData)[i];
|
((float *)outputBuffer)[i] = ((float *)OutData)[i];
|
||||||
}
|
}
|
||||||
// TODO: copy the input data somewhere
|
// TODO: copy the input data somewhere
|
||||||
jl_call2(RemotePutFunc, JuliaRemote, RemotePutArg);
|
write(JuliaPipeWriteFD, &fd_data, 1);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,15 +13,22 @@ const PA_NO_ERROR = 0
|
||||||
############ Exported Functions #############
|
############ Exported Functions #############
|
||||||
|
|
||||||
function play_sin(sample_rate, buf_size)
|
function play_sin(sample_rate, buf_size)
|
||||||
jl_remote = RemoteRef()
|
precompile(process!, (Array{Float32}, Array{Float32}))
|
||||||
|
|
||||||
ccall((:open_stream, libportaudio_shim), PaError,
|
fd = ccall((:make_pipe, libportaudio_shim), Cint, ())
|
||||||
(Cuint, Cuint, RemoteRef),
|
|
||||||
sample_rate, buf_size, jl_remote)
|
|
||||||
|
|
||||||
info("Launching Audio Task...")
|
info("Launching Audio Task...")
|
||||||
yieldto(Task(audio_task))
|
function task_wrapper()
|
||||||
info("Audio Task Yielded")
|
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
|
end
|
||||||
|
|
||||||
#function stop_sin()
|
#function stop_sin()
|
||||||
|
@ -32,7 +39,7 @@ end
|
||||||
############ Internal Functions ############
|
############ Internal Functions ############
|
||||||
|
|
||||||
const sample_rate = 44100
|
const sample_rate = 44100
|
||||||
const buf_size = 512
|
const buf_size = 1024
|
||||||
const freq = 100
|
const freq = 100
|
||||||
phase = 0.0
|
phase = 0.0
|
||||||
|
|
||||||
|
@ -54,10 +61,13 @@ function wake_callback_thread(out_array)
|
||||||
out_array, size(out_array, 1))
|
out_array, size(out_array, 1))
|
||||||
end
|
end
|
||||||
|
|
||||||
function audio_task()
|
function audio_task(jl_filedesc)
|
||||||
info("Audio Task Launched")
|
info("Audio Task Launched")
|
||||||
in_array = zeros(buf_size)
|
in_array = convert(Array{Float32}, zeros(buf_size))
|
||||||
out_array = 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
|
while true
|
||||||
process!(out_array, in_array)
|
process!(out_array, in_array)
|
||||||
# wake the C code so it knows we've given it some more data
|
# 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
|
# 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
|
# have processed our last frame of data). At some point we should do
|
||||||
# something with the data we get from the callback
|
# 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
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue