Cabbage Logo
Back to Cabbage Site

Problem with an if statement or the score section

I know this forum is for Cabbage related questions but I couldn’t get any answers in the Csound forum and I’m desperate for help.
I have this if statement but it only runs on the first time. I’m trying to send a pitch bend message everytime the C note is pressed.

<CsOptions>
; Select audio/midi flags here according to platform
; Audio out   Audio in    No messages
-+rtmidi=NULL -M0 -Q0 ;;;RT audio I/O with MIDI in
; For Non-realtime ouput leave only the line below:
; -o midiin.wav -W ;;; for file output any platform
</CsOptions>

<CsInstruments>

sr        =  44100
ksmps     =  10
nchnls    =  1

massign         0, 130 
pgmassign       0, 130  

instr   130

kstatus, kchan, kdata1, kdata2                  midiin


if (kstatus == 144 && kdata1%12==0 &&kdata2>0 ) then


outkpb 1, 70, -200, 200

endif
if (kstatus == 144 && kdata1%12==1 &&kdata2>0 ) then


outkpb 1, 30, -200, 200

endif

  endin

</CsInstruments>

<CsScore>
i130 0 3600
e
</CsScore>


</CsoundSynthesizer> 

Is it a problem with the score section? I tried a while loop but I get the same result.

You have a closing CsoundSynthesizer but you don’t appear to have an opening one? Or is that simple a copy/paste error?

I added the missing tag and it runs for me. But I don’t have a device with a pitch bend wheel. I suspect kdata1%12==0 might be an issue. If I remove it, those if blocks are hit as epected:

<Cabbage>
form size(500, 300), caption("Untitled")
keyboard bounds(10, 27, 400, 100) channel("keyboard10000")
</Cabbage>
<CsoundSynthesizer>
<CsOptions>
-+rtmidi=NULL -M0 -Q0 ;;RT audio I/O with MIDI in
</CsOptions>

<CsInstruments>

sr        =  44100
ksmps     =  10
nchnls    =  1

massign         0, 130 
pgmassign       0, 130  

instr   130

kstatus, kchan, kdata1, kdata2                  midiin

if (kstatus == 144 && kdata2>0 ) then
    printks "kdata1", 0
endif

if (kstatus == 144 && kdata2>0 ) then
    printks "kdata2", 0
endif

endin

</CsInstruments>

<CsScore>
i130 0 3600
</CsScore>
1 Like

I might be off topic but I experienced issues with “if” statements and solved them by adding more parenthesis

Ex, instead of:

if (kstatus == 144 && kdata1%12==1 &&kdata2>0 )

Maybe try:

if ((kstatus==144) && (kdata1%12==1) && (kdata2>0 ))

I am not sure it’s the root cause though, but it’s worth trying it since it solved one of my errors.

1 Like

I need the kdata1 because I will build turkish microtonal scales with this. I want specific pitch bend values to happen when I press specific keys.
Edit: I now checked and it was a copy paste error. I have the opening csound synthesizer part in my original code.

Thank you, your method seems more organized anyway.

Here is a really crazy thing.
ps:selam means hello in turkish.

<Cabbage>
form size(500, 300), caption("Untitled")
keyboard bounds(10, 27, 400, 100) channel("keyboard10000")
</Cabbage>
<CsoundSynthesizer>
<CsOptions>
-+rtmidi=NULL -M0 -Q0 ;;RT audio I/O with MIDI in
</CsOptions>

<CsInstruments>

sr        =  44100
ksmps     =  10
nchnls    =  1

massign         0, 130 
pgmassign       0, 130  

instr   130

kstatus, kchan, kdata1, kdata2                  midiin




if ((kstatus == 144) && (kdata1%12==0) ) then
      prints "selam"
      outkpb 1, 70, -200, 200
    endif
endin

</CsInstruments>

<CsScore>
i130 0 3600
</CsScore>

