[Csnd] Soundscape Generator / SR mismatch

Hello dear csound-folks!

yesterday i was procrastinating a little bit and started thinking about an soundscape generator in csound.
I want to give as an input an directory of soundfiles and get a properly composed soundscape as an result.
Right now it is just reacting randomly on the input but i want to make it more systematic.In which way i don’t know yet. But im thinking about generating some different sections over time with different processing, density and more.

I’m curious if someone of you already thought on something like a soundscape generator (i think so) and i want to hear about your results and thoughts.

Also an other problem that occured for me:
I don’t want to think about SR mismatch with the csound instrument and the samples that are played. To be precise, when i play a soundfile with a different SR then the csound instrument the playing speed is not right.
How can i solve this?

Here is my instrument for you to trying out and to give me some feedback:

<CsoundSynthesizer>
<CsOptions>
-d -odac -W -3
</CsOptions>
<CsInstruments>
sr = 96000
ksmps = 64
nchnls = 2
0dbfs = 1.0

seed 0
gSdir = "/Users/philippneumann/Documents/Kompositionen/Auftakt-Festival/Auftakt_Performance_Seance/Material/Okkultes"

;-----------------------------------------------------------
instr 1
giLowestLoopSpeed = 0.125
giMaxLoopSpeed = 1.1
iCounter = 0
iloopAmp init -6
iloopSpeed = (giLowestLoopSpeed+giMaxLoopSpeed)/2
ipanPos init 0.5
iPanSpeed init 0.01
iStart init 0
iInstances random 4, 11
while iCounter < iInstances do
  schedule 100, iStart, p3, iloopSpeed, iloopAmp, iPanSpeed
  iloopSpeed random giLowestLoopSpeed, giMaxLoopSpeed ; Loop Speed Inkrement
  iloopAmp += +1
  iPanSpeed linrnd_low 0.01, 0.2
  iCounter += 1
od
endin

instr 100 ; Soundfile Looper with playbackspeed change and panning
kSpeed init p4
; Lese einen Ordner auf .wav aus
iCount init 0
SFilenames[] directory gSdir, ".wav"
iNumberOfFiles lenarray SFilenames
iFile random 0, iNumberOfFiles
iFile = round(iFile)
Sfile = SFilenames[iFile]
; Lese einen Soundfile mit einem Phasor aus einem Table aus
iNchnls filenchnls Sfile
if iNchnls == 1 goto monoFile
        goto stereoFile
monoFile:
iloopTableL ftgen 0, 0, 0, 1, Sfile, 0, 0, 1
iloopTableR = iloopTableL
;MkSpeed init p4
aIndex phasor (sr/ftlen(iloopTableL))*kSpeed
aloopL table3 aIndex, iloopTableL, 1
aloopR = aloopL
aloopR delay aloopR, 0.008
        goto weiter
stereoFile:
iloopTableL ftgen 0, 0, 0, 1, Sfile, 0, 0, 1
iloopTableR ftgen 0, 0, 0, 1, Sfile, 0, 0, 2
;kSpeed init p4
aIndex phasor (sr/ftlen(iloopTableL))*kSpeed
aloopL table3 aIndex, iloopTableL, 1
aloopR table3 aIndex, iloopTableR, 1
weiter:
; Set new playbackspeed after the soundfile played once
kCurrentPhs = k(aIndex)
kPreviousPhase init 0
if k(aIndex) < kPreviousPhase then
  kSpeed random giLowestLoopSpeed, giMaxLoopSpeed
endif
kPreviousPhase = k(aIndex)
; Lowspass Filter
kCF scale p5, 1600, 80, -12, -24;, 1, 0.1
aloopL butterlp aloopL, kCF
aloopR butterlp aloopR, kCF
; Panning
aPanLFO oscil 1, p6
aPanLFO = (aPanLFO+1)*0.5
aSigL1, aSigR1 pan2 aloopL, aPanLFO
aSigL2, aSigR2 pan2 aloopR, aPanLFO
aSigL sum aSigL1, aSigL2
aSigR sum aSigR1, aSigR2
; Output
kAmpReduction scale2 kSpeed, 1, .25, giMaxLoopSpeed, giLowestLoopSpeed
kAmpReduction port kAmpReduction, 0.25
aEnv linseg 0, 0.05, 1, p3 - 0.1, 1, 0.05, 0
aOutL = ((aSigL * aEnv) * kAmpReduction)* ampdbfs(p5)
aOutR = ((aSigR * aEnv) * kAmpReduction)* ampdbfs(p5)
outs aOutL, aOutR
;send to reverb
kReverbSendAmount scale2 kSpeed, -6, -3, giMaxLoopSpeed, giLowestLoopSpeed
kReverbSendAmount port kReverbSendAmount, 0.25
ksend = ampdbfs(kReverbSendAmount)
garev1=+ aOutL*ksend
garev2=+ aOutR*ksend
endin

instr 2 ; Paul-Stretch Background Ambient
; Lese einen Ordner auf .wav aus
iCount init 0
SFilenames[] directory gSdir, ".wav"
iNumberOfFiles lenarray SFilenames
iFile random 0, iNumberOfFiles
iFile = round(iFile)
Sfile = SFilenames[iFile]
;;; Paul-Stretch
istretchFact = 50 ; Stretch Faktor
iwindowSize = .1 ; Window Size
giSmp1 ftgen 0, 0, 0, 1, Sfile, 0.5, 0, 1
giSmp2 ftgen 0, 0, 0, 1, Sfile, 0.5, 0, 1
aStretchLeft paulstretch istretchFact, iwindowSize, giSmp1
aStretchRight paulstretch istretchFact, iwindowSize, giSmp2
; Lowpass Filter
aRMSIn sum aStretchLeft, aStretchRight
kRMS rms aRMSIn
;printk 0.125, kRMS
kCF port kRMS, 0.5
kCF scale kCF, 80, 1600, 0.2, 0.
aStretchLeftLP butterlp aStretchLeft, kCF
aStretchRightLP butterlp aStretchRight, kCF
; Output
aEnv linseg 0, 0.05, 1, p3 - 0.1, 1, 0.05, 0
aOutL = (aStretchLeftLP * aEnv)* ampdbfs(-6)
aOutR = (aStretchRightLP * aEnv)* ampdbfs(-6)
outs aOutL, aOutR
endin

