Csound Csound-dev Csound-tekno Search About

[Csnd] Template for plugins in zig

Date2025-02-14 12:57
FromEduardo Moguillansky
Subject[Csnd] Template for plugins in zig
For anyone interested in experimenting with building csound plugins in zig, here is an example plugin. One interesting aspect is that zig can cross compile to any platform so from one local build it is possible to produce binaries for many platforms.

const std = @import("std");

const cs = @cImport({
    @cInclude("csound/csdl.h");
});

const TestGain = extern struct {
    h: cs.OPDS,
    out: [*]f64,
    in: [*]f64,
    kgain: *f64
};

fn testgain_init(csoundptr: [*c]cs.CSOUND, p: ?*anyopaque) callconv(.C) c_int {
    _ = csoundptr;
    _ = p;
    // std.debug.print("testgain_init\n", .{});
    return cs.OK;
}

fn testgain_perf(csoundptr: [*c]cs.CSOUND, p0: ?*anyopaque) callconv(.C) c_int {
    _ = &csoundptr[0];
    const p: *TestGain = @ptrCast(@alignCast(p0));
    const nsmps = cs.GetLocalKsmps(&p.h);
    var i: u32 = 0;
    var out: [*]f64 = p.*.out;
    const in: [*]f64 = p.*.in;
    const gain: f64 = p.*.kgain.*;
    while (i <= nsmps) : (i += 1) {
        out[i] = in[i] * gain;
    }
    return cs.OK;
}

const localops7: []const cs.OENTRY = &.{
    .{.opname=@constCast("testgain"), .dsblksiz=@sizeOf(TestGain), .flags=0, .outypes=@constCast("a"), .intypes=@constCast("ak"), .init=&testgain_init, .perf=&testgain_perf}
};

export fn csound_opcode_init(csound: *cs.CSOUND, ep: *[*]cs.OENTRY) i64 {
    _ = csound;
    ep.* = @constCast(localops7.ptr);
    return @sizeOf(cs.OENTRY) * localops7.len;
}

export fn csoundModuleInfo() i32 {
    const version = ((cs.CS_VERSION << 16) + (cs.CS_SUBVER << 8) + @sizeOf(cs.MYFLT));
    // std.debug.print("testgain - module info. version: {}\n", .{version});
    return version;
}

Saved to a file "testplugin.zig", it can be compiled with "zig build-lib -dynamic -lc -I/usr/local/include testplugin.zig", the folders need to be adapted to the local system.

cheers,
Eduardo
Csound mailing list Csound@listserv.heanet.ie https://listserv.heanet.ie/cgi-bin/wa?A0=CSOUND Send bugs reports to https://github.com/csound/csound/issues Discussions of bugs and features can be posted here

Date2025-02-14 13:48
FromHlöðver Sigurðsson
SubjectRe: [Csnd] Template for plugins in zig
bravo, I'll use it, I tried similar things in the past but didn't find the time :)

On Fri, 14 Feb 2025 at 14:58, Eduardo Moguillansky <eduardo.moguillansky@gmail.com> wrote:
For anyone interested in experimenting with building csound plugins in zig, here is an example plugin. One interesting aspect is that zig can cross compile to any platform so from one local build it is possible to produce binaries for many platforms.

const std = @import("std");

const cs = @cImport({
    @cInclude("csound/csdl.h");
});

const TestGain = extern struct {
    h: cs.OPDS,
    out: [*]f64,
    in: [*]f64,
    kgain: *f64
};

fn testgain_init(csoundptr: [*c]cs.CSOUND, p: ?*anyopaque) callconv(.C) c_int {
    _ = csoundptr;
    _ = p;
    // std.debug.print("testgain_init\n", .{});
    return cs.OK;
}

