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 <devon...@gmail.com> 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

Reply via email to