instr 999;reverb
ain1 = garev1
ain2 = garev2
kfblvl = 0.6
kfco = sr/6

arev1, arev2 reverbsc ain1, ain2, kfblvl, kfco

outs arev1, arev2

clear garev1, garev2
endin
;---------------------------------------------------
</CsInstruments>
<CsScore>
i111 0 60
i1 0 60
i2 0 60
i999 0 80
</CsScore>
</CsoundSynthesizer>
Csound mailing list
Csound@listserv.heanet.ie
https://listserv.heanet.ie/cgi-bin/wa?A0=CSOUND
Send bugs reports to
        Issues · csound/csound · GitHub
Discussions of bugs and features can be posted here

Sorry, i forgot that there is an UDO involved.

A new version of my instrument:

<CsoundSynthesizer>
<CsOptions>
-d -odac -W -3
</CsOptions>
<CsInstruments>
sr = 96000
ksmps = 64
nchnls = 2
0dbfs = 1.0

seed 0
gSdir = „Insert you Directory here"
;-----------------------------------------------------------
instr 1
giLowestLoopSpeed = 0.125
giMaxLoopSpeed = 1.1
iCounter = 0
iloopAmp init -6
iloopSpeed = (giLowestLoopSpeed+giMaxLoopSpeed)/2
ipanPos init 0.5
iPanSpeed init 0.01
iStart init 0
iInstances random 4, 11
while iCounter < iInstances do
  schedule 100, iStart, p3, iloopSpeed, iloopAmp, iPanSpeed
  iloopSpeed random giLowestLoopSpeed, giMaxLoopSpeed ; Loop Speed Inkrement
  iloopAmp += +1
  iPanSpeed random 0.01, 0.2
  iCounter += 1
od
endin

instr 100 ; Soundfile Looper with playbackspeed change and panning
kSpeed init p4
; Lese einen Ordner auf .wav aus
iCount init 0
SFilenames[] directory gSdir, ".wav"
iNumberOfFiles lenarray SFilenames
iFile random 0, iNumberOfFiles
iFile = round(iFile)
Sfile = SFilenames[iFile]
; Lese einen Soundfile mit einem Phasor aus einem Table aus
iNchnls filenchnls Sfile
if iNchnls == 1 goto monoFile
        goto stereoFile
monoFile:
iloopTableL ftgen 0, 0, 0, 1, Sfile, 0, 0, 1
iloopTableR = iloopTableL
;MkSpeed init p4
aIndex phasor (sr/ftlen(iloopTableL))*kSpeed
aloopL table3 aIndex, iloopTableL, 1
aloopR = aloopL
aloopR delay aloopR, 0.008
        goto weiter
stereoFile:
iloopTableL ftgen 0, 0, 0, 1, Sfile, 0, 0, 1
iloopTableR ftgen 0, 0, 0, 1, Sfile, 0, 0, 2
;kSpeed init p4
aIndex phasor (sr/ftlen(iloopTableL))*kSpeed
aloopL table3 aIndex, iloopTableL, 1
aloopR table3 aIndex, iloopTableR, 1
weiter:
; Set new playbackspeed after the soundfile played once
kCurrentPhs = k(aIndex)
kPreviousPhase init 0
if k(aIndex) < kPreviousPhase then
  kSpeed random giLowestLoopSpeed, giMaxLoopSpeed
endif
kPreviousPhase = k(aIndex)
; Lowspass Filter
kCF scale p5, 1600, 80, -12, -24;, 1, 0.1
aloopL butterlp aloopL, kCF
aloopR butterlp aloopR, kCF
; Panning
aPanLFO oscil 1, p6
aPanLFO = (aPanLFO+1)*0.5
aSigL1, aSigR1 pan2 aloopL, aPanLFO
aSigL2, aSigR2 pan2 aloopR, aPanLFO
aSigL sum aSigL1, aSigL2
aSigR sum aSigR1, aSigR2
; Output
kAmpReduction scale2 kSpeed, 1, .25, giMaxLoopSpeed, giLowestLoopSpeed
kAmpReduction port kAmpReduction, 0.25
aEnv linseg 0, 0.05, 1, p3 - 0.1, 1, 0.05, 0
aOutL = ((aSigL * aEnv) * kAmpReduction)* ampdbfs(p5)
aOutR = ((aSigR * aEnv) * kAmpReduction)* ampdbfs(p5)
outs aOutL, aOutR
;send to reverb
kReverbSendAmount scale2 kSpeed, -6, -3, giMaxLoopSpeed, giLowestLoopSpeed
kReverbSendAmount port kReverbSendAmount, 0.25
ksend = ampdbfs(kReverbSendAmount)
garev1=+ aOutL*ksend
garev2=+ aOutR*ksend
endin

instr 2 ; Paul-Stretch Background Ambient
; Lese einen Ordner auf .wav aus
iCount init 0
SFilenames[] directory gSdir, ".wav"
iNumberOfFiles lenarray SFilenames
iFile random 0, iNumberOfFiles
iFile = round(iFile)
Sfile = SFilenames[iFile]
;;; Paul-Stretch
istretchFact = 50 ; Stretch Faktor
iwindowSize = .1 ; Window Size
giSmp1 ftgen 0, 0, 0, 1, Sfile, 0.5, 0, 1
giSmp2 ftgen 0, 0, 0, 1, Sfile, 0.5, 0, 1
aStretchLeft paulstretch istretchFact, iwindowSize, giSmp1
aStretchRight paulstretch istretchFact, iwindowSize, giSmp2
; Lowpass Filter
aRMSIn sum aStretchLeft, aStretchRight
kRMS rms aRMSIn
;printk 0.125, kRMS
kCF port kRMS, 0.5
kCF scale kCF, 80, 1600, 0.2, 0.
aStretchLeftLP butterlp aStretchLeft, kCF
aStretchRightLP butterlp aStretchRight, kCF
; Output
aEnv linseg 0, 0.05, 1, p3 - 0.1, 1, 0.05, 0
aOutL = (aStretchLeftLP * aEnv)* ampdbfs(-6)
aOutR = (aStretchRightLP * aEnv)* ampdbfs(-6)
outs aOutL, aOutR
endin