fn testgain_perf(csoundptr: [*c]cs.CSOUND, p0: ?*anyopaque) callconv(.C) c_int {
    _ = &csoundptr[0];
    const p: *TestGain = @ptrCast(@alignCast(p0));
    const nsmps = cs.GetLocalKsmps(&p.h);
    var i: u32 = 0;
    var out: [*]f64 = p.*.out;
    const in: [*]f64 = p.*.in;
    const gain: f64 = p.*.kgain.*;
    while (i <= nsmps) : (i += 1) {
        out[i] = in[i] * gain;
    }
    return cs.OK;
}

const localops7: []const cs.OENTRY = &.{
    .{.opname=@constCast("testgain"), .dsblksiz=@sizeOf(TestGain), .flags=0, .outypes=@constCast("a"), .intypes=@constCast("ak"), .init=&testgain_init, .perf=&testgain_perf}
};

export fn csound_opcode_init(csound: *cs.CSOUND, ep: *[*]cs.OENTRY) i64 {
    _ = csound;
    ep.* = @constCast(localops7.ptr);
    return @sizeOf(cs.OENTRY) * localops7.len;
}

export fn csoundModuleInfo() i32 {
    const version = ((cs.CS_VERSION << 16) + (cs.CS_SUBVER << 8) + @sizeOf(cs.MYFLT));
    // std.debug.print("testgain - module info. version: {}\n", .{version});
    return version;
}

Saved to a file "testplugin.zig", it can be compiled with "zig build-lib -dynamic -lc -I/usr/local/include testplugin.zig", the folders need to be adapted to the local system.

cheers,
Eduardo
Csound mailing list Csound@listserv.heanet.ie https://listserv.heanet.ie/cgi-bin/wa?A0=CSOUND Send bugs reports to https://github.com/csound/csound/issues Discussions of bugs and features can be posted here
Csound mailing list Csound@listserv.heanet.ie https://listserv.heanet.ie/cgi-bin/wa?A0=CSOUND Send bugs reports to https://github.com/csound/csound/issues Discussions of bugs and features can be posted here

Date2025-02-14 14:38
From"Dr. Richard Boulanger"
SubjectRe: [Csnd] Template for plugins in zig
Nice!

Dr. Richard Boulanger
Professor
Electronic Production and Design
Berklee College of Music

On Feb 14, 2025, at 8:49 AM, Hlöðver Sigurðsson <hlolli@gmail.com> wrote:


bravo, I'll use it, I tried similar things in the past but didn't find the time :)

On Fri, 14 Feb 2025 at 14:58, Eduardo Moguillansky <eduardo.moguillansky@gmail.com> wrote:
For anyone interested in experimenting with building csound plugins in zig, here is an example plugin. One interesting aspect is that zig can cross compile to any platform so from one local build it is possible to produce binaries for many platforms.

const std = @import("std");

const cs = @cImport({
    @cInclude("csound/csdl.h");
});

const TestGain = extern struct {
    h: cs.OPDS,
    out: [*]f64,
    in: [*]f64,
    kgain: *f64
};

fn testgain_init(csoundptr: [*c]cs.CSOUND, p: ?*anyopaque) callconv(.C) c_int {
    _ = csoundptr;
    _ = p;
    // std.debug.print("testgain_init\n", .{});
    return cs.OK;
}

fn testgain_perf(csoundptr: [*c]cs.CSOUND, p0: ?*anyopaque) callconv(.C) c_int {
    _ = &csoundptr[0];
    const p: *TestGain = @ptrCast(@alignCast(p0));
    const nsmps = cs.GetLocalKsmps(&p.h);
    var i: u32 = 0;
    var out: [*]f64 = p.*.out;
    const in: [*]f64 = p.*.in;
    const gain: f64 = p.*.kgain.*;
    while (i <= nsmps) : (i += 1) {
        out[i] = in[i] * gain;
    }
    return cs.OK;
}

const localops7: []const cs.OENTRY = &.{
    .{.opname=@constCast("testgain"), .dsblksiz=@sizeOf(TestGain), .flags=0, .outypes=@constCast("a"), .intypes=@constCast("ak"), .init=&testgain_init, .perf=&testgain_perf}
};

