Playing music with GP v3

Bill Allombert <[email protected]> Fri, 12 Sep 2025 19:56:43 +0200
Newsgroups gmane.comp.mathematics.pari.user
Message-ID <aMRe27ZqPSdohKxe@seventeen>
> Dear PARI lovers,
> 
> I have a made a new attempt at music, this one in stereo.
> 
> If you prefer to use ffplay, just change the first line to
> START="start_aplay";

An attempt to use digital instruments that sound better!

Cheers,
Bill
music2.gp (text/plain, 2.6 KB)
START="start_aplay";
FREQ=8000;
A=440;
TEMPO=60/100*4;
CHANNEL=2;
start_aplay(fifo="/tmp/parififo")=
{
  system(Str("test -p ",fifo" || mkfifo ",fifo,"; aplay -r",FREQ," -q -traw -c",CHANNEL," < ",fifo," &"));
  fileopen(fifo,"w");
}
start_ffplay(fifo="/tmp/parififo")=
{
  system(Str("test -p ",fifo" || mkfifo ",fifo,"; ffplay -i pipe: -f u8 -ar ",FREQ," -ac ",CHANNEL," -hide_banner -autoexit -v 0 < ",fifo," &"));
  fileopen(fifo,"w");
}
start_ffplaygit() = fileextern(Str("ffplay -i pipe: -f u8 -ar ",FREQ," -ac ",CHANNEL," -hide_banner -autoexit -v 0"),"w");
start_aplaygit() = fileextern(Str("aplay -r",FREQ," -q -traw -c",CHANNEL),"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);
}

playsound(f,freq,t,amp)=
{
  my(l=FREQ*TEMPO*t,a=FREQ*0.025,d=FREQ*0.05,s=0.66,r=FREQ*0.05);
  for(i=1,round(l), my(c=4*Pi*freq*i/FREQ);
     my(r=round(128+adsr(i,l,a,d,s,r)*(amp*besselj(0,c)*sqrt(c))));
     filewrite1(f,strchr(r));
     if (CHANNEL==1, next()); my(c=Pi*freq*i/FREQ);
     my(r=round(128+adsr(i,l,a,d,s,r)*(amp*besselj(Pi/2,c)*sqrt(c))));
     filewrite1(f,strchr(r));
  );
  print1(".");
  fileflush(f);
}

ode_to_joy="b4 b c' d' d' c' b a g g a b b4. a8 a2 b4 b c' d' d' c' b a g g a b a4. g8 g2 a4 a b g a b8 c' b4 g a b8 c' b4 a g a d2 b4 b c' d' d' c' b a g g a b a4. g8 g2";

la_marseillaise="r2 r8 r16 d16 d8. d16 g4 g a a d4. b8 g r16 g b8. g16 e4 c'2 a8. fis16 g2 r4 g8. a16 b4 b b c8. b16 b4 a r4 a8. b16 c4 c c d8. c16 b2 r4 d8. d16 d4 b8. g16 d'4 b8. g16 d2 r8 r16 d16 d8. fis16 a2 c4 a8. fis16 a4 g f2 e4 g8. g16 g4 fis8. g16 a2. r8 a8 bes4. bes8 bes bes c d a2. bes8 a g4. g8 g bes a g g4 fis8 r8 r4 r8 r16 d' d2 d8. d16 b8. g16 a2. r8 r16 d16 d2 d8. d16 b8. g16 a2 a8 r8 d,4 g2 r4 a4 b2 r2 c2 d4 e a,2 a8 r8 e'4 d2 d8. b16 c8. a16 g2. r4";
play(S,rl=0,rel)=
{
  my(mode=Map([0,0;1,2;2,3;3,5;4,7;5,9;6,10])); /*G major */
  my(f = call(eval(START),[]), T=4,d);
  foreach(strsplit(S," "), s,
    my(p=0,m=1,V=Vec(s),amp=120,nt=0,di=0);
    if (V[1]=="r",
       amp=0;
     , p=vecsearch(Vec("abcdefg"),V[1])-1;
       if (p<0,error(V));
       p=rel+centerlift(Mod(p-rel,7));
       );
    for(i=2,#V,
      my(c=V[i]);
      if(c=="i" && V[i+1]=="s",di++;i++
        ,c=="e" && V[i+1]=="s",di--;i++
        ,c=="'",p+=7
        ,c==",",p-=7
        ,c==".",m=3/2
        ,d=vecsearch(Vec("0123456789"),c), nt+=10*nt+d-1,
        ,error(V);
       ));
    if (nt,T = nt);
    if (amp,
      if(rl,rel = p);
      p = mapget(mode,p%7)+12*(p\7) + di);
    playsound(f,freq(p),m/T,amp));
  fileclose(f);
}
play(ode_to_joy,0,-2);
\\play(la_marseillaise,1,-7);