instr 999;reverb
ain1 = garev1
ain2 = garev2
kfblvl = 0.6
kfco = sr/6

arev1, arev2 reverbsc ain1, ain2, kfblvl, kfco

outs arev1, arev2

clear garev1, garev2
endin
;---------------------------------------------------
</CsInstruments>
<CsScore>
i111 0 60
i1 0 60
i2 0 60
i999 0 80
</CsScore>
</CsoundSynthesizer>

Here is a nice solution to the resampling issue, courtesy of Victor. It uses diskin to resample the sample and then loads it to a function table.

opcode ResampleAndLoad,k,S
kfun init 0
Sfile xin
if kfun == 0 then
andx init 0
kk init 0
ifl = filelen(Sfile)*sr
ifn ftgen 0,0,ifl,2,0
while kk < ksmps do
andx[kk] = kk
kk += 1
od
kk = 0
while kk < ifl do
asig diskin2 Sfile
tablew asig, andx+kk, ifn
kk += ksmps
od
kfun = ifn
endif
xout kfun
endop

instr 1
gkf ResampleAndLoad “fox.wav”,1
endin
schedule(1,0,1/kr)

instr 2
a1 poscil 0.5,sr/ftlen(i(gkf)),i(gkf)
out a1
endin
schedule(2,1/kr,4)

why don't you use diskin? it has a good builtin SR conversion, in my opinion.
and with the modern solid state disks the speed of reading is so fast that in most cases we do not need any more sample playback from tables.
but i did not look close to your csd --- perhaps you are doing things with the tables other than just playback.

I would use disking. But i need to loop the file and i need the reading position as a value to trigger some other processes. Is there a way to get this working? i also never understood what the „‚wrap“ thing is.

the wraparound is the same as looping. but yes, you cannot loop from arbitrary points; only the whole length.

so perhaps you use what rory suggested. in general, there is the ftsr opcode which lets you know the sample rate of a GEN01 imported file:
https://csound.com/docs/manual/ftsr.html

Joaquim, I thought the iskptim
parameter allowed for starting at what you refer to as “arbitrary points”. Am I mistaken?

Scott

Wraparound is looping. With diskin you can do it forwards or backwards.

I think you can use times, timeinstk or one of the other time opcodes to measure how much time has passed since the instance of the instr began.

Scott

the iskiptime parameter sets the *first* starting point. but then it will loop from the beginning, not?

In fact, if you are reading the table with an oscillator etc you don't even need to do the sample rate conversion beforehand. All you need is to scale the read out speed (e.g. frequency, pitch) by sr/ftsr() and you will get the correct output. Assuming that you are using some form of interpolation, the quality should not be too different from diskin.

Prof. Victor Lazzarini
Maynooth University
Ireland

Thank you all for your tips!

I use the solution of Victor now. If you are interested it works like this:

giSndflTbl ftgen 0, 0, 0, 1, „Soundfile-Path", 0, 0, 1
kSpeed = 1
iSpeedBase = sr/ftlen(giSndflTbl)
iSrConv = (sr/ftsr(giSndflTbl))
aIndex phasor (iSpeedBase*kSpeed)/iSrConv
aSmp table3 aIndex, giSndflTbl, 1

Will probably sound amazing! I didn’t know Csound had Paulstretch!!

I’ve always used Partikkel or the Grain opcode for stuff like this!

Yes, you are correct Joachim. Thank you for the clarification. I was sort of basing my reply on the fact that Philipp’s code was seeming to alter the pitch or speed with each loop iteration & that perhaps in that context it might be possible to start each from a different point in time if that was desired. But of course I might be mistaken.

Scott

Hi Philipp, finally got around to trying out your code today. Was able to piece together your first two code bits and got it working, sounds great so far!

However I’m having trouble figuring out how to incorporate the final bit of code you added (the solution of Victor’s). Would you be able to post the full final version? As a relative newbie it would be very helpful, it’s a great example to learn from.

Scott

Hi Scott,

here is my actual version. There are some UDOs on weighted randomness involved, which i stole from the floss manual. Just replace some with the normal random opcode and it should run fine.

I also added a ling ringmodulation thing.

My next step is to broaden the frequency spectrum of the output, to make the soundscape more diverse and to be able to fill the whole freq spectrum. Then i will try to organize these parts over time. This is my plan so far.

greetings,
Philipp

<CsoundSynthesizer>
<CsOptions>
-d -odac -W -3
</CsOptions>
<CsInstruments>
sr = 96000
ksmps = 64
nchnls = 2
0dbfs = 1.0

seed 0
gSdir = „Your Directory"
;-----------------------------------------------------------
#include "/Users/philippneumann/Documents/Csound/PHN-UDOs.txt"
;-----------------------------------------------------------
instr 1
giLowestLoopSpeed = -0.25
giMaxLoopSpeed = 1.125
iloopAmp = -6
iloopSpeed = (giLowestLoopSpeed+giMaxLoopSpeed)/2
ipanPos init 0.5
iPanSpeed init 0.01
iStart init 0
iInstances linrnd_high 4, 11
iCounter = 0
while iCounter < iInstances do
  schedule 100, iStart, p3, iloopSpeed, iloopAmp, iPanSpeed
  iloopSpeed linrnd_high giLowestLoopSpeed, giMaxLoopSpeed ; Loop Speed Inkrement
  iPanSpeed random 0.1, .5
  iCounter += 1
