csound / ctcsound

Python Bindings for Csound using ctypes. Can be used from python2.x and python3.x as well.
GNU Lesser General Public License v2.1
67 stars 10 forks source link

In case there's interest, I'm developing a cython csound wrapper: cycsound #25

Open shakfu opened 3 months ago

shakfu commented 3 months ago

Hi, In case this is useful somehow, I started work on a cython wrapper for the csound.h api a little while ago called cycsound.

It's still early stage, but so far it wraps a small subset of the api with audio output. It compiles (dynamic linking) on macOS, windows, and linux, with full static linking on macOS, which means it can currently generate a self-contained 2MB python wheel for macOS (which was my initial driver to start this project).

Reading the excellent ctcsound.py source has been enormously helpful and I've been using it as a development guide.

I'll keep chipping away... it helps me to learn csound, but any feedback would be welcome (-:

fggp commented 3 months ago

Beware that in Csound7 (probably released in next September) the host API will be redefined. Maybe you should wait for this new API before going on.

François

Le sam. 22 juin 2024 à 23:32, Shakeeb Alireza @.***> a écrit :

Hi, In case this is useful somehow, I started work on a cython wrapper for the csound.h api a little while ago called cycsound https://github.com/shakfu/cycsound.

It's still early stage, but so far it wraps a small subset of the api with audio output. It compiles (dynamic linking) on macOS, windows, and linux, with full static linking on macOS, which means it can currently generate a self-contained 2MB python wheel for macOS (which was my initial driver to start this project).

Reading the excellent ctcsound.py source has been enormously helpful and I've been using it as a development guide.

I'll keep chipping away... it helps me to learn csound, but any feedback would be welcome (-:

— Reply to this email directly, view it on GitHub https://github.com/csound/ctcsound/issues/25, or unsubscribe https://github.com/notifications/unsubscribe-auth/ABNOAKN5SIX7YSYRUIUZHA3ZIXUPNAVCNFSM6AAAAABJXXYIEOVHI2DSMVQWIX3LMV43ASLTON2WKOZSGM3DQMBTGIYTCMY . You are receiving this because you are subscribed to this thread.Message ID: @.***>

shakfu commented 3 months ago

@fggp Thanks for the heads up...

I'll keep an eye out for changes in the api...

shakfu commented 3 months ago

@fggp It's not clear to me where changes in the api are occurring. Is there some branch somewhere where this is happening?

fggp commented 3 months ago

There's a new branch: feature/newapi. In its include directory the file csound_new.h is the starting place for defining the new API.

François

Le mar. 25 juin 2024, 04:16, Shakeeb Alireza @.***> a écrit :

@fggp https://github.com/fggp It's not clear to me where changes in the api are occurring. Is there some branch somewhere where this is happening?

— Reply to this email directly, view it on GitHub https://github.com/csound/ctcsound/issues/25#issuecomment-2187820334, or unsubscribe https://github.com/notifications/unsubscribe-auth/ABNOAKKR72ICPK5XR23RBPLZJDHGXAVCNFSM6AAAAABJXXYIEOVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDCOBXHAZDAMZTGQ . You are receiving this because you were mentioned.Message ID: @.***>

shakfu commented 3 months ago

@fggp Thanks for the info about the new api. Will check it out. 👍

shakfu commented 3 months ago

@fggp The new api is a lot shorter than the old one:

#ifndef CSOUND_H
#define CSOUND_H

//Instantiation
PUBLIC int  csoundInitialize (int flags)
PUBLIC CSOUND*  csoundCreate (void *hostData) 
PUBLIC void     csoundDestroy (CSOUND *) 

// Performance
// One compilation function that does everything
// For example, we could potentially use "argc" as a code
// > 0 - argc/argv as main() command-line parameters
// 0 - start csound as a daemon with no code, ignore argv
// -1 - argv[0] is an orchestra string (csoundCompileStr)
// -2 - argv[0] is a complete csound   (csoundCompileCsdText)
// First call to csoundCompile() also starts Csound so we remove csoundStart()
// async defines async operation
// NB - interface with double pointers may not be ideal for non C/C++
PUBLIC int  csoundCompile (CSOUND *, int argc, const char **argv, int async);
PUBLIC int  csoundPerformKsmps (CSOUND *);

// Realtime Audio
// this is now effectively -n since there is no access to buffer, only to spin.
// we need a better name I think
PUBLIC void csoundSetHostImplementedAudioIO(CSOUND *, int state);
// access to spin/spout (no need to give individual sample access)
PUBLIC MYFLT *csoundGetSpin (CSOUND *);
PUBLIC MYFLT *csoundGetSpout (CSOUND *csound);

