Routing the output of ctcsound to /dev/null

Hi,

I’m using the ctcsound API to control the rendering process with performKsmps(). I’m analysing every k and using the analysis to train a Pytorch model.

I would like to send the output of the ctcsound rendering to /dev/null. I basically want to achieve what –logfile=null does, but as it says in the docs, this option only works when calling Csound from the command line. Is there a way to achieve this through the ctcsound API?

I’ve tried to set sys.stdout and sys.stderr to /dev/null within a context, as suggested here. That works for pure Python code, but not for the parts that make calls to Csound.

Routing all the Python logs to /dev/null is not an option since I want to be able to log other parts of my program.

Any ideas?

Hi @ulrikah I’m not overly familiar with the Phyton bindings, but can’t you use csoundSetOption() to specify what command line flags you wish to put in place?

Unfortunately, that doesn’t seem to work. I’ve tried with some variations of the same option, and all seem to give me a CSOUND_SUCCESS. However, even illegal options seem to give the same success code.

The result is that Csound renders, but with all the standard logging.

Here is the code for ref:

import sys
import ctcsound

csd_text = '''
  <CsoundSynthesizer>
  <CsOptions>
    -odac
  </CsOptions>
  <CsInstruments>
  instr 1
    out(linen(oscili(p4,p5),0.1,p3,0.1))
  endin
  </CsInstruments>
  <CsScore>
  i1 0 5 1000 440
  </CsScore>
  </CsoundSynthesizer>'''

cs = ctcsound.Csound()
options = [
    "--logfile=null",
    "-O null",
    "-Onull",
    "illegal_option"
]
for option in options:
    if cs.setOption(option) != 0:
        raise Exception("Illegal option", option)
result = cs.compileCsdText(csd_text)
result = cs.start()
while True:
    result = cs.performKsmps()
    if result != 0:
        break
result = cs.cleanup()
cs.reset()
del cs
sys.exit(result)

Can you create your own message callback and then simply ignore everything that gets piped to it from Csound?

I prefer to use the message buffer, where you can pull and pop messages from it at your leisure.

Again, I’ve no idea how these are implemented in ctcsound…

That seems to have removed most of the output. Thanks!

However, there is still some meta information that gets printed when I use messages:

0dBFS level = 32768.0
--Csound version 6.15 (double samples) Nov 20 2020
[commit: 18c2c7897425f462b9a7743cee157cb410c88198]
libsndfile-1.0.28
0dBFS level = 32768.0
--Csound version 6.15 (double samples) Nov 20 2020
[commit: 18c2c7897425f462b9a7743cee157cb410c88198]
libsndfile-1.0.28
end of score.		   overall amps:      0.0
	   overall samples out of range:        0
0 errors in performance
Elapsed time at end of performance: real: 0.000s, CPU: 0.000s

Hmm, I’m not sure how to get rid of that. I think we might need to ping @stevenyi!

I’m not too familiar with this part of the codebase, but I seem to remember similar issues discussed on the mailing list some time back. If there’s some example code that uses setMessageCallback() I can do a debug session to investigate.

Actually, it seems like setMessageCallback() is deprecated in the latest version of ctcsound.py.

Right now, instead of creating a callback, I’m simply deleting the content of the buffer when I’m done rendering.

just to let you know that i asked françois pinot (the author of
ctcsound) about this because he is not on this forum. his reply was:

I’m afraid it’s not a ctcsound problem. You can try this in a python
console:

import ctcsound
cs = ctcsound.Csound()
0dBFS level = 32768.0
–Csound version 6.15 (double samples) Oct 29 2020
[commit: 89d14ffa12fcac632181b309dc5e4f3cf7b73085]
libsndfile-1.0.28

del cs
end of score. overall amps: 0.0
overall samples out of range: 0
0 errors in performance
Elapsed time at end of performance: real: 3.063s, CPU: 0.001s

We see that python systematically echoes what’s coming back from
ctcsound. For me, it’s a python problem…

best -
joachim

1 Like

Yes there’s a bit of a chicken and egg issue here with Csound printing right at instantiation. I had to look again and in the C API there is this function:

PUBLIC void csoundSetDefaultMessageCallback(
           void (*csoundMessageCallback)(CSOUND *csound,
                                         int attr,
                                         const char *format,
                                         va_list args))
{
    if (csoundMessageCallback) {
      msgcallback_ = csoundMessageCallback;
    } else {
      msgcallback_ = csoundDefaultMessageCallback;
    }
}

That sets the default message callback. This is also used by the logging system. It is part of the C API but is not available in ctcsound.py. I wonder if this could be added to ctcsound to accomodate messages that happen during csound creation and deletion.

1 Like

ctypes does not provide a clear way of dealing with varargs functions and I have actually no much time to study the problem. But I did add setDefaultMessageCallback to ctcsound.py; it’s not fully implemented but it will allow you to define a noMessage callback like this:

import ctcsound
import sys

def noMessage(csound, attr, flags, *args):
    pass

csd_text = '''
  <CsoundSynthesizer>
  <CsOptions>
    -odac
  </CsOptions>
  <CsInstruments>
  instr 1
    out(linen(oscili(p4,p5),0.1,p3,0.1))
  endin
  </CsInstruments>
  <CsScore>
  i1 0 5 1000 440
  </CsScore>
  </CsoundSynthesizer>'''

ctcsound.setDefaultMessageCallback(noMessage)
cs = ctcsound.Csound()

result = cs.compileCsdText(csd_text)
result = cs.start()
while True:
    result = cs.performKsmps()
    if result != 0:
        break
result = cs.cleanup()
cs.reset()
del cs
sys.exit(result)

I hope this will help you and I’ll come back to this when I have more time…

You can download the new ctcsound.py file directly from github (https://github.com/csound/csound/blob/develop/interfaces/ctcsound.py

Regards

François

1 Like