export fn csound_opcode_init(csound: *cs.CSOUND, ep: *[*]cs.OENTRY) i64 {
    _ = csound;
    ep.* = @constCast(localops7.ptr);
    return @sizeOf(cs.OENTRY) * localops7.len;
}

export fn csoundModuleInfo() i32 {
    const version = ((cs.CS_VERSION << 16) + (cs.CS_SUBVER << 8) + @sizeOf(cs.MYFLT));
    // std.debug.print("testgain - module info. version: {}\n", .{version});
    return version;
}

Saved to a file "testplugin.zig", it can be compiled with "zig build-lib -dynamic -lc -I/usr/local/include testplugin.zig", the folders need to be adapted to the local system.

cheers,
Eduardo
Csound mailing list Csound@listserv.heanet.ie https://listserv.heanet.ie/cgi-bin/wa?A0=CSOUND Send bugs reports to https://github.com/csound/csound/issues Discussions of bugs and features can be posted here
Csound mailing list Csound@listserv.heanet.ie https://listserv.heanet.ie/cgi-bin/wa?A0=CSOUND Send bugs reports to https://github.com/csound/csound/issues Discussions of bugs and features can be posted here

Date2025-02-14 15:42
FromSteven Yi
SubjectRe: [Csnd] Template for plugins in zig
Fantastic, thanks for sharing this! I've also been curious about zig and plugins but haven't had a chance to try it out. Looking forward to experimenting with this!

On Fri, Feb 14, 2025 at 7:58 AM Eduardo Moguillansky <eduardo.moguillansky@gmail.com> wrote:
For anyone interested in experimenting with building csound plugins in zig, here is an example plugin. One interesting aspect is that zig can cross compile to any platform so from one local build it is possible to produce binaries for many platforms.

const std = @import("std");

const cs = @cImport({
    @cInclude("csound/csdl.h");
});

const TestGain = extern struct {
    h: cs.OPDS,
    out: [*]f64,
    in: [*]f64,
    kgain: *f64
};

fn testgain_init(csoundptr: [*c]cs.CSOUND, p: ?*anyopaque) callconv(.C) c_int {
    _ = csoundptr;
    _ = p;
    // std.debug.print("testgain_init\n", .{});
    return cs.OK;
}

fn testgain_perf(csoundptr: [*c]cs.CSOUND, p0: ?*anyopaque) callconv(.C) c_int {
    _ = &csoundptr[0];
    const p: *TestGain = @ptrCast(@alignCast(p0));
    const nsmps = cs.GetLocalKsmps(&p.h);
    var i: u32 = 0;
    var out: [*]f64 = p.*.out;
    const in: [*]f64 = p.*.in;
    const gain: f64 = p.*.kgain.*;
    while (i <= nsmps) : (i += 1) {
        out[i] = in[i] * gain;
    }
    return cs.OK;
}

const localops7: []const cs.OENTRY = &.{
    .{.opname=@constCast("testgain"), .dsblksiz=@sizeOf(TestGain), .flags=0, .outypes=@constCast("a"), .intypes=@constCast("ak"), .init=&testgain_init, .perf=&testgain_perf}
};

export fn csound_opcode_init(csound: *cs.CSOUND, ep: *[*]cs.OENTRY) i64 {
    _ = csound;
    ep.* = @constCast(localops7.ptr);
    return @sizeOf(cs.OENTRY) * localops7.len;
}

export fn csoundModuleInfo() i32 {
    const version = ((cs.CS_VERSION << 16) + (cs.CS_SUBVER << 8) + @sizeOf(cs.MYFLT));
    // std.debug.print("testgain - module info. version: {}\n", .{version});
    return version;
}

Saved to a file "testplugin.zig", it can be compiled with "zig build-lib -dynamic -lc -I/usr/local/include testplugin.zig", the folders need to be adapted to the local system.