// no audio IO callbacks - that's only available in the module API now.
// MIDI callbacks can be set with a single new function
typedef struct {
  int(*open)(CSOUND *, void **userData, const char *devName, int mode); // MIDI open callback (mode=CS_MIDI_IN, CS_MIDI_OUT)
  int(*read)(CSOUND *, void *userData, unsigned char *buf, int nBytes);
  int(*write)(CSOUND *, void *userData, unsigned char *buf, int nBytes);
  int(*close)(CSOUND *, void *userData);
} CS_MIDI_CALLBACKS;
PUBLIC void csoundSetMIDICallbacks(CSOUND *, CS_MIDI_CALLBACKS *);

// Messages
PUBLIC void        csoundCreateMessageBuffer (CSOUND *csound, int toStdOut)
PUBLIC const char *csoundGetFirstMessage (CSOUND *csound)
PUBLIC void        csoundPopFirstMessage (CSOUND *csound)
PUBLIC int         csoundGetMessageCnt (CSOUND *csound)
void PUBLIC        csoundDestroyMessageBuffer (CSOUND *csound)

// Channels
PUBLIC int csoundListChannels(CSOUND *, controlChannelInfo_t **lst);
PUBLIC void csoundDeleteChannelList(CSOUND *, controlChannelInfo_t *lst);
// basic types
PUBLIC MYFLT csoundGetControlChannel(CSOUND *csound, const char *name, int *err);
PUBLIC void csoundSetControlChannel(CSOUND *csound, const char *name, MYFLT val);
PUBLIC void csoundGetAudioChannel(CSOUND *csound, const char *name, MYFLT *samples);
PUBLIC void csoundSetAudioChannel(CSOUND *csound, const char *name, MYFLT *samples);
PUBLIC void csoundGetStringChannel(CSOUND *csound, const char *name, char *string);
PUBLIC  void csoundSetStringChannel(CSOUND *csound, const char *name, char *string);
// generic data access (e.g. for other types, structs, etc)
PUBLIC int csoundGetChannelPtr(CSOUND *, MYFLT **p, const char *name, int type);
PUBLIC int csoundGetChannelDatasize(CSOUND *csound, const char *name);

// events:
// async selects asynchronous operation
// new function - replaces csoundInputMessage
PUBLIC void  csoundEventString (CSOUND *, const char *message, int async);
// new function - replaces csoundScoreEvent
// type 0 - instrument instance     CS_INSTR_EVENT
// type 1 - functiob table instance CS_TABLE_EVENT
PUBLIC void  csoundEvent (CSOUND *, int type, MYFLT *params, int async);

//Tables
PUBLIC int  csoundTableLength (CSOUND *, int table);
PUBLIC void csoundTableCopyIn (CSOUND *csound, int table, MYFLT *src);
PUBLIC void csoundTableCopyOut (CSOUND *csound, int table, MYFLT *dest);

//Opcodes - adapted for new internals
PUBLIC int  csoundAppendOpcode (CSOUND *, const char *opname, int dsblksiz, int flags,
                                    const char *outypes, const char *intypes, int(*init)(CSOUND *, void *),
                                    int(*perf)(CSOUND *, void *), int(*deinit)(CSOUND *, void *));

//Threading and concurrency

#endif  /* CSOUND_H */
fggp commented 3 months ago

It's just a draft starting point. We're working on it. In the attachment you can read some proposals. Any suggestions are welcome.

François

Le ven. 28 juin 2024 à 16:28, Shakeeb Alireza @.***> a écrit :

@fggp https://github.com/fggp The new api is a lot shorter than the old one:

ifndef CSOUND_H#define CSOUND_H

