convertion of local string variable to global float variable

Hi Guys, I’m working on a Csound code where I’m trying to convert local string variables to global float variables. I’ve been trying to use both strtodk and strtod , but I keep encountering an error where strtodk reads an empty string. Could anyone help me figure out how these opcodes need to be used correctly to avoid this issue? Below is the code snippet I’ve been working on:

<CsoundSynthesizer>
<CsOptions>
-odac
</CsOptions>
<CsInstruments>

sr = 44100
ksmps = 128
nchnls = 2
0dbfs = 1

instr 2

read:
Sline, kLineNum readf "config.txt"
printk 0,kLineNum
printf "Line %d: %s", kLineNum, kLineNum, Sline
if (kLineNum==1) then
printks "Sline(volume) : %s",1,Sline
kVol strtodk Sline
printks " kVol:%s\n", 1, kVol
gkVol = kVol

printks "global value(float): %f\n",8, gkVol
elseif (kLineNum==2) then
printks "Sline(pause) : %s\n",1,Sline
kPause strtodk Sline
printks "kPause : %s\n",1, kPause

gkPause = kPause
printks "global pause(float) :%f\n",8, gkPause

endif

if (kLineNum<2) kgoto read
turnoff

endin

</CsInstruments>
<CsScore>
i2 0 1 ; Read and store values
</CsScore>
</CsoundSynthesizer>

Here is the error message I’m receiving:

SECTION 1:

new alloc for instr 2:
INIT ERROR in instr 2 (opcode (null)) line 20: strtodk: empty string
from file arc54.csd (1)
kVol strtodk Sline
B 0.000 - note deleted. i2 had 1 init errors
End of Performance inactive allocs returned to freespace
overall amps: 0.00000 0.00000
overall samples out of range: 0 0
1 errors in performance
Elapsed time at end of performance: real: 0.184s, CPU: 0.004s
0 512 sample blks of 64-bit floats written to dac

Maybe you can first check the string using strlenk to make sure it is valid?

<CsoundSynthesizer>
<CsOptions>
-odac
</CsOptions>
<CsInstruments>
sr = 44100
ksmps = 128
nchnls = 2
0dbfs = 1

gkVolume init 0     ; Global float variable for volume
gkPause init 0      ; Global float variable for pause

instr 2
  kLineNum init 0
  Sline init ""
  
  read:
    Sline, kLineNum readf "config.txt"
    printk 0, kLineNum
    printf "Sline %d: %s\n", kLineNum, kLineNum, Sline

    kLen strlenk Sline
    if (kLen > 0) then
        if (kLineNum == 1) then
            kVol strtodk Sline
            gkVolume = kVol
            printks "global volume (float): %f\n", 1, gkVolume
        elseif (kLineNum == 2) then
            kPause strtodk Sline
            gkPause = kPause
            printks "global pause (float): %f\n", 1, gkPause
        endif
    else
        printks "Warning: Skipping empty line %d\n", 1, kLineNum
    endif

    if (kLineNum < 2) kgoto read

  turnoff
endin

</CsInstruments>
<CsScore>
i2 0 1
</CsScore>
</CsoundSynthesizer>

Tried using strlenk as adviced, below is the output i got

SECTION 1:
new alloc for instr 2:
INIT ERROR in instr 2 (opcode init.k) line 27: strtodk: empty string
 from file arc54_try_01.csd (1)
kVol    strtodk Sline
          B  0.000 - note deleted.  i2 had 1 init errors
End of Performance inactive allocs returned to freespace
                   overall amps:  0.00000  0.00000
           overall samples out of range:        0        0
1 errors in performance
Elapsed time at end of performance: real: 0.184s, CPU: 0.004s
0 512 sample blks of 64-bit floats written to dac

So if i comment out strtodk, Sline is able to print out the values correctly
Below is the output when i comment out strtodk

SECTION 1:
new alloc for instr 2:
instr 2:        time     0.00000:     1.00000
Sline 1: 0.1
instr 2:        time     0.00000:     2.00000
Sline 2: 0.5
B  0.000 ..  1.000 T  1.001 TT  1.001 M:  0.00000  0.00000

or if i hardcode the value of Sline i’m able to use strtodk correctly

instr 2
    Sline  = "0.1"
    printks "Sline: %s\n", 1, Sline
    gkVol strtodk Sline
    printks "global variable (float): %f\n",8, gkVol
endin

Output:

SECTION 1:
new alloc for instr 2:
Sline: 0.1
global variable (float): 0.100000
B  0.000 ..  1.000 T  1.001 TT  1.001 M:  0.00000  0.00000

can you please help me understand why strtodk keeps throwing an empty string error on my main code, or is it possible for you to provide me a snippet of code for better explanation?

Hi!

I remember I had problems with strtod at some point and assumed that strtod wants the String to be evaluated in i-time to works.
Can you try to rewrite your codes so that reading the file happens in i-time with https://csound.com/docs/manual/readfi.html

Hope it helps.

tarmo