od
endin

instr 100 ; Soundfile Looper with playbackspeed change and panning
kSpeed init p4
; Lese einen Ordner auf .wav aus
iCount init 0
SFilenames[] directory gSdir, ".wav"
iNumberOfFiles lenarray SFilenames
iFile random 0, iNumberOfFiles
iFile = round(iFile)
Sfile = SFilenames[iFile]
; Lese einen Soundfile mit einem Phasor aus einem Table aus
iNchnls filenchnls Sfile
if iNchnls == 1 goto monoFile
        goto stereoFile
monoFile:
iloopTableL ftgen 0, 0, 0, 1, Sfile, 0, 0, 1
iloopTableR = iloopTableL
;MkSpeed init p4
aIndex phasor (sr/ftlen(iloopTableL))*kSpeed
aloopL table3 aIndex, iloopTableL, 1
aloopR = aloopL
aloopR delay aloopR, 0.008
        goto weiter
stereoFile:
iloopTableL ftgen 0, 0, 0, 1, Sfile, 0, 0, 1
iloopTableR ftgen 0, 0, 0, 1, Sfile, 0, 0, 2
;kSpeed init p4
aIndex phasor (sr/ftlen(iloopTableL))*kSpeed
aloopL table3 aIndex, iloopTableL, 1
aloopR table3 aIndex, iloopTableR, 1
weiter:
; Set new playbackspeed after the soundfile played once
kCurrentPhs = k(aIndex)
kPreviousPhase init 0
if k(aIndex) < kPreviousPhase then
  kSpeed random giLowestLoopSpeed, giMaxLoopSpeed
endif
kPreviousPhase = k(aIndex)
; Lowspass Filter
kCF scale p5, 1600, 80, -12, -24;, 1, 0.1
aloopL butterlp aloopL, kCF
aloopR butterlp aloopR, kCF
; Panning
aPanLFO randomi 0, 1, p6, 2, .5
aPanLFO = (aPanLFO+1)*0.5
aSigL1, aSigR1 pan2 aloopL, aPanLFO
aSigL2, aSigR2 pan2 aloopR, aPanLFO
aSigL sum aSigL1, aSigL2
aSigR sum aSigR1, aSigR2
; Output
kAmpReduction scale2 kSpeed, 1, .125, giMaxLoopSpeed, giLowestLoopSpeed
kAmpReduction port kAmpReduction, 0.25
aEnv linseg 0, 1, 1, p3 - 2, 1, 1, 0
aOutL = ((aSigL * aEnv) * kAmpReduction)* ampdbfs(p5)
aOutR = ((aSigR * aEnv) * kAmpReduction)* ampdbfs(p5)
outs aOutL, aOutR
;send to reverb
kReverbSendAmount scale2 kSpeed, -9, -3, giMaxLoopSpeed, giLowestLoopSpeed
kReverbSendAmount port kReverbSendAmount, 0.25
ksend = ampdbfs(kReverbSendAmount)
garev1=+ aOutL*ksend
garev2=+ aOutR*ksend
endin

instr 2 ; Paul-Stretch Background Ambient
; Lese einen Ordner auf .wav aus
iCount init 0
SFilenames[] directory gSdir, ".wav"
iNumberOfFiles lenarray SFilenames
iFile random 0, iNumberOfFiles
iFile = round(iFile)
Sfile = SFilenames[iFile]
;;; Paul-Stretch
istretchFact = 50 ; Stretch Faktor
iwindowSize = .1 ; Window Size
giSmp1 ftgen 0, 0, 0, 1, Sfile, 0.5, 0, 1
giSmp2 ftgen 0, 0, 0, 1, Sfile, 0.5, 0, 1
aStretchLeft paulstretch istretchFact, iwindowSize, giSmp1
aStretchRight paulstretch istretchFact, iwindowSize, giSmp2
; Lowpass Filter
aRMSIn sum aStretchLeft, aStretchRight
kRMS rms aRMSIn
;printk 0.125, kRMS
kCF port kRMS, 0.5
kCF scale kCF, 50, 1600, 0.2, 0.
aStretchLeftLP butterlp aStretchLeft, kCF
aStretchRightLP butterlp aStretchRight, kCF
;;; Sub-Sine
isinTableDrone ftgen 0, 0, 2^10, 10, 1, 0.125, 0.125, 0.015
aFollowSum sum aStretchLeft, aStretchRight
aEnvfollower follow2 aFollowSum, 0.5, 0.5
kEnvfollower downsamp aEnvfollower
kEnvfollower port kEnvfollower, 0.5
aSub40 poscil3 ampdbfs(-2), 40, isinTableDrone
aSub = aSub40
aSub delay aSub * kEnvfollower, 2
;;; Ringmod
kRingModFreq randomh 800, 1200, 20, 2, 900
aRingmod poscil3 1, kRingModFreq, giSmp1
aStretchLeftHP butterhp aStretchLeft, 800
aStretchRightHP butterhp aStretchRight, 800
aRingSigL = aStretchLeftHP*aRingmod
aRingSigR = aStretchRightHP*aRingmod
;;; Tremolo for Ringmod Signal
iTremShape ftgen 0, 0, 2^10, 7, -1, 2^10, 1
kTremspeed randomi 0.01, 4, 0.5
aTrem poscil3 1, kTremspeed, iTremShape
aTrem = (aTrem+1)*0.5
;;; Modded Signal
aModdedSigL = (aRingSigL * aTrem)
aModdedSigL delay aModdedSigL, 4
aModdedSigR = (aRingSigR * aTrem)
aModdedSigR delay aModdedSigR, 3.8
; Output
aEnv linseg 0, 1, 1, p3 - 2, 1, 1, 0
aOutL sum (aStretchLeftLP * aEnv), (aSub * aEnv), (aModdedSigL * aEnv)
aOutR sum (aStretchRightLP * aEnv), (aSub * aEnv), (aModdedSigR * aEnv)
outs aOutL * ampdbfs(-6), aOutR * ampdbfs(-6)
endin