//InstantiationPUBLIC int csoundInitialize (int flags)PUBLIC CSOUND csoundCreate (void hostData) PUBLIC void csoundDestroy (CSOUND ) // Performance// One compilation function that does everything// For example, we could potentially use "argc" as a code// > 0 - argc/argv as main() command-line parameters// 0 - start csound as a daemon with no code, ignore argv// -1 - argv[0] is an orchestra string (csoundCompileStr)// -2 - argv[0] is a complete csound (csoundCompileCsdText)// First call to csoundCompile() also starts Csound so we remove csoundStart()// async defines async operation// NB - interface with double pointers may not be ideal for non C/C++PUBLIC int csoundCompile (CSOUND , int argc, const char argv, int async);PUBLIC int csoundPerformKsmps (CSOUND ); // Realtime Audio// this is now effectively -n since there is no access to buffer, only to spin.// we need a better name I thinkPUBLIC void csoundSetHostImplementedAudioIO(CSOUND , int state);// access to spin/spout (no need to give individual sample access)PUBLIC MYFLT csoundGetSpin (CSOUND );PUBLIC MYFLT csoundGetSpout (CSOUND csound); // no audio IO callbacks - that's only available in the module API now.// MIDI callbacks can be set with a single new functiontypedef struct { int(open)(CSOUND , void userData, const char devName, int mode); // MIDI open callback (mode=CS_MIDI_IN, CS_MIDI_OUT) int(read)(CSOUND , void userData, unsigned char buf, int nBytes); int(write)(CSOUND , void userData, unsigned char buf, int nBytes); int(close)(CSOUND , void userData); } CS_MIDI_CALLBACKS;PUBLIC void csoundSetMIDICallbacks(CSOUND , CS_MIDI_CALLBACKS ); // MessagesPUBLIC void csoundCreateMessageBuffer (CSOUND csound, int toStdOut)PUBLIC const char csoundGetFirstMessage (CSOUND csound)PUBLIC void csoundPopFirstMessage (CSOUND csound)PUBLIC int csoundGetMessageCnt (CSOUND csound)void PUBLIC csoundDestroyMessageBuffer (CSOUND csound) // ChannelsPUBLIC int csoundListChannels(CSOUND *, controlChannelInfo_t lst);PUBLIC void csoundDeleteChannelList(CSOUND , controlChannelInfo_t lst);// basic typesPUBLIC MYFLT csoundGetControlChannel(CSOUND csound, const char name, int err);PUBLIC void csoundSetControlChannel(CSOUND csound, const char name, MYFLT val);PUBLIC void csoundGetAudioChannel(CSOUND csound, const char name, MYFLT samples);PUBLIC void csoundSetAudioChannel(CSOUND csound, const char name, MYFLT samples);PUBLIC void csoundGetStringChannel(CSOUND csound, const char name, char string);PUBLIC void csoundSetStringChannel(CSOUND csound, const char name, char string);// generic data access (e.g. for other types, structs, etc)PUBLIC int csoundGetChannelPtr(CSOUND , MYFLT p, const char name, int type);PUBLIC int csoundGetChannelDatasize(CSOUND csound, const char name); // events:// async selects asynchronous operation// new function - replaces csoundInputMessagePUBLIC void csoundEventString (CSOUND , const char message, int async);// new function - replaces csoundScoreEvent// type 0 - instrument instance CS_INSTR_EVENT// type 1 - functiob table instance CS_TABLE_EVENTPUBLIC void csoundEvent (CSOUND , int type, MYFLT params, int async); //TablesPUBLIC int csoundTableLength (CSOUND , int table);PUBLIC void csoundTableCopyIn (CSOUND csound, int table, MYFLT src);PUBLIC void csoundTableCopyOut (CSOUND csound, int table, MYFLT dest); //Opcodes - adapted for new internalsPUBLIC int csoundAppendOpcode (CSOUND , const char opname, int dsblksiz, int flags, const char outypes, const char intypes, int(init)(CSOUND , void ), int(perf)(CSOUND , void ), int(deinit)(CSOUND , void *)); //Threading and concurrency

endif / CSOUND_H /

— Reply to this email directly, view it on GitHub https://github.com/csound/ctcsound/issues/25#issuecomment-2197071412, or unsubscribe https://github.com/notifications/unsubscribe-auth/ABNOAKIX6EZW64PEVH2IZS3ZJVXHBAVCNFSM6AAAAABJXXYIEOVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDCOJXGA3TCNBRGI . You are receiving this because you were mentioned.Message ID: @.***>

shakfu commented 3 months ago

@fggp wrote

In the attachment you can read some proposals.

I'm sorry but I did not see any attachment.

fggp commented 3 months ago

Maybe it's been automatically removed by the list reception? Anyway the conclusion summaries the main ideas:

"In summary one should develop a new host API. This API should be simpler with less granularity when possible and mainly based on C functions using an opaque pointer as first argument to mimic an Object Oriented paradigm. Direct memory access through pointers and length information should be used for buffers, tables, arrays, fsigs and other similar types, with care about memory management. State information struct should be accessed through getter and setter functions. No variadic functions and try to avoid callbacks when possible. Thread and concurrency mechanisms should be treated apart. Complex displays and graphics should be left to third party programs, the host API transmitting raw data."

François

Le dim. 30 juin 2024 à 05:54, Shakeeb Alireza @.***> a écrit :

@fggp https://github.com/fggp wrote

In the attachment you can read some proposals.

I'm sorry but I did not see any attachment.

— Reply to this email directly, view it on GitHub https://github.com/csound/ctcsound/issues/25#issuecomment-2198423744, or unsubscribe https://github.com/notifications/unsubscribe-auth/ABNOAKOBGAEJAXNKVCDKFYLZJ56OLAVCNFSM6AAAAABJXXYIEOVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDCOJYGQZDGNZUGQ . You are receiving this because you were mentioned.Message ID: @.***>

shakfu commented 3 months ago

Thanks for the summary. I completely agree with its contents.

This is good news since it looks like the csound7 api is really mostly a subset of the csound6 api.

I might as well continue my earlier work then.