Compare commits

...

2 Commits

2 changed files with 124 additions and 19 deletions

View File

@ -0,0 +1,104 @@
import std/[logging, math, os]
import signal
import jacket
var jclient: ClientTPtr
var out1: PortTPtr
var status: cint
var log = newConsoleLogger(when defined(release): lvlInfo else: lvlDebug)
type
SampleT = DefaultAudioSampleT
JackBufferPtr = ptr UncheckedArray[SampleT]
const
tableSize = 4096
sineFreq = 440.0
twoPi = Pi * 2.0
type
SineOsc = object
waveform: array[0..tableSize, float]
phase: float
idxInc: float
SineOscPtr = ref SineOsc
proc initSineOsc(sr: float, freq: float): SineOsc =
let phsInc = twoPi / tableSize
var phase = 0.0
for i in 0 ..< tableSize:
result.waveform[i] = sin(phase)
phase += phsInc
result.phase = 0.0
result.idxInc = tableSize / sr * freq
proc tick(osc: SineOscPtr): float =
result = osc.waveform[int(osc.phase)]
osc.phase += osc.idxInc;
if osc.phase >= tableSize:
osc.phase -= tableSize
proc errorCb(msg: cstring) {.cdecl.} =
# Suppress verbose JACK error messages when server is not available by
# default. Pass ``lvlAll`` when creating the logger to enable them.
debug "JACK error: " & $msg
proc cleanup(sig: cint = 0) {.noconv.} =
debug "Cleaning up..."
if jclient != nil:
discard jclient.deactivate()
discard jclient.clientClose()
jclient = nil
quit QuitSuccess
proc shutdownCb(arg: pointer = nil) {.cdecl.} =
debug "Server has shut down"
cleanup()
proc process(nFrames: NFramesT, arg: pointer): cint {.cdecl.} =
var outbuf = cast[JackBufferPtr](portGetBuffer(out1, nFrames))
let osc = cast[SineOscPtr](arg)
for i in 0 ..< nFrames:
outbuf[i] = osc.tick() * 0.2
return 0
addHandler(log)
# create JACK client
setErrorFunction(errorCb)
jclient = clientOpen("jacket_port_register", NoStartServer.ord or UseExactName.ord, status.addr)
debug "Server status: " & $status
if jclient == nil:
error getJackStatusErrorString(status)
quit 1
let sampleRate =(float) jclient.getSampleRate()
var osc = initSineOsc(sampleRate, sineFreq)
when defined(windows):
setSignalProc(cleanup, SIGABRT, SIGINT, SIGTERM)
else:
setSignalProc(cleanup, SIGABRT, SIGHUP, SIGINT, SIGQUIT, SIGTERM)
if jclient.setProcessCallback(process, osc.addr) != 0:
error "Could not set process callback function."
cleanup()
jclient.onShutdown(shutdownCb, nil)
out1 = jclient.portRegister("out_1", JACK_DEFAULT_AUDIO_TYPE, PortIsOutput.ord, 0)
if jclient.activate() == 0:
# keep running until the Ctrl+C
while true:
sleep(50)
cleanup() # normally not reached

View File