instr 999;reverb
ain1 = garev1
ain2 = garev2
kfblvl = 0.6
kfco = sr/6

arev1, arev2 reverbsc ain1, ain2, kfblvl, kfco

outs arev1, arev2

clear garev1, garev2
endin
;---------------------------------------------------
</CsInstruments>
<CsScore>
i111 0 60
i1 0 60
i2 0 60
i999 0 80
</CsScore>
</CsoundSynthesizer>

Sorry again….this was my old version.
Here is the proper version

<CsoundSynthesizer>
<CsOptions>
-d -odac -W -3
</CsOptions>
<CsInstruments>
sr = 96000
ksmps = 64
nchnls = 2
0dbfs = 1.0

seed 0
;gSdir = "/Users/philippneumann/Documents/Kompositionen/Funktionslust/Material/One-Shots/Reverb"
gSdir = "/Users/philippneumann/Documents/Kompositionen/Auftakt-Festival/Auftakt_Performance_Seance/Material/Okkultes"
;-----------------------------------------------------------
#include "/Users/philippneumann/Documents/Csound/PHN-UDOs.txt"
;-----------------------------------------------------------
instr 1
giLowestLoopSpeed = -0.125
giMaxLoopSpeed = 1.25
iloopAmp = -6
iloopSpeed random (giLowestLoopSpeed+giMaxLoopSpeed)/2, 1
ipanPos init 0.5
iPanSpeed init 0.01
iStart init 0
iInstances linrnd_high 4, 11
iCounter = 0
while iCounter < iInstances do
  schedule 100, iStart, p3, iloopSpeed, iloopAmp, iPanSpeed
  iloopSpeed linrnd_high giLowestLoopSpeed, giMaxLoopSpeed ; Loop Speed Inkrement
  iPanSpeed random 0.1, .5
  iCounter += 1
od
endin

instr 100 ; Soundfile Looper with playbackspeed change and panning
kSpeed init p4
; Lese einen Ordner auf .wav aus
iCount init 0
SFilenames[] directory gSdir, ".wav"
iNumberOfFiles lenarray SFilenames
iFile random 0, iNumberOfFiles
iFile = round(iFile)
Sfile = SFilenames[iFile]
; read a soundfile into a table and read it with a phasor
; mono and stereo files
kSpeed init p4

iSndflNumChnls filenchnls Sfile
if iSndflNumChnls == 1 kgoto monoFile
            kgoto stereoFile

monoFile:
iSndflTblLeft ftgen 0, 0, 0, 1, Sfile, 0, 0, 1
iSndflTblRight = iSndflTblLeft
iSpeedBase = sr/ftlen(iSndflTblLeft)
iSrConv = sr/ftsr(iSndflTblLeft)
aIndex phasor (iSpeedBase*kSpeed)/iSrConv
aloopL table3 aIndex, iSndflTblLeft, 1
aloopR delay aloopL, 0.08
            kgoto output

stereoFile:
iSndflTblLeft ftgen 0, 0, 0, 1, Sfile, 0, 0, 1
iSndflTblRight ftgen 0, 0, 0, 1, Sfile, 0, 0, 2
iSpeedBase = sr/ftlen(iSndflTblLeft)
iSrConv = sr/ftsr(iSndflTblLeft)
aIndex phasor (iSpeedBase*kSpeed)/iSrConv
aloopL table3 aIndex, iSndflTblLeft, 1
aloopR table3 aIndex, iSndflTblLeft, 1

output:
; Set new playbackspeed after the soundfile played once
kCurrentPhs = k(aIndex)
kPreviousPhase init 0
if kCurrentPhs < kPreviousPhase then
  kSpeed random giLowestLoopSpeed, giMaxLoopSpeed
endif
kPreviousPhase = kCurrentPhs
; Lowspass Filter
kCF scale kSpeed, 1800, 50, giMaxLoopSpeed, giLowestLoopSpeed;, 1, 0.1
aloopL butterlp aloopL, kCF
aloopR butterlp aloopR, kCF
; Panning
aPanLFO randomi 0, 1, p6, 2, .5
aPanLFO = (aPanLFO+1)*0.5
aSigL1, aSigR1 pan2 aloopL, aPanLFO
aSigL2, aSigR2 pan2 aloopR, aPanLFO
aSigL sum aSigL1, aSigL2
aSigR sum aSigR1, aSigR2
; Output
kAmpReduction scale2 kSpeed, 1, .125, giMaxLoopSpeed, giLowestLoopSpeed
kAmpReduction port kAmpReduction, 0.25
aEnv linseg 0, 1, 1, p3 - 2, 1, 1, 0
aOutL = ((aSigL * aEnv) * kAmpReduction)* ampdbfs(p5)
aOutR = ((aSigR * aEnv) * kAmpReduction)* ampdbfs(p5)
outs aOutL, aOutR
;send to reverb
kReverbSendAmount scale2 kSpeed, -9, -2, giMaxLoopSpeed, giLowestLoopSpeed
kReverbSendAmount port kReverbSendAmount, 0.25
ksend = ampdbfs(kReverbSendAmount)
garev1=+ aOutL*ksend
garev2=+ aOutR*ksend
endin