Kontakt Sanjana Bhat via The Csound Community (<noreply@forum.csound.com>) kirjutas kuupäeval E, 7. aprill 2025 kell 10:19:

Hi @Sanjana_Bhat I tested this here, and it looks like @tarmo is right. The strtodk opcode needs string to be valid at i-time. And it seems that the readf opcode doesn’t produce valid strings at i-time which is what causes the problem. I’m surprised by this. Tarmo’s suggestion is probably the best thing. You could write all teh value in the file to an array at i-time, an then read through them later as needed.

Tried using readfi on both strtod and strtodk

Using strtodk:

instr 2
  kLineNum init 0
  Sline init ""
  
  read:
    Sline, iLineNum readfi "config.txt"
    printk 0, kLineNum
    printf_i "Sline %d: %s", iLineNum, iLineNum, Sline

    kLen strlenk Sline
    if (kLen > 0) then
        if (kLineNum == 1) then
            kVol strtodk Sline
            gkVolume = kVol
            printks "global volsume (float): %f\n", 1, gkVolume
        elseif (kLineNum == 2) then
            kPause strtodk Sline
            gkPause = kPause
            printks "global pause (float): %f\n", 1, gkPause
        endif
    else
        printks "Warning: Skipping empty line %d\n", 1, kLineNum
    endif

    if (kLineNum < 2) kgoto read

  turnoff
endin

Output:

SECTION 1:
new alloc for instr 2:
Sline 1: 0.1
INIT ERROR in instr 2 (opcode init.k) line 27: strtodk: invalid format
 from file arc54_try_01.csd (1)
kVol    strtodk Sline
          B  0.000 - note deleted.  i2 had 1 init errors
End of Performance inactive allocs returned to frees

Using strtod:

instr 1
    Sline init ""
    iLineNum init 0
    iVal init 0
    
    read:
        Sline, iLineNum readfi "config.txt"
        printf_i "Line %d: %s\n", iLineNum, iLineNum, Sline
        
        if (iLineNum == 1) then
            iVal strtod Sline
            gkVolume = iVal
            printf_i "Global volume(float): %f\n", 1, gkVolume
        elseif (iLineNum == 2) then
            iVal strtod Sline
            gkPause = iVal
            printf_i "Global Pause(float): %f\n", 1, gkPause
        endif
        
        if iLineNum != -1 igoto read
endin

Ouput:

SECTION 1:
new alloc for instr 1:
Line 1: 0.1

INIT ERROR in instr 1 (opcode init.k) line 25: strtod: invalid format
 from file arc54.csd (1)
iVal    strtod  Sline
          B  0.000 - note deleted.  i1 had 1 init errors
End of Performance inactive allocs returned to freespace
                   overall amps:  0.00000  0.00000

I used these opcodes according to the manual but they seem to be showing some errors

Wonder if the initial version would work by adding an init to a valid value as a workaround, something like:

    Sline, kLineNum readf "config.txt"
    Sline init "0"

@stevenyi This sort of overwrites the string that is read from the file

read:
        Sline, iLineNum readfi "config.txt"
        Sline init "0"
SECTION 1:
new alloc for instr 1:
Line 1: 0
Global volume(float): 0.000000
Line 2: 0
Global Pause(float): 0.000000

and if i use Sline init " ", i get back with the same error

read:
        Sline, iLineNum readfi "config.txt"
        Sline init ""
        printf_i "Line %d: %s\n", iLineNum, iLineNum, Sline
SECTION 1:
new alloc for instr 1:
Line 1: 
INIT ERROR in instr 1 (opcode init.k) line 26: strtod: empty string
 from file arc54.csd (1)
iVal    strtod  Sline
          B  0.000 - note deleted.  i1 had 1 init errors
End of Performance inactive allocs returned to freespace

Yes, this will work Steven :slight_smile: I tried something similar, but put the init before the call to readf which didn’t work. Nice. This is a simple solution.

@Sanjana_Bhat I tried your latest code and get the same isues. In this instance Steven’s trick won’t work, but I guess the k-rate code is more useful to you anyway.

@rory Is it possible for code snippet explanation for this?

Just add Sline init "0" after the call to readf. Works fine here.

@rory so i can go ahead and use readf with strtodk or strtod ,or do i have to use readfi?

Correct. You should still check for valid strings though.

instr 2
  ;kLineNum init 0
  
  read:
    Sline, kLineNum readf "config.txt"
    Sline init "0"
    printf "Sline %d: %s\n", kLineNum, kLineNum, Sline

    kLen strlenk Sline
    if (kLen > 0) then
        if (kLineNum == 1) then
            iVol strtod Sline
            gkVolume = iVol
            printks "global volume (float): %f\n", 1, gkVolume
        elseif (kLineNum == 2) then
            iPause strtod Sline
            gkPause = iPause
            printks "global pause (float): %f\n", 1, gkPause
        endif
    else
        printks "Warning: Skipping empty line %d\n", 1, kLineNum
    endif

    if (kLineNum < 2) kgoto read

  turnoff
endin
SECTION 1:
new alloc for instr 2:
Sline 1: 0.1

