aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Knight <q@1bpm.net>2021-08-25 22:18:18 +0100
committerRichard Knight <q@1bpm.net>2021-08-25 22:18:18 +0100
commit5f084737a2899d2765432d672c6ef608e6203e14 (patch)
treea6410439f25dce28fab4d8fe12f40d79b5de76e3
parent38c0b050496563ed2d2d347f3fd7c122d8c9d5b6 (diff)
downloadcsound-opl-5f084737a2899d2765432d672c6ef608e6203e14.tar.gz
csound-opl-5f084737a2899d2765432d672c6ef608e6203e14.tar.bz2
csound-opl-5f084737a2899d2765432d672c6ef608e6203e14.zip
examples update
-rw-r--r--examples/0-fltk_gui.csd145
-rw-r--r--examples/1-chord_sequence.csd73
-rw-r--r--examples/2-random_params.csd36
-rw-r--r--examples/3-controlchanges.csd31
4 files changed, 177 insertions, 108 deletions
diff --git a/examples/0-fltk_gui.csd b/examples/0-fltk_gui.csd
index d81a48a..558d73f 100644
--- a/examples/0-fltk_gui.csd
+++ b/examples/0-fltk_gui.csd
@@ -2,23 +2,37 @@
<CsOptions>
-odac
-+rtmidi=virtual -M0
+-m0
</CsOptions>
-; ==============================================
<CsInstruments>
+/*
+ csound-opl example 0
+ FLTK gui for instrument editing
+
+ Richard Knight 2021 : examples are licensed as public domain equivalent : http://unlicense.org/
-sr = 44100
+*/
+
+sr = 44100
kr = 4410
-nchnls = 2
-0dbfs = 1
+nchnls = 2
+0dbfs = 1
seed 0
+; operator parameters and handles
gkop[][] init 4, 12
giop[][] init 4, 12
+
+; global instrument parameters and handles
gkinstr[] init 8
giinstr[] init 8
+
+; GUI spacing variables
giopwidth = 200
gidiv = 60
+
+; FLTK GUI objects for an operator
opcode operator, 0, i
iop xin
ix = giopwidth * iop
@@ -39,33 +53,18 @@ opcode operator, 0, i
endop
-opcode randomise, 0, 0
- iop = 0
- while (iop < 4) do
- FLsetVal_i random(30, 63), giop[iop][0]
- FLsetVal_i random(0, 3), giop[iop][1]
- FLsetVal_i random(0, 15), giop[iop][2]
- FLsetVal_i random(0, 15), giop[iop][3]
- FLsetVal_i random(0, 15), giop[iop][4]
- FLsetVal_i random(0, 15), giop[iop][5]
- FLsetVal_i random(0, 7), giop[iop][6]
- FLsetVal_i random(0, 15), giop[iop][7]
- FLsetVal_i random(0, 1), giop[iop][8]
- FLsetVal_i random(0, 1), giop[iop][9]
- FLsetVal_i random(0, 1), giop[iop][10]
- FLsetVal_i random(0, 1), giop[iop][11]
- iop += 1
- od
- FLsetVal_i random(0, 7), giinstr[2]
- FLsetVal_i random(0, 7), giinstr[3]
-endop
+; run the GUI
instr gui
FLpanel "OPL3", 1000, 768
+
+ ; operator columns
operator 0
operator 1
operator 2
operator 3
+
+ ; global column
ix = 800
iy = 0
ihl FLbox "Globals", 1, 2, 14, giopwidth, 30, ix, iy
@@ -81,12 +80,48 @@ instr gui
knull1, inull1 FLbutton "Panic", 1, 0, 1, giopwidth, 30, ix, iy+(gidiv*6), 0, nstrnum("panic"), 0, 1
FLpanelEnd
FLrun
+
+ ; initially, hide the last two operators (ie non four-operator mode)
event_i "i", "fouropset", 0, 1, 0
endin
+; audio processing
+instr main
+
+ ; the synthesiser
+ giopl, aL, aR opl
+ outs aL, aR
+
+ ; get operator handles and set the global instrument parameters from the FLTK widgets
+ iop1, iop2, iop3, iop4 oplinstrument giopl, gkinstr[0], gkinstr[1], gkinstr[2], gkinstr[3], gkinstr[4], gkinstr[5], gkinstr[6], gkinstr[7]
+
+ ; set the operator parameters from the FLTK widgets
+ oploperator iop1, gkop[0][0], gkop[0][1], gkop[0][2], gkop[0][3], gkop[0][4], gkop[0][5], gkop[0][6], gkop[0][7], gkop[0][8], gkop[0][9], gkop[0][10], gkop[0][11]
+ oploperator iop2, gkop[1][0], gkop[1][1], gkop[1][2], gkop[1][3], gkop[1][4], gkop[1][5], gkop[1][6], gkop[1][7], gkop[1][8], gkop[1][9], gkop[1][10], gkop[1][11]
+ oploperator iop3, gkop[2][0], gkop[2][1], gkop[2][2], gkop[2][3], gkop[2][4], gkop[2][5], gkop[2][6], gkop[2][7], gkop[2][8], gkop[2][9], gkop[2][10], gkop[2][11]
+ oploperator iop4, gkop[3][0], gkop[3][1], gkop[3][2], gkop[3][3], gkop[3][4], gkop[3][5], gkop[3][6], gkop[3][7], gkop[3][8], gkop[3][9], gkop[3][10], gkop[3][11]
+
+endin
+
+
+; respond to realtime MIDI input accordingly
+instr 1
+ inote notnum
+ iveloc veloc
+ oplnote giopl, 0, inote, iveloc
+endin
+
+
+; panic: reset the opl instance
+instr panic
+ oplpanic giopl
+endin
+
+; to be called when the '4OP' or 'Pseudo 4OP' buttons are pressed
instr fouroptrig
+ ; elicit the state and call the set instrument
kstate = 0
if (gkinstr[4] == 1 || gkinstr[5] == 1) then
kstate = 1
@@ -95,6 +130,8 @@ instr fouroptrig
turnoff
endin
+
+; show/hide the last two operators depending on the value of p4
instr fouropset
istate = p4
iop = 2
@@ -113,50 +150,30 @@ instr fouropset
od
endin
+
+; randomise slider values. NB does not actually work for the check boxes but they are still in here
instr randomiser
- randomise
+ iop = 0
+ while (iop < 4) do
+ FLsetVal_i random(30, 63), giop[iop][0]
+ FLsetVal_i random(0, 3), giop[iop][1]
+ FLsetVal_i random(0, 15), giop[iop][2]
+ FLsetVal_i random(0, 15), giop[iop][3]
+ FLsetVal_i random(0, 15), giop[iop][4]
+ FLsetVal_i random(0, 15), giop[iop][5]
+ FLsetVal_i random(0, 7), giop[iop][6]
+ FLsetVal_i random(0, 15), giop[iop][7]
+ FLsetVal_i random(0, 1), giop[iop][8]
+ FLsetVal_i random(0, 1), giop[iop][9]
+ FLsetVal_i random(0, 1), giop[iop][10]
+ FLsetVal_i random(0, 1), giop[iop][11]
+ iop += 1
+ od
+ FLsetVal_i random(0, 7), giinstr[2]
+ FLsetVal_i random(0, 7), giinstr[3]
turnoff
endin
-instr main
- giopl, aL, aR opl 5
- outs aL, aR
-
-
- iop1, iop2, iop3, iop4 oplinstrument giopl, gkinstr[0], gkinstr[1], gkinstr[2], gkinstr[3], gkinstr[4], gkinstr[5], gkinstr[6], gkinstr[7]
-
-
- ; level, keyscale, attack, decay
- kattack init 2
- kdecay init 13
-
- oploperator iop1, gkop[0][0], gkop[0][1], gkop[0][2], gkop[0][3], gkop[0][4], gkop[0][5], gkop[0][6], gkop[0][7], gkop[0][8], gkop[0][9], gkop[0][10], gkop[0][11]
- oploperator iop2, gkop[1][0], gkop[1][1], gkop[1][2], gkop[1][3], gkop[1][4], gkop[1][5], gkop[1][6], gkop[1][7], gkop[1][8], gkop[1][9], gkop[1][10], gkop[1][11]
- oploperator iop3, gkop[2][0], gkop[2][1], gkop[2][2], gkop[2][3], gkop[2][4], gkop[2][5], gkop[2][6], gkop[2][7], gkop[2][8], gkop[2][9], gkop[2][10], gkop[2][11]
- oploperator iop4, gkop[3][0], gkop[3][1], gkop[3][2], gkop[3][3], gkop[3][4], gkop[3][5], gkop[3][6], gkop[3][7], gkop[3][8], gkop[3][9], gkop[3][10], gkop[3][11]
-
-endin
-
-
-instr 2
- ;inotes[] fillarray 48, 52, 53, 57, 60, 64, 65, 69
- ;inote = 56;inotes[int(random(0, lenarray(inotes)-1))]-36
- oplnote giopl, 0, 60, 120
- oplnote giopl, 0, 64, 120
- oplnote giopl, 0, 65, 120
- oplnote giopl, 0, 69, 120
-
-endin
-
-instr 1
- inote notnum
- iveloc veloc
- oplnote giopl, 0, inote, iveloc
-endin
-
-instr panic
- oplpanic giopl
-endin
</CsInstruments>
diff --git a/examples/1-chord_sequence.csd b/examples/1-chord_sequence.csd
index 38e0ed6..b45ee0f 100644
--- a/examples/1-chord_sequence.csd
+++ b/examples/1-chord_sequence.csd
@@ -3,6 +3,12 @@
-odac
</CsOptions>
<CsInstruments>
+/*
+ csound-opl example 1
+ Multiple channel chord sequence
+
+ Richard Knight 2021 : examples are licensed as public domain equivalent : http://unlicense.org/
+*/
sr = 44100
kr = 4410
@@ -11,19 +17,17 @@ nchnls = 2
giopl init 0
-instr main
- giopl, aL, aR opl
- outs aL, aR
-
- oplpatchchange giopl, 0, 89
- oplpatchchange giopl, 1, 12
- oplpatchchange giopl, 2, 72
- oplpatchchange giopl, 3, 96
-
- event_i "i", "sequencer", 0, p3
-endin
+/*
+ Play notes with certain parameters:
+ kinstr : the instrument number to play
+ kduration : play duration
+ kbase : base MIDI note number
+ kintervals : intervals to form a chord with from kbase
+ ktimeinc : how much time to step with each interval
+ kreadmode : read intervals 0=forward, 1=reverse
+*/
opcode playchord, 0, kkkk[]kk
kinstr, kduration, kbase, kintervals[], ktimeinc, kreadmode xin
ktime = 0
@@ -45,15 +49,40 @@ opcode playchord, 0, kkkk[]kk
endif
endop
+
+; audio output, voice setting and sequencer invocation
+instr main
+ ; the synthesiser
+ giopl, aL, aR opl
+ outs aL, aR
+
+ ; set the voices for four channels
+ oplpatchchange giopl, 0, 89
+ oplpatchchange giopl, 1, 12
+ oplpatchchange giopl, 2, 72
+ oplpatchchange giopl, 3, 96
+ oplpatchchange giopl, 4, 39
+
+ ; start the sequencer
+ event_i "i", "sequencer", 0, p3
+endin
+
+
+; basic chord triggering pseudo-sequencer
instr sequencer
itempo = 120
ibeatduration = 60/itempo
- kintervals[] fillarray 0, 4, 5, 9
- knotes[] fillarray 50, 54, 56, 48
+
+ ; intervals for chords, and notes for progression
+ kintervalsall[][] init 4, 4
+ kintervalsall fillarray 0, 4, 5, 9, 4, 5, 7, 9, 0, 5, 7, 14, 0, 5, 7, 8
+ knotes[] fillarray 50, 54, 56, 54
+
knotedx init 0
kbeat metro itempo/60
kbar0 init 0
if (kbeat == 1) then
+ kintervals[] getrow kintervalsall, knotedx
if (kbar0 == 0) then
playchord 3, ibeatduration*4, knotes[knotedx], kintervals, 0, 0
elseif (kbar0 == 1) then
@@ -64,6 +93,11 @@ instr sequencer
playchord 4, ibeatduration, knotes[knotedx]+12, kintervals, ibeatduration/4, 1
endif
+ kbassnote = knotes[knotedx]
+ event "i", 5, 0, ibeatduration*0.2, kbassnote-24
+ event "i", 5, ibeatduration*0.5, ibeatduration*0.16, kbassnote-12
+
+
if (kbar0 < 3) then
kbar0 += 1
else
@@ -78,24 +112,35 @@ instr sequencer
endin
+; play note on channel 0
instr 1
oplnote giopl, 0, p4, 120
endin
+
+; play note on channel 1
instr 2
oplnote giopl, 1, p4, 100
endin
+
+; play note on channel 2
instr 3
oplnote giopl, 2, p4, 100
endin
+
+; play note on channel 3
instr 4
oplnote giopl, 3, p4, 100
endin
+; play note on channel 4
+instr 5
+ oplnote giopl, 4, p4, 80
+endin
+
</CsInstruments>
-; ==============================================
<CsScore>
i"main" 0 3600
diff --git a/examples/2-random_params.csd b/examples/2-random_params.csd
index 37b951d..266406e 100644
--- a/examples/2-random_params.csd
+++ b/examples/2-random_params.csd
@@ -2,30 +2,35 @@
<CsOptions>
-odac
</CsOptions>
-; ==============================================
<CsInstruments>
+/*
+ csound-opl example 2
+ Parametric instrument modification with randomisation
-sr = 44100
+ Richard Knight 2021 : examples are licensed as public domain equivalent : http://unlicense.org/
+
+*/
+
+sr = 44100
kr = 4410
-nchnls = 2
-0dbfs = 1
+nchnls = 2
+0dbfs = 1
seed 0
instr main
- giopl, aL, aR opl 0
+ ; synthesiser
+ giopl, aL, aR opl
outs aL, aR
+ ; play a note each second
kmetro metro 1
schedkwhen kmetro, 0, 0, 2, 0, 1
+ ; randomise instrument parameters, but always set as four operator
iop1, iop2, iop3, iop4 oplinstrument giopl, int:k(random:k(0, 2)), int:k(random:k(0, 2)), random:k(0, 7), random:k(0, 7), 1, 1, int:k(random:k(0, 2)), int:k(random:k(0, 2))
-
- ; level, keyscale, attack, decay
- kattack init 2
- kdecay init 13
-;0 -15 freq mult
+ ; randomise all of the operators
oploperator iop1, random:k(60, 63), random:k(0, 3), random:k(0, 15), random:k(0, 15), random:k(0, 15), random:k(0, 1), random:k(0, 7), 0, random:k(0, 2), random:k(0, 2), random:k(0, 2), random:k(0, 2)
oploperator iop2, random:k(60, 63), random:k(0, 3), random:k(0, 15), random:k(0, 15), random:k(0, 15), random:k(0, 1), random:k(0, 7), 0, random:k(0, 2), random:k(0, 2), random:k(0, 2), random:k(0, 2)
oploperator iop3, random:k(60, 63), random:k(0, 3), random:k(0, 15), random:k(0, 15), random:k(0, 15), random:k(0, 1), random:k(0, 7), 0, random:k(0, 2), random:k(0, 2), random:k(0, 2), random:k(0, 2)
@@ -33,24 +38,15 @@ instr main
endin
+; play a random note from the array
instr 2
inotes[] fillarray 48, 52, 53, 57
inote = inotes[int(random(0, lenarray(inotes)-1))]+24
oplnote giopl, 0, inote, 120
endin
-instr 3
- inote = 48+24
- oplnote giopl, 1, inote, 120
- oplnote giopl, 1, inote+4, 120
- oplnote giopl, 1, inote+5, 120
- oplnote giopl, 1, inote+9, 120
-endin
-
-
</CsInstruments>
-; ==============================================
<CsScore>
i"main" 0 3600
</CsScore>
diff --git a/examples/3-controlchanges.csd b/examples/3-controlchanges.csd
index 93749b1..f2ae31d 100644
--- a/examples/3-controlchanges.csd
+++ b/examples/3-controlchanges.csd
@@ -3,6 +3,12 @@
-odac -m0
</CsOptions>
<CsInstruments>
+/*
+ csound-opl example 3
+ Control change, pitch bend, bank change and patch change with randomly selected patches
+
+ Richard Knight 2021 : examples are licensed as public domain equivalent : http://unlicense.org/
+*/
sr = 44100
kr = 4410
@@ -10,40 +16,45 @@ nchnls = 2
0dbfs = 1
seed 0
+; do bank changes: causes device reset which will stop current notes/possibly cause clicks but demonstrates nonetheless
+gichangebank = 0
+gistartbank = 0
+
+; loop through each bank and play a note or two for each
instr main
giopl, aL, aR opl
outs aL, aR
gSbanks[] oplbanknames giopl
- index = 0
itime = 0
inote = 0
inotes[] fillarray 50, 52, 64, 56, 53, 59, 62
- while (index < lenarray(gSbanks)) do
- event_i "i", "play", itime, 2, index, inotes[inote], 0
+ while (gistartbank < lenarray(gSbanks)) do
+ event_i "i", "play", itime, 2, gistartbank, inotes[inote], 0
if (inote < lenarray(inotes)-1) then
inote += 1
else
inote = 0
endif
if (random(0, 1) > 0.5) then
- event_i "i", "play", itime+0.5, 0.5, index, inotes[inote], 1
+ event_i "i", "play", itime+0.5, 0.5, gistartbank, inotes[inote], 1
endif
itime += 1
- index += 1
+ gistartbank += 1
od
p3 = itime
endin
+; set the patch, play the note, optionally set the bank and call the control change instrument
instr play
ibank = p4
inote = p5
ichannel = p6
ipatch random 0, 127
- prints sprintf("%d-%d (%s)\n", ibank, ipatch, gSbanks[ibank])
- if (ichannel == 0) then
+ if (ichannel == 0 && gichangebank = 1) then
+ prints sprintf("%d-%d (%s)\n", ibank, ipatch, gSbanks[ibank])
oplsetbank giopl, ibank
endif
oplpatchchange giopl, ichannel, ipatch
@@ -52,6 +63,7 @@ instr play
endin
+; conditionally add a pitch bend and control change
instr cc
ichannel = p4
if (random(0, 1) > 0.6) then
@@ -60,8 +72,8 @@ instr cc
oplpitchbend giopl, ichannel, kbend
endif
-
- if (random(0, 1) > 0.6) then
+ ; control change for type 1 (modulation)
+ if (random(0, 1) > 0.4) then
kmod linseg 0, p3*0.7, 255, p3*0.3, 0
oplcontrolchange giopl, ichannel, 1, kmod
endif
@@ -69,7 +81,6 @@ endin
</CsInstruments>
-; ==============================================
<CsScore>
i"main" 0 3600
</CsScore>