@ -27,10 +27,11 @@ const
type type
TimeT* = culonglong TimeT* = culonglong
NframesT* = culong NFramesT* = culong
UuidT* = culonglong UuidT* = culonglong
PortIdT* = culong PortIdT* = culong
PortTypeIdT* = culong PortTypeIdT* = culong
DefaultAudioSampleT* = cfloat
type type
ClientT = distinct object ClientT = distinct object
@ -80,13 +81,13 @@ type
# Callback function types # Callback function types
type type
JackProcessCallback* = proc (nframes: NframesT; arg: pointer): cint {.cdecl.} JackProcessCallback* = proc (nframes: NFramesT; arg: pointer): cint {.cdecl.}
JackThreadCallback* = proc (arg: pointer): pointer {.cdecl.} JackThreadCallback* = proc (arg: pointer): pointer {.cdecl.}
JackThreadInitCallback* = proc (arg: pointer) {.cdecl.} JackThreadInitCallback* = proc (arg: pointer) {.cdecl.}
JackGraphOrderCallback* = proc (arg: pointer): cint {.cdecl.} JackGraphOrderCallback* = proc (arg: pointer): cint {.cdecl.}
JackXRunCallback* = proc (arg: pointer): cint {.cdecl.} JackXRunCallback* = proc (arg: pointer): cint {.cdecl.}
JackBufferSizeCallback* = proc (nframes: NframesT; arg: pointer): cint {.cdecl.} JackBufferSizeCallback* = proc (nframes: NFramesT; arg: pointer): cint {.cdecl.}
JackSampleRateCallback* = proc (nframes: NframesT; arg: pointer): cint {.cdecl.} JackSampleRateCallback* = proc (nframes: NFramesT; arg: pointer): cint {.cdecl.}
JackPortRegistrationCallback* = proc (port: PortIdT; flag: cint; arg: pointer) {.cdecl.} JackPortRegistrationCallback* = proc (port: PortIdT; flag: cint; arg: pointer) {.cdecl.}
JackClientRegistrationCallback* = proc (name: cstring; flag: cint; arg: pointer) {.cdecl.} JackClientRegistrationCallback* = proc (name: cstring; flag: cint; arg: pointer) {.cdecl.}
JackPortConnectCallback* = proc (portA: PortIdT; portB: PortIdT; connect: cint; arg: pointer) {.cdecl.} JackPortConnectCallback* = proc (portA: PortIdT; portB: PortIdT; connect: cint; arg: pointer) {.cdecl.}
@ -169,11 +170,11 @@ proc getClientPid*(name: cstring): cint {.importc: "jack_get_client_pid".}
proc isRealtime*(client: ClientTPtr): cint {.importc: "jack_is_realtime".} proc isRealtime*(client: ClientTPtr): cint {.importc: "jack_is_realtime".}
# DEPRECATED # DEPRECATED
# proc threadWait*(client: ClientTPtr; status: cint): NframesT {. # proc threadWait*(client: ClientTPtr; status: cint): NFramesT {.
# importc: "jack_thread_wait".} # importc: "jack_thread_wait".}
# jack_nframes_t jack_cycle_wait (jack_client_t* client) ; # jack_nframes_t jack_cycle_wait (jack_client_t* client) ;
proc cycleWait*(client: ClientTPtr): NframesT {.importc: "jack_cycle_wait".} proc cycleWait*(client: ClientTPtr): NFramesT {.importc: "jack_cycle_wait".}
# void jack_cycle_signal (jack_client_t* client, int status) ; # void jack_cycle_signal (jack_client_t* client, int status) ;
proc cycleSignal*(client: ClientTPtr; status: cint) {.importc: "jack_cycle_signal".} proc cycleSignal*(client: ClientTPtr; status: cint) {.importc: "jack_cycle_signal".}
@ -235,13 +236,13 @@ proc setLatencyCallback*(client: ClientTPtr; latencyCallback: JackLatencyCallbac
proc setFreewheel*(client: ClientTPtr; onoff: cint): cint {.importc: "jack_set_freewheel".} proc setFreewheel*(client: ClientTPtr; onoff: cint): cint {.importc: "jack_set_freewheel".}
# int jack_set_buffer_size (jack_client_t *client, jack_nframes_t nframes) ; # int jack_set_buffer_size (jack_client_t *client, jack_nframes_t nframes) ;
proc setBufferSize*(client: ClientTPtr; nframes: NframesT): cint {.importc: "jack_set_buffer_size".} proc setBufferSize*(client: ClientTPtr; nframes: NFramesT): cint {.importc: "jack_set_buffer_size".}
#jack_nframes_t jack_get_sample_rate (jack_client_t *) ; #jack_nframes_t jack_get_sample_rate (jack_client_t *) ;
proc getSampleRate*(client: ClientTPtr): NframesT {.importc: "jack_get_sample_rate".} proc getSampleRate*(client: ClientTPtr): NFramesT {.importc: "jack_get_sample_rate".}
# jack_nframes_t jack_get_buffer_size (jack_client_t *) ; # jack_nframes_t jack_get_buffer_size (jack_client_t *) ;
proc getBufferSize*(client: ClientTPtr): NframesT {.importc: "jack_get_buffer_size".} proc getBufferSize*(client: ClientTPtr): NFramesT {.importc: "jack_get_buffer_size".}
# DEPRECATED # DEPRECATED
# proc engineTakeoverTimebase*(a1: ClientTPtr): cint {. # proc engineTakeoverTimebase*(a1: ClientTPtr): cint {.
@ -265,7 +266,7 @@ proc portRegister*(client: ClientTPtr; portName: cstring; portType: cstring;
proc portUnregister*(client: ClientTPtr; port: PortTPtr): cint {.importc: "jack_port_unregister".} proc portUnregister*(client: ClientTPtr; port: PortTPtr): cint {.importc: "jack_port_unregister".}
# void * jack_port_get_buffer (jack_port_t *port, jack_nframes_t) ; # void * jack_port_get_buffer (jack_port_t *port, jack_nframes_t) ;
proc portGetBuffer*(port: PortTPtr; nframes: NframesT): pointer {.importc: "jack_port_get_buffer".} proc portGetBuffer*(port: PortTPtr; nframes: NFramesT): pointer {.importc: "jack_port_get_buffer".}
# jack_uuid_t jack_port_uuid (const jack_port_t *port) ; # jack_uuid_t jack_port_uuid (const jack_port_t *port) ;
proc portUuid*(port: PortTPtr): UuidT {.importc: "jack_port_uuid".} proc portUuid*(port: PortTPtr): UuidT {.importc: "jack_port_uuid".}
@ -374,7 +375,7 @@ proc portTypeGetBufferSize*(client: ClientTPtr; portType: cstring): csize_t {.
#[ FIXME: not implemented yet #[ FIXME: not implemented yet
# void jack_port_set_latency (jack_port_t *port, jack_nframes_t) ; # void jack_port_set_latency (jack_port_t *port, jack_nframes_t) ;
proc portSetLatency*(port: PortTPtr; a2: NframesT) {.importc: "jack_port_set_latency".} proc portSetLatency*(port: PortTPtr; a2: NFramesT) {.importc: "jack_port_set_latency".}
#[ FIXME: not implemented yet #[ FIXME: not implemented yet
# void jack_port_get_latency_range (jack_port_t *port, jack_latency_callback_mode_t mode, jack_latency_range_t *range) ; # void jack_port_get_latency_range (jack_port_t *port, jack_latency_callback_mode_t mode, jack_latency_range_t *range) ;
@ -387,9 +388,9 @@ proc portSetLatencyRange*(port: PortTPtr; mode: LatencyCallbackModeT;
proc recomputeTotalLatencies*(client: ClientTPtr): cint {.importc: "jack_recompute_total_latencies".} proc recomputeTotalLatencies*(client: ClientTPtr): cint {.importc: "jack_recompute_total_latencies".}
proc portGetLatency*(port: PortTPtr): NframesT {.importc: "jack_port_get_latency".} proc portGetLatency*(port: PortTPtr): NFramesT {.importc: "jack_port_get_latency".}
proc portGetTotalLatency*(client: ClientTPtr; port: PortTPtr): NframesT {.importc: "jack_port_get_total_latency".} proc portGetTotalLatency*(client: ClientTPtr; port: PortTPtr): NFramesT {.importc: "jack_port_get_total_latency".}
proc recomputeTotalLatency*(a1: ClientTPtr; port: PortTPtr): cint {.importc: "jack_recompute_total_latency".} proc recomputeTotalLatency*(a1: ClientTPtr; port: PortTPtr): cint {.importc: "jack_recompute_total_latency".}
]# ]#
@ -415,28 +416,28 @@ proc portById*(client: ClientTPtr; portId: PortIdT): PortTPtr {.importc: "jack_p
# ----------------------------- Time handling ----------------------------- # ----------------------------- Time handling -----------------------------
# jack_nframes_t jack_frames_since_cycle_start (const jack_client_t *) ; # jack_nframes_t jack_frames_since_cycle_start (const jack_client_t *) ;
proc framesSinceCycleStart*(client: ClientTPtr): NframesT {.importc: "jack_frames_since_cycle_start".} proc framesSinceCycleStart*(client: ClientTPtr): NFramesT {.importc: "jack_frames_since_cycle_start".}
# jack_nframes_t jack_frame_time (const jack_client_t *) ; # jack_nframes_t jack_frame_time (const jack_client_t *) ;
proc frameTime*(client: ClientTPtr): NframesT {.importc: "jack_frame_time".} proc frameTime*(client: ClientTPtr): NFramesT {.importc: "jack_frame_time".}
# jack_nframes_t jack_last_frame_time (const jack_client_t *client) ; # jack_nframes_t jack_last_frame_time (const jack_client_t *client) ;
proc lastFrameTime*(client: ClientTPtr): NframesT {.importc: "jack_last_frame_time".} proc lastFrameTime*(client: ClientTPtr): NFramesT {.importc: "jack_last_frame_time".}
# int jack_get_cycle_times(const jack_client_t *client, # int jack_get_cycle_times(const jack_client_t *client,
# jack_nframes_t *current_frames, # jack_nframes_t *current_frames,
# jack_time_t *current_usecs, # jack_time_t *current_usecs,
# jack_time_t *next_usecs, # jack_time_t *next_usecs,
# float *period_usecs) ; # float *period_usecs) ;
proc getCycleTimes*(client: ClientTPtr; currentFrames: ptr NframesT; proc getCycleTimes*(client: ClientTPtr; currentFrames: ptr NFramesT;
currentUsecs: ptr TimeT; nextUsecs: ptr TimeT; currentUsecs: ptr TimeT; nextUsecs: ptr TimeT;
periodUsecs: ptr cfloat): cint {.importc: "jack_get_cycle_times".} periodUsecs: ptr cfloat): cint {.importc: "jack_get_cycle_times".}
# jack_time_t jack_frames_to_time(const jack_client_t *client, jack_nframes_t) ; # jack_time_t jack_frames_to_time(const jack_client_t *client, jack_nframes_t) ;
proc framesToTime*(client: ClientTPtr; nframes: NframesT): TimeT {.importc: "jack_frames_to_time".} proc framesToTime*(client: ClientTPtr; nframes: NFramesT): TimeT {.importc: "jack_frames_to_time".}
# jack_nframes_t jack_time_to_frames(const jack_client_t *client, jack_time_t) ; # jack_nframes_t jack_time_to_frames(const jack_client_t *client, jack_time_t) ;
proc timeToFrames*(client: ClientTPtr; time: TimeT): NframesT {.importc: "jack_time_to_frames".} proc timeToFrames*(client: ClientTPtr; time: TimeT): NFramesT {.importc: "jack_time_to_frames".}
# jack_time_t jack_get_time(void) ; # jack_time_t jack_get_time(void) ;
proc getTime*(): TimeT {.importc: "jack_get_time".} proc getTime*(): TimeT {.importc: "jack_get_time".}