I have a couple of files one is rough and hastily thrown together. But it pulls
together a few ideas from various people and tries to implement a VOSS
algorithm to randomly generate music in a fractal pattern. It will also
generate MusicXML so you can load it it into a musical score application.
Tom McGuire
NB. Script withj02.ijs for creating wave files from notes.
NB. Sample fractal music "smoke puffs" is created fractal music
NB. Associated with "With J: Musical Smoke Puffs", APL Quote Quad
NB. Cliff Reiter, Last Modified 1998; 12-15
NB.
NB. Running the script creates 'sp.wav' which may be listened to using sound
recorder.
NB.
NB. requires 'files'
require 'format/printf'
ic=: 3!:4
j2l=:2&ic
j2i=: 1&ic
cnotes =: 'CcDeEFgGaAbB'
waveheader=:3 : 0 NB. y is input data size
1 22050 22050 1 8 waveheader y
:
'chan sampr Bpsec Bpsamp bpchan'=.x
'RIFF',(j2l 36+y),'WAVEfmt ',(16 0 0 0 1 0{a.),(j2i chan),(j2l
sampr,Bpsec),(j2i Bpsamp,bpchan),'data',j2l y
)
L2f=:{&(440*2^1r12*_9+i.12)@('CcDeEFgGaAbB'&i.)
NB. right now this is set to create frequencies from
NB. relative note numbers from the voss function
NB. right now it is simulated with 4 dice giving a range
NB. of 32 notes. Since we are using A4 as the starting
NB. frequency I will try to center notes around A4
NB.
N2f=: 13 : '{&(440*2^1r12*_16+i.32)@(_4&+) y'
note=:3 : 0 "0 NB. x is duration, y is freq
1r8 note y
:
<a.{~<.127.999*>:1 o. (2p1*<.0.5+y*x)*(i.%])<.0.5+22050*x
)
nmono=:;@:note
wwavemono=:(waveheader@#,])@[ fwrite ]
nstereo=:;@:(,@|:@,:&.>/"1)@:note NB. stero
wwavestereo=:(2 22050 44100 1 8&waveheader@#,])@[ fwrite ]
cile=: $@] $ ((/:@/:@] <.@:* (% #)),)
f19cile=:{&(110*2^1r6*i.19)@(19&cile)
sin=:1&o.
cos=:2&o.
four=:1: ,. cos ,. cos@+: ,. sin ,. sin@+:
mx=:+/ . *
CMM=:1 : '2p1&|@(+({.mx m"_ mx{:)@:four) f.'
dat=:_0.62 0.33 0.93 _0.59 0.05 _0.48
ind=:0 1 4;1 1 3;2 1 4;3 0 1;4 0 0;4 0 2
spp=:dat ind}5 2 5$0
f=:spp CMM
f^:(i.4) 0.3 0.4
fsp=:f19cile f^:(1000+i.200) 0.3 0.4
s=:1r6 nstereo fsp NB. create stereo notes
s wwavestereo '~temp/sp.wav' NB. write sound to wave file
NB. wd' winexec "C:\WINNT\system32\mplay32.exe sp.wav";'
NB. Sample syntax for starting a media window to play the wave file from J
NB. on mac use:
NB. 2!:0 'afplay ',jpath '~temp/sp.wav'
NB. create 2 notes wav data
NB. $s=:1r2 1r4 nmono 110 440
NB.
NB. create a wav file around the notes
NB. s wwavemono '~temp/temp.wav'
NB.
NB. Mary had a little lamb, create note data
NB. $s =: 1r3 nmono L2f mhall
NB. place in wav file
NB. s wwavemono '~temp/mhall.wav'
NB. play the file
NB. 2!:0 'afplay ',jpath '~temp/mhall.wav'
NB.
NB. Add spaces between the same note played contiguously
NB. s =: (, |:1r6,:26$1r3) nmono ,|:0,:L2f mhall
NB. create wav file
NB. s wwavemono '~temp/mhall.wav'
NB. play it
NB. 2!:0 'afplay ',jpath '~temp/mhall.wav'
noteno =: 13 : '_45 + y + 12*x-1'
nmonosp =: 4 : 0
'spc mnote' =. x
(, |: spc,:(#y)$mnote) nmono ,|:0,:N2f y
)
xor =: ((+.)*.(-.@:*.))
NB. voss - voss algorithm for creating fractal music
NB.
NB. References
NB. Martin Gardner. Mathematical games-white and brown music, fractal curves
and one-over-f fluctuations. Scientific American, 238(4):16â32, 1978.
NB. Pachet F et al Generating 1/f Noise Sequences as Constraint Satisfaction:
The Voss Constraint Proceedings of the Twenty-Fourth International Joint
Conference on Artificial Intelligence
NB. parameters: x - number of notes to create
NB. y - number of dice to use
NB.
voss =: 4 : 0
N =. x
nDice =. y
NB. dVal tracks the current dice values
dVal =. 1+?nDice$6
NB. Loop set up. previous dice roll bits will be all 1s
NB. and the first time into the loop will roll all dice therefore
z=. 0$0
prevbits =. nDice$1
for_i. i.N do.
ibits =. (nDice$2) #: i
NB. ip1bits =. (nDice$2) #: i+1
dchg =. ibits xor prevbits
prevbits =. ibits
NB. dchg is the vector of which dice to replace.
NB. Roll all dice and use dchg as mask to select the dice
NB. add that to the inverse mask on dVal and we should
NB. mimick the Voss method for 1/f noise
dVal =. ((-.dchg)*dVal) + dchg* 1+ ?nDice$6
z =. z, +/dVal
end.
z
)
NB. voss use:
NB. notes =: 30 voss 3
NB. s =: (, |:1r6,:(#notes)$1r3) nmono ,|:0,:N2f notes
NB. s wwavemono '~temp/temp8.wav'
NB. 2!:0 'afplay ',jpath '~temp/temp8.wav'
NB. create a musicML file with the notes
NB.
shfl =: 'cegab'
alt =: 1 _1 1 1 _1
NB. notes2 mk_score '~temp/temp10.xml'
mk_score =: 4 : 0
hdr =. freads '~temp/mxmlhdr.txt'
end =. freads '~temp/mxmlend.txt'
attr =. freads '~temp/mxmlattr.txt'
me =. '</measure>',LF
NB. first measure
anotes =. 12| _3+ x
aoct =. 4 + x >: 12
hdr fwrites y
for_i. anotes,.aoct do.
'nt oct' =. i
if. 0 = 4|i_index do.
if. i_index = 0 do.
m1 =. '<measure number="1">',LF,attr
else.
m1 =. (me,'<measure number="%d">',LF) sprintf < 1+<.i_index%4
end.
m1 fappends y
end.
if. (nt{cnotes) e. shfl do.
idx =. shfl i. nt{cnotes
nt1 =.
('<note>',LF,'<pitch>',LF,'<step>','%s','</step>',LF,'<alter>%d</alter>',LF,'<octave>','%d','</octave>',LF,'</pitch>',LF,'<duration>','1','</duration>',LF,'<type>','quarter','</type>',LF,'</note>',LF)
sprintf (toupper ({.nt){cnotes);(idx{alt);{.oct
else.
nt1 =.
('<note>',LF,'<pitch>',LF,'<step>','%s','</step>',LF,'<octave>','%d','</octave>',LF,'</pitch>',LF,'<duration>','1','</duration>',LF,'<type>','quarter','</type>',LF,'</note>',LF)
sprintf (({.nt){cnotes);{.oct
end.
nt1 fappends y
end.
(me,end) fappends y
)
cscale =: 'CDEFGABC'
mk_scoreC =: 4 : 0
hdr =. freads '~temp/mxmlhdr.txt'
end =. freads '~temp/mxmlend.txt'
attr =. freads '~temp/mxmlattr.txt'
me =. '</measure>',LF
NB. first measure
anotes =. 8| _3+ x
aoct =. 3 + <. x % 8
hdr fwrites y
for_i. anotes,.aoct do.
'nt oct' =. i
if. 0 = 4|i_index do.
if. i_index = 0 do.
m1 =. '<measure number="1">',LF,attr
else.
m1 =. (me,'<measure number="%d">',LF) sprintf < 1+<.i_index%4
end.
m1 fappends y
end.
nt1 =.
('<note>',LF,'<pitch>',LF,'<step>','%s','</step>',LF,'<octave>','%d','</octave>',LF,'</pitch>',LF,'<duration>','1','</duration>',LF,'<type>','quarter','</type>',LF,'</note>',LF)
sprintf (nt{cscale);{.oct
nt1 fappends y
end.
(me,end) fappends y
) <attributes>
<divisions>1</divisions>
<key>
<fifths>0</fifths>
</key>
<time>
<beats>4</beats>
<beat-type>4</beat-type>
</time>
<clef>
<sign>G</sign>
<line>2</line>
</clef>
</attributes>
</part>
</score-partwise>
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE score-partwise PUBLIC
"-//Recordare//DTD MusicXML 3.0 Partwise//EN"
"http://www.musicxml.org/dtds/partwise.dtd">
<score-partwise version="3.0">
<part-list>
<score-part id="P1">
<part-name>Music</part-name>
</score-part>
</part-list>
<part id="P1">
> On Mar 28, 2020, at 5:27 PM, Devon McCormick <[email protected]> wrote:
>
> Hi -
> has anyone done work with generating music or musical phrases in J? I'm
> helping someone develop a music training game that starts by generating
> sounds with a particular key, tempo, and phrase length. The idea is to
> help students to train their ears by testing them on their ability to play
> back a randomly-generated musical phrase.
>
> I've told my collaborator that I think the generation part should be
> relatively straightforward but I am not schooled in music, so I'm not sure
> how to start.
> I'm guessing that the second part of comparing the user's response to the
> generated phrase will be more difficult but I'd like to get any kind of
> start I can.
>
> Does anyone have any ideas about this?
>
> Thanks,
>
> Devon
>
> --
>
> Devon McCormick, CFA
>
> Quantitative Consultant
> ----------------------------------------------------------------------
> For information about J forums see http://www.jsoftware.com/forums.htm
----------------------------------------------------------------------
For information about J forums see http://www.jsoftware.com/forums.htm