Bill Allombert on Fri, 11 Jul 2025 15:02:27 +0200


[Date Prev] [Date Next] [Thread Prev] [Thread Next] [Date Index] [Thread Index]

Re: playing music with GP


On Thu, Jul 10, 2025 at 01:25:12PM -0700, American Citizen wrote:
> Hmmm, Hans, your script works great, but there seems to be a mild
> dissonance, due to the scale of octave being used. Are you using chromatic
> scale? I am curious, because the exact tones don't match my orchestral
> memory of those tones in "Ode to Joy"

I am not a musician and there are so many way this could be wrong.

Anyway, I have made a new version incorporating Hans improvement.

Cheers,
Bill
FREQ=8000;
A=440;
TEMPO=60/100*4;
start() = fileextern(Str("aplay -r",FREQ," -q -traw"),"w");

freq(n)= 2^(n/12)*A;

lerp(a,b,t) = a*(1-t)+b*t;

adsr(i,l,a,d,s,r) = 
{
  if(
     i<a, i/a,
     i<a+d, lerp(1,s,(i-a)/d),
     i>l-r, lerp(0,s,(l-i)/r),
     s);
}

playnote(f,freq,t)=
{
  my(l=FREQ*TEMPO*t,a=FREQ*0.025,d=FREQ*0.05,s=0.66,r=FREQ*0.05);
  for(i=1,l, my(c=2*Pi*freq*i/FREQ);
     my(r=round(128+adsr(i,l,a,d,s,r)*(120*sin(c))));
     filewrite1(f,strchr(r));
  );
  fileflush(f);
}

my(note=Map(["a",0;"b",2;"c",3;"d",5;"e",7;"f",8;"g",10])); play(f,s)=
{ 
  my(p,m=1,V=Vec(s),T=4);
  p=mapget(note,V[1]);
  foreach(V[^1],c,if(c=="#",p++,
                     c=="b",p--,
                     c=="'",p+=12,
                     c==",",p-=12,
                     c==".",m=3/2,
                     T=eval(c)));
  playnote(f,freq(p),m/T);
}


ode_to_joy=strsplit("b b c d d c b a g, g, a b b. a8 a2 b b c d d c b a g, g, a b a. g,8 g,2"," ");
ode_to_joy2=strsplit("d d eb f f eb d c bb bb c d d. c8 c2 d d eb f f eb d c bb bb c d c. bb8 bb2"," ");

f = start();
for(i=1,#ode_to_joy2,play(f,ode_to_joy[i]));
fileclose(f);