cheers,
Eduardo
Csound mailing list Csound@listserv.heanet.ie https://listserv.heanet.ie/cgi-bin/wa?A0=CSOUND Send bugs reports to https://github.com/csound/csound/issues Discussions of bugs and features can be posted here
Csound mailing list Csound@listserv.heanet.ie https://listserv.heanet.ie/cgi-bin/wa?A0=CSOUND Send bugs reports to https://github.com/csound/csound/issues Discussions of bugs and features can be posted here

Date2025-02-14 16:27
FromCian
SubjectRe: [Csnd] Template for plugins in zig
Well now I know what I will be doing this weekend. Thank you!

For anyone who hasn't dipped their toes into Zig yet, this is a pretty good (free) introductory book:
https://pedropark99.github.io/zig-book/

On Fri, Feb 14, 2025 at 10:46 AM Steven Yi <stevenyi@gmail.com> wrote:
Fantastic, thanks for sharing this! I've also been curious about zig and plugins but haven't had a chance to try it out. Looking forward to experimenting with this!

On Fri, Feb 14, 2025 at 7:58 AM Eduardo Moguillansky <eduardo.moguillansky@gmail.com> wrote:
For anyone interested in experimenting with building csound plugins in zig, here is an example plugin. One interesting aspect is that zig can cross compile to any platform so from one local build it is possible to produce binaries for many platforms.

const std = @import("std");

const cs = @cImport({
    @cInclude("csound/csdl.h");
});

const TestGain = extern struct {
    h: cs.OPDS,
    out: [*]f64,
    in: [*]f64,
    kgain: *f64
};

fn testgain_init(csoundptr: [*c]cs.CSOUND, p: ?*anyopaque) callconv(.C) c_int {
    _ = csoundptr;
    _ = p;
    // std.debug.print("testgain_init\n", .{});
    return cs.OK;
}

fn testgain_perf(csoundptr: [*c]cs.CSOUND, p0: ?*anyopaque) callconv(.C) c_int {
    _ = &csoundptr[0];
    const p: *TestGain = @ptrCast(@alignCast(p0));
    const nsmps = cs.GetLocalKsmps(&p.h);
    var i: u32 = 0;
    var out: [*]f64 = p.*.out;
    const in: [*]f64 = p.*.in;
    const gain: f64 = p.*.kgain.*;
    while (i <= nsmps) : (i += 1) {
        out[i] = in[i] * gain;
    }
    return cs.OK;
}

const localops7: []const cs.OENTRY = &.{
    .{.opname=@constCast("testgain"), .dsblksiz=@sizeOf(TestGain), .flags=0, .outypes=@constCast("a"), .intypes=@constCast("ak"), .init=&testgain_init, .perf=&testgain_perf}
};

export fn csound_opcode_init(csound: *cs.CSOUND, ep: *[*]cs.OENTRY) i64 {
    _ = csound;
    ep.* = @constCast(localops7.ptr);
    return @sizeOf(cs.OENTRY) * localops7.len;
}

export fn csoundModuleInfo() i32 {
    const version = ((cs.CS_VERSION << 16) + (cs.CS_SUBVER << 8) + @sizeOf(cs.MYFLT));
    // std.debug.print("testgain - module info. version: {}\n", .{version});
    return version;
}

Saved to a file "testplugin.zig", it can be compiled with "zig build-lib -dynamic -lc -I/usr/local/include testplugin.zig", the folders need to be adapted to the local system.

cheers,
Eduardo
Csound mailing list Csound@listserv.heanet.ie https://listserv.heanet.ie/cgi-bin/wa?A0=CSOUND Send bugs reports to https://github.com/csound/csound/issues Discussions of bugs and features can be posted here
Csound mailing list Csound@listserv.heanet.ie https://listserv.heanet.ie/cgi-bin/wa?A0=CSOUND Send bugs reports to https://github.com/csound/csound/issues Discussions of bugs and features can be posted here
Csound mailing list Csound@listserv.heanet.ie https://listserv.heanet.ie/cgi-bin/wa?A0=CSOUND Send bugs reports to https://github.com/csound/csound/issues Discussions of bugs and features can be posted here