instr 2 ; Paul-Stretch Background Ambient
; Lese einen Ordner auf .wav aus
iCount init 0
SFilenames[] directory gSdir, ".wav"
iNumberOfFiles lenarray SFilenames
iFile random 0, iNumberOfFiles
iFile = round(iFile)
Sfile = SFilenames[iFile]
;;; Paul-Stretch
istretchFact = 50 ; Stretch Faktor
iwindowSize = .1 ; Window Size
giSmp1 ftgen 0, 0, 0, 1, Sfile, 0.5, 0, 1
giSmp2 ftgen 0, 0, 0, 1, Sfile, 0.5, 0, 1
aStretchLeft paulstretch istretchFact, iwindowSize, giSmp1
aStretchRight paulstretch istretchFact, iwindowSize, giSmp2
; Lowpass Filter
aRMSIn sum aStretchLeft, aStretchRight
kRMS rms aRMSIn
;printk 0.125, kRMS
kCF port kRMS, 0.5
kCF scale kCF, 50, 1600, 0.2, 0.
aStretchLeftLP butterlp aStretchLeft, kCF
aStretchRightLP butterlp aStretchRight, kCF
;;; Sub-Sine
isinTableDrone ftgen 0, 0, 2^10, 10, 1, 0.125, 0.125, 0.015
aFollowSum sum aStretchLeft, aStretchRight
aEnvfollower follow2 aFollowSum, 0.5, 0.5
kEnvfollower downsamp aEnvfollower
kEnvfollower port kEnvfollower, 0.5
aSub40 poscil3 ampdbfs(-2), 40, isinTableDrone
aSub = aSub40
aSub delay aSub * kEnvfollower, 2
;;; Ringmod
kRingModFreq randomh 800, 1200, 20, 2, 900
aRingmod poscil3 1, kRingModFreq, giSmp1
aStretchLeftHP butterhp aStretchLeft, 800
aStretchRightHP butterhp aStretchRight, 800
aRingSigL = aStretchLeftHP*aRingmod
aRingSigR = aStretchRightHP*aRingmod
;;; Tremolo for Ringmod Signal
iTremShape ftgen 0, 0, 2^10, 7, -1, 2^10, 1
kTremspeed randomi 0.01, 4, 0.5
aTrem poscil3 1, kTremspeed, iTremShape
aTrem = (aTrem+1)*0.5
;;; Modded Signal
kLFOfreq randomi 0.01, 0.2, 2
aLFOsigAmount oscil 1, kLFOfreq
aLFOsigAmount = (aLFOsigAmount+1)*0.5
aModdedSigL = (aRingSigL * aTrem)*aLFOsigAmount
aModdedSigL delay aModdedSigL, 4
aModdedSigR = (aRingSigR * aTrem)*aLFOsigAmount
aModdedSigR delay aModdedSigR, 3.8
; Output
aEnv linseg 0, 1, 1, p3 - 2, 1, 1, 0
aOutL sum (aStretchLeftLP * aEnv), (aSub * aEnv), (aModdedSigL * aEnv)
aOutR sum (aStretchRightLP * aEnv), (aSub * aEnv), (aModdedSigR * aEnv)
outs aOutL * ampdbfs(-6), aOutR * ampdbfs(-6)
endin

instr 999;reverb
ain1 = garev1
ain2 = garev2
kfblvl = 0.55
kfco = sr/6

arev1, arev2 reverbsc ain1, ain2, kfblvl, kfco

outs arev1, arev2

clear garev1, garev2
endin
;---------------------------------------------------
</CsInstruments>
<CsScore>
i111 0 60
i1 0 60
i2 0 60
i999 0 80
</CsScore>
</CsoundSynthesizer>

Hi Philipp, thanks for the updated files, I appreciate it.

A few quick notes from my end.
The garev1 & 2 were not initialized but that’s an easy fix. Also the reverb sends didn’t seem to work (around lines 113, 114):
garev1=+ aOutLksend
garev2=+ aOutR
ksend

Again likely a minor oversight, changed =+ to += and that solved the problem.

Also for some odd reason there seems an issue with loading some mono files, (“failed to open” appears in console) - or perhaps it’s just giving an error because maybe then trying to load as stereo? Not sure. But I don’t hear them so leaning towards them not loading.

Also some occasional quite loud clicks, perhaps the files I’m using? Again not sure as I generally make sure all my files stop and start with a sample value of zero. Maybe I can adjust that for myself somehow with an env tweak.

Last, as I’ve sometimes encountered rendering my own soundscape type files (which generally also use some type of granular synthesis and butter filters) there is on occasion some noticeable DC offset, again was easy to fix with dcblock2.

Some of these could obviously be only on my end (having to do with my own source wav files) but just thought I’d point them out. Aside from that it’s a nice code here, right up my alley as I enjoy creating these types of textured soundscapes.

Thanks again & best regards,

Scott

Hey Scott!

Thank you for your Mail! I didn’t noticed some of these problems - so really thank you!

The garev1 & 2 were not initialized but that's an easy fix. Also the reverb sends didn't seem to work around lines 113, 114:
garev1=+ aOutL*ksend
garev2=+ aOutR*ksend
Again likely a minor oversi

I already wondered why i can’t hear the reverb and i was always checking my settings on this…

Also for some odd reason there seems an issue with loading some mono files, &quot;failed to open&quot; appears in console - or perhaps it's just giving an error because maybe then trying to load as stereo? Not sure. But I don't hear them so leaning towards them not loading.

This came from because i was using ‚kgoto‘ and not ‚goto‘. I solved this in the new version. Thought i had checked this with mono files - but i didn’t.

Also some occasional quite loud clicks, perhaps the files I'm using? Again not sure as I generally make sure all my files stop and start with a sample value of zero. Maybe I can adjust that for myself somehow with an env tweak.

This could came from how i was using my aEnv. It was depending on longer wav files, because it was using a 1 second long attack and decay time. So if there were used short files there could be a click as a result. Did you use short files?
But during writing these lines i notice that this makes no sense…. Because the files were looping, so it should not depend on the length of the files. Do you have an idea?

Last, as I've sometimes encountered rendering my own soundscape type files which generally also use some type of granular synthesis and butter filters there is on occasion some noticeable DC offset, again was easy to fix with dcblock2.