global volume (float): 0.000000
Sline 2: 0.5

global pause (float): 0.000000

@rory the global float variable gets overwritten to 0 its not reading the value from the file

You’re mixing up some k and i rate variables here. Here is the version that works fine for me:

<CsoundSynthesizer>
<CsOptions>
-odac
</CsOptions>
<CsInstruments>
sr = 44100
ksmps = 128
nchnls = 2
0dbfs = 1

gkVolume init 0     ; Global float variable for volume
gkPause init 0      ; Global float variable for pause

instr 2
  kLineNum init 0
  Sline init ""
  
  read:
    Sline, kLineNum readf "/Users/rwalsh/Desktop/config.txt"
    Sline init "0"
    printk 0, kLineNum
    printf "Sline %d: %s\n", kLineNum, kLineNum, Sline

    kLen strlenk Sline
    if (kLen > 0) then
        if (kLineNum == 1) then
            kVol strtodk Sline
            gkVolume = kVol
            printks "global volume (float): %f\n", 1, gkVolume
        elseif (kLineNum == 2) then
            kPause strtodk Sline
            gkPause = kPause
            printks "global pause (float): %f\n", 1, gkPause
        endif
    else
        printks "Warning: Skipping empty line %d\n", 1, kLineNum
    endif

    if (kLineNum < 2) kgoto read

  turnoff
endin

</CsInstruments>
<CsScore>
i2 0 1
</CsScore>
</CsoundSynthesizer>








Oh! I used the same code

<CsoundSynthesizer>
<CsOptions>
-odac
</CsOptions>
<CsInstruments>
sr = 44100
ksmps = 128
nchnls = 2
0dbfs = 1

gkVolume init 0     ; Global float variable for volume
gkPause init 0      ; Global float variable for pause

instr 2
  kLineNum init 0
  Sline init ""
  
  read:
    Sline, kLineNum readf "config.txt"
    Sline init "0"
    printk 0, kLineNum
    printf "Sline %d: %s\n", kLineNum, kLineNum, Sline

    kLen strlenk Sline
    if (kLen > 0) then
        if (kLineNum == 1) then
            kVol strtodk Sline
            gkVolume = kVol
            printks "global volume (float): %f\n", 1, gkVolume
        elseif (kLineNum == 2) then
            kPause strtodk Sline
            gkPause = kPause
            printks "global pause (float): %f\n", 1, gkPause
        endif
    else
        printks "Warning: Skipping empty line %d\n", 1, kLineNum
    endif

    if (kLineNum < 2) kgoto read

  turnoff
endin

</CsInstruments>
<CsScore>
i2 0 1
</CsScore>
</CsoundSynthesizer>

But im getting error for it

SECTION 1:
new alloc for instr 2:
instr 2:        time     0.00000:     1.00000
Sline 1: 0.1

PERF ERROR in instr 2 (opcode strtodk) line 27: strtodk: invalid format
 from file arc54.csd (1)
kVol    strtodk Sline
   note aborted
B  0.000 ..  1.000 T  1.001 TT  1.001 M:  0.00000  0.00000
End of Performance inactive allocs returned to freespace
                   overall amps:  0.00000  0.00000
           overall samples out of range:        0        0
1 errors in performance

It’s most like the config file. Mine looks like this:

1 1
2 2
3 3
4 4
5 5

Okay went ahead and used the code and config file as the same

instr 2
  kLineNum init 0
  Sline init ""
  
  read:
    Sline, kLineNum readf "config.txt"
    Sline init "0"
    printk 0, kLineNum
    printf "Sline %d: %s\n", kLineNum, kLineNum, Sline

    kLen strlenk Sline
    if (kLen > 0) then
        if (kLineNum == 1) then
            kVol strtodk Sline
            gkVolume = kVol
            printks "global volume (float): %f\n", 1, gkVolume
        elseif (kLineNum == 2) then
            kPause strtodk Sline
            gkPause = kPause
            printks "global pause (float): %f\n", 1, gkPause
        endif
    else
        printks "Warning: Skipping empty line %d\n", 1, kLineNum
    endif

    if (kLineNum < 2) kgoto read

  turnoff
endin

config.txt file:
1 1
2 2

but my output is still like this, thats weird
SECTION 1:

new alloc for instr 2:
instr 2:        time     0.00000:     1.00000
Sline 1: 1 1

PERF ERROR in instr 2 (opcode strtodk) line 27: strtodk: invalid format
 from file pausetime.csd (1)
kVol    strtodk Sline
   note aborted
B  0.000 ..  1.000 T  1.001 TT  1.001 M:  0.00000  0.00000
End of Performance inactive allocs returned to freespace
                   overall amps:  0.00000  0.00000
           overall samples out of range:        0        0

Here are the exact files I’m using. Btw, I haven’t looked at anything else apart from the issues with strtodk. I’ve no idea if the instrument actually does what you want :slight_smile:

test1.csd (1.0 KB)
config.txt (19 Bytes)

could you show me the output that you are got