Skip to content

Commit

Permalink
Using proper struct casting for event header when processing. (#2)
Browse files Browse the repository at this point in the history
Also smaller stuff:

* Added logging; auto-configured at library load.
* Build target for generating intermediary C form.
* Extended `DEBUG` flag for tracing all calls.
* Less copying in the example audio buffer processing.
  • Loading branch information
odiroot authored Jan 20, 2024
1 parent e7f7637 commit f14f4eb
Show file tree
Hide file tree
Showing 9 changed files with 54 additions and 41 deletions.
10 changes: 10 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,16 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [Unreleased]
### Changed
* Using proper struct casting for event header when processing.
* Less copying in the example audio buffer processing.

### Added
* Logging.
* Build target for generating intermediary C form.
* Extended DEBUG flag for tracing all calls.

## [0.1.1] - 2024-01-17

### Changed
Expand Down
9 changes: 8 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
SOURCEDIR = src
BUILDDIR = build
TARGET = $(BUILDDIR)/hello_world.clap
V_CMD = v -cc gcc -shared -enable-globals

# List all V source files
V_SRC = $(wildcard $(SOURCEDIR)/*.v)
Expand All @@ -10,6 +11,9 @@ V_SRC = $(wildcard $(SOURCEDIR)/*.v)
DEBUG ?= 0
RELEASE ?= 0
ifeq ($(DEBUG),1)
V_FLAGS = -cg -show-c-output
else ifeq ($(DEBUG),2)
# Even more debug! Very noisy.
V_FLAGS = -cg -show-c-output -trace-calls
else ifeq ($(RELEASE),1)
V_FLAGS = -prod -skip-unused -cflags -fvisibility=hidden
Expand All @@ -20,7 +24,7 @@ all: $(TARGET)

# Use dependency on V source files to avoid recompilation
$(TARGET): $(V_SRC) | dir
v -cc gcc -shared -enable-globals $(V_FLAGS) $(SOURCEDIR) -o $@.so
$(V_CMD) $(V_FLAGS) $(SOURCEDIR) -o $@.so
ifeq ($(RELEASE),1)
strip [email protected]
endif
Expand All @@ -35,6 +39,9 @@ clean:
info: $(TARGET)
clap-info $<

genc: $(V_SRC) | dir
$(V_CMD) $(V_FLAGS) $(SOURCEDIR) -o $(TARGET).c

install: $(TARGET)
mkdir -p ~/.clap
cp $(TARGET) ~/.clap/
Expand Down
11 changes: 4 additions & 7 deletions src/c_abi.v
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
module plugin

#flag -I./include
#include "clap/clap.h"

Expand Down Expand Up @@ -103,8 +101,7 @@ mut:
struct C.clap_input_events_t {
ctx voidptr
size fn (&C.clap_input_events_t) u32
// TODO: How to avoid `voidptr` and use header/event structs instead?
get fn (&C.clap_input_events_t, u32) voidptr
get fn (&C.clap_input_events_t, u32) &C.clap_event_header_t
}

@[typedef]
Expand All @@ -116,9 +113,9 @@ struct C.clap_event_header_t {
flags u32
}

// TODO: Why doesn't typedef C structs work here?
struct ClapEventNote {
C.clap_event_header_t
@[typedef]
struct C.clap_event_note_t {
header C.clap_event_header_t
note_id int
port_index i16
channel i16
Expand Down
2 changes: 0 additions & 2 deletions src/ext_audio_ports.v
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
module plugin

const clap_ext_audio_ports = unsafe { (&char(C.CLAP_EXT_AUDIO_PORTS)).vstring() }
const clap_port_stereo = unsafe { (&char(C.CLAP_PORT_STEREO)).vstring() }
const clap_port_mono = unsafe { (&char(C.CLAP_PORT_MONO)).vstring() }
Expand Down
2 changes: 0 additions & 2 deletions src/ext_latency.v
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
module plugin

const clap_ext_latency = unsafe { (&char(C.CLAP_EXT_LATENCY)).vstring() }

@[typedef]
Expand Down
2 changes: 0 additions & 2 deletions src/ext_note_ports.v
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
module plugin

const clap_ext_note_ports = unsafe { (&char(C.CLAP_EXT_NOTE_PORTS)).vstring() }

@[typedef]
Expand Down
11 changes: 9 additions & 2 deletions src/main.v
Original file line number Diff line number Diff line change
@@ -1,9 +1,16 @@
module plugin

import log
// Exposes the plugin to the host (DAW).

// This requires modification to `clap/entry.h`.
// Remove "const" so you get:
// CLAP_EXPORT extern clap_plugin_entry_t clap_entry;
@[markused]
__global clap_entry = plugin_entry

fn init() {
$if debug {
log.set_level(log.Level.debug)
} $else {
log.set_level(log.Level.info)
}
}
46 changes: 23 additions & 23 deletions src/plugin.v
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
module plugin
import log

// This should be the actual implementation of the plugin with
// all the interesting logic like DSP, UI, etc.
struct MinimalPlugin {
host &C.clap_host_t
mut:
sample_rate f64
latency u32
latency u32
}

// Extract our actual pluging from CLAP plugin wrapper.
Expand Down Expand Up @@ -42,33 +42,31 @@ fn MinimalPlugin.reset(clap_plugin &C.clap_plugin_t) {
// Cleanup plugin members here.
}

fn (mp MinimalPlugin) process_event (raw_event voidptr) {
header := unsafe { &C.clap_event_header_t(raw_event) }

fn (mp MinimalPlugin) process_event(header &C.clap_event_header_t) {
if header.space_id != clap_core_event_space_id {
return
}

match header.@type {
u16(ClapEventType.note_on) {
// Handle note playing.
event := unsafe { &ClapEventNote(raw_event) }
println("Note ON: ${event.note_id}")
event := &C.clap_event_note_t(header)
log.debug('Note ON: ${event.note_id}')
}
u16(ClapEventType.note_off) {
// Handle note stop playing.
event := unsafe { &ClapEventNote(raw_event) }
println("Note OFF: ${event.note_id}")
event := &C.clap_event_note_t(header)
log.debug('Note OFF: ${event.note_id}')
}
// And so on...
else {
t := unsafe { ClapEventType(header.@type) }
println("Unsupported event type: ${t}")
log.debug('Unsupported event type: ${t}')
}
}
}

fn MinimalPlugin.process(clap_plugin &C.clap_plugin_t, mut process &C.clap_process_t) ClapProcessStatus {
fn MinimalPlugin.process(clap_plugin &C.clap_plugin_t, mut process C.clap_process_t) ClapProcessStatus {
p := from_clap(clap_plugin)

nframes := process.frames_count
Expand All @@ -77,17 +75,16 @@ fn MinimalPlugin.process(clap_plugin &C.clap_plugin_t, mut process &C.clap_proce
mut ev_index := u32(0)
mut next_ev_frame := if nev > 0 { 0 } else { nframes }

for i := 0 ; i < nframes ; {
for i := 0; i < nframes; {
for ev_index < nev && next_ev_frame == i {
event := process.in_events.get(process.in_events, ev_index)
header := unsafe { &C.clap_event_header_t(event) }
header := process.in_events.get(process.in_events, ev_index)

if header.time != i {
next_ev_frame = header.time
break
}

p.process_event(event)
p.process_event(header)
ev_index++

if ev_index == nev {
Expand All @@ -96,14 +93,18 @@ fn MinimalPlugin.process(clap_plugin &C.clap_plugin_t, mut process &C.clap_proce
}
}

for ; i < next_ev_frame ; i++ {
in_l := unsafe { process.audio_inputs[0].data32[0][i] }
in_r := unsafe { process.audio_inputs[0].data32[1][i] }
for ; i < next_ev_frame; i++ {
// In general:
// mut inputs := []C.clap_audio_buffer_t{cap: int(process.audio_inputs_count)}
// for k := 0; k < process.audio_inputs_count; k++ {
// inputs << unsafe{ process.audio_inputs[k] }
// }
input_left := unsafe { process.audio_inputs[0].data32[0][i] }
input_right := unsafe { process.audio_inputs[0].data32[1][i] }

// Swap left and right channels.
out_l := in_r
out_r := in_l
unsafe { process.audio_outputs[0].data32[0][i] = out_l }
unsafe { process.audio_outputs[0].data32[1][i] = out_r }
unsafe { process.audio_outputs[0].data32[0][i] = input_right }
unsafe { process.audio_outputs[0].data32[1][i] = input_left }
}
}

Expand All @@ -122,7 +123,6 @@ fn MinimalPlugin.get_extension(clap_plugin &C.clap_plugin_t, id &char) voidptr {
}
}
}

clap_ext_audio_ports {
return &C.clap_plugin_audio_ports_t{
count: fn (clap_plugin &C.clap_plugin_t, is_input bool) u32 {
Expand Down
2 changes: 0 additions & 2 deletions src/setup.v
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
module plugin

// Features of the CLAP plugin.
// Have to be defined separately here, otherwise wrong C is generated.
const _plugin_features = [
Expand Down

0 comments on commit f14f4eb

Please sign in to comment.