1# 2# ctcsound.py: 3# 4# Copyright (C) 2016 Francois Pinot 5# 6# This file is part of Csound. 7# 8# This code is free software; you can redistribute it 9# and/or modify it under the terms of the GNU Lesser General Public 10# License as published by the Free Software Foundation; either 11# version 2.1 of the License, or (at your option) any later version. 12# 13# Csound is distributed in the hope that it will be useful, 14# but WITHOUT ANY WARRANTY; without even the implied warranty of 15# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16# GNU Lesser General Public License for more details. 17# 18# You should have received a copy of the GNU Lesser General Public 19# License along with Csound; if not, write to the Free Software 20# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 21# 02110-1301 USA 22# 23 24import ctypes as ct 25import numpy as np 26import sys 27 28# This is a workaround to yield the PEP 3118 problem which appeared with 29# numpy 1.15.0 30if np.__version__ < '1.15': 31 arrFromPointer = lambda p : np.ctypeslib.as_array(p) 32elif np.__version__ < '1.16': 33 sys.exit("ctcsound won't work with numpy 1.15.x. Please revert numpy" + 34 " to an older version or update numpy to a version >= 1.16") 35else: 36 arrFromPointer = lambda p : p.contents 37 38if sys.platform.startswith('linux'): 39 libcsound = ct.CDLL("libcsound64.so") 40elif sys.platform.startswith('win'): 41 if sys.version_info.major <=3 and sys.version_info.minor < 8: 42 libcsound = ct.cdll.csound64 43 else: 44 import ctypes.util 45 libcsound = ct.CDLL(ctypes.util.find_library("csound64")) 46elif sys.platform.startswith('darwin'): 47 libcsound = ct.CDLL("CsoundLib64.framework/CsoundLib64") 48else: 49 sys.exit("Don't know your system! Exiting...") 50 51MYFLT = ct.c_double 52 53class CsoundParams(ct.Structure): 54 _fields_ = [("debug_mode", ct.c_int), # debug mode, 0 or 1 55 ("buffer_frames", ct.c_int), # number of frames in in/out buffers 56 ("hardware_buffer_frames", ct.c_int), # ibid. hardware 57 ("displays", ct.c_int), # graph displays, 0 or 1 58 ("ascii_graphs", ct.c_int), # use ASCII graphs, 0 or 1 59 ("postscript_graphs", ct.c_int), # use postscript graphs, 0 or 1 60 ("message_level", ct.c_int), # message printout control 61 ("tempo", ct.c_int), # tempo ("sets Beatmode) 62 ("ring_bell", ct.c_int), # bell, 0 or 1 63 ("use_cscore", ct.c_int), # use cscore for processing 64 ("terminate_on_midi", ct.c_int), # terminate performance at the end 65 # of midifile, 0 or 1 66 ("heartbeat", ct.c_int), # print heart beat, 0 or 1 67 ("defer_gen01_load", ct.c_int), # defer GEN01 load, 0 or 1 68 ("midi_key", ct.c_int), # pfield to map midi key no 69 ("midi_key_cps", ct.c_int), # pfield to map midi key no as cps 70 ("midi_key_oct", ct.c_int), # pfield to map midi key no as oct 71 ("midi_key_pch", ct.c_int), # pfield to map midi key no as pch 72 ("midi_velocity", ct.c_int), # pfield to map midi velocity 73 ("midi_velocity_amp", ct.c_int), # pfield to map midi velocity as amplitude 74 ("no_default_paths", ct.c_int), # disable relative paths from files, 0 or 1 75 ("number_of_threads", ct.c_int), # number of threads for multicore performance 76 ("syntax_check_only", ct.c_int), # do not compile, only check syntax 77 ("csd_line_counts", ct.c_int), # csd line error reporting 78 ("compute_weights", ct.c_int), # deprecated, kept for backwards comp. 79 ("realtime_mode", ct.c_int), # use realtime priority mode, 0 or 1 80 ("sample_accurate", ct.c_int), # use sample-level score event accuracy 81 ("sample_rate_override", MYFLT), # overriding sample rate 82 ("control_rate_override", MYFLT), # overriding control rate 83 ("nchnls_override", ct.c_int), # overriding number of out channels 84 ("nchnls_i_override", ct.c_int), # overriding number of in channels 85 ("e0dbfs_override", MYFLT), # overriding 0dbfs 86 ("daemon", ct.c_int), # daemon mode 87 ("ksmps_override", ct.c_int), # ksmps override 88 ("FFT_library", ct.c_int)] # fft_lib 89 90string64 = ct.c_char * 64 91 92class CsoundAudioDevice(ct.Structure): 93 _fields_ = [("device_name", string64), 94 ("device_id", string64), 95 ("rt_module", string64), 96 ("max_nchnls", ct.c_int), 97 ("isOutput", ct.c_int)] 98 99class CsoundMidiDevice(ct.Structure): 100 _fields_ = [("device_name", string64), 101 ("interface_name", string64), 102 ("device_id", string64), 103 ("midi_module", string64), 104 ("isOutput", ct.c_int)] 105 106class CsoundRtAudioParams(ct.Structure): 107 _fields_ = [("devName", ct.c_char_p), # device name (NULL/empty: default) 108 ("devNum", ct.c_int), # device number (0-1023), 1024: default 109 ("bufSamp_SW", ct.c_uint), # buffer fragment size (-b) in sample frames 110 ("bufSamp_HW", ct.c_int), # total buffer size (-B) in sample frames 111 ("nChannels", ct.c_int), # number of channels 112 ("sampleFormat", ct.c_int), # sample format (AE_SHORT etc.) 113 ("sampleRate", ct.c_float)] # sample rate in Hz 114 115class RtClock(ct.Structure): 116 _fields_ = [("starttime_real", ct.c_int64), 117 ("starttime_CPU", ct.c_int64)] 118 119class OpcodeListEntry(ct.Structure): 120 _fields_ = [("opname", ct.c_char_p), 121 ("outypes", ct.c_char_p), 122 ("intypes", ct.c_char_p), 123 ("flags", ct.c_int)] 124 125class CsoundRandMTState(ct.Structure): 126 _fields_ = [("mti", ct.c_int), 127 ("mt", ct.c_uint32*624)] 128 129# PVSDATEXT is a variation on PVSDAT used in the pvs bus interface 130class PvsdatExt(ct.Structure): 131 _fields_ = [("N", ct.c_int32), 132 ("sliding", ct.c_int), # Flag to indicate sliding case 133 ("NB", ct.c_int32), 134 ("overlap", ct.c_int32), 135 ("winsize", ct.c_int32), 136 ("wintype", ct.c_int), 137 ("format", ct.c_int32), 138 ("framecount", ct.c_uint32), 139 ("frame", ct.POINTER(ct.c_float))] 140 141# This structure holds the parameter hints for control channels 142class ControlChannelHints(ct.Structure): 143 _fields_ = [("behav", ct.c_int), 144 ("dflt", MYFLT), 145 ("min", MYFLT), 146 ("max", MYFLT), 147 ("x", ct.c_int), 148 ("y", ct.c_int), 149 ("width", ct.c_int), 150 ("height", ct.c_int), 151 # This member must be set explicitly to None if not used 152 ("attributes", ct.c_char_p)] 153 154class ControlChannelInfo(ct.Structure): 155 _fields_ = [("name", ct.c_char_p), 156 ("type", ct.c_int), 157 ("hints", ControlChannelHints)] 158 159CAPSIZE = 60 160 161class Windat(ct.Structure): 162 _fields_ = [("windid", ct.POINTER(ct.c_uint)), # set by makeGraph() 163 ("fdata", ct.POINTER(MYFLT)), # data passed to drawGraph() 164 ("npts", ct.c_int32), # size of above array 165 ("caption", ct.c_char * CAPSIZE), # caption string for graph 166 ("waitflg", ct.c_int16 ), # set =1 to wait for ms after Draw 167 ("polarity", ct.c_int16), # controls positioning of X axis 168 ("max", MYFLT), # workspace .. extrema this frame 169 ("min", MYFLT), 170 ("absmax", MYFLT), # workspace .. largest of above 171 ("oabsmax", MYFLT), # Y axis scaling factor 172 ("danflag", ct.c_int), # set to 1 for extra Yaxis mid span 173 ("absflag", ct.c_int)] # set to 1 to skip abs check 174 175# Symbols for Windat.polarity field 176NOPOL = 0 177NEGPOL = 1 178POSPOL = 2 179BIPOL = 3 180 181class NamedGen(ct.Structure): 182 pass 183 184NamedGen._fields_ = [ 185 ("name", ct.c_char_p), 186 ("genum", ct.c_int), 187 ("next", ct.POINTER(NamedGen))] 188 189 190libcsound.csoundSetOpcodedir.argtypes = [ct.c_char_p] 191libcsound.csoundCreate.restype = ct.c_void_p 192libcsound.csoundCreate.argtypes = [ct.py_object] 193libcsound.csoundLoadPlugins.argtypes = [ct.c_void_p, ct.c_char_p] 194libcsound.csoundDestroy.argtypes = [ct.c_void_p] 195 196libcsound.csoundParseOrc.restype = ct.c_void_p 197libcsound.csoundParseOrc.argtypes = [ct.c_void_p, ct.c_char_p] 198 199libcsound.csoundCompileTree.argtypes = [ct.c_void_p, ct.c_void_p] 200libcsound.csoundCompileTreeAsync.argtypes = [ct.c_void_p, ct.c_void_p] 201libcsound.csoundDeleteTree.argtypes = [ct.c_void_p, ct.c_void_p] 202libcsound.csoundCompileOrc.argtypes = [ct.c_void_p, ct.c_char_p] 203libcsound.csoundCompileOrcAsync.argtypes = [ct.c_void_p, ct.c_char_p] 204 205libcsound.csoundEvalCode.restype = MYFLT 206libcsound.csoundEvalCode.argtypes = [ct.c_void_p, ct.c_char_p] 207 208libcsound.csoundCompileArgs.argtypes = [ct.c_void_p, ct.c_int, ct.POINTER(ct.c_char_p)] 209libcsound.csoundStart.argtypes = [ct.c_void_p] 210libcsound.csoundCompile.argtypes = [ct.c_void_p, ct.c_int, ct.POINTER(ct.c_char_p)] 211libcsound.csoundCompileCsd.argtypes = [ct.c_void_p, ct.c_char_p] 212libcsound.csoundCompileCsdText.argtypes = [ct.c_void_p, ct.c_char_p] 213 214libcsound.csoundPerform.argtypes = [ct.c_void_p] 215libcsound.csoundPerformKsmps.argtypes = [ct.c_void_p] 216libcsound.csoundPerformBuffer.argtypes = [ct.c_void_p] 217libcsound.csoundStop.argtypes = [ct.c_void_p] 218libcsound.csoundCleanup.argtypes = [ct.c_void_p] 219libcsound.csoundReset.argtypes = [ct.c_void_p] 220 221libcsound.csoundUDPServerStart.argtypes = [ct.c_void_p, ct.c_uint] 222libcsound.csoundUDPServerStatus.argtypes = [ct.c_void_p] 223libcsound.csoundUDPServerClose.argtypes = [ct.c_void_p] 224libcsound.csoundUDPConsole.argtypes = [ct.c_void_p, ct.c_char_p, ct.c_uint, ct.c_uint] 225libcsound.csoundStopUDPConsole.argtypes = [ct.c_void_p] 226 227libcsound.csoundGetSr.restype = MYFLT 228libcsound.csoundGetSr.argtypes = [ct.c_void_p] 229libcsound.csoundGetKr.restype = MYFLT 230libcsound.csoundGetKr.argtypes = [ct.c_void_p] 231libcsound.csoundGetKsmps.restype = ct.c_uint32 232libcsound.csoundGetKsmps.argtypes = [ct.c_void_p] 233libcsound.csoundGetNchnls.restype = ct.c_uint32 234libcsound.csoundGetNchnls.argtypes = [ct.c_void_p] 235libcsound.csoundGetNchnlsInput.restype = ct.c_uint32 236libcsound.csoundGetNchnlsInput.argtypes = [ct.c_void_p] 237libcsound.csoundGet0dBFS.restype = MYFLT 238libcsound.csoundGet0dBFS.argtypes = [ct.c_void_p] 239libcsound.csoundGetA4.restype = MYFLT 240libcsound.csoundGetA4.argtypes = [ct.c_void_p] 241libcsound.csoundGetCurrentTimeSamples.restype = ct.c_int64 242libcsound.csoundGetCurrentTimeSamples.argtypes = [ct.c_void_p] 243libcsound.csoundGetHostData.restype = ct.py_object 244libcsound.csoundGetHostData.argtypes = [ct.c_void_p] 245libcsound.csoundSetHostData.argtypes = [ct.c_void_p, ct.py_object] 246libcsound.csoundSetOption.argtypes = [ct.c_void_p, ct.c_char_p] 247libcsound.csoundSetParams.argtypes = [ct.c_void_p, ct.POINTER(CsoundParams)] 248libcsound.csoundGetParams.argtypes = [ct.c_void_p, ct.POINTER(CsoundParams)] 249libcsound.csoundGetDebug.argtypes = [ct.c_void_p] 250libcsound.csoundSetDebug.argtypes = [ct.c_void_p, ct.c_int] 251libcsound.csoundSystemSr.restype = MYFLT 252libcsound.csoundSystemSr.argtypes = [ct.c_void_p, MYFLT] 253 254libcsound.csoundGetOutputName.restype = ct.c_char_p 255libcsound.csoundGetOutputName.argtypes = [ct.c_void_p] 256libcsound.csoundGetInputName.restype = ct.c_char_p 257libcsound.csoundGetInputName.argtypes = [ct.c_void_p] 258libcsound.csoundSetOutput.argtypes = [ct.c_void_p, ct.c_char_p, ct.c_char_p, ct.c_char_p] 259libcsound.csoundGetOutputFormat.argtypes = [ct.c_void_p, ct.c_char_p, ct.c_char_p] 260libcsound.csoundSetInput.argtypes = [ct.c_void_p, ct.c_char_p] 261libcsound.csoundSetMIDIInput.argtypes = [ct.c_void_p, ct.c_char_p] 262libcsound.csoundSetMIDIFileInput.argtypes = [ct.c_void_p, ct.c_char_p] 263libcsound.csoundSetMIDIOutput.argtypes = [ct.c_void_p, ct.c_char_p] 264libcsound.csoundSetMIDIFileOutput.argtypes = [ct.c_void_p, ct.c_char_p] 265FILEOPENFUNC = ct.CFUNCTYPE(None, ct.c_void_p, ct.c_char_p, ct.c_int, ct.c_int, ct.c_int) 266libcsound.csoundSetFileOpenCallback.argtypes = [ct.c_void_p, FILEOPENFUNC] 267 268libcsound.csoundSetRTAudioModule.argtypes = [ct.c_void_p, ct.c_char_p] 269libcsound.csoundGetModule.argtypes = [ct.c_void_p, ct.c_int, ct.POINTER(ct.c_char_p), ct.POINTER(ct.c_char_p)] 270libcsound.csoundGetInputBufferSize.restype = ct.c_long 271libcsound.csoundGetInputBufferSize.argtypes = [ct.c_void_p] 272libcsound.csoundGetOutputBufferSize.restype = ct.c_long 273libcsound.csoundGetOutputBufferSize.argtypes = [ct.c_void_p] 274libcsound.csoundGetInputBuffer.restype = ct.POINTER(MYFLT) 275libcsound.csoundGetInputBuffer.argtypes = [ct.c_void_p] 276libcsound.csoundGetOutputBuffer.restype = ct.POINTER(MYFLT) 277libcsound.csoundGetOutputBuffer.argtypes = [ct.c_void_p] 278libcsound.csoundGetSpin.restype = ct.POINTER(MYFLT) 279libcsound.csoundGetSpin.argtypes = [ct.c_void_p] 280libcsound.csoundClearSpin.argtypes = [ct.c_void_p] 281libcsound.csoundAddSpinSample.argtypes = [ct.c_void_p, ct.c_int, ct.c_int, MYFLT] 282libcsound.csoundSetSpinSample.argtypes = [ct.c_void_p, ct.c_int, ct.c_int, MYFLT] 283libcsound.csoundGetSpout.restype = ct.POINTER(MYFLT) 284libcsound.csoundGetSpout.argtypes = [ct.c_void_p] 285libcsound.csoundGetSpoutSample.restype = MYFLT 286libcsound.csoundGetSpoutSample.argtypes = [ct.c_void_p, ct.c_int, ct.c_int] 287libcsound.csoundGetRtRecordUserData.restype = ct.POINTER(ct.c_void_p) 288libcsound.csoundGetRtRecordUserData.argtypes = [ct.c_void_p] 289libcsound.csoundGetRtPlayUserData.restype = ct.POINTER(ct.c_void_p) 290libcsound.csoundGetRtPlayUserData.argtypes = [ct.c_void_p] 291libcsound.csoundSetHostImplementedAudioIO.argtypes = [ct.c_void_p, ct.c_int, ct.c_int] 292libcsound.csoundGetAudioDevList.argtypes = [ct.c_void_p, ct.c_void_p, ct.c_int] 293PLAYOPENFUNC = ct.CFUNCTYPE(ct.c_int, ct.c_void_p, ct.POINTER(CsoundRtAudioParams)) 294libcsound.csoundSetPlayopenCallback.argtypes = [ct.c_void_p, PLAYOPENFUNC] 295RTPLAYFUNC = ct.CFUNCTYPE(None, ct.c_void_p, ct.POINTER(MYFLT), ct.c_int) 296libcsound.csoundSetRtplayCallback.argtypes = [ct.c_void_p, RTPLAYFUNC] 297RECORDOPENFUNC = ct.CFUNCTYPE(ct.c_int, ct.c_void_p, ct.POINTER(CsoundRtAudioParams)) 298libcsound.csoundSetRecopenCallback.argtypes = [ct.c_void_p, RECORDOPENFUNC] 299RTRECORDFUNC = ct.CFUNCTYPE(ct.c_int, ct.c_void_p, ct.POINTER(MYFLT), ct.c_int) 300libcsound.csoundSetRtrecordCallback.argtypes = [ct.c_void_p, RTRECORDFUNC] 301RTCLOSEFUNC = ct.CFUNCTYPE(None, ct.c_void_p) 302libcsound.csoundSetRtcloseCallback.argtypes = [ct.c_void_p, RTCLOSEFUNC] 303AUDIODEVLISTFUNC = ct.CFUNCTYPE(ct.c_int, ct.c_void_p, ct.POINTER(CsoundAudioDevice), ct.c_int) 304libcsound.csoundSetAudioDeviceListCallback.argtypes = [ct.c_void_p, AUDIODEVLISTFUNC] 305 306libcsound.csoundSetMIDIModule.argtypes = [ct.c_void_p, ct.c_char_p] 307libcsound.csoundSetHostImplementedMIDIIO.argtypes = [ct.c_void_p, ct.c_int] 308libcsound.csoundGetMIDIDevList.argtypes = [ct.c_void_p, ct.c_void_p, ct.c_int] 309MIDIINOPENFUNC = ct.CFUNCTYPE(ct.c_int, ct.c_void_p, ct.POINTER(ct.c_void_p), ct.c_char_p) 310libcsound.csoundSetExternalMidiInOpenCallback.argtypes = [ct.c_void_p, MIDIINOPENFUNC] 311MIDIREADFUNC = ct.CFUNCTYPE(ct.c_int, ct.c_void_p, ct.c_void_p, ct.c_char_p, ct.c_int) 312libcsound.csoundSetExternalMidiReadCallback.argtypes = [ct.c_void_p, MIDIREADFUNC] 313MIDIINCLOSEFUNC = ct.CFUNCTYPE(ct.c_int, ct.c_void_p, ct.c_void_p) 314libcsound.csoundSetExternalMidiInCloseCallback.argtypes = [ct.c_void_p, MIDIINCLOSEFUNC] 315MIDIOUTOPENFUNC = ct.CFUNCTYPE(ct.c_int, ct.c_void_p, ct.POINTER(ct.c_void_p), ct.c_char_p) 316libcsound.csoundSetExternalMidiOutOpenCallback.argtypes = [ct.c_void_p, MIDIOUTOPENFUNC] 317MIDIWRITEFUNC = ct.CFUNCTYPE(ct.c_int, ct.c_void_p, ct.c_void_p, ct.c_char_p, ct.c_int) 318libcsound.csoundSetExternalMidiWriteCallback.argtypes = [ct.c_void_p, MIDIWRITEFUNC] 319MIDIOUTCLOSEFUNC = ct.CFUNCTYPE(ct.c_int, ct.c_void_p, ct.c_void_p) 320libcsound.csoundSetExternalMidiOutCloseCallback.argtypes = [ct.c_void_p, MIDIOUTCLOSEFUNC] 321MIDIERRORFUNC = ct.CFUNCTYPE(ct.c_char_p, ct.c_int) 322libcsound.csoundSetExternalMidiErrorStringCallback.argtypes = [ct.c_void_p, MIDIERRORFUNC] 323MIDIDEVLISTFUNC = ct.CFUNCTYPE(ct.c_int, ct.c_void_p, ct.POINTER(CsoundMidiDevice), ct.c_int) 324libcsound.csoundSetMIDIDeviceListCallback.argtypes = [ct.c_void_p, MIDIDEVLISTFUNC] 325 326libcsound.csoundReadScore.argtypes = [ct.c_void_p, ct.c_char_p] 327libcsound.csoundReadScoreAsync.argtypes = [ct.c_void_p, ct.c_char_p] 328libcsound.csoundGetScoreTime.restype = ct.c_double 329libcsound.csoundGetScoreTime.argtypes = [ct.c_void_p] 330libcsound.csoundIsScorePending.argtypes = [ct.c_void_p] 331libcsound.csoundSetScorePending.argtypes = [ct.c_void_p, ct.c_int] 332libcsound.csoundGetScoreOffsetSeconds.restype = MYFLT 333libcsound.csoundGetScoreOffsetSeconds.argtypes = [ct.c_void_p] 334libcsound.csoundSetScoreOffsetSeconds.argtypes = [ct.c_void_p, MYFLT] 335libcsound.csoundRewindScore.argtypes = [ct.c_void_p] 336CSCOREFUNC = ct.CFUNCTYPE(None, ct.c_void_p) 337libcsound.csoundSetCscoreCallback.argtypes = [ct.c_void_p, CSCOREFUNC] 338 339libcsound.csoundMessage.argtypes = [ct.c_void_p, ct.c_char_p, ct.c_char_p] 340libcsound.csoundMessageS.argtypes = [ct.c_void_p, ct.c_int, ct.c_char_p, ct.c_char_p] 341libcsound.csoundGetMessageLevel.argtypes = [ct.c_void_p] 342libcsound.csoundSetMessageLevel.argtypes = [ct.c_void_p, ct.c_int] 343libcsound.csoundCreateMessageBuffer.argtypes = [ct.c_void_p, ct.c_int] 344libcsound.csoundGetFirstMessage.restype = ct.c_char_p 345libcsound.csoundGetFirstMessage.argtypes = [ct.c_void_p] 346libcsound.csoundGetFirstMessageAttr.argtypes = [ct.c_void_p] 347libcsound.csoundPopFirstMessage.argtypes = [ct.c_void_p] 348libcsound.csoundGetMessageCnt.argtypes = [ct.c_void_p] 349libcsound.csoundDestroyMessageBuffer.argtypes = [ct.c_void_p] 350 351libcsound.csoundGetChannelPtr.argtypes = [ct.c_void_p, ct.POINTER(ct.POINTER(MYFLT)), ct.c_char_p, ct.c_int] 352libcsound.csoundListChannels.argtypes = [ct.c_void_p, ct.POINTER(ct.POINTER(ControlChannelInfo))] 353libcsound.csoundDeleteChannelList.argtypes = [ct.c_void_p, ct.POINTER(ControlChannelInfo)] 354libcsound.csoundSetControlChannelHints.argtypes = [ct.c_void_p, ct.c_char_p, ControlChannelHints] 355libcsound.csoundGetControlChannelHints.argtypes = [ct.c_void_p, ct.c_char_p, ct.POINTER(ControlChannelHints)] 356libcsound.csoundGetChannelLock.restype = ct.POINTER(ct.c_int) 357libcsound.csoundGetChannelLock.argtypes = [ct.c_void_p, ct.c_char_p] 358libcsound.csoundGetControlChannel.restype = MYFLT 359libcsound.csoundGetControlChannel.argtypes = [ct.c_void_p, ct.c_char_p, ct.POINTER(ct.c_int)] 360libcsound.csoundSetControlChannel.argtypes = [ct.c_void_p, ct.c_char_p, MYFLT] 361libcsound.csoundGetAudioChannel.argtypes = [ct.c_void_p, ct.c_char_p, ct.POINTER(ct.c_int)] 362libcsound.csoundSetAudioChannel.argtypes = [ct.c_void_p, ct.c_char_p, ct.POINTER(ct.c_int)] 363libcsound.csoundGetStringChannel.argtypes = [ct.c_void_p, ct.c_char_p, ct.c_char_p] 364libcsound.csoundSetStringChannel.argtypes = [ct.c_void_p, ct.c_char_p, ct.c_char_p] 365libcsound.csoundGetChannelDatasize.argtypes = [ct.c_void_p, ct.c_char_p] 366CHANNELFUNC = ct.CFUNCTYPE(None, ct.c_void_p, ct.c_char_p, ct.c_void_p, ct.c_void_p) 367libcsound.csoundSetInputChannelCallback.argtypes = [ct.c_void_p, CHANNELFUNC] 368libcsound.csoundSetOutputChannelCallback.argtypes = [ct.c_void_p, CHANNELFUNC] 369libcsound.csoundSetPvsChannel.argtypes = [ct.c_void_p, ct.POINTER(PvsdatExt), ct.c_char_p] 370libcsound.csoundGetPvsChannel.argtypes = [ct.c_void_p, ct.POINTER(PvsdatExt), ct.c_char_p] 371libcsound.csoundScoreEvent.argtypes = [ct.c_void_p, ct.c_char, ct.POINTER(MYFLT), ct.c_long] 372libcsound.csoundScoreEventAsync.argtypes = [ct.c_void_p, ct.c_char, ct.POINTER(MYFLT), ct.c_long] 373libcsound.csoundScoreEventAbsolute.argtypes = [ct.c_void_p, ct.c_char, ct.POINTER(MYFLT), ct.c_long, ct.c_double] 374libcsound.csoundScoreEventAbsoluteAsync.argtypes = [ct.c_void_p, ct.c_char, ct.POINTER(MYFLT), ct.c_long, ct.c_double] 375libcsound.csoundInputMessage.argtypes = [ct.c_void_p, ct.c_char_p] 376libcsound.csoundInputMessageAsync.argtypes = [ct.c_void_p, ct.c_char_p] 377libcsound.csoundKillInstance.argtypes = [ct.c_void_p, MYFLT, ct.c_char_p, ct.c_int, ct.c_int] 378SENSEFUNC = ct.CFUNCTYPE(None, ct.c_void_p, ct.py_object) 379libcsound.csoundRegisterSenseEventCallback.argtypes = [ct.c_void_p, SENSEFUNC, ct.py_object] 380libcsound.csoundKeyPress.argtypes = [ct.c_void_p, ct.c_char] 381KEYBOARDFUNC = ct.CFUNCTYPE(ct.c_int, ct.py_object, ct.c_void_p, ct.c_uint) 382libcsound.csoundRegisterKeyboardCallback.argtypes = [ct.c_void_p, KEYBOARDFUNC, ct.py_object, ct.c_uint] 383libcsound.csoundRemoveKeyboardCallback.argtypes = [ct.c_void_p, KEYBOARDFUNC] 384 385libcsound.csoundTableLength.argtypes = [ct.c_void_p, ct.c_int] 386libcsound.csoundTableGet.restype = MYFLT 387libcsound.csoundTableGet.argtypes = [ct.c_void_p, ct.c_int, ct.c_int] 388libcsound.csoundTableSet.argtypes = [ct.c_void_p, ct.c_int, ct.c_int, MYFLT] 389libcsound.csoundTableCopyOut.argtypes = [ct.c_void_p, ct.c_int, ct.POINTER(MYFLT)] 390libcsound.csoundTableCopyOutAsync.argtypes = [ct.c_void_p, ct.c_int, ct.POINTER(MYFLT)] 391libcsound.csoundTableCopyIn.argtypes = [ct.c_void_p, ct.c_int, ct.POINTER(MYFLT)] 392libcsound.csoundTableCopyInAsync.argtypes = [ct.c_void_p, ct.c_int, ct.POINTER(MYFLT)] 393libcsound.csoundGetTable.argtypes = [ct.c_void_p, ct.POINTER(ct.POINTER(MYFLT)), ct.c_int] 394libcsound.csoundGetTableArgs.argtypes = [ct.c_void_p, ct.POINTER(ct.POINTER(MYFLT)), ct.c_int] 395libcsound.csoundIsNamedGEN.argtypes = [ct.c_void_p, ct.c_int] 396libcsound.csoundGetNamedGEN.argtypes = [ct.c_void_p, ct.c_int, ct.c_char_p, ct.c_int] 397 398libcsound.csoundSetIsGraphable.argtypes = [ct.c_void_p, ct.c_int] 399MAKEGRAPHFUNC = ct.CFUNCTYPE(None, ct.c_void_p, ct.POINTER(Windat), ct.c_char_p) 400libcsound.csoundSetMakeGraphCallback.argtypes = [ct.c_void_p, MAKEGRAPHFUNC] 401DRAWGRAPHFUNC = ct.CFUNCTYPE(None, ct.c_void_p, ct.POINTER(Windat)) 402libcsound.csoundSetDrawGraphCallback.argtypes = [ct.c_void_p, DRAWGRAPHFUNC] 403KILLGRAPHFUNC = ct.CFUNCTYPE(None, ct.c_void_p, ct.POINTER(Windat)) 404libcsound.csoundSetKillGraphCallback.argtypes = [ct.c_void_p, KILLGRAPHFUNC] 405EXITGRAPHFUNC = ct.CFUNCTYPE(ct.c_int, ct.c_void_p) 406libcsound.csoundSetExitGraphCallback.argtypes = [ct.c_void_p, EXITGRAPHFUNC] 407 408libcsound.csoundGetNamedGens.restype = ct.c_void_p 409libcsound.csoundGetNamedGens.argtypes = [ct.c_void_p] 410libcsound.csoundNewOpcodeList.argtypes = [ct.c_void_p, ct.POINTER(ct.POINTER(OpcodeListEntry))] 411libcsound.csoundDisposeOpcodeList.argtypes = [ct.c_void_p, ct.POINTER(OpcodeListEntry)] 412OPCODEFUNC = ct.CFUNCTYPE(ct.c_int, ct.c_void_p, ct.c_void_p) 413libcsound.csoundAppendOpcode.argtypes = [ct.c_void_p, ct.c_char_p, ct.c_int, ct.c_int, ct.c_int, \ 414 ct.c_char_p, ct.c_char_p, OPCODEFUNC, OPCODEFUNC, OPCODEFUNC] 415 416YIELDFUNC = ct.CFUNCTYPE(ct.c_int, ct.c_void_p) 417libcsound.csoundSetYieldCallback.argtypes = [ct.c_void_p, YIELDFUNC] 418THREADFUNC = ct.CFUNCTYPE(ct.POINTER(ct.c_uint), ct.py_object) 419libcsound.csoundCreateThread.restype = ct.c_void_p 420libcsound.csoundCreateThread.argtypes = [THREADFUNC, ct.py_object] 421libcsound.csoundGetCurrentThreadId.restype = ct.c_void_p 422libcsound.csoundJoinThread.restype = ct.POINTER(ct.c_uint) 423libcsound.csoundJoinThread.argtypes = [ct.c_void_p] 424libcsound.csoundCreateThreadLock.restype = ct.c_void_p 425libcsound.csoundWaitThreadLock.argtypes = [ct.c_void_p, ct.c_uint] 426libcsound.csoundWaitThreadLockNoTimeout.argtypes = [ct.c_void_p] 427libcsound.csoundNotifyThreadLock.argtypes = [ct.c_void_p] 428libcsound.csoundDestroyThreadLock.argtypes = [ct.c_void_p] 429libcsound.csoundCreateMutex.restype = ct.c_void_p 430libcsound.csoundCreateMutex.argtypes = [ct.c_int] 431libcsound.csoundLockMutex.argtypes = [ct.c_void_p] 432libcsound.csoundLockMutexNoWait.argtypes = [ct.c_void_p] 433libcsound.csoundUnlockMutex.argtypes = [ct.c_void_p] 434libcsound.csoundDestroyMutex.argtypes = [ct.c_void_p] 435libcsound.csoundCreateBarrier.restype = ct.c_void_p 436libcsound.csoundCreateBarrier.argtypes = [ct.c_uint] 437libcsound.csoundDestroyBarrier.argtypes = [ct.c_void_p] 438libcsound.csoundWaitBarrier.argtypes = [ct.c_void_p] 439libcsound.csoundSleep.argtypes = [ct.c_uint] 440libcsound.csoundSpinLockInit.argtypes = [ct.POINTER(ct.c_int32)] 441libcsound.csoundSpinLock.argtypes = [ct.POINTER(ct.c_int32)] 442libcsound.csoundSpinTryLock.argtypes = [ct.POINTER(ct.c_int32)] 443libcsound.csoundSpinUnLock.argtypes = [ct.POINTER(ct.c_int32)] 444 445libcsound.csoundRunCommand.restype = ct.c_long 446libcsound.csoundRunCommand.argtypes = [ct.POINTER(ct.c_char_p), ct.c_int] 447libcsound.csoundInitTimerStruct.argtypes = [ct.POINTER(RtClock)] 448libcsound.csoundGetRealTime.restype = ct.c_double 449libcsound.csoundGetRealTime.argtypes = [ct.POINTER(RtClock)] 450libcsound.csoundGetCPUTime.restype = ct.c_double 451libcsound.csoundGetCPUTime.argtypes = [ct.POINTER(RtClock)] 452libcsound.csoundGetRandomSeedFromTime.restype = ct.c_uint32 453libcsound.csoundGetEnv.restype = ct.c_char_p 454libcsound.csoundGetEnv.argtypes = [ct.c_void_p, ct.c_char_p] 455libcsound.csoundSetGlobalEnv.argtypes = [ct.c_char_p, ct.c_char_p] 456libcsound.csoundCreateGlobalVariable.argtypes = [ct.c_void_p, ct.c_char_p, ct.c_uint] 457libcsound.csoundQueryGlobalVariable.restype = ct.c_void_p 458libcsound.csoundQueryGlobalVariable.argtypes = [ct.c_void_p, ct.c_char_p] 459libcsound.csoundQueryGlobalVariableNoCheck.restype = ct.c_void_p 460libcsound.csoundQueryGlobalVariableNoCheck.argtypes = [ct.c_void_p, ct.c_char_p] 461libcsound.csoundDestroyGlobalVariable.argtypes = [ct.c_void_p, ct.c_char_p] 462libcsound.csoundRunUtility.argtypes = [ct.c_void_p, ct.c_char_p, ct.c_int, ct.POINTER(ct.c_char_p)] 463libcsound.csoundListUtilities.restype = ct.POINTER(ct.c_char_p) 464libcsound.csoundListUtilities.argtypes = [ct.c_void_p] 465libcsound.csoundDeleteUtilityList.argtypes = [ct.c_void_p, ct.POINTER(ct.c_char_p)] 466libcsound.csoundGetUtilityDescription.restype = ct.c_char_p 467libcsound.csoundGetUtilityDescription.argtypes = [ct.c_void_p, ct.c_char_p] 468libcsound.csoundRand31.argtypes = [ct.POINTER(ct.c_int)] 469libcsound.csoundSeedRandMT.argtypes = [ct.POINTER(CsoundRandMTState), ct.POINTER(ct.c_uint32), ct.c_uint32] 470libcsound.csoundRandMT.restype = ct.c_uint32 471libcsound.csoundRandMT.argtypes = [ct.POINTER(CsoundRandMTState)] 472libcsound.csoundCreateCircularBuffer.restype = ct.c_void_p 473libcsound.csoundCreateCircularBuffer.argtypes = [ct.c_void_p, ct.c_int, ct.c_int] 474libcsound.csoundReadCircularBuffer.argtypes = [ct.c_void_p, ct.c_void_p, ct.c_void_p, ct.c_int] 475libcsound.csoundPeekCircularBuffer.argtypes = [ct.c_void_p, ct.c_void_p, ct.c_void_p, ct.c_int] 476libcsound.csoundWriteCircularBuffer.argtypes = [ct.c_void_p, ct.c_void_p, ct.c_void_p, ct.c_int] 477libcsound.csoundFlushCircularBuffer.argtypes = [ct.c_void_p, ct.c_void_p] 478libcsound.csoundDestroyCircularBuffer.argtypes = [ct.c_void_p, ct.c_void_p] 479libcsound.csoundOpenLibrary.argtypes = [ct.POINTER(ct.c_void_p), ct.c_char_p] 480libcsound.csoundCloseLibrary.argtypes = [ct.c_void_p] 481libcsound.csoundGetLibrarySymbol.retype = ct.c_void_p 482libcsound.csoundGetLibrarySymbol.argtypes = [ct.c_void_p, ct.c_char_p] 483 484 485def cchar(s): 486 if sys.version_info[0] >= 3: 487 return ct.c_char(ord(s[0])) 488 return ct.c_char(s[0]) 489 490def cstring(s): 491 if sys.version_info[0] >= 3 and s != None: 492 return bytes(s, 'utf-8') 493 return s 494 495def pstring(s): 496 if sys.version_info[0] >= 3 and s != None: 497 return str(s, 'utf-8') 498 return s 499 500def csoundArgList(lst): 501 if len(lst) == 1 and type(lst[0]) is list: 502 lst = lst[0] 503 argc = len(lst) 504 argv = (ct.POINTER(ct.c_char_p) * argc)() 505 for i in range(argc): 506 v = cstring(lst[i]) 507 argv[i] = ct.cast(ct.pointer(ct.create_string_buffer(v)), ct.POINTER(ct.c_char_p)) 508 return ct.c_int(argc), ct.cast(argv, ct.POINTER(ct.c_char_p)) 509 510 511# message types (only one can be specified) 512CSOUNDMSG_DEFAULT = 0x0000 # standard message 513CSOUNDMSG_ERROR = 0x1000 # error message (initerror, perferror, etc.) 514CSOUNDMSG_ORCH = 0x2000 # orchestra opcodes (e.g. printks) 515CSOUNDMSG_REALTIME = 0x3000 # for progress display and heartbeat characters 516CSOUNDMSG_WARNING = 0x4000 # warning messages 517CSOUNDMSG_STDOUT = 0x5000 518 519# format attributes (colors etc.), use the bitwise OR of any of these: 520CSOUNDMSG_FG_BLACK = 0x0100 521CSOUNDMSG_FG_RED = 0x0101 522CSOUNDMSG_FG_GREEN = 0x0102 523CSOUNDMSG_FG_YELLOW = 0x0103 524CSOUNDMSG_FG_BLUE = 0x0104 525CSOUNDMSG_FG_MAGENTA = 0x0105 526CSOUNDMSG_FG_CYAN = 0x0106 527CSOUNDMSG_FG_WHITE = 0x0107 528 529CSOUNDMSG_FG_BOLD = 0x0008 530CSOUNDMSG_FG_UNDERLINE = 0x0080 531 532CSOUNDMSG_BG_BLACK = 0x0200 533CSOUNDMSG_BG_RED = 0x0210 534CSOUNDMSG_BG_GREEN = 0x0220 535CSOUNDMSG_BG_ORANGE = 0x0230 536CSOUNDMSG_BG_BLUE = 0x0240 537CSOUNDMSG_BG_MAGENTA = 0x0250 538CSOUNDMSG_BG_CYAN = 0x0260 539CSOUNDMSG_BG_GREY = 0x0270 540 541CSOUNDMSG_TYPE_MASK = 0x7000 542CSOUNDMSG_FG_COLOR_MASK = 0x0107 543CSOUNDMSG_FG_ATTR_MASK = 0x0088 544CSOUNDMSG_BG_COLOR_MASK = 0x0270 545 546 547# ERROR DEFINITIONS 548CSOUND_SUCCESS = 0 # Completed successfully. 549CSOUND_ERROR = -1 # Unspecified failure. 550CSOUND_INITIALIZATION = -2 # Failed during initialization. 551CSOUND_PERFORMANCE = -3 # Failed during performance. 552CSOUND_MEMORY = -4 # Failed to allocate requested memory. 553CSOUND_SIGNAL = -5 # Termination requested by SIGINT or SIGTERM. 554 555# Flags for csoundInitialize(). 556CSOUNDINIT_NO_SIGNAL_HANDLER = 1 557CSOUNDINIT_NO_ATEXIT = 2 558 559# Types for keyboard callbacks set in registerKeyboardCallback() 560CSOUND_CALLBACK_KBD_EVENT = 1 561CSOUND_CALLBACK_KBD_TEXT = 2 562 563# Constants used by the bus interface (csoundGetChannelPtr() etc.). 564CSOUND_CONTROL_CHANNEL = 1 565CSOUND_AUDIO_CHANNEL = 2 566CSOUND_STRING_CHANNEL = 3 567CSOUND_PVS_CHANNEL = 4 568CSOUND_VAR_CHANNEL = 5 569 570CSOUND_CHANNEL_TYPE_MASK = 15 571 572CSOUND_INPUT_CHANNEL = 16 573CSOUND_OUTPUT_CHANNEL = 32 574 575CSOUND_CONTROL_CHANNEL_NO_HINTS = 0 576CSOUND_CONTROL_CHANNEL_INT = 1 577CSOUND_CONTROL_CHANNEL_LIN = 2 578CSOUND_CONTROL_CHANNEL_EXP = 3 579 580# list of languages 581CSLANGUAGE_DEFAULT = 0 582CSLANGUAGE_AFRIKAANS = 1 583CSLANGUAGE_ALBANIAN = 2 584CSLANGUAGE_ARABIC = 3 585CSLANGUAGE_ARMENIAN = 4 586CSLANGUAGE_ASSAMESE = 5 587CSLANGUAGE_AZERI = 6 588CSLANGUAGE_BASQUE = 7 589CSLANGUAGE_BELARUSIAN = 8 590CSLANGUAGE_BENGALI = 9 591CSLANGUAGE_BULGARIAN = 10 592CSLANGUAGE_CATALAN = 11 593CSLANGUAGE_CHINESE = 12 594CSLANGUAGE_CROATIAN = 13 595CSLANGUAGE_CZECH = 14 596CSLANGUAGE_DANISH = 15 597CSLANGUAGE_DUTCH = 16 598CSLANGUAGE_ENGLISH_UK = 17 599CSLANGUAGE_ENGLISH_US = 18 600CSLANGUAGE_ESTONIAN = 19 601CSLANGUAGE_FAEROESE = 20 602CSLANGUAGE_FARSI = 21 603CSLANGUAGE_FINNISH = 22 604CSLANGUAGE_FRENCH = 23 605CSLANGUAGE_GEORGIAN = 24 606CSLANGUAGE_GERMAN = 25 607CSLANGUAGE_GREEK = 26 608CSLANGUAGE_GUJARATI = 27 609CSLANGUAGE_HEBREW = 28 610CSLANGUAGE_HINDI = 29 611CSLANGUAGE_HUNGARIAN = 30 612CSLANGUAGE_ICELANDIC = 31 613CSLANGUAGE_INDONESIAN = 32 614CSLANGUAGE_ITALIAN = 33 615CSLANGUAGE_JAPANESE = 34 616CSLANGUAGE_KANNADA = 35 617CSLANGUAGE_KASHMIRI = 36 618CSLANGUAGE_KAZAK = 37 619CSLANGUAGE_KONKANI = 38 620CSLANGUAGE_KOREAN = 39 621CSLANGUAGE_LATVIAN = 40 622CSLANGUAGE_LITHUANIAN = 41 623CSLANGUAGE_MACEDONIAN = 42 624CSLANGUAGE_MALAY = 43 625CSLANGUAGE_MALAYALAM = 44 626CSLANGUAGE_MANIPURI = 45 627CSLANGUAGE_MARATHI = 46 628CSLANGUAGE_NEPALI = 47 629CSLANGUAGE_NORWEGIAN = 48 630CSLANGUAGE_ORIYA = 49 631CSLANGUAGE_POLISH = 50 632CSLANGUAGE_PORTUGUESE = 51 633CSLANGUAGE_PUNJABI = 52 634CSLANGUAGE_ROMANIAN = 53 635CSLANGUAGE_RUSSIAN = 54 636CSLANGUAGE_SANSKRIT = 55 637CSLANGUAGE_SERBIAN = 56 638CSLANGUAGE_SINDHI = 57 639CSLANGUAGE_SLOVAK = 58 640CSLANGUAGE_SLOVENIAN = 59 641CSLANGUAGE_SPANISH = 60 642CSLANGUAGE_SWAHILI = 61 643CSLANGUAGE_SWEDISH = 62 644CSLANGUAGE_TAMIL = 63 645CSLANGUAGE_TATAR = 64 646CSLANGUAGE_TELUGU = 65 647CSLANGUAGE_THAI = 66 648CSLANGUAGE_TURKISH = 67 649CSLANGUAGE_UKRAINIAN = 68 650CSLANGUAGE_URDU = 69 651CSLANGUAGE_UZBEK = 70 652CSLANGUAGE_VIETNAMESE = 71 653CSLANGUAGE_COLUMBIAN = 72 654 655 656#Instantiation 657def csoundInitialize(flags): 658 """Initializes Csound library with specific flags. 659 660 This function is called internally by csoundCreate(), so there is generally 661 no need to use it explicitly unless you need to avoid default initialization 662 that sets signal handlers and atexit() callbacks. 663 Return value is zero on success, positive if initialization was 664 done already, and negative on error. 665 """ 666 return libcsound.csoundInitialize(flags) 667 668def setOpcodedir(s): 669 """Sets an opcodedir override for csoundCreate().""" 670 libcsound.csoundSetOpcodedir(cstring(s)) 671 672class Csound: 673 #Instantiation 674 def __init__(self, hostData=None, pointer_=None): 675 """Creates an instance of Csound. 676 677 Gets an opaque pointer that must be passed to most Csound API 678 functions. The *hostData* parameter can be :code:`None`, or it can be 679 any sort of data; these data can be accessed from the Csound instance 680 that is passed to callback routines. 681 """ 682 if pointer_: 683 self.cs = pointer_ 684 self.fromPointer = True 685 else: 686 self.cs = libcsound.csoundCreate(ct.py_object(hostData)) 687 self.fromPointer = False 688 689 def loadPlugins(self, directory): 690 """Loads all plugins from a given directory.""" 691 return libcsound.csoundLoadPlugins(self.cs, cstring(directory)) 692 693 def __del__(self): 694 """Destroys an instance of Csound.""" 695 if not self.fromPointer and libcsound: 696 libcsound.csoundDestroy(self.cs) 697 698 def csound(self): 699 """Returns the opaque pointer to the running Csound instance.""" 700 return self.cs 701 702 def version(self): 703 """Returns the version number times 1000 (5.00.0 = 5000).""" 704 return libcsound.csoundGetVersion() 705 706 def APIVersion(self): 707 """Returns the API version number times 100 (1.00 = 100).""" 708 return libcsound.csoundGetAPIVersion() 709 710 #Performance 711 def parseOrc(self, orc): 712 """Parses the given orchestra from an ASCII string into a TREE. 713 714 This can be called during performance to parse new code. 715 """ 716 return libcsound.csoundParseOrc(self.cs, cstring(orc)) 717 718 def compileTree(self, tree): 719 """Compiles the given TREE node into structs for Csound to use. 720 721 This can be called during performance to compile a new TREE. 722 """ 723 return libcsound.csoundCompileTree(self.cs, tree) 724 725 def compileTreeAsync(self, tree): 726 """Asynchronous version of :py:meth:`compileTree()`.""" 727 return libcsound.csoundCompileTreeAsync(self.cs, tree) 728 729 def deleteTree(self, tree): 730 """Frees the resources associated with the TREE *tree*. 731 732 This function should be called whenever the TREE was 733 created with :py:meth:`parseOrc` and memory can be deallocated. 734 """ 735 libcsound.csoundDeleteTree(self.cs, tree) 736 737 def compileOrc(self, orc): 738 """Parses, and compiles the given orchestra from an ASCII string. 739 740 Also evaluating any global space code (i-time only). 741 This can be called during performance to compile a new orchestra:: 742 743 orc = 'instr 1 \\n a1 rand 0dbfs/4 \\n out a1 \\n' 744 cs.compileOrc(orc) 745 """ 746 return libcsound.csoundCompileOrc(self.cs, cstring(orc)) 747 748 def compileOrcAsync(self, orc): 749 """Async version of :py:meth:`compileOrc()`. 750 751 The code is parsed and compiled, then placed on a queue for 752 asynchronous merge into the running engine, and evaluation. 753 The function returns following parsing and compilation. 754 """ 755 return libcsound.csoundCompileOrcAsync(self.cs, cstring(orc)) 756 757 def evalCode(self, code): 758 """Parses and compiles an orchestra given on an string. 759 760 Evaluating any global space code (i-time only). 761 On SUCCESS it returns a value passed to the 762 'return' opcode in global space:: 763 764 code = 'i1 = 2 + 2 \\n return i1 \\n' 765 retval = cs.evalCode(code) 766 """ 767 return libcsound.csoundEvalCode(self.cs, cstring(code)) 768 769 #def initializeCscore(insco, outsco): 770 771 def compileArgs(self, *args): 772 """Compiles *args*. 773 774 Reads arguments, parses and compiles an orchestra, 775 reads, processes and loads a score. 776 """ 777 argc, argv = csoundArgList(args) 778 return libcsound.csoundCompileArgs(self.cs, argc, argv) 779 780 def start(self): 781 """Prepares Csound for performance. 782 783 Normally called after compiling a csd file or an orc file, in which 784 case score preprocessing is performed and performance terminates 785 when the score terminates. 786 787 However, if called before compiling a csd file or an orc file, 788 score preprocessing is not performed and "i" statements are dispatched 789 as real-time events, the <CsOptions> tag is ignored, and performance 790 continues indefinitely or until ended using the API. 791 792 NB: this is called internally by :py:meth:`compile_()`, therefore 793 it is only required if performance is started without 794 a call to that function. 795 """ 796 return libcsound.csoundStart(self.cs) 797 798 def compile_(self, *args): 799 """Compiles Csound input files (such as an orchestra and score). 800 801 As directed by the supplied command-line arguments, 802 but does not perform them. Returns a non-zero error code on failure. 803 This function cannot be called during performance, and before a 804 repeated call, :py:meth:`reset()` needs to be called. 805 In this (host-driven) mode, the sequence of calls should be as follows:: 806 807 cs.compile_(args) 808 while cs.performBuffer() == 0: 809 pass 810 cs.cleanup() 811 cs.reset() 812 813 Calls :py:meth:`start()` internally. 814 """ 815 argc, argv = csoundArgList(args) 816 return libcsound.csoundCompile(self.cs, argc, argv) 817 818 def compileCsd(self, csd_filename): 819 """Compiles a Csound input file (.csd file). 820 821 The input file includes command-line arguments, but does not 822 perform the file. Returns a non-zero error code on failure. 823 In this (host-driven) mode, the sequence of calls should be 824 as follows:: 825 826 cs.compileCsd(args) 827 while cs.performBuffer() == 0: 828 pass 829 cs.cleanup() 830 cs.reset() 831 832 NB: this function can be called during performance to 833 replace or add new instruments and events. 834 On a first call and if called before :py:meth:`start()`, this function 835 behaves similarly to :py:meth:`compile_()`. 836 """ 837 return libcsound.csoundCompileCsd(self.cs, cstring(csd_filename)) 838 839 def compileCsdText(self, csd_text): 840 """Compiles a Csound input file contained in a string of text. 841 842 The string of text includes command-line arguments, orchestra, score, 843 etc., but it is not performed. Returns a non-zero error code on failure. 844 In this (host-driven) mode, the sequence of calls should be as follows:: 845 846 cs.compileCsdText(csd_text) 847 while cs.performBuffer() == 0: 848 pass 849 cs.cleanup() 850 cs.reset() 851 852 NB: a temporary file is created, the csd_text is written to the 853 temporary file, and :py:meth:`compileCsd` is called with the name of 854 the temporary file, which is deleted after compilation. Behavior may 855 vary by platform. 856 """ 857 return libcsound.csoundCompileCsdText(self.cs, cstring(csd_text)) 858 859 def perform(self): 860 """Senses input events and performs audio output. 861 862 This is done until the end of score is reached (positive return value), 863 an error occurs (negative return value), or performance is stopped by 864 calling :py:meth:`stop()` from another thread (zero return value). 865 866 Note that :py:meth:`compile_()`, or :py:meth:`compileOrc()`, 867 :py:meth:`readScore()`, :py:meth:`start()` must be 868 called first. 869 870 In the case of zero return value, :py:meth:`perform()` can be called 871 again to continue the stopped performance. Otherwise, :py:meth:`reset()` 872 should be called to clean up after the finished or failed performance. 873 """ 874 return libcsound.csoundPerform(self.cs) 875 876 def performKsmps(self): 877 """Senses input events, and performs audio output. 878 879 This is done for one control sample worth (ksmps). 880 881 Note that :py:meth:`compile_()`, or :py:meth:`compileOrc()`, 882 :py:meth:`readScore()`, :py:meth:`start()` must be called first. 883 884 Returns :code:`False` during performance, and :code:`True` when 885 performance is finished. If called until it returns :code:`True`, 886 it will perform an entire score. 887 888 Enables external software to control the execution of Csound, 889 and to synchronize performance with audio input and output. 890 """ 891 return libcsound.csoundPerformKsmps(self.cs) 892 893 def performBuffer(self): 894 """Performs Csound, sensing real-time and score events. 895 896 Processing one buffer's worth (-b frames) of interleaved audio. 897 898 Note that :py:meth:`compile_()` must be called first, then call 899 :py:meth:`outputBuffer()` and :py:meth:`inputBuffer(`) to get ndarrays 900 pointing to Csound's I/O buffers. 901 902 Returns :code:`False` during performance, and :code:`true` when 903 performance is finished. 904 """ 905 return libcsound.csoundPerformBuffer(self.cs) 906 907 def stop(self): 908 """Stops a :py:meth:`perform()` running in another thread. 909 910 Note that it is not guaranteed that :py:meth:`perform()` has already 911 stopped when this function returns. 912 """ 913 libcsound.csoundStop(self.cs) 914 915 def cleanup(self): 916 """Prints information and closes audio and MIDI devices. 917 918 | The information is about the end of a performance. 919 | Note: after calling cleanup(), the operation of the perform 920 function is undefined. 921 """ 922 return libcsound.csoundCleanup(self.cs) 923 924 def reset(self): 925 """Resets all internal memory and state. 926 927 In preparation for a new performance. 928 Enable external software to run successive Csound performances 929 without reloading Csound. Implies :py:meth:`cleanup()`, unless already 930 called. 931 """ 932 libcsound.csoundReset(self.cs) 933 934 #UDP server 935 def UDPServerStart(self, port): 936 """Starts the UDP server on a supplied port number. 937 938 Returns CSOUND_SUCCESS if server has been started successfully, 939 otherwise, CSOUND_ERROR. 940 """ 941 return libcsound.csoundUDPServerStart(self.cs, ct.c_uint(port)) 942 943 def UDPServerStatus(self): 944 """Returns the port number on which the server is running. 945 946 If the server is not running, CSOUND_ERROR is returned. 947 """ 948 return libcsound.csoundUDPServerStatus(self.cs) 949 950 def UDPServerClose(self): 951 """Closes the UDP server. 952 953 Returns CSOUND_SUCCESS if the running server was successfully closed, 954 CSOUND_ERROR otherwise. 955 """ 956 return libcsound.csoundUDPServerClose(self.cs) 957 958 def UDPConsole(self, addr, port, mirror): 959 """Turns on the transmission of console messages to UDP on addr:port. 960 961 If mirror is one, the messages will continue to be sent to the usual 962 destination (see :py:meth:`setMessageCallback()`) as well as to UDP. 963 Returns CSOUND_SUCCESS or CSOUND_ERROR if the UDP transmission 964 could not be set up. 965 """ 966 return libcsound.csoundUDPConsole(self.cs, cstring(addr), ct.c_uint(port), ct.c_uint(mirror)) 967 968 def stopUDPConsole(self): 969 """Stops transmitting console messages via UDP.""" 970 libcsound.csoundStopUDPConsole(self.cs) 971 972 #Attributes 973 def sr(self): 974 """Returns the number of audio sample frames per second.""" 975 return libcsound.csoundGetSr(self.cs) 976 977 def kr(self): 978 """Returns the number of control samples per second.""" 979 return libcsound.csoundGetKr(self.cs) 980 981 def ksmps(self): 982 """Returns the number of audio sample frames per control sample.""" 983 return libcsound.csoundGetKsmps(self.cs) 984 985 def nchnls(self): 986 """Returns the number of audio output channels. 987 988 Set through the :code:`nchnls` header variable in the csd file. 989 """ 990 return libcsound.csoundGetNchnls(self.cs) 991 992 def nchnlsInput(self): 993 """Returns the number of audio input channels. 994 995 Set through the :code:`nchnls_i` header variable in the csd file. If 996 this variable is not set, the value is taken from :code:`nchnls`. 997 """ 998 return libcsound.csoundGetNchnlsInput(self.cs) 999 1000 def get0dBFS(self): 1001 """Returns the 0dBFS level of the spin/spout buffers.""" 1002 return libcsound.csoundGet0dBFS(self.cs) 1003 1004 def A4(self): 1005 """Returns the A4 frequency reference.""" 1006 return libcsound.csoundGetA4(self.cs) 1007 1008 def currentTimeSamples(self): 1009 """Returns the current performance time in samples.""" 1010 return libcsound.csoundGetCurrentTimeSamples(self.cs) 1011 1012 def sizeOfMYFLT(self): 1013 """Returns the size of MYFLT in bytes.""" 1014 return libcsound.csoundGetSizeOfMYFLT() 1015 1016 def hostData(self): 1017 """Returns host data.""" 1018 return libcsound.csoundGetHostData(self.cs) 1019 1020 def setHostData(self, data): 1021 """Sets host data.""" 1022 libcsound.csoundSetHostData(self.cs, ct.py_object(data)) 1023 1024 def setOption(self, option): 1025 """Sets a single csound option (flag). 1026 1027 | Returns CSOUND_SUCCESS on success. 1028 | NB: blank spaces are not allowed. 1029 """ 1030 return libcsound.csoundSetOption(self.cs, cstring(option)) 1031 1032 def setParams(self, params): 1033 """Configures Csound with a given set of parameters. 1034 1035 These parameters are defined in the CsoundParams structure. 1036 They are the part of the OPARMS struct that are configurable through 1037 command line flags. 1038 The CsoundParams structure can be obtained using :py:meth:`params()`. 1039 These options should only be changed before performance has started. 1040 """ 1041 libcsound.csoundSetParams(self.cs, ct.byref(params)) 1042 1043 def params(self, params): 1044 """Gets the current set of parameters from a CSOUND instance. 1045 1046 These parameters are in a CsoundParams structure. See 1047 :py:meth:`setParams()`:: 1048 1049 p = CsoundParams() 1050 cs.params(p) 1051 """ 1052 libcsound.csoundGetParams(self.cs, ct.byref(params)) 1053 1054 def debug(self): 1055 """Returns whether Csound is set to print debug messages. 1056 1057 Those messages are sent through the :code:`DebugMsg()` internal API 1058 function. 1059 """ 1060 return libcsound.csoundGetDebug(self.cs) != 0 1061 1062 def setDebug(self, debug): 1063 """Sets whether Csound prints debug messages. 1064 1065 The debug argument must have value :code:`True` or :code:`False`. 1066 Those messages come from the :code:`DebugMsg()` internal API function. 1067 """ 1068 libcsound.csoundSetDebug(self.cs, ct.c_int(debug)) 1069 1070 def systemSr(self, val): 1071 """If val > 0, sets the internal variable holding the system HW sr. 1072 1073 Returns the stored value containing the system HW sr.""" 1074 return libcsound.csoundSystemSr(self.cs, val) 1075 1076 #General Input/Output 1077 def outputName(self): 1078 """Returns the audio output name (-o)""" 1079 s = libcsound.csoundGetOutputName(self.cs) 1080 return pstring(s) 1081 1082 def inputName(self): 1083 """Returns the audio input name (-i)""" 1084 s = libcsound.csoundGetInputName(self.cs) 1085 return pstring(s) 1086 1087 def setOutput(self, name, type_, format): 1088 """Sets output destination, type and format. 1089 1090 | *type_* can be one of "wav", "aiff", "au", "raw", "paf", "svx", "nist", 1091 "voc", "ircam", "w64", "mat4", "mat5", "pvf", "xi", "htk", "sds", 1092 "avr", "wavex", "sd2", "flac", "caf", "wve", "ogg", "mpc2k", "rf64", 1093 or NULL (use default or realtime IO). 1094 | *format* can be one of "alaw", "schar", "uchar", "float", "double", 1095 "long", "short", "ulaw", "24bit", "vorbis", or NULL (use default or 1096 realtime IO). 1097 1098 For RT audio, use device_id from CS_AUDIODEVICE for a given audio 1099 device. 1100 """ 1101 n = cstring(name) 1102 t = cstring(type_) 1103 f = cstring(format) 1104 libcsound.csoundSetOutput(self.cs, n, t, f) 1105 1106 def outputFormat(self): 1107 """Gets output type and format.""" 1108 type_ = ct.create_string_buffer(6) 1109 format = ct.create_string_buffer(8) 1110 libcsound.csoundGetOutputFormat(self.cs, type_, format) 1111 return pstring(string_at(type_)), pstring(string_at(format)) 1112 1113 def setInput(self, name): 1114 """Sets input source.""" 1115 libcsound.csoundSetInput(self.cs, cstring(name)) 1116 1117 def setMIDIInput(self, name): 1118 """Sets MIDI input device name/number.""" 1119 libcsound.csoundSetMidiInput(self.cs, cstring(name)) 1120 1121 def setMIDIFileInput(self, name): 1122 """Sets MIDI file input name.""" 1123 libcsound.csoundSetMIDIFileInput(self.cs, cstring(name)) 1124 1125 def setMIDIOutput(self, name): 1126 """Sets MIDI output device name/number.""" 1127 libcsound.csoundSetMIDIOutput(self.cs, cstring(name)) 1128 1129 def setMIDIFileOutput(self, name): 1130 """Sets MIDI file output name.""" 1131 libcsound.csoundSetMIDIFileOutput(self.cs, cstring(name)) 1132 1133 def setFileOpenCallback(self, function): 1134 """Sets a callback for receiving notices whenever Csound opens a file. 1135 1136 The callback is made after the file is successfully opened. 1137 The following information is passed to the callback: 1138 1139 bytes 1140 pathname of the file; either full or relative to current dir 1141 int 1142 a file type code from the enumeration CSOUND_FILETYPES 1143 int 1144 1 if Csound is writing the file, 0 if reading 1145 int 1146 1 if a temporary file that Csound will delete; 0 if not 1147 1148 Pass NULL to disable the callback. 1149 This callback is retained after a :py:meth:`reset()` call. 1150 """ 1151 self.fileOpenCbRef = FILEOPENFUNC(function) 1152 libcsound.csoundSetFileOpenCallback(self.cs, self.fileOpenCbRef) 1153 1154 #Realtime Audio I/O 1155 def setRTAudioModule(self, module): 1156 """Sets the current RT audio module.""" 1157 libcsound.csoundSetRTAudioModule(self.cs, cstring(module)) 1158 1159 def module(self, number): 1160 """Retrieves a module name and type given a number. 1161 1162 Type is "audio" or "midi". Modules are added to list as csound loads 1163 them. Return CSOUND_SUCCESS on success and CSOUND_ERROR if module 1164 number was not found:: 1165 1166 n = 0 1167 while True: 1168 name, type_, err = cs.module(n) 1169 if err == ctcsound.CSOUND_ERROR: 1170 break 1171 print("Module %d:%s (%s)\\n" % (n, name, type_)) 1172 n = n + 1 1173 """ 1174 name = ct.pointer(ct.c_char_p(cstring("dummy"))) 1175 type_ = ct.pointer(ct.c_char_p(cstring("dummy"))) 1176 err = libcsound.csoundGetModule(self.cs, number, name, type_) 1177 if err == CSOUND_ERROR: 1178 return None, None, err 1179 n = pstring(string_at(name.contents)) 1180 t = pstring(string_at(type_.contents)) 1181 return n, t, err 1182 1183 def inputBufferSize(self): 1184 """Returns the number of samples in Csound's input buffer.""" 1185 return libcsound.csoundGetInputBufferSize(self.cs) 1186 1187 def outputBufferSize(self): 1188 """Returns the number of samples in Csound's output buffer.""" 1189 return libcsound.csoundGetOutputBufferSize(self.cs) 1190 1191 def inputBuffer(self): 1192 """Returns the Csound audio input buffer as an ndarray. 1193 1194 Enables external software to write audio into Csound before 1195 calling :py:meth:`performBuffer()`. 1196 """ 1197 buf = libcsound.csoundGetInputBuffer(self.cs) 1198 size = libcsound.csoundGetInputBufferSize(self.cs) 1199 arrayType = np.ctypeslib.ndpointer(MYFLT, 1, (size,), 'C_CONTIGUOUS') 1200 p = ct.cast(buf, arrayType) 1201 return arrFromPointer(p) 1202 1203 def outputBuffer(self): 1204 """Returns the Csound audio output buffer as an ndarray. 1205 1206 Enables external software to read audio from Csound after 1207 calling :py:meth:`performBuffer()`. 1208 """ 1209 buf = libcsound.csoundGetOutputBuffer(self.cs) 1210 size = libcsound.csoundGetOutputBufferSize(self.cs) 1211 arrayType = np.ctypeslib.ndpointer(MYFLT, 1, (size,), 'C_CONTIGUOUS') 1212 p = ct.cast(buf, arrayType) 1213 return arrFromPointer(p) 1214 1215 def spin(self): 1216 """Returns the Csound audio input working buffer (spin) as an ndarray. 1217 1218 Enables external software to write audio into Csound before 1219 calling :py:meth:`performKsmps()`. 1220 """ 1221 buf = libcsound.csoundGetSpin(self.cs) 1222 size = self.ksmps() * self.nchnlsInput() 1223 arrayType = np.ctypeslib.ndpointer(MYFLT, 1, (size,), 'C_CONTIGUOUS') 1224 p = ct.cast(buf, arrayType) 1225 return arrFromPointer(p) 1226 1227 def clearSpin(self): 1228 """Clears the input buffer (spin).""" 1229 libcsound.csoundClearSpin(self.cs) 1230 1231 def addSpinSample(self, frame, channel, sample): 1232 """Adds the indicated sample into the audio input working buffer (spin). 1233 1234 This only ever makes sense before calling :py:meth:`performKsmps()`. 1235 The frame and channel must be in bounds relative to :py:meth:`ksmps()` 1236 and :py:meth:`nchnlsInput()`. 1237 1238 NB: the spin buffer needs to be cleared at every k-cycle by calling 1239 :py:meth:`clearSpin()`. 1240 """ 1241 libcsound.csoundAddSpinSample(self.cs, frame, channel, sample) 1242 1243 def setSpinSample(self, frame, channel, sample): 1244 """Sets the audio input working buffer (spin) to the indicated sample. 1245 1246 This only ever makes sense before calling :py:meth:`performKsmps()`. 1247 The frame and channel must be in bounds relative to :py:meth:`ksmps()` 1248 and :py:meth:`nchnlsInput()`. 1249 """ 1250 libcsound.csoundSetSpinSample(self.cs, frame, channel, sample) 1251 1252 def spout(self): 1253 """Returns the address of the Csound audio output working buffer (spout). 1254 1255 Enables external software to read audio from Csound after 1256 calling :py:meth:`performKsmps`. 1257 """ 1258 buf = libcsound.csoundGetSpout(self.cs) 1259 size = self.ksmps() * self.nchnls() 1260 arrayType = np.ctypeslib.ndpointer(MYFLT, 1, (size,), 'C_CONTIGUOUS') 1261 p = ct.cast(buf, arrayType) 1262 return arrFromPointer(p) 1263 1264 def spoutSample(self, frame, channel): 1265 """Returns one sample from the Csound audio output working buf (spout). 1266 1267 Only ever makes sense after calling :py:meth:`performKsmps()`. The 1268 *frame* and *channel* must be in bounds relative to :py:meth:`ksmps()` 1269 and :py:meth:`nchnls()`. 1270 """ 1271 return libcsound.csoundGetSpoutSample(self.cs, frame, channel) 1272 1273 def rtRecordUserData(self): 1274 """Returns pointer to user data pointer for real time audio input.""" 1275 return libcsound.csoundGetRtRecordUserData(self.cs) 1276 1277 def rtPlaydUserData(self): 1278 """Returns pointer to user data pointer for real time audio output.""" 1279 return libcsound.csoundGetRtPlayUserData(self.cs) 1280 1281 def setHostImplementedAudioIO(self, state, bufSize): 1282 """Sets user handling of sound I/O. 1283 1284 Calling this function with a :code:`True` *state* value between creation 1285 of the Csound object and the start of performance will disable all 1286 default handling of sound I/O by the Csound library, allowing the host 1287 application to use the spin/spout/input/output buffers directly. 1288 1289 For applications using spin/spout, *bufSize* should be set to 0. 1290 If *bufSize* is greater than zero, the buffer size (-b) will be 1291 set to the integer multiple of :py:meth:`ksmps()` that is nearest to the 1292 value specified. 1293 """ 1294 libcsound.csoundSetHostImplementedAudioIO(self.cs, ct.c_int(state), bufSize) 1295 1296 def audioDevList(self, isOutput): 1297 """Returns a list of available input or output audio devices. 1298 1299 Each item in the list is a dictionnary representing a device. The 1300 dictionnary keys are *device_name*, *device_id*, *rt_module* (value 1301 type string), *max_nchnls* (value type int), and *isOutput* (value 1302 type boolean). 1303 1304 Must be called after an orchestra has been compiled 1305 to get meaningful information. 1306 """ 1307 n = libcsound.csoundGetAudioDevList(self.cs, None, ct.c_int(isOutput)) 1308 devs = (CsoundAudioDevice * n)() 1309 libcsound.csoundGetAudioDevList(self.cs, ct.byref(devs), ct.c_int(isOutput)) 1310 lst = [] 1311 for dev in devs: 1312 d = {} 1313 d["device_name"] = pstring(dev.device_name) 1314 d["device_id"] = pstring(dev.device_id) 1315 d["rt_module"] = pstring(dev.rt_module) 1316 d["max_nchnls"] = dev.max_nchnls 1317 d["isOutput"] = (dev.isOutput == 1) 1318 lst.append(d) 1319 return lst 1320 1321 def setPlayOpenCallback(self, function): 1322 """Sets a callback for opening real-time audio playback.""" 1323 self.playOpenCbRef = PLAYOPENFUNC(function) 1324 libcsound.csoundSetPlayopenCallback(self.cs, self.playOpenCbRef) 1325 1326 def setRtPlayCallback(self, function): 1327 """Sets a callback for performing real-time audio playback.""" 1328 self.rtPlayCbRef = RTPLAYFUNC(function) 1329 libcsound.csoundSetRtplayCallback(self.cs, self.rtPlayCbRef) 1330 1331 def setRecordOpenCallback(self, function): 1332 """Sets a callback for opening real-time audio recording.""" 1333 self.recordOpenCbRef = RECORDOPENFUNC(function) 1334 libcsound.csoundSetRecopenCallback(self.cs, self.recordOpenCbRef) 1335 1336 def setRtRecordCallback(self, function): 1337 """Sets a callback for performing real-time audio recording.""" 1338 self.rtRecordCbRef = RTRECORDFUNC(function) 1339 libcsound.csoundSetRtrecordCallback(self.cs, self.rtRecordCbRef) 1340 1341 def setRtCloseCallback(self, function): 1342 """Sets a callback for closing real-time audio playback and recording.""" 1343 self.rtCloseCbRef = RTCLOSEFUNC(function) 1344 libcsound.csoundSetRtcloseCallback(self.cs, self.rtCloseCbRef) 1345 1346 def setAudioDevListCallback(self, function): 1347 """Sets a callback for obtaining a list of audio devices. 1348 1349 This should be set by rtaudio modules and should not be set by hosts. 1350 (See :py:meth:`audioDevList()`). 1351 """ 1352 self.audioDevListCbRef = AUDIODEVLISTFUNC(function) 1353 libcsound.csoundSetAudioDeviceListCallback(self.cs, self.audioDevListCbRef) 1354 1355 #Realtime MIDI I/O 1356 def setMIDIModule(self, module): 1357 """Sets the current MIDI IO module.""" 1358 libcsound.csoundSetMIDIModule(self.cs, cstring(module)) 1359 1360 def setHostImplementedMIDIIO(self, state): 1361 """Called with *state* :code:`True` if the host is implementing via callbacks.""" 1362 libcsound.csoundSetHostImplementedMIDIIO(self.cs, ct.c_int(state)) 1363 1364 def midiDevList(self, isOutput): 1365 """Returns a list of available input or output midi devices. 1366 1367 Each item in the list is a dictionnary representing a device. The 1368 dictionnary keys are *device_name*, *interface_name*, *device_id*, 1369 *midi_module* (value type string), *isOutput* (value type boolean). 1370 1371 Must be called after an orchestra has been compiled 1372 to get meaningful information. 1373 """ 1374 n = libcsound.csoundGetMIDIDevList(self.cs, None, ct.c_int(isOutput)) 1375 devs = (csoundMidiDevice * n)() 1376 libcsound.csoundGetMIDIDevList(self.cs, ct.byref(devs), ct.c_int(isOutput)) 1377 lst = [] 1378 for dev in devs: 1379 d = {} 1380 d["device_name"] = pstring(dev.device_name) 1381 d["interface_name"] = pstring(dev.max_nchnlsinterface_name) 1382 d["device_id"] = pstring(dev.device_id) 1383 d["midi_module"] = pstring(dev.midi_module) 1384 d["isOutput"] = (dev.isOutput == 1) 1385 lst.append(d) 1386 return lst 1387 1388 def setExternalMidiInOpenCallback(self, function): 1389 """Sets a callback for opening real-time MIDI input.""" 1390 self.extMidiInOpenCbRef = MIDIINOPENFUNC(function) 1391 libcsound.csoundSetExternalMidiInOpenCallback(self.cs, self.extMidiInOpenCbRef) 1392 1393 def setExternalMidiReadCallback(self, function): 1394 """Sets a callback for reading from real time MIDI input.""" 1395 self.extMidiReadCbRef = MIDIREADFUNC(function) 1396 libcsound.csoundSetExternalMidiReadCallback(self.cs, self.extMidiReadCbRef) 1397 1398 def setExternalMidiInCloseCallback(self, function): 1399 """Sets a callback for closing real time MIDI input.""" 1400 self.extMidiInCloseCbRef = MIDIINCLOSEFUNC(function) 1401 libcsound.csoundSetExternalMidiInCloseCallback(self.cs, self.extMidiInCloseCbRef) 1402 1403 def setExternalMidiOutOpenCallback(self, function): 1404 """Sets a callback for opening real-time MIDI input.""" 1405 self.extMidiOutOpenCbRef = MIDIOUTOPENFUNC(function) 1406 libcsound.csoundSetExternalMidiOutOpenCallback(self.cs, self.extMidiOutOpenCbRef) 1407 1408 def setExternalMidiWriteCallback(self, function): 1409 """Sets a callback for reading from real time MIDI input.""" 1410 self.extMidiWriteCbRef = MIDIWRITEFUNC(function) 1411 libcsound.csoundSetExternalMidiWriteCallback(self.cs, self.extMidiWriteCbRef) 1412 1413 def setExternalMidiOutCloseCallback(self, function): 1414 """Sets a callback for closing real time MIDI input.""" 1415 self.extMidiOutCloseCbRef = MIDIOUTCLOSEFUNC(function) 1416 libcsound.csoundSetExternalMidiOutCloseCallback(self.cs, self.extMidiOutCloseCbRef) 1417 1418 def setExternalMidiErrorStringCallback(self, function): 1419 """ Sets a callback for converting MIDI error codes to strings.""" 1420 self.extMidiErrStrCbRef = MIDIERRORFUNC(function) 1421 libcsound.csoundSetExternalMidiErrorStringCallback(self.cs, self.extMidiErrStrCbRef) 1422 1423 def setMidiDevListCallback(self, function): 1424 """Sets a callback for obtaining a list of MIDI devices. 1425 1426 This should be set by IO plugins and should not be set by hosts. 1427 (See :py:meth:`midiDevList()`). 1428 """ 1429 self.midiDevListCbRef = MIDIDEVLISTFUNC(function) 1430 libcsound.csoundSetMIDIDeviceListCallback(self.cs, self.midiDevListCbRef) 1431 1432 #Score Handling 1433 def readScore(self, sco): 1434 """Reads, preprocesses, and loads a score from an ASCII string. 1435 1436 It can be called repeatedly, with the new score events 1437 being added to the currently scheduled ones. 1438 """ 1439 return libcsound.csoundReadScore(self.cs, cstring(sco)) 1440 1441 def readScoreAsync(self, sco): 1442 """Asynchronous version of :py:meth:`readScore()`.""" 1443 libcsound.csoundReadScoreAsync(self.cs, cstring(sco)) 1444 1445 def scoreTime(self): 1446 """Returns the current score time. 1447 1448 The return value is the time in seconds since the beginning of 1449 performance. 1450 """ 1451 return libcsound.csoundGetScoreTime(self.cs) 1452 1453 def isScorePending(self): 1454 """Tells whether Csound score events are performed or not. 1455 1456 Independently of real-time MIDI events (see :py:meth:`setScorePending()`). 1457 """ 1458 return libcsound.csoundIsScorePending(self.cs) != 0 1459 1460 def setScorePending(self, pending): 1461 """Sets whether Csound score events are performed or not. 1462 1463 Real-time events will continue to be performed. Can be used by external 1464 software, such as a VST host, to turn off performance of score events 1465 (while continuing to perform real-time events), for example to mute 1466 a Csound score while working on other tracks of a piece, or to play 1467 the Csound instruments live. 1468 """ 1469 libcsound.csoundSetScorePending(self.cs, ct.c_int(pending)) 1470 1471 def scoreOffsetSeconds(self): 1472 """Returns the score time beginning midway through a Csound score. 1473 1474 At this time score events will actually immediately be performed 1475 (see :py:meth:`setScoreOffsetSeconds()`). 1476 """ 1477 return libcsound.csoundGetScoreOffsetSeconds(self.cs) 1478 1479 def setScoreOffsetSeconds(self, time): 1480 """Csound score events prior to the specified time are not performed. 1481 1482 Performance begins immediately at the specified time (real-time events 1483 will continue to be performed as they are received). Can be used by 1484 external software, such as a VST host, to begin score performance 1485 midway through a Csound score, for example to repeat a loop in a 1486 sequencer, or to synchronize other events with the Csound score. 1487 """ 1488 libcsound.csoundSetScoreOffsetSeconds(self.cs, MYFLT(time)) 1489 1490 def rewindScore(self): 1491 """Rewinds a compiled Csound score. 1492 1493 It is rewinded to the time specified with :py:meth:`setScoreOffsetSeconds()`. 1494 """ 1495 libcsound.csoundRewindScore(self.cs) 1496 1497 def setCscoreCallback(self, function): 1498 """Sets an external callback for Cscore processing. 1499 1500 Pass :code:`None` to reset to the internal :code:`cscore()` function 1501 (which does nothing). This callback is retained after a 1502 :py:meth:`reset()` call. 1503 """ 1504 self.cscoreCbRef = CSCOREFUNC(function) 1505 libcsound.csoundSetCscoreCallback(self.cs, self.cscoreCbRef) 1506 1507 #def scoreSort(self, inFile, outFile): 1508 1509 #def scoreExtract(self, inFile, outFile, extractFile) 1510 1511 #Messages and Text 1512 def message(self, fmt, *args): 1513 """Displays an informational message. 1514 1515 This is a workaround because :program:`ctypes` does not support 1516 variadic functions. 1517 The arguments are formatted in a string, using the python way, either 1518 old style or new style, and then this formatted string is passed to 1519 the Csound display message system. 1520 """ 1521 if fmt[0] == '{': 1522 s = fmt.format(*args) 1523 else: 1524 s = fmt % args 1525 libcsound.csoundMessage(self.cs, cstring("%s"), cstring(s)) 1526 1527 def messageS(self, attr, fmt, *args): 1528 """Prints message with special attributes. 1529 1530 (See msg_attr for the list of available attributes). With attr=0, 1531 messageS() is identical to :py:meth:`message()`. 1532 This is a workaround because :program:`ctypes` does not support 1533 variadic functions. 1534 The arguments are formatted in a string, using the python way, either 1535 old style or new style, and then this formatted string is passed to 1536 the csound display message system. 1537 """ 1538 if fmt[0] == '{': 1539 s = fmt.format(*args) 1540 else: 1541 s = fmt % args 1542 libcsound.csoundMessageS(self.cs, attr, cstring("%s"), cstring(s)) 1543 1544 #def setDefaultMessageCallback(): 1545 1546 #def setMessageCallback(): 1547 1548 #def setMessageStringCallback() 1549 1550 def messageLevel(self): 1551 """Returns the Csound message level (from 0 to 231).""" 1552 return libcsound.csoundGetMessageLevel(self.cs) 1553 1554 def setMessageLevel(self, messageLevel): 1555 """Sets the Csound message level (from 0 to 231).""" 1556 libcsound.csoundSetMessageLevel(self.cs, messageLevel) 1557 1558 def createMessageBuffer(self, toStdOut): 1559 """Creates a buffer for storing messages printed by Csound. 1560 1561 Should be called after creating a Csound instance and the buffer 1562 can be freed by calling :py:meth:`destroyMessageBuffer()` before 1563 deleting the Csound instance. You will generally want to call 1564 :py:meth:`cleanup()` to make sure the last messages are flushed to 1565 the message buffer before destroying Csound. 1566 1567 If *toStdOut* is :code:`True`, the messages are also printed to 1568 stdout and stderr (depending on the type of the message), 1569 in addition to being stored in the buffer. 1570 1571 Using the message buffer ties up the internal message callback, so 1572 :py:meth:`setMessageCallback()` should not be called after creating the 1573 message buffer. 1574 """ 1575 libcsound.csoundCreateMessageBuffer(self.cs, ct.c_int(toStdOut)) 1576 1577 def firstMessage(self): 1578 """Returns the first message from the buffer.""" 1579 s = libcsound.csoundGetFirstMessage(self.cs) 1580 return pstring(s) 1581 1582 def firstMessageAttr(self): 1583 """Returns the attribute parameter of the first message in the buffer.""" 1584 return libcsound.csoundGetFirstMessageAttr(self.cs) 1585 1586 def popFirstMessage(self): 1587 """Removes the first message from the buffer.""" 1588 libcsound.csoundPopFirstMessage(self.cs) 1589 1590 def messageCnt(self): 1591 """Returns the number of pending messages in the buffer.""" 1592 return libcsound.csoundGetMessageCnt(self.cs) 1593 1594 def destroyMessageBuffer(self): 1595 """Releases all memory used by the message buffer.""" 1596 libcsound.csoundDestroyMessageBuffer(self.cs) 1597 1598 #Channels, Control and Events 1599 def channelPtr(self, name, type_): 1600 """Returns a pointer to the specified channel and an error message. 1601 1602 If the channel is a control or an audio channel, the pointer is 1603 translated to an ndarray of MYFLT. If the channel is a string channel, 1604 the pointer is casted to :code:`ct.c_char_p`. The error message is either 1605 an empty string or a string describing the error that occured. 1606 1607 The channel is created first if it does not exist yet. 1608 *type_* must be the bitwise OR of exactly one of the following values, 1609 1610 CSOUND_CONTROL_CHANNEL 1611 control data (one MYFLT value) 1612 CSOUND_AUDIO_CHANNEL 1613 audio data (:py:meth:`ksmps()` MYFLT values) 1614 CSOUND_STRING_CHANNEL 1615 string data (MYFLT values with enough space to store 1616 :py:meth:`getChannelDatasize()` characters, including the 1617 NULL character at the end of the string) 1618 1619 and at least one of these: 1620 1621 CSOUND_INPUT_CHANNEL 1622 1623 CSOUND_OUTPUT_CHANNEL 1624 1625 If the channel already exists, it must match the data type 1626 (control, audio, or string), however, the input/output bits are 1627 OR'd with the new value. Note that audio and string channels 1628 can only be created after calling :py:meth:`compile_()`, because the 1629 storage size is not known until then. 1630 1631 Return value is zero on success, or a negative error code, 1632 1633 CSOUND_MEMORY 1634 there is not enough memory for allocating the channel 1635 CSOUND_ERROR 1636 the specified name or type is invalid 1637 1638 or, if a channel with the same name but incompatible type 1639 already exists, the type of the existing channel. In the case 1640 of any non-zero return value, \*p is set to NULL. 1641 Note: to find out the type of a channel without actually 1642 creating or changing it, set *type_* to zero, so that the return 1643 value will be either the type of the channel, or CSOUND_ERROR 1644 if it does not exist. 1645 1646 Operations on the pointer are not thread-safe by default. The host is 1647 required to take care of threadsafety by retrieving the channel lock 1648 with :py:meth:`channelLock()` and using :py:meth:`spinLock()` and 1649 :py:meth:`spinUnLock()` to protect access to the pointer. 1650 1651 See Top/threadsafe.c in the Csound library sources for 1652 examples. Optionally, use the channel get/set functions 1653 provided below, which are threadsafe by default. 1654 """ 1655 length = 0 1656 chanType = type_ & CSOUND_CHANNEL_TYPE_MASK 1657 if chanType == CSOUND_CONTROL_CHANNEL: 1658 length = 1 1659 elif chanType == CSOUND_AUDIO_CHANNEL: 1660 length = libcsound.csoundGetKsmps(self.cs) 1661 ptr = ct.POINTER(MYFLT)() 1662 err = '' 1663 ret = libcsound.csoundGetChannelPtr(self.cs, ct.byref(ptr), cstring(name), type_) 1664 if ret == CSOUND_SUCCESS: 1665 if chanType == CSOUND_STRING_CHANNEL: 1666 return ct.cast(ptr, ct.c_char_p), err 1667 else: 1668 arrayType = np.ctypeslib.ndpointer(MYFLT, 1, (length,), 'C_CONTIGUOUS') 1669 p = ct.cast(ptr, arrayType) 1670 return arrFromPointer(p), err 1671 elif ret == CSOUND_MEMORY: 1672 err = 'Not enough memory for allocating channel' 1673 elif ret == CSOUND_ERROR: 1674 err = 'The specified channel name or type is not valid' 1675 elif ret == CSOUND_CONTROL_CHANNEL: 1676 err = 'A control channel named {} already exists'.format(name) 1677 elif ret == CSOUND_AUDIO_CHANNEL: 1678 err = 'An audio channel named {} already exists'.format(name) 1679 elif ret == CSOUND_STRING_CHANNEL: 1680 err = 'A string channel named {} already exists'.format(name) 1681 else: 1682 err = 'Unknown error' 1683 return None, err 1684 1685 def listChannels(self): 1686 """Returns a pointer and an error message. 1687 1688 The pointer points to a list of ControlChannelInfo objects for allocated 1689 channels. A ControlChannelInfo object contains the channel 1690 characteristics. The error message indicates if there is not enough 1691 memory for allocating the list or it is an empty string if there is no 1692 error. In the case of no channels or an error, the pointer is 1693 :code:`None`. 1694 1695 Notes: the caller is responsible for freeing the list returned by the 1696 C API with :py:meth:`deleteChannelList()`. The name pointers may become 1697 invalid after calling :py:meth:`reset()`. 1698 """ 1699 cInfos = None 1700 err = '' 1701 ptr = ct.cast(ct.POINTER(ct.c_int)(), ct.POINTER(ControlChannelInfo)) 1702 n = libcsound.csoundListChannels(self.cs, ct.byref(ptr)) 1703 if n == CSOUND_MEMORY : 1704 err = 'There is not enough memory for allocating the list' 1705 if n > 0: 1706 cInfos = ct.cast(ptr, ct.POINTER(ControlChannelInfo * n)).contents 1707 return cInfos, err 1708 1709 def deleteChannelList(self, lst): 1710 """Releases a channel list previously returned by :py:meth:`listChannels()`.""" 1711 ptr = ct.cast(lst, ct.POINTER(ControlChannelInfo)) 1712 libcsound.csoundDeleteChannelList(self.cs, ptr) 1713 1714 def setControlChannelHints(self, name, hints): 1715 """Sets parameters hints for a control channel. 1716 1717 These hints have no internal function but can be used by front ends to 1718 construct GUIs or to constrain values. See the ControlChannelHints 1719 structure for details. 1720 Returns zero on success, or a non-zero error code on failure: 1721 1722 CSOUND_ERROR 1723 the channel does not exist, is not a control channel, 1724 or the specified parameters are invalid 1725 CSOUND_MEMORY 1726 could not allocate memory 1727 """ 1728 return libcsound.csoundSetControlChannelHints(self.cs, cstring(name), hints) 1729 1730 def controlChannelHints(self, name): 1731 """Returns special parameters (if any) of a control channel. 1732 1733 Those parameters have been previously set with 1734 :py:meth:`setControlChannelHints()` or the :code:`chnparams` opcode. 1735 1736 The return values are a ControlChannelHints structure and 1737 CSOUND_SUCCESS if the channel exists and is a control channel, 1738 otherwise, :code:`None` and an error code are returned. 1739 """ 1740 hints = ControlChannelHints() 1741 ret = libcsound.csoundGetControlChannelHints(self.cs, cstring(name), ct.byref(hints)) 1742 if ret != CSOUND_SUCCESS: 1743 hints = None 1744 return hints, ret 1745 1746 def channelLock(self, name): 1747 """Recovers a pointer to a lock for the specified channel called *name*. 1748 1749 The returned lock can be locked/unlocked with the :py:meth:`spinLock()` 1750 and :py:meth:`spinUnLock()` functions. 1751 Returns the address of the lock or NULL if the channel does not exist. 1752 """ 1753 return libcsound.csoundGetChannelLock(self.cs, cstring(name)) 1754 1755 def controlChannel(self, name): 1756 """Retrieves the value of control channel identified by *name*. 1757 1758 A second value is returned, which is the error (or success) code 1759 finding or accessing the channel. 1760 """ 1761 err = ct.c_int(0) 1762 ret = libcsound.csoundGetControlChannel(self.cs, cstring(name), ct.byref(err)) 1763 return ret, err 1764 1765 def setControlChannel(self, name, val): 1766 """Sets the value of control channel identified by *name*.""" 1767 libcsound.csoundSetControlChannel(self.cs, cstring(name), MYFLT(val)) 1768 1769 def audioChannel(self, name, samples): 1770 """Copies the audio channel identified by *name* into ndarray samples. 1771 1772 *samples* should contain enough memory for :py:meth:`ksmps()` MYFLTs. 1773 """ 1774 ptr = samples.ctypes.data_as(ct.POINTER(MYFLT)) 1775 libcsound.csoundGetAudioChannel(self.cs, cstring(name), ptr) 1776 1777 def setAudioChannel(self, name, samples): 1778 """Sets the audio channel *name* with data from the ndarray *samples*. 1779 1780 *samples* should contain at least :py:meth:`ksmps()` MYFLTs. 1781 """ 1782 ptr = samples.ctypes.data_as(ct.POINTER(MYFLT)) 1783 libcsound.csoundSetAudioChannel(self.cs, cstring(name), ptr) 1784 1785 def stringChannel(self, name, string): 1786 """Copies the string channel identified by *name* into *string*. 1787 1788 *string* should contain enough memory for the string 1789 (see :py:meth:`channelDatasize()` below). 1790 """ 1791 libcsound.csoundGetStringChannel(self.cs, cstring(name), cstring(string)) 1792 1793 def setStringChannel(self, name, string): 1794 """Sets the string channel identified by *name* with *string*.""" 1795 libcsound.csoundSetStringChannel(self.cs, cstring(name), cstring(string)) 1796 1797 def channelDatasize(self, name): 1798 """Returns the size of data stored in a channel. 1799 1800 For string channels this might change if the channel space gets 1801 reallocated. Since string variables use dynamic memory allocation in 1802 Csound6, this function can be called to get the space required for 1803 :py:meth:`stringChannel()`. 1804 """ 1805 return libcsound.csoundGetChannelDatasize(self.cs, cstring(name)) 1806 1807 def setInputChannelCallback(self, function): 1808 """Sets the function to call whenever the :code:`invalue` opcode is used.""" 1809 self.inputChannelCbRef = CHANNELFUNC(function) 1810 libcsound.csoundSetInputChannelCallback(self.cs, self.inputChannelCbRef) 1811 1812 def setOutputChannelCallback(self, function): 1813 """Sets the function to call whenever the :code:`outvalue` opcode is used.""" 1814 self.outputChannelCbRef = CHANNELFUNC(function) 1815 libcsound.csoundSetOutputChannelCallback(self.cs, self.outputChannelCbRef) 1816 1817 def setPvsChannel(self, fin, name): 1818 """Sends a PvsdatExt *fin* to the :code:`pvsin` opcode (f-rate) for channel *name*. 1819 1820 | Returns zero on success, CSOUND_ERROR if the index is invalid or 1821 fsig framesizes are incompatible. 1822 | CSOUND_MEMORY if there is not enough memory to extend the bus. 1823 """ 1824 return libcsound.csoundSetPvsChannel(self.cs, ct.byref(fin), cstring(name)) 1825 1826 def pvsChannel(self, fout, name): 1827 """Receives a PvsdatExt *fout* from the :code:`pvsout` opcode (f-rate) at channel *name*. 1828 1829 | Returns zero on success, CSOUND_ERROR if the index is invalid or 1830 if fsig framesizes are incompatible. 1831 | CSOUND_MEMORY if there is not enough memory to extend the bus. 1832 """ 1833 return libcsound.csoundGetPvsChannel(self.cs, ct.byref(fout), cstring(name)) 1834 1835 def scoreEvent(self, type_, pFields): 1836 """Sends a new score event. 1837 1838 | *type_* is the score event type ('a', 'i', 'q', 'f', or 'e'). 1839 | *pFields* is a tuple, a list, or an ndarray of MYFLTs with all the 1840 pfields for this event, starting with the p1 value specified in 1841 pFields[0]. 1842 """ 1843 p = np.array(pFields).astype(MYFLT) 1844 ptr = p.ctypes.data_as(ct.POINTER(MYFLT)) 1845 numFields = ct.c_long(p.size) 1846 return libcsound.csoundScoreEvent(self.cs, cchar(type_), ptr, numFields) 1847 1848 def scoreEventAsync(self, type_, pFields): 1849 """Asynchronous version of :py:meth:`scoreEvent()`.""" 1850 p = np.array(pFields).astype(MYFLT) 1851 ptr = p.ctypes.data_as(ct.POINTER(MYFLT)) 1852 numFields = ct.c_long(p.size) 1853 libcsound.csoundScoreEventAsync(self.cs, cchar(type_), ptr, numFields) 1854 1855 def scoreEventAbsolute(self, type_, pFields, timeOffset): 1856 """Like :py:meth:`scoreEvent()`, this function inserts a score event. 1857 1858 The event is inserted at absolute time with respect to the start of 1859 performance, or from an offset set with timeOffset. 1860 """ 1861 p = np.array(pFields).astype(MYFLT) 1862 ptr = p.ctypes.data_as(ct.POINTER(MYFLT)) 1863 numFields = ct.c_long(p.size) 1864 return libcsound.csoundScoreEventAbsolute(self.cs, cchar(type_), ptr, numFields, ct.c_double(timeOffset)) 1865 1866 def scoreEventAbsoluteAsync(self, type_, pFields, timeOffset): 1867 """Asynchronous version of :py:meth:`scoreEventAbsolute()`.""" 1868 p = np.array(pFields).astype(MYFLT) 1869 ptr = p.ctypes.data_as(ct.POINTER(MYFLT)) 1870 numFields = ct.c_long(p.size) 1871 libcsound.csoundScoreEventAbsoluteAsync(self.cs, cchar(type_), ptr, numFields, ct.c_double(timeOffset)) 1872 1873 def inputMessage(self, message): 1874 """Inputs a NULL-terminated string (as if from a console). 1875 1876 Used for line events. 1877 """ 1878 libcsound.csoundInputMessage(self.cs, cstring(message)) 1879 1880 def inputMessageAsync(self, message): 1881 """Asynchronous version of :py:meth:`inputMessage()`.""" 1882 libcsound.csoundInputMessageAsync(self.cs, cstring(message)) 1883 1884 def killInstance(self, instr, instrName, mode, allowRelease): 1885 """Kills off one or more running instances of an instrument. 1886 1887 The instances are identified by *instr* (number) or *instrName* (name). 1888 If *instrName* is :code:`None`, the instrument number is used. 1889 1890 | *mode* is a sum of the following values: 1891 | 0, 1, 2: kill all instances (0), oldest only (1), or newest (2) 1892 | 4: only turnoff notes with exactly matching (fractional) instr number 1893 | 8: only turnoff notes with indefinite duration (p3 < 0 or MIDI). 1894 1895 If *allowRelease* is :code:`True`, the killed instances are allowed to 1896 release. 1897 """ 1898 return libcsound.csoundKillInstance(self.cs, MYFLT(instr), cstring(instrName), mode, ct.c_int(allowRelease)) 1899 1900 def registerSenseEventCallback(self, function, userData): 1901 """Registers a function to be called by :code:`sensevents()`. 1902 1903 This function will be called once in every control period. Any number 1904 of functions may be registered, and will be called in the order of 1905 registration. 1906 1907 The callback function takes two arguments: the Csound instance 1908 pointer, and the *userData* pointer as passed to this function. 1909 1910 This facility can be used to ensure a function is called synchronously 1911 before every csound control buffer processing. It is important 1912 to make sure no blocking operations are performed in the callback. 1913 The callbacks are cleared on :py:meth:`cleanup()`. 1914 1915 Returns zero on success. 1916 """ 1917 self.senseEventCbRef = SENSEFUNC(function) 1918 return libcsound.csoundRegisterSenseEventCallback(self.cs, self.senseEventCbRef, ct.py_object(userData)) 1919 1920 def keyPress(self, c): 1921 """Sets the ASCII code of the most recent key pressed. 1922 1923 This value is used by the :code:`sensekey` opcode if a callback for 1924 returning keyboard events is not set (see 1925 :py:meth:`registerKeyboardCallback()`). 1926 """ 1927 libcsound.csoundKeyPress(self.cs, cchar(c)) 1928 1929 def registerKeyboardCallback(self, function, userData, type_): 1930 """Registers general purpose callback functions for keyboard events. 1931 1932 These callbacks are called on every control period by the sensekey 1933 opcode. 1934 1935 The callback is preserved on :py:meth:`reset()`, and multiple 1936 callbacks may be set and will be called in reverse order of 1937 registration. If the same function is set again, it is only moved 1938 in the list of callbacks so that it will be called first, and the 1939 user data and type mask parameters are updated. *type_* can be the 1940 bitwise OR of callback types for which the function should be called, 1941 or zero for all types. 1942 1943 Returns zero on success, CSOUND_ERROR if the specified function 1944 pointer or type mask is invalid, and CSOUND_MEMORY if there is not 1945 enough memory. 1946 1947 The callback function takes the following arguments: 1948 1949 *userData* 1950 the "user data" pointer, as specified when setting the callback 1951 *p* 1952 data pointer, depending on the callback type 1953 *type_* 1954 callback type, can be one of the following (more may be added in 1955 future versions of Csound): 1956 1957 CSOUND_CALLBACK_KBD_EVENT 1958 1959 CSOUND_CALLBACK_KBD_TEXT 1960 called by the :code:`sensekey` opcode to fetch key codes. The 1961 data pointer is a pointer to a single value of type :code:`int`, 1962 for returning the key code, which can be in the range 1 to 1963 65535, or 0 if there is no keyboard event. 1964 1965 For CSOUND_CALLBACK_KBD_EVENT, both key press and release 1966 events should be returned (with 65536 (0x10000) added to the 1967 key code in the latter case) as unshifted ASCII codes. 1968 CSOUND_CALLBACK_KBD_TEXT expects key press events only as the 1969 actual text that is typed. 1970 1971 The return value should be zero on success, negative on error, and 1972 positive if the callback was ignored (for example because the type is 1973 not known). 1974 """ 1975 if type_ == CSOUND_CALLBACK_KBD_EVENT: 1976 self.keyboardCbEventRef = KEYBOARDFUNC(function) 1977 else: 1978 self.keyboardCbTextRef = KEYBOARDFUNC(function) 1979 return libcsound.csoundRegisterKeyboardCallback(self.cs, KEYBOARDFUNC(function), ct.py_object(userData), ct.c_uint(type_)) 1980 1981 def removeKeyboardCallback(self, function): 1982 """Removes a callback previously set with :py:meth:`registerKeyboardCallback()`.""" 1983 libcsound.csoundRemoveKeyboardCallback(self.cs, KEYBOARDFUNC(function)) 1984 1985 #Tables 1986 def tableLength(self, table): 1987 """Returns the length of a function table. 1988 1989 (Not including the guard point). 1990 If the table does not exist, returns -1. 1991 """ 1992 return libcsound.csoundTableLength(self.cs, table) 1993 1994 def tableGet(self, table, index): 1995 """Returns the value of a slot in a function table. 1996 1997 The *table* number and *index* are assumed to be valid. 1998 """ 1999 return libcsound.csoundTableGet(self.cs, table, index) 2000 2001 def tableSet(self, table, index, value): 2002 """Sets the value of a slot in a function table. 2003 2004 The *table* number and *index* are assumed to be valid. 2005 """ 2006 libcsound.csoundTableSet(self.cs, table, index, MYFLT(value)) 2007 2008 def tableCopyOut(self, table, dest): 2009 """Copies the contents of a function table into a supplied ndarray *dest*. 2010 2011 The *table* number is assumed to be valid, and the destination needs to 2012 have sufficient space to receive all the function table contents. 2013 """ 2014 ptr = dest.ctypes.data_as(ct.POINTER(MYFLT)) 2015 libcsound.csoundTableCopyOut(self.cs, table, ptr) 2016 2017 def tableCopyOutAsync(self, table, dest): 2018 """Asynchronous version of :py:meth:`tableCopyOut()`.""" 2019 ptr = dest.ctypes.data_as(ct.POINTER(MYFLT)) 2020 libcsound.csoundTableCopyOutAsync(self.cs, table, ptr) 2021 2022 def tableCopyIn(self, table, src): 2023 """Copies the contents of an ndarray *src* into a given function *table*. 2024 2025 The *table* number is assumed to be valid, and the table needs to 2026 have sufficient space to receive all the array contents. 2027 """ 2028 ptr = src.ctypes.data_as(ct.POINTER(MYFLT)) 2029 libcsound.csoundTableCopyIn(self.cs, table, ptr) 2030 2031 def tableCopyInAsync(self, table, src): 2032 """Asynchronous version of :py:meth:`tableCopyIn()`.""" 2033 ptr = src.ctypes.data_as(ct.POINTER(MYFLT)) 2034 libcsound.csoundTableCopyInAsync(self.cs, table, ptr) 2035 2036 def table(self, tableNum): 2037 """Returns a pointer to function table *tableNum* as an ndarray. 2038 2039 The ndarray does not include the guard point. If the table does not 2040 exist, :code:`None` is returned. 2041 """ 2042 ptr = ct.POINTER(MYFLT)() 2043 size = libcsound.csoundGetTable(self.cs, ct.byref(ptr), tableNum) 2044 if size < 0: 2045 return None 2046 arrayType = np.ctypeslib.ndpointer(MYFLT, 1, (size,), 'C_CONTIGUOUS') 2047 p = ct.cast(ptr, arrayType) 2048 return arrFromPointer(p) 2049 2050 def tableArgs(self, tableNum): 2051 """Returns a pointer to the args used to generate a function table. 2052 2053 The pointer is returned as an ndarray. If the table does not exist, 2054 :code:`None` is returned. 2055 2056 NB: the argument list starts with the GEN number and is followed by 2057 its parameters. eg. f 1 0 1024 10 1 0.5 yields the list 2058 {10.0, 1.0, 0.5} 2059 """ 2060 ptr = ct.POINTER(MYFLT)() 2061 size = libcsound.csoundGetTableArgs(self.cs, ct.byref(ptr), tableNum) 2062 if size < 0: 2063 return None 2064 arrayType = np.ctypeslib.ndpointer(MYFLT, 1, (size,), 'C_CONTIGUOUS') 2065 p = ct.cast(ptr, arrayType) 2066 return arrFromPointer(p) 2067 2068 def isNamedGEN(self, num): 2069 """Checks if a given GEN number *num* is a named GEN. 2070 2071 If so, it returns the string length. Otherwise it returns 0. 2072 """ 2073 return libcsound.csoundIsNamedGEN(self.cs, num) 2074 2075 def namedGEN(self, num, nameLen): 2076 """Gets the GEN name from a GEN number, if this is a named GEN. 2077 2078 The final parameter is the max len of the string. 2079 """ 2080 s = ct.create_string_buffer(nameLen) 2081 libcsound.csoundGetNamedGEN(self.cs, num, s, nameLen) 2082 return pstring(string_at(s, nameLen)) 2083 2084 #Function Table Display 2085 def setIsGraphable(self, isGraphable): 2086 """Tells Csound whether external graphic table display is supported. 2087 2088 Return the previously set value (initially False). 2089 """ 2090 ret = libcsound.csoundSetIsGraphable(self.cs, ct.c_int(isGraphable)) 2091 return (ret != 0) 2092 2093 def setMakeGraphCallback(self, function): 2094 """Called by external software to set Csound's MakeGraph function.""" 2095 self.makeGraphCbRef = MAKEGRAPHFUNC(function) 2096 libcsound.csoundSetMakeGraphCallback(self.cs, self.makeGraphCbRef) 2097 2098 def setDrawGraphCallback(self, function): 2099 """Called by external software to set Csound's DrawGraph function.""" 2100 self.drawGraphCbRef = DRAWGRAPHFUNC(function) 2101 libcsound.csoundSetDrawGraphCallback(self.cs, self.drawGraphCbRef) 2102 2103 def setKillGraphCallback(self, function): 2104 """Called by external software to set Csound's KillGraph function.""" 2105 self.killGraphCbRef = KILLGRAPHFUNC(function) 2106 libcsound.csoundSetKillGraphCallback(self.cs, self.killGraphCbRef) 2107 2108 def setExitGraphCallback(self, function): 2109 """Called by external software to set Csound's ExitGraph function.""" 2110 self.exitGraphCbRef = EXITGRAPHFUNC(function) 2111 libcsound.csoundSetExitGraphCallback(self.cs, self.exitGraphCbRef) 2112 2113 #Opcodes 2114 def namedGens(self): 2115 """Finds the list of named gens.""" 2116 lst = [] 2117 ptr = libcsound.csoundGetNamedGens(self.cs) 2118 ptr = ct.cast(ptr, ct.POINTER(NamedGen)) 2119 while (ptr): 2120 ng = ptr.contents 2121 lst.append((pstring(ng.name), int(ng.genum))) 2122 ptr = ng.next 2123 return lst 2124 2125 def newOpcodeList(self): 2126 """Gets an alphabetically sorted list of all opcodes. 2127 2128 Should be called after externals are loaded by :py:meth:`compile_()`. 2129 Returns a pointer to the list of OpcodeListEntry structures and the 2130 number of opcodes, or a negative error code on failure. 2131 Make sure to call :py:meth:`disposeOpcodeList()` when done with the 2132 list. 2133 """ 2134 opcodes = None 2135 ptr = ct.cast(ct.POINTER(ct.c_int)(), ct.POINTER(OpcodeListEntry)) 2136 n = libcsound.csoundNewOpcodeList(self.cs, ct.byref(ptr)) 2137 if n > 0: 2138 opcodes = ct.cast(ptr, ct.POINTER(OpcodeListEntry * n)).contents 2139 return opcodes, n 2140 2141 def disposeOpcodeList(self, lst): 2142 """Releases an opcode list.""" 2143 ptr = ct.cast(lst, ct.POINTER(OpcodeListEntry)) 2144 libcsound.csoundDisposeOpcodeList(self.cs, ptr) 2145 2146 def appendOpcode(self, opname, dsblksiz, flags, thread, outypes, intypes, iopfunc, kopfunc, aopfunc): 2147 """Appends an opcode implemented by external software. 2148 2149 This opcode is added to Csound's internal opcode list. 2150 The opcode list is extended by one slot, and the parameters are copied 2151 into the new slot. 2152 2153 Returns zero on success. 2154 """ 2155 return libcsound.csoundAppendOpcode(self.cs, cstring(opname), dsblksiz, flags, thread,\ 2156 cstring(outypes), cstring(intypes),\ 2157 OPCODEFUNC(iopfunc),\ 2158 OPCODEFUNC(kopfunc), 2159 OPCODEFUNC(aopfunc)) 2160 2161 #Threading and Concurrency 2162 def setYieldCallback(self, function): 2163 """ 2164 Called by external software to set a yield function. 2165 2166 This callback is used for checking system events, yielding cpu time 2167 for coopertative multitasking, etc. 2168 2169 This function is optional. It is often used as a way to 'turn off' 2170 Csound, allowing it to exit gracefully. In addition, some operations 2171 like utility analysis routines are not reentrant and you should use 2172 this function to do any kind of updating during the operation. 2173 2174 Returns an 'OK to continue' boolean. 2175 """ 2176 self.yieldCbRef = YIELDFUNC(function) 2177 libcsound.csoundSetYieldCallback(self.cs, self.yieldCbRef) 2178 2179 def createThread(self, function, userdata): 2180 """Creates and starts a new thread of execution. 2181 2182 Returns an opaque pointer that represents the thread on success, 2183 or :code:`None` for failure. 2184 The *userdata* pointer is passed to the thread routine. 2185 """ 2186 ret = libcsound.csoundCreateThread(THREADFUNC(function), ct.py_object(userdata)) 2187 if (ret): 2188 return ret 2189 return None 2190 2191 def currentThreadId(self): 2192 """Returns the ID of the currently executing thread, or :code:`None` 2193 for failure. 2194 2195 NOTE: The return value can be used as a pointer 2196 to a thread object, but it should not be compared 2197 as a pointer. The pointed to values should be compared, 2198 and the user must free the pointer after use. 2199 """ 2200 ret = libcsound.csoundGetCurrentThreadId() 2201 if (ret): 2202 return ret 2203 return None 2204 2205 def joinThread(self, thread): 2206 """Waits until the indicated thread's routine has finished. 2207 2208 Returns the value returned by the thread routine. 2209 """ 2210 return libcsound.csoundJoinThread(thread) 2211 2212 def createThreadLock(self): 2213 """Creates and returns a monitor object, or :code:`None` if not successful. 2214 2215 The object is initially in signaled (notified) state. 2216 """ 2217 ret = libcsound.csoundCreateThreadLock() 2218 if (ret): 2219 return ret 2220 return None 2221 2222 def waitThreadLock(self, lock, milliseconds): 2223 """Waits on the indicated monitor object for the indicated period. 2224 2225 The function returns either when the monitor object is notified, 2226 or when the period has elapsed, whichever is sooner; in the first case, 2227 zero is returned. 2228 2229 If *milliseconds* is zero and the object is not notified, the function 2230 will return immediately with a non-zero status. 2231 """ 2232 return libcsound.csoundWaitThreadLock(lock, ct.c_uint(milliseconds)) 2233 2234 def waitThreadLockNoTimeout(self, lock): 2235 """Waits on the indicated monitor object until it is notified. 2236 2237 This function is similar to :py:meth:`waitThreadLock()` with an infinite 2238 wait time, but may be more efficient. 2239 """ 2240 libcsound.csoundWaitThreadLockNoTimeout(lock) 2241 2242 def notifyThreadLock(self, lock): 2243 """Notifies the indicated monitor object.""" 2244 libcsound.csoundNotifyThreadLock(lock) 2245 2246 def destroyThreadLock(self, lock): 2247 """Destroys the indicated monitor object.""" 2248 libcsound.csoundDestroyThreadLock(lock) 2249 2250 def createMutex(self, isRecursive): 2251 """Creates and returns a mutex object, or :code:`None` if not successful. 2252 2253 Mutexes can be faster than the more general purpose monitor objects 2254 returned by :py:meth:`createThreadLock()` on some platforms, and can 2255 also be recursive, but the result of unlocking a mutex that is owned by 2256 another thread or is not locked is undefined. 2257 2258 If *isRecursive'* id :code:`True`, the mutex can be re-locked multiple 2259 times by the same thread, requiring an equal number of unlock calls; 2260 otherwise, attempting to re-lock the mutex results in undefined 2261 behavior. 2262 2263 Note: the handles returned by :py:meth:`createThreadLock()` and 2264 :py:meth:`createMutex()` are not compatible. 2265 """ 2266 ret = libcsound.csoundCreateMutex(ct.c_int(isRecursive)) 2267 if ret: 2268 return ret 2269 return None 2270 2271 def lockMutex(self, mutex): 2272 """Acquires the indicated mutex object. 2273 2274 If it is already in use by another thread, the function waits until 2275 the mutex is released by the other thread. 2276 """ 2277 libcsound.csoundLockMutex(mutex) 2278 2279 def lockMutexNoWait(self, mutex): 2280 """Acquire the indicated mutex object. 2281 2282 Returns zero, unless it is already in use by another thread, in which 2283 case a non-zero value is returned immediately, rather than waiting 2284 until the mutex becomes available. 2285 2286 Note: this function may be unimplemented on Windows. 2287 """ 2288 return libcsound.csoundLockMutexNoWait(mutex) 2289 2290 def unlockMutex(self, mutex): 2291 """Releases the indicated mutex object. 2292 2293 The mutex should be owned by the current thread, otherwise the 2294 operation of this function is undefined. A recursive mutex needs 2295 to be unlocked as many times as it was locked previously. 2296 """ 2297 libcsound.csoundUnlockMutex(mutex) 2298 2299 def destroyMutex(self, mutex): 2300 """Destroys the indicated mutex object. 2301 2302 Destroying a mutex that is currently owned by a thread results 2303 in undefined behavior. 2304 """ 2305 libcsound.csoundDestroyMutex(mutex) 2306 2307 def createBarrier(self, max_): 2308 """Creates a Thread Barrier. 2309 2310 Max value parameter should be equal to the number of child threads 2311 using the barrier plus one for the master thread. 2312 """ 2313 ret = libcsound.csoundCreateBarrier(ct.c_uint(max_)) 2314 if (ret): 2315 return ret 2316 return None 2317 2318 def destroyBarrier(self, barrier): 2319 """Destroys a Thread Barrier.""" 2320 return libcsound.csoundDestroyBarrier(barrier) 2321 2322 def waitBarrier(self, barrier): 2323 """Waits on the thread barrier.""" 2324 return libcsound.csoundWaitBarrier(barrier) 2325 2326 #def createCondVar(self): 2327 #def condWait(self, condVar, mutex): 2328 #def condSignal(self, condVar): 2329 #def destroyCondVar(self, condVar): 2330 2331 def sleep(self, milliseconds): 2332 """Waits for at least the specified number of *milliseconds*. 2333 2334 It yields the CPU to other threads. 2335 """ 2336 libcsound.csoundSleep(ct.c_uint(milliseconds)) 2337 2338 def spinLockInit(self, spinlock): 2339 """Inits the spinlock. 2340 2341 If the spinlock is not locked, locks it and returns; 2342 if is is locked, waits until it is unlocked, then locks it and returns. 2343 Uses atomic compare and swap operations that are safe across processors 2344 and safe for out of order operations, 2345 and which are more efficient than operating system locks. 2346 2347 Use spinlocks to protect access to shared data, especially in functions 2348 that do little more than read or write such data, for example:: 2349 2350 lock = ctypes.ct.c_int32(0) 2351 cs.spinLockInit(lock) 2352 def write(cs, frames, signal): 2353 cs.spinLock(lock) 2354 for frame in range(frames) : 2355 global_buffer[frame] += signal[frame]; 2356 cs.spinUnlock(lock) 2357 """ 2358 return libcsound.csoundSpinLockInit(ct.byref(spinlock)) 2359 2360 def spinLock(self, spinlock): 2361 """Locks the spinlock.""" 2362 libcsound.csoundSpinLock(ct.byref(spinlock)) 2363 2364 def spinTryLock(self,spinlock): 2365 """Tries the spinlock. 2366 2367 returns CSOUND_SUCCESS if lock could be acquired, 2368 CSOUND_ERROR, otherwise. 2369 """ 2370 return libcsound.csoundSpinLock(ct.byref(spinlock)) 2371 2372 def spinUnlock(self, spinlock): 2373 """Unlocks the spinlock.""" 2374 libcsound.csoundSpinUnLock(ct.byref(spinlock)) 2375 2376 #Miscellaneous Functions 2377 def runCommand(self, args, noWait): 2378 """Runs an external command with the arguments specified in list *args*. 2379 2380 args[0] is the name of the program to execute (if not a full path 2381 file name, it is searched in the directories defined by the PATH 2382 environment variable). 2383 2384 If *noWait* is :code:`False`, the function waits until the external 2385 program finishes, otherwise it returns immediately. In the first case, 2386 a non-negative return value is the exit status of the command (0 to 2387 255), otherwise it is the PID of the newly created process. 2388 On error, a negative value is returned. 2389 """ 2390 n = len(args) 2391 argv = (ct.POINTER(ct.c_char_p) * (n+1))() 2392 for i in range(n): 2393 v = cstring(args[i]) 2394 argv[i] = ct.cast(ct.pointer(ct.create_string_buffer(v)), ct.POINTER(ct.c_char_p)) 2395 argv[n] = None 2396 return libcsound.csoundRunCommand(ct.cast(argv, ct.POINTER(ct.c_char_p)), ct.c_int(noWait)) 2397 2398 def initTimerStruct(self, timerStruct): 2399 """Initializes a timer structure.""" 2400 libcsound.csoundInitTimerStruct(ct.byref(timerStruct)) 2401 2402 def realTime(self, timerStruct): 2403 """Returns the elapsed real time (in seconds). 2404 2405 The time is measured since the specified timer structure was initialised. 2406 """ 2407 return libcsound.csoundGetRealTime(ct.byref(timerStruct)) 2408 2409 def CPUTime(self, timerStruct): 2410 """Returns the elapsed CPU time (in seconds). 2411 2412 The time is measured since the specified timer structure was initialised. 2413 """ 2414 return libcsound.csoundGetCPUTime(ct.byref(timerStruct)) 2415 2416 def randomSeedFromTime(self): 2417 """Returns a 32-bit unsigned integer to be used as seed from current time.""" 2418 return libcsound.csoundGetRandomSeedFromTime() 2419 2420 def setLanguage(self, lang_code): 2421 """Sets language to *lang_code*. 2422 2423 *lang_code* can be for example CSLANGUAGE_ENGLISH_UK or 2424 CSLANGUAGE_FRENCH or many others, (see n_getstr.h for the list of 2425 languages). This affects all Csound instances running in the address 2426 space of the current process. The special language code 2427 CSLANGUAGE_DEFAULT can be used to disable translation of messages and 2428 free all memory allocated by a previous call to setLanguage(). 2429 setLanguage() loads all files for the selected language 2430 from the directory specified by the CSSTRNGS environment 2431 variable. 2432 """ 2433 libcsound.csoundSetLanguage(lang_code) 2434 2435 def env(self, name, withCsoundInstance = True): 2436 """Gets the value of environment variable *name*. 2437 2438 The searching order is: local environment of Csound (if 2439 *withCsoundInstance* is :code:`True`), variables set with 2440 :py:meth:`setGlobalEnv()`, 2441 and system environment variables. If *withCsoundInstance* is 2442 :code:`True`, should be called after :py:meth:`compile_()`. 2443 2444 Return value is :code:`None` if the variable is not set. 2445 """ 2446 if withCsoundInstance: 2447 ret = libcsound.csoundGetEnv(self.cs, cstring(name)) 2448 else: 2449 ret = libcsound.csoundGetEnv(None, cstring(name)) 2450 if (ret): 2451 return pstring(ret) 2452 return None 2453 2454 def setGlobalEnv(self, name, value): 2455 """Sets the global value of environment variable *name* to *value*. 2456 2457 The variable is deleted if *value* is :code:`None`. It is not safe to 2458 call this function while any Csound instances are active. 2459 2460 Returns zero on success. 2461 """ 2462 return libcsound.csoundSetGlobalEnv(cstring(name), cstring(value)) 2463 2464 def createGlobalVariable(self, name, nbytes): 2465 """Allocates *nbytes* bytes of memory. 2466 2467 This memory can be accessed later by calling 2468 :py:meth`queryGlobalVariable()` with the specified name; the space is 2469 cleared to zero. 2470 2471 Returns CSOUND_SUCCESS on success, CSOUND_ERROR in case of invalid 2472 parameters (zero *nbytes*, invalid or already used *name*), or 2473 CSOUND_MEMORY if there is not enough memory. 2474 """ 2475 return libcsound.csoundCreateGlobalVariable(self.cs, cstring(name), ct.c_uint(nbytes)) 2476 2477 def queryGlobalVariable(self, name): 2478 """Gets pointer to space allocated with the name *name*. 2479 2480 Return :code:`None` if the specified *name* is not defined. 2481 """ 2482 ret = libcsound.csoundQueryGlobalVariable(self.cs, cstring(name)) 2483 if (ret): 2484 return ret 2485 return None 2486 2487 def queryGlobalVariableNoCheck(self, name): 2488 """This function is the similar to :py:meth`queryGlobalVariable()`. 2489 2490 Except the variable is assumed to exist and no error checking is done. 2491 Faster, but may crash or return an invalid pointer if *name* is 2492 not defined. 2493 """ 2494 return libcsound.csoundQueryGlobalVariableNoCheck(self.cs, cstring(name)) 2495 2496 def destroyGlobalVariable(self, name): 2497 """Frees memory allocated for *name* and remove *name* from the database. 2498 2499 Return value is CSOUND_SUCCESS on success, or CSOUND_ERROR if the *name* 2500 is not defined. 2501 """ 2502 return libcsound.csoundDestroyGlobalVariable(self.cs, cstring(name)) 2503 2504 def runUtility(self, name, args): 2505 """Runs utility with the specified *name* and command line arguments. 2506 2507 Should be called after loading utility plugins. 2508 Use :py:meth`reset()` to clean up after calling this function. 2509 Returns zero if the utility was run successfully. 2510 """ 2511 argc, argv = csoundArgList(args) 2512 return libcsound.csoundRunUtility(self.cs, cstring(name), argc, argv) 2513 2514 def listUtilities(self): 2515 """Returns a list of registered utility names. 2516 2517 The return value may be :code:`None` in case of an error. 2518 """ 2519 ptr = libcsound.csoundListUtilities(self.cs) 2520 if (ptr): 2521 i = 0 2522 lst = [] 2523 while (ptr[i]): 2524 lst.append(pstring(ptr[i])) 2525 i += 1 2526 libcsound.csoundDeleteUtilityList(self.cs, ptr) 2527 return lst 2528 return None 2529 2530 def utilityDescription(self, name): 2531 """Gets utility description. 2532 2533 Returns :code:`None` if the utility was not found, or it has no 2534 description, or an error occured. 2535 """ 2536 ptr = libcsound.csoundGetUtilityDescription(self.cs, cstring(name)) 2537 if (ptr): 2538 return pstring(ptr) 2539 return None 2540 2541 def rand31(self, seed): 2542 """Simple linear congruential random number generator:: 2543 2544 seed = seed * 742938285 % 2147483647 2545 2546 The initial value of *seed* must be in the range 1 to 2147483646. 2547 Returns the next number from the pseudo-random sequence, in the range 2548 1 to 2147483646. 2549 """ 2550 n = ct.c_int(seed) 2551 return libcsound.csoundRand31(ct.byref(n)) 2552 2553 def seedRandMT(self, initKey): 2554 """Initializes Mersenne Twister (MT19937) random number generator. 2555 2556 *initKey* can be a single int, a list of int, or an ndarray of int. 2557 Those int values are converted to unsigned 32 bit values and used for 2558 seeding. 2559 2560 Returns a CsoundRandMTState stuct to be used by :py:meth`csoundRandMT()`. 2561 """ 2562 state = CsoundRandMTState() 2563 if type(initKey) == int: 2564 if initKey < 0: 2565 initKey = -initKey 2566 libcsound.csoundSeedRandMT(ct.byref(state), None, ct.c_uint32(initKey)) 2567 elif type(initKey) == list or type(initKey) == np.ndarray: 2568 n = len(initKey) 2569 lst = (ct.c_uint32 * n)() 2570 for i in range(n): 2571 k = initKey[i] 2572 if k < 0 : 2573 k = -k 2574 lst[i] = ct.c_uint32(k) 2575 p = ct.pointer(lst) 2576 p = ct.cast(p, ct.POINTER(ct.c_uint32)) 2577 libcsound.csoundSeedRandMT(ct.byref(state), p, ct.c_uint32(len(lst))) 2578 return state 2579 2580 def randMT(self, state): 2581 """Returns next random number from MT19937 generator. 2582 2583 The PRNG must be initialized first by calling :py:meth`csoundSeedRandMT()`. 2584 """ 2585 return libcsound.csoundRandMT(ct.byref(state)) 2586 2587 def createCircularBuffer(self, numelem, elemsize): 2588 """Creates a circular buffer with *numelem* number of elements. 2589 2590 The element's size is set from *elemsize*. It should be used like:: 2591 2592 rb = cs.createCircularBuffer(1024, cs.sizeOfMYFLT()) 2593 """ 2594 return libcsound.csoundCreateCircularBuffer(self.cs, numelem, elemsize) 2595 2596 def readCircularBuffer(self, circularBuffer, out, items): 2597 """Reads from circular buffer. 2598 2599 *circular_buffer* 2600 pointer to an existing circular buffer 2601 *out* 2602 preallocated ndarray with at least items number of elements, 2603 where buffer contents will be read into 2604 *items* 2605 number of samples to be read 2606 2607 Returns the actual number of items read (0 <= n <= items). 2608 """ 2609 if len(out) < items: 2610 return 0 2611 ptr = out.ctypes.data_as(ct.c_void_p) 2612 return libcsound.csoundReadCircularBuffer(self.cs, circularBuffer, ptr, items) 2613 2614 def peekCircularBuffer(self, circularBuffer, out, items): 2615 """Reads from circular buffer without removing them from the buffer. 2616 2617 *circular_buffer* 2618 pointer to an existing circular buffer 2619 *out* 2620 preallocated ndarray with at least items number of elements, 2621 where buffer contents will be read into 2622 *items* 2623 number of samples to be read 2624 2625 Returns the actual number of items read (0 <= n <= items). 2626 """ 2627 if len(out) < items: 2628 return 0 2629 ptr = out.ctypes.data_as(ct.c_void_p) 2630 return libcsound.csoundPeekCircularBuffer(self.cs, circularBuffer, ptr, items) 2631 2632 def writeCircularBuffer(self, circularBuffer, in_, items): 2633 """Writes to circular buffer. 2634 2635 *circular_buffer* 2636 pointer to an existing circular buffer 2637 *in_* 2638 ndarray with at least items number of elements to be written 2639 into circular buffer 2640 *items* 2641 number of samples to write 2642 2643 Returns the actual number of items written (0 <= n <= items). 2644 """ 2645 if len(in_) < items: 2646 return 0 2647 ptr = in_.ctypes.data_as(ct.c_void_p) 2648 return libcsound.csoundWriteCircularBuffer(self.cs, circularBuffer, ptr, items) 2649 2650 def flushCircularBuffer(self, circularBuffer): 2651 """Empties circular buffer of any remaining data. 2652 2653 This function should only be used if there is no reader actively 2654 getting data from the buffer. 2655 2656 *circular_buffer* 2657 pointer to an existing circular buffer 2658 """ 2659 libcsound.csoundFlushCircularBuffer(self.cs, circularBuffer) 2660 2661 def destroyCircularBuffer(self, circularBuffer): 2662 """Frees circular buffer.""" 2663 libcsound.csoundDestroyCircularBuffer(self.cs, circularBuffer) 2664 2665 def openLibrary(self, libraryPath): 2666 """Platform-independent function to load a shared library.""" 2667 ptr = ct.POINTER(ct.c_int)() 2668 library = ct.cast(ptr, ct.c_void_p) 2669 ret = libcsound.csoundOpenLibrary(ct.byref(library), cstring(libraryPath)) 2670 return ret, library 2671 2672 def closeLibrary(self, library): 2673 """Platform-independent function to unload a shared library.""" 2674 return libcsound.csoundCloseLibrary(library) 2675 2676 def getLibrarySymbol(self, library, symbolName): 2677 """Platform-independent function to get a symbol address in a shared library.""" 2678 return libcsound.csoundGetLibrarySymbol(library, cstring(symbolName)) 2679 2680 2681if sys.platform.startswith('linux'): 2682 libcspt = ct.CDLL("libcsnd6.so") 2683elif sys.platform.startswith('win'): 2684 if sys.version_info.major <=3 and sys.version_info.minor < 8: 2685 libcspt = ct.cdll.csnd6 2686 else: 2687 libcspt = ct.CDLL(ctypes.util.find_library("csnd6")) 2688elif sys.platform.startswith('darwin'): 2689 libcspt = ct.CDLL("libcsnd6.6.0.dylib") 2690else: 2691 sys.exit("Don't know your system! Exiting...") 2692 2693libcspt.NewCsoundPT.restype = ct.c_void_p 2694libcspt.NewCsoundPT.argtypes = [ct.c_void_p] 2695libcspt.DeleteCsoundPT.argtypes = [ct.c_void_p] 2696libcspt.CsoundPTisRunning.argtypes = [ct.c_void_p] 2697PROCESSFUNC = ct.CFUNCTYPE(None, ct.c_void_p) 2698libcspt.CsoundPTgetProcessCB.restype = ct.c_void_p 2699libcspt.CsoundPTgetProcessCB.argtypes = [ct.c_void_p] 2700libcspt.CsoundPTsetProcessCB.argtypes = [ct.c_void_p, PROCESSFUNC, ct.c_void_p] 2701libcspt.CsoundPTgetCsound.restype = ct.c_void_p 2702libcspt.CsoundPTgetCsound.argtypes = [ct.c_void_p] 2703libcspt.CsoundPTgetStatus.argtypes = [ct.c_void_p] 2704libcspt.CsoundPTplay.argtypes = [ct.c_void_p] 2705libcspt.CsoundPTpause.argtypes = [ct.c_void_p] 2706libcspt.CsoundPTtogglePause.argtypes = [ct.c_void_p] 2707libcspt.CsoundPTstop.argtypes = [ct.c_void_p] 2708libcspt.CsoundPTrecord.argtypes = [ct.c_void_p, ct.c_char_p, ct.c_int, ct.c_int] 2709libcspt.CsoundPTstopRecord.argtypes = [ct.c_void_p] 2710libcspt.CsoundPTscoreEvent.argtypes = [ct.c_void_p, ct.c_int, ct.c_char, ct.c_int, ct.POINTER(MYFLT)] 2711libcspt.CsoundPTinputMessage.argtypes = [ct.c_void_p, ct.c_char_p] 2712libcspt.CsoundPTsetScoreOffsetSeconds.argtypes = [ct.c_void_p, ct.c_double] 2713libcspt.CsoundPTjoin.argtypes = [ct.c_void_p] 2714libcspt.CsoundPTflushMessageQueue.argtypes = [ct.c_void_p] 2715 2716 2717class CsoundPerformanceThread: 2718 """Performs a score in a separate thread until the end of score is reached. 2719 2720 The playback (which is paused by default) is stopped by calling 2721 :py:meth:`stop()`, or if an error occurs. 2722 The constructor takes a Csound instance pointer as argument; it assumes 2723 that :py:meth:`ctcsound.compile_()` was called successfully before creating 2724 the performance thread. Once the playback is stopped for one of the above 2725 mentioned reasons, the performance thread calls :py:meth:`ctcsound.cleanup()` 2726 and returns. 2727 """ 2728 def __init__(self, csp): 2729 self.cpt = libcspt.NewCsoundPT(csp) 2730 2731 def __del__(self): 2732 libcspt.DeleteCsoundPT(self.cpt) 2733 2734 def isRunning(self): 2735 """Returns :code:`True` if the performance thread is running, :code:`False` otherwise.""" 2736 return libcspt.CsoundPTisRunning(self.cpt) != 0 2737 2738 def processCB(self): 2739 """Returns the process callback.""" 2740 return PROCESSFUNC(libcspt.CsoundPTgetProcessCB(self.cpt)) 2741 2742 def setProcessCB(self, function, data): 2743 """Sets the process callback.""" 2744 libcspt.CsoundPTsetProcessCB(self.cpt, PROCESSFUNC(function), ct.byref(data)) 2745 2746 def csound(self): 2747 """Returns the Csound instance pointer.""" 2748 return libcspt.CsoundPTgetCsound(self.cpt) 2749 2750 def status(self): 2751 """Returns the current status. 2752 2753 Zero if still playing, positive if the end of score was reached or 2754 performance was stopped, and negative if an error occured. 2755 """ 2756 return libcspt.CsoundPTgetStatus(self.cpt) 2757 2758 def play(self): 2759 """Continues performance if it was paused.""" 2760 libcspt.CsoundPTplay(self.cpt) 2761 2762 def pause(self): 2763 """Pauses performance (can be continued by calling :py:meth:`play()`).""" 2764 libcspt.CsoundPTpause(self.cpt) 2765 2766 def togglePause(self): 2767 """Pauses or continues performance, depending on current state.""" 2768 libcspt.CsoundPTtogglePause(self.cpt) 2769 2770 def stop(self): 2771 """Stops performance (cannot be continued).""" 2772 libcspt.CsoundPTstop(self.cpt) 2773 2774 def record(self, filename, samplebits, numbufs): 2775 """Starts recording the output from Csound. 2776 2777 The sample rate and number of channels are taken directly from the 2778 running Csound instance. 2779 """ 2780 libcspt.CsoundPTrecord(self.cpt, cstring(filename), samplebits, numbufs) 2781 2782 def stopRecord(self): 2783 """Stops recording and closes audio file.""" 2784 libcspt.CsoundPTstopRecord(self.cpt) 2785 2786 def scoreEvent(self, absp2mode, opcod, pFields): 2787 """Sends a score event. 2788 2789 The event has type *opcod* (e.g. 'i' for a note event). 2790 *pFields* is tuple, a list, or an ndarray of MYFLTs with all the pfields 2791 for this event, starting with the p1 value specified in *pFields[0]*. 2792 If *absp2mode* is non-zero, the start time of the event is measured 2793 from the beginning of performance, instead of the default of relative 2794 to the current time. 2795 """ 2796 p = np.array(pFields).astype(MYFLT) 2797 ptr = p.ctypes.data_as(ct.POINTER(MYFLT)) 2798 numFields = p.size 2799 libcspt.CsoundPTscoreEvent(self.cpt, ct.c_int(absp2mode), cchar(opcod), numFields, ptr) 2800 2801 def inputMessage(self, s): 2802 """Sends a score event as a string, similarly to line events (-L).""" 2803 libcspt.CsoundPTinputMessage(self.cpt, cstring(s)) 2804 2805 def setScoreOffsetSeconds(self, timeVal): 2806 """Sets the playback time pointer to the specified value (in seconds).""" 2807 libcspt.CsoundPTsetScoreOffsetSeconds(self.cpt, ct.c_double(timeVal)) 2808 2809 def join(self): 2810 """Waits until the performance is finished or fails. 2811 2812 Returns a positive value if the end of score was reached or 2813 :py:meth:`stop()` was called, and a negative value if an error occured. 2814 Also releases any resources associated with the performance thread 2815 object. 2816 """ 2817 return libcspt.CsoundPTjoin(self.cpt) 2818 2819 def flushMessageQueue(self): 2820 """Waits until all pending messages are actually received. 2821 2822 (pause, send score event, etc.) 2823 """ 2824 libcspt.CsoundPTflushMessageQueue(self.cpt) 2825 2826