When I run this code, The pitch bend function runs only once and only with the C note. When I check the console, regardless of which note I play, the print function works and not only once. How can an if statement work this way? If it only took action when the C note was pressed, why did I see selam every time I played random notes on the console? If not why doesn’t it send a pitch wheel message when I play any other note(I restarted before trying other keys so it’s not because it already sent it and won’t send it the second time.)?

That’s an i-rate print function. You’re mixing i and k rate. Expect odd results.

Ohh that was my bad sorry. It works now even though the outkpb only works once.

I might be able to get access to a MIDI device with pitchbend wheel during the week. If I do I will test this out. :+1:

I’m looking forward to it. It just doesn’t make any sense that it only does it once.

Depends if you are using printks or printf. Printf is probably a better option but requires a ktrig value that has to change to print more than once. Perhaps there’s another solution but this seems to work.

kprint  init 0
ktrig   changed kstatus
    if  ktrig == 1 then
        kprint += 1
    endif
    
    if  kstatus == 144 && kdata1 % 12 == 0 then
        printf "\nselam\n", kprint
        outkpb 1, 70, -200, 200
    endif

Thank you for the advice. I actually solved the issue with the printing part, which was basically a test to see where the problem was. The if loop by itself works fine, I get the “selam” print everytime I play a C note from my MIDI keyboard. I just don’t understand why it sends the pitch bend message only once. I tried adding a second if statement for a B note to see if the pitch bend value needed to change before sending it again but it didn’t work either. They both run only once. Sometimes the code seems to trigger a new midi alloc(ation?) on its own and then it sends one more but I’m not sure how it does that.

What is this about? I don’t follow your use modulus here? I just now get my hands on a device with pitchbend, and it does seem a little strange. The status byte is only 224 momentarily, which messes up the if the statement. Have you considering using the midipitchbend opcode instead?

kdata1 is the midi note number of the midi message. kstatus is the note on. kdata1 changes accordingly to the midi message type. I use it to determine which note is played. So if kdata1 is perfectly dividable with 12, then it’s a C note.
Edit: Doesn’t midipitchbend opcode only return the value? I want the code to output pitchbend values that I set.

Why not simplify it. Use the midi interop command line flags and then simply check if the note is middle C?

<CsoundSynthesizer>
<CsOptions>
-+rtmidi=NULL -M0 --midi-key=4 -Q0 ;;RT audio I/O with MIDI in
</CsOptions>

<CsInstruments>
ksmps = 32

instr   1
    if p4 == 60 then
          printks "Output pitch bend data", 1
    endif
endin

</CsInstruments>
<CsScore>
i1 0 z
</CsScore>
</CsoundSynthesizer>

Where can I learn more about those? I might have to add the %12==0 part again because I want it to perform on every octave.

Yeah the modulus will work fine there. You can read about those command line flags here. Just scroll down to the --midi ones…

I played around with this one. The outkpb still only works once. The modulus with p4 seems to make everything worse.It goes into a state where if a second passes any key triggers the print.Also, the midi key command line flag returns values that are shifted(Ex:C1 has a midi note number of 24 but p4 returns it as 36 and the order of other notes isn’t broken.). Without the modulus the printks works okay but again, no luck with the pitch bend.

<CsoundSynthesizer>
<CsOptions>
-+rtmidi=NULL -M0 --midi-key=4 -Q0 ;;RT audio I/O with MIDI in
</CsOptions>

<CsInstruments>
ksmps = 32

instr   1

    if (p4==36) then
          printks "Output pitch bend data", 1
          outkpb 1, 70, -200, 200
    endif
endin

</CsInstruments>
<CsScore>
i1 0 z
</CsScore>
</CsoundSynthesizer>

I won’t have access to a MIDI keyboard again until Thurday, but I’ll try then. The problem is I have no clear way of testing the output from the pitch bend opcode. Try replacing the i1 0 z in the score with f0 z so that the instrument is only triggered to play with the keyboard rather than the score.

According to who? There is no standard numbering for MIDI octaves. According to the MIDI specificiation middle C is C60, but afaik, C3/C4 etc are not defined in those specs. Which is many synth manufacturers use different octave numbering.