Thanks for making me think about this! I always thought a DC-Offset is a result of recording soundfiles. Can you explain where in the Csound Instrument could slip an DC-Offset in?

Thanks again Scott for your interested in my instrument! I will work on this and keep you updated.

Greetings,
Philipp

<CsoundSynthesizer>
<CsOptions>
-d -odac -W -3
</CsOptions>
<CsInstruments>
sr = 96000
ksmps = 64
nchnls = 2
0dbfs = 1.0

seed 0
gSdir = "//Users/philippneumann/Documents/Kompositionen/Funktionslust/Material/Stimme/Vokal E"
;gSdir = "/Users/philippneumann/Documents/Kompositionen/Auftakt-Festival/Auftakt_Performance_Seance/Material/Okkultes"
;-----------------------------------------------------------
#include "/Users/philippneumann/Documents/Csound/PHN-UDOs.txt"
;-----------------------------------------------------------
instr 1
giLowestLoopSpeed = -0.125
giMaxLoopSpeed = 1.25
iloopAmp = -6
iloopSpeed random giLowestLoopSpeed\+giMaxLoopSpeed/2, 1
ipanPos init 0.5
iPanSpeed init 0.01
iStart init 0
iInstances linrnd_high 4, 11
iCounter = 0
while iCounter < iInstances do
  schedule 100, iStart, p3, iloopSpeed, iloopAmp, iPanSpeed
  iloopSpeed linrnd_high giLowestLoopSpeed, giMaxLoopSpeed ; Loop Speed Inkrement
  iPanSpeed random 0.1, .5
  iCounter += 1
od
endin

instr 100 ; Soundfile Looper with playbackspeed change and panning
kSpeed init p4
; Lese einen Ordner auf .wav aus
iCount init 0
SFilenames[] directory gSdir, ".wav"
iNumberOfFiles lenarray SFilenames
iFile random 0, iNumberOfFiles
iFile = roundiFile
Sfile = SFilenames[iFile]
; read a soundfile into a table and read it with a phasor
; mono and stereo files
kSpeed init p4

iSndflNumChnls filenchnls Sfile
if iSndflNumChnls == 1 goto monoFile
            goto stereoFile
            
monoFile:
iSndflTblLeft ftgen 0, 0, 0, 1, Sfile, 0, 0, 1
iSndflTblRight = iSndflTblLeft
iSpeedBase = sr/ftleniSndflTblLeft
iSrConv = sr/ftsriSndflTblLeft
aIndex phasor iSpeedBase\*kSpeed/iSrConv
aloopL table3 aIndex, iSndflTblLeft, 1
aloopR table3 aIndex, iSndflTblRight, 1
            goto output

stereoFile:
iSndflTblLeft ftgen 0, 0, 0, 1, Sfile, 0, 0, 1
iSndflTblRight ftgen 0, 0, 0, 1, Sfile, 0, 0, 2
iSpeedBase = sr/ftleniSndflTblLeft
iSrConv = sr/ftsriSndflTblLeft
aIndex phasor iSpeedBase\*kSpeed/iSrConv
aloopL table3 aIndex, iSndflTblLeft, 1
aloopR table3 aIndex, iSndflTblRight, 1

output:
; Set new playbackspeed after the soundfile played once
kCurrentPhs = kaIndex
kPreviousPhase init 0
if kCurrentPhs < kPreviousPhase then
  kSpeed random giLowestLoopSpeed, giMaxLoopSpeed
endif
kPreviousPhase = kCurrentPhs
; Lowspass Filter
kCF scale kSpeed, 1800, 50, giMaxLoopSpeed, giLowestLoopSpeed;, 1, 0.1
aloopL butterlp aloopL, kCF
aloopR butterlp aloopR, kCF
; Panning
aPanLFO randomi 0, 1, p6, 2, .5
aPanLFO = aPanLFO\+1*0.5
aSigL1, aSigR1 pan2 aloopL, aPanLFO
aSigL2, aSigR2 pan2 aloopR, aPanLFO
aSigL sum aSigL1, aSigL2
aSigR sum aSigR1, aSigR2
; Output
kAmpReduction scale2 kSpeed, 1, .125, giMaxLoopSpeed, giLowestLoopSpeed
kAmpReduction port kAmpReduction, 0.25
aEnv linseg 0, p3*.1, 1, p3 - .2, 1, p3*.1, 0
aOutL = \(aSigL \* aEnv * kAmpReduction)* ampdbfsp5
aOutR = \(aSigR \* aEnv * kAmpReduction)* ampdbfsp5
outs aOutL, aOutR
;send to reverb
kReverbSendAmount scale2 kSpeed, -12, -6, giMaxLoopSpeed, giLowestLoopSpeed
kReverbSendAmount port kReverbSendAmount, 0.25
ksend = ampdbfskReverbSendAmount
garev1 += aOutL*ksend
garev2 += aOutR*ksend
endin

instr 2 ; Paul-Stretch Background Ambient
; Lese einen Ordner auf .wav aus
iCount init 0
SFilenames[] directory gSdir, ".wav"
iNumberOfFiles lenarray SFilenames
iFile random 0, iNumberOfFiles
iFile = roundiFile
Sfile = SFilenames[iFile]
;;; Paul-Stretch
istretchFact = 50 ; Stretch Faktor
iwindowSize = .1 ; Window Size
giSmp1 ftgen 0, 0, 0, 1, Sfile, 0.5, 0, 1
giSmp2 ftgen 0, 0, 0, 1, Sfile, 0.5, 0, 1
aStretchLeft paulstretch istretchFact, iwindowSize, giSmp1
aStretchRight paulstretch istretchFact, iwindowSize, giSmp2
; Lowpass Filter
aRMSIn sum aStretchLeft, aStretchRight
kRMS rms aRMSIn
;printk 0.125, kRMS
kCF port kRMS, 0.5
kCF scale kCF, 50, 1600, 0.2, 0.
aStretchLeftLP butterlp aStretchLeft, kCF
aStretchRightLP butterlp aStretchRight, kCF
;;; Sub-Sine
isinTableDrone ftgen 0, 0, 2^10, 10, 1, 0.125, 0.125, 0.015
aFollowSum sum aStretchLeft, aStretchRight
aEnvfollower follow2 aFollowSum, 0.5, 0.5
kEnvfollower downsamp aEnvfollower
kEnvfollower port kEnvfollower, 0.5
aSub40 poscil3 ampdbfs\-2, 40, isinTableDrone
aSub = aSub40
aSub delay aSub * kEnvfollower, 2
;;; Ringmod
kRingModFreq randomh 800, 1200, 20, 2, 900
aRingmod poscil3 1, kRingModFreq, giSmp1
aStretchLeftHP butterhp aStretchLeft, 800
aStretchRightHP butterhp aStretchRight, 800
aRingSigL = aStretchLeftHP*aRingmod
aRingSigR = aStretchRightHP*aRingmod
;;; Tremolo for Ringmod Signal
iTremShape ftgen 0, 0, 2^10, 7, -1, 2^10, 1
kTremspeed randomi 0.01, 4, 0.5
aTrem poscil3 1, kTremspeed, iTremShape
aTrem = aTrem\+1*0.5
;;; Modded Signal
kLFOfreq randomi 0.01, 0.2, 2
aLFOsigAmount oscil 1, kLFOfreq
aLFOsigAmount = aLFOsigAmount\+1*0.5
aModdedSigL = aRingSigL \* aTrem*aLFOsigAmount
aModdedSigL delay aModdedSigL, 4
aModdedSigR = aRingSigR \* aTrem*aLFOsigAmount
aModdedSigR delay aModdedSigR, 3.8
; Output
aEnv linseg 0, p3*0.1, 1, p3 - 0.2, 1, p3*0.1, 0
aOutL sum aStretchLeftLP \* aEnv, aSub \* aEnv, aModdedSigL \* aEnv
aOutR sum aStretchRightLP \* aEnv, aSub \* aEnv, aModdedSigR \* aEnv
outs aOutL * ampdbfs\-6, aOutR * ampdbfs\-6
endin

instr 999;reverb
ain1 = garev1
ain2 = garev2
kfblvl = 0.55
kfco = sr/6

arev1, arev2 reverbsc ain1, ain2, kfblvl, kfco

outs arev1, arev2

clear garev1, garev2
endin
;---------------------------------------------------
</CsInstruments>
<CsScore>
i111 0 60
i1 0 60
i2 0 60
i999 0 80
</CsScore>
</CsoundSynthesizer>

Hi again Philipp,

Ok, seems the DC offset is introduced by the LFO. I was suspicious as soon as I looked close at the lfo setup but always good to look how we can find the culprit.

Here is an original output, hopefully the png files work for you. If not let me know and I can post jpg instead:
https://www.dropbox.com/s/622z9syz96nanib/dc1.png?dl=0

As you can see the DC offset is really extreme, causing alot of distortion.

Here I introduced dcblock2:
https://www.dropbox.com/s/r35swhv46f81e9w/dc2.png?dl=0

DC offset gone.

So, then the issue was, which outs were creating dc offset & why. You have outs right before the lfos then after. Leaving dcblock 2 on the post lfo and testing first outs:
https://www.dropbox.com/s/vcbeujgv7yavmmx/dc3.png?dl=0

No DC offset. Likely problem therefore second outs.

Using dcblock2 on first outs and removing dcblock2 from post lfo outs:
https://www.dropbox.com/s/rgrdp7rcsepf5vz/dc4.png?dl=0

DC very bad, causing alot of distortion and simple attenuation will result in a very limited dynamic range before clipping.

After modifying your lfo & using no dcblock2 at all:
https://www.dropbox.com/s/o9rzcfo9le9uiyb/dc5.png?dl=0

Here’s an example of a very simple lfo, done using k rate instead. Also uses delayk. Can’t confirm but I would suspect is a little more cpu efficient that audio rate. But I’m no expert so maybe is more cpu intensive? Anyways, can be done either way:

instr 1
kLfoL = lfo(.3, .2, 0)+.7
kLfoR delayk kLfoL, .4
kEnv = linseg(0, .5, 1, p3 - 1, 1, .5, 0)
aSig = oscil(kEnv, 440)
outs aSig * kLfoL, aSig * kLfoR
endin

Here’s how I modified your lfos to get rid of the DC offset (I also removed some redundant lines, hope that’s ok):

kLFOfreq randomi 0.01, 0.2, 2
kLFOsigAmount = lfo(.3, kLFOfreq, 0)+0.5
kModdedSigL delayk kLFOsigAmount, 4
kModdedSigR delayk kLFOsigAmount, 3.8
; Output
aEnv linseg 0, 1, 1, p3 - 2, 1, 1, 0
aOutL = (aloopL * aEnv * kModdedSigL)
aOutR = (aloopR * aEnv * kModdedSigR)

outs aOutL * ampdbfs(-6), aOutR * ampdbfs(-6)
endin

I tested the output several times & still no DC offset anymore so appears that does the trick. I haven’t noticed any zippering using the k rate lfos (I haven’t really checked that closely) but of course one can use a rate if preferred

Hopefully that makes sense. I’ll try to look at why clicking is happening when I can as well but maybe you or someone else will notice a solution.

Cheers,

Scott

Csound mailing list Csound@listserv.heanet.ie https://listserv.heanet.ie/cgi-bin/wa?A0=CSOUND Send bugs reports to https://github.com/csound/csound/issues Discussions of bugs and features can be posted here

Ok, now I realize I had tested the version prior to the ringmod addition etc. to make finding the DC offset easier. The DC offset isn’t nearly as bad for some reason. But I got no clicking in the previous version either so culprit might be in the second outs. In my previous mod I should have applied the env to the delays as well. Oops…

Cheers,

Scott