changeset 14:cf56b64a3c11

Prototyping of a improved zaxplay with SDL audio output. Does not work as intended yet.
author Matti Hamalainen <ccr@tnsp.org>
date Thu, 20 May 2010 17:17:36 +0300
parents e5049100f6ac
children fa87f8897f21
files pwpzax/orig.c pwpzax/zaxplay.c
diffstat 2 files changed, 510 insertions(+), 200 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/pwpzax/orig.c	Thu May 20 17:17:36 2010 +0300
@@ -0,0 +1,313 @@
+/*
+ *  PWP music player. Uses /dev/dsp (8-bit unsigned raw)
+ *
+ *  compile: gcc zaxplay.c -o zaxplay -lm
+ *
+ *  run: zaxplay <tunenum 0..3>
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <string.h>
+/* #include <linux/string.h> */
+
+#include <unistd.h>
+#include <fcntl.h>
+#include <math.h>
+
+typedef struct
+{
+  char*title;
+  int numchans;
+  int tempo;
+
+  unsigned char*patord;
+  unsigned char*tracks;
+}pwpmusic;
+
+#include "Final_Isi.h"
+#include "Future_Moottori.h"
+#include "Go_Mazzembly.h"
+#include "Ikuisuus.h"
+
+struct {
+   int wvlgt;
+   int wvleft;
+   int wvphase;
+}
+gb_ch[3];
+#define ch gb_ch
+
+int fd;
+int freq=8000;
+
+pwpmusic*tune;
+pwpmusic*tunes[]={&Final_Isi,&Future_Moottori,&Go_Mazzembly,&Ikuisuus};
+#define NUMTUNES 4
+
+gb_gen1chan(char*d,int l,int freq)
+{
+  int ph=128*256;
+  while(l--){
+    *d++=64+((ph>>8)&0x80);
+    ph+=freq;
+  }
+}
+
+gb_beepemu(char*d,int l)
+{
+  static int pf=0;
+  int
+    fq0=ch[0].wvlgt,
+    fq1=ch[1].wvlgt,
+    fq2=ch[2].wvlgt,fq;
+  if(ch[0].wvphase==0)fq0=32768;
+  if(ch[1].wvphase==0)fq1=32768;
+  if(ch[2].wvphase==0)fq2=32768;
+
+  if(fq0>fq1){int tmp=fq0;fq0=fq1;fq1=tmp;}
+  if(fq0>fq2){int tmp=fq0;fq0=fq2;fq2=tmp;}
+  if(fq1>fq2){int tmp=fq1;fq1=fq2;fq2=tmp;}
+
+  if(pf&1){
+    if(pf&2)fq=fq1;else fq=fq2;
+    if(!fq)fq=fq0;
+  }else{
+    fq=fq0;
+    if(fq==32768){fq=fq1;
+      if(fq==32768)fq=fq2;}
+  }
+  if(fq==32768)memset(d,128,l);else
+  {
+    fq=(65536*256)/fq; 
+    gb_gen1chan(d,l,fq);
+  }
+  pf++;
+}
+
+gb_genwave(char*d,int l)  /* tee oBtiMoITU versio joskus */
+{
+   int remain=0;
+
+   l<<=8;
+   while(l){
+      int min=ch[0].wvleft,w,sum;
+          w=ch[1].wvleft;if(w<min)min=w;
+          w=ch[2].wvleft;if(w<min)min=w;
+
+      /* tuon laskenta loppuun? */
+      sum=ch[0].wvphase+ch[1].wvphase+ch[2].wvphase+128;
+      if(sum<0)sum=0;else if(sum>255)sum=255;
+
+      if(min>l)min=l; l-=min;
+      memset(d,sum,(min+remain)>>8);
+        d+=((min+remain)>>8);
+        remain=(min+remain)&255;
+
+      {int i=0;
+      for(;i<3;i++){
+         w=ch[i].wvleft-=min;
+         if(!w){
+           ch[i].wvleft=ch[i].wvlgt;	/* add pulseratio */
+           ch[i].wvphase=0-ch[i].wvphase;
+         }
+      }}
+    }
+}
+
+/* my_memset, ... */
+
+/*
+gb_genwave_opt(char*buf,int endptr)
+{
+   #define SETTILL(a) \
+     {int bord=w##a,rs;if(bord>endptr)goto last;\
+      rs=sum;if(rs&~0xff){if(rs<0)rs=0;else rs=255;}\
+      memset(buf+(ptr>>8),rs,2+((bord-ptr)>>8));ptr=bord;\
+      ch[a].wvphase=0-ch[a].wvphase;\
+      sum+=(ch[a].wvphase)<<1;\
+      w##a=ptr+ch[a].wvlgt;}
+   #define HANDLE(s0,s1,s2) \
+      {SETTILL(s0); \
+      if(w##s0<=w##s1)goto w##s0##w##s1##w##s2;else \
+      if(w##s0<=w##s2)goto w##s1##w##s0##w##s2;else \
+                      goto w##s1##w##s2##w##s0;}
+
+   int ptr=0,sum=ch[0].wvphase+
+                 ch[1].wvphase+
+                 ch[2].wvphase;
+
+   int w0=ch[0].wvleft,
+       w1=ch[1].wvleft,
+       w2=ch[2].wvleft;
+
+   endptr<<=8;
+
+   w1w2w0:HANDLE(1,2,0);
+   w2w1w0:HANDLE(2,1,0);
+   w0w2w1:HANDLE(0,2,1);
+   w2w0w1:HANDLE(2,0,1);
+   w0w1w2:HANDLE(0,1,2);
+   w1w0w2:HANDLE(1,0,2);
+
+   last:
+     {int rs=sum;
+     if(rs&~0xff){if(rs<0)rs=0;else rs=255;}
+     memset(buf+(ptr>>8),rs,(endptr-ptr)>>8);}
+
+     ch[0].wvleft=w0-endptr;
+     ch[1].wvleft=w1-endptr;
+     ch[2].wvleft=w2-endptr;
+
+   #undef SETTILL
+}
+*/
+
+gb_genwave_opt(char*buf,int endptr)
+{
+   int ptr=0,sum=ch[0].wvphase+
+                 ch[1].wvphase+
+                 ch[2].wvphase;
+
+   #define w0 ch[0].wvleft
+   #define w1 ch[1].wvleft
+   #define w2 ch[2].wvleft
+
+/*   volatile int w0=ch[0].wvleft,
+       w1=ch[1].wvleft,
+       w2=ch[2].wvleft;*/
+
+   endptr<<=8;
+
+   #define SETTILL(a) \
+     {int bord=w##a,rs;if(bord>endptr)goto last;\
+      rs=sum;if(rs&~0xff){if(rs<0)rs=0;else rs=255;}\
+      memset(buf+(ptr>>8),rs,2+((bord-(ptr&~0xff))>>8));ptr=bord;\
+      ch[a].wvphase=0-ch[a].wvphase;\
+      sum+=(ch[a].wvphase)<<1;\
+      w##a=ptr+ch[a].wvlgt;}
+
+   if(w0<=w1){
+      if(w1<=w2)goto w0w1w2;else
+      if(w2<=w0)goto w2w0w1;else
+                goto w0w2w1;
+   }else{
+      if(w0<=w2)goto w1w0w2;else
+      if(w2<=w1)goto w2w1w0;       //.. else w1w2w0 (next)
+   }
+
+   w1w2w0:
+     SETTILL(1);
+     if(w1<=w2)goto w1w2w0;else
+     if(w1<=w0)goto w2w1w0;else   //.. if(w1>w0)goto w2w0w1;
+               goto w2w0w1;
+   w2w1w0:
+     SETTILL(2);
+     if(w2<=w1)goto w2w1w0;else
+     if(w2<=w0)goto w1w2w0;else
+               goto w1w0w2;
+
+   w0w2w1:
+     SETTILL(0);
+     if(w0<=w2)goto w0w2w1;else
+     if(w0<=w1)goto w2w0w1;else   //.. if(w0>w1)goto w2w1w0;
+               goto w2w1w0;
+   w2w0w1:
+     SETTILL(2);
+     if(w2<=w0)goto w2w0w1;else
+     if(w2<=w1)goto w0w2w1;else
+               goto w0w1w2;       //.. not reqd
+
+   w0w1w2:
+     SETTILL(0);
+     if(w0<=w1)goto w0w1w2;else
+     if(w0<=w2)goto w1w0w2;else   //.. if(w0>w2)goto w1w2w0;
+               goto w1w2w0;
+
+   w1w0w2:
+     SETTILL(1);
+     if(w1<=w0)goto w1w0w2;else
+     if(w1<=w2)goto w0w1w2;else
+               goto w0w2w1;
+
+   last:
+     {int rs=sum;
+     if(rs&~0xff){if(rs<0)rs=0;else rs=255;}
+     memset(buf+(ptr>>8),rs,2+((endptr-ptr)>>8));}
+
+     ch[0].wvleft=w0-endptr;
+     ch[1].wvleft=w1-endptr;
+     ch[2].wvleft=w2-endptr;
+
+   #undef SETTILL
+}
+#define VOLUME 32
+
+playnote(char*buf) /* ==> playtick */
+{
+  static int ord=0,row=0;
+  int chan=0,pat=tune->patord[ord];
+
+  for(;chan<tune->numchans;chan++){
+    unsigned char b=tune->tracks[(pat*tune->numchans+chan)*64+row];
+
+    if(b==254)gb_ch[chan].wvphase=0;else
+    if(b!=255){
+       b=(b>>4)*12+(b&15);
+       gb_ch[chan].wvlgt=
+         ((double)(400.0*256)/pow(1.059465,b));
+         
+       if(gb_ch[chan].wvlgt<512)
+          gb_ch[chan].wvlgt=512;
+
+       gb_ch[chan].wvleft=gb_ch[chan].wvlgt/(chan+2);
+       gb_ch[chan].wvphase=VOLUME;
+    }
+  }
+
+  gb_genwave(buf,tune->tempo*freq/73);
+  write(fd,buf,tune->tempo*freq/73);
+
+/*  {int j=4;for(;j;j--){
+  gb_beepemu(buf,tune->tempo*freq/(73*4));
+  write(fd,buf,tune->tempo*freq/(73*4));}}*/
+
+  row++;if(row==64){
+    row=0;pat=tune->patord[++ord];
+    if(pat==255)ord=0;
+  }
+}
+
+playzax()
+{
+  int i=0;
+  char*buf=malloc(tune->tempo*freq/73);
+  fd=open("/dev/dsp",O_WRONLY);
+
+  for(;i<3;i++){
+  gb_ch[i].wvlgt=gb_ch[i].wvleft=32000;gb_ch[i].wvphase=0;}
+
+  for(;;){
+    playnote(buf);
+  }
+}
+
+int main(int argc,char**argv)
+{
+   if(argc!=2)
+   {
+      fprintf(stderr,"usage: %s <tunenum 0..%d>\n",
+        argv[0],NUMTUNES-1);
+      return 0;
+   }
+
+   {int i=argv[1][0]-'0';
+    if(i<0 || i>=NUMTUNES)i=rand()%NUMTUNES;
+    tune=tunes[i];
+   }
+
+   playzax();
+   return 0;
+}
--- a/pwpzax/zaxplay.c	Tue May 18 20:47:07 2010 +0300
+++ b/pwpzax/zaxplay.c	Thu May 20 17:17:36 2010 +0300
@@ -1,20 +1,16 @@
 /*
- *  PWP music player. Uses /dev/dsp (8-bit unsigned raw)
+ *  PWP music player. Uses libSDL for audio output.
  *
- *  compile: gcc zaxplay.c -o zaxplay -lm
+ *  compile: gcc -O3 -o zaxplay zaxplay.c `sdl-config --libs --cflags`
  *
- *  run: zaxplay <tunenum 0..3>
+ *  run: zaxplay <tunenum>
  *
  */
 
 #include <stdio.h>
 #include <stdlib.h>
-
 #include <string.h>
-/* #include <linux/string.h> */
-
-#include <unistd.h>
-#include <fcntl.h>
+#include <SDL.h>
 #include <math.h>
 
 typedef struct
@@ -25,29 +21,64 @@
 
   unsigned char*patord;
   unsigned char*tracks;
-}pwpmusic;
+} pwpmusic;
 
 #include "Final_Isi.h"
 #include "Future_Moottori.h"
 #include "Go_Mazzembly.h"
 #include "Ikuisuus.h"
 
+static const pwpmusic *tunes[] = {
+    &Final_Isi, &Future_Moottori, &Go_Mazzembly, &Ikuisuus
+};
+static const int ntunes = sizeof(tunes) / sizeof(tunes[0]);
+pwpmusic *tune;
+
+
 struct {
-   int wvlgt;
-   int wvleft;
-   int wvphase;
-}
-gb_ch[3];
-#define ch gb_ch
+  struct {
+     int wvlgt;
+     int wvleft;
+     int wvphase;
+     int wvlgt1;
+  }ch[3];
+  int freq;
+} pwpgb;
+
+#define pwplib_volume 64
+#define pwplib_sound_off(c)       gb_sound(c,0,0,0)
+#define pwplib_sound_n(c,n) p     gb_sound(c,n,128,128)
+#define pwplib_sound_nv(c,n,v)    gb_sound(c,n,v,128)  
+#define pwplib_sound_nvr(c,n,v,r) gb_sound(c,n,v,r)
 
-int fd;
-int freq=8000;
+void gb_sound(int chan,int freq,int volume,int ratio)
+{
+  if(volume&&freq){
+    int wvlgt=
+      ((double)(pwpgb.freq*12)/pow(1.059465,freq/256.0));
+
+    if(ratio<1)ratio=1;else if(ratio>255)ratio=255;
+
+    pwpgb.ch[chan].wvlgt=(wvlgt*ratio)>>7;
+    pwpgb.ch[chan].wvlgt1=2*pwpgb.ch[chan].wvlgt-wvlgt;
 
-pwpmusic*tune;
-pwpmusic*tunes[]={&Final_Isi,&Future_Moottori,&Go_Mazzembly,&Ikuisuus};
-#define NUMTUNES 4
+    pwpgb.ch[chan].wvleft=pwpgb.ch[chan].wvlgt/(chan+2);
+    pwpgb.ch[chan].wvphase=volume;
+  }else{
+    pwpgb.ch[chan].wvphase=0;
+    pwpgb.ch[chan].wvleft=pwpgb.ch[chan].wvlgt=32123;
+  }
+}
 
-gb_gen1chan(char*d,int l,int freq)
+void gb_init(int freq)
+{
+  int i;
+  pwpgb.freq = freq;
+  for(i=0;i<3;i++)
+     gb_sound(i,0,0,0);
+}
+
+void gb_gen1chan(char*d,int l,int freq)
 {
   int ph=128*256;
   while(l--){
@@ -56,7 +87,9 @@
   }
 }
 
-gb_beepemu(char*d,int l)
+#define ch pwpgb.ch
+
+void gb_beepemu(char*d,int l)
 {
   static int pf=0;
   int
@@ -87,17 +120,17 @@
   pf++;
 }
 
-gb_genwave(char*d,int l)  /* tee oBtiMoITU versio joskus */
+void gb_genwave(char*d,int l)
 {
    int remain=0;
 
    l<<=8;
-   while(l){
+   while(l)
+   {
       int min=ch[0].wvleft,w,sum;
           w=ch[1].wvleft;if(w<min)min=w;
           w=ch[2].wvleft;if(w<min)min=w;
 
-      /* tuon laskenta loppuun? */
       sum=ch[0].wvphase+ch[1].wvphase+ch[2].wvphase+128;
       if(sum<0)sum=0;else if(sum>255)sum=255;
 
@@ -109,205 +142,169 @@
       {int i=0;
       for(;i<3;i++){
          w=ch[i].wvleft-=min;
-         if(!w){
-           ch[i].wvleft=ch[i].wvlgt;	/* add pulseratio */
+         if(!w)
+         {
+           ch[i].wvleft=ch[i].wvlgt1;
+           ch[i].wvlgt1=ch[i].wvlgt;
+           ch[i].wvlgt=ch[i].wvleft;
            ch[i].wvphase=0-ch[i].wvphase;
          }
-      }}
+       }
+      }
     }
 }
 
-/* my_memset, ... */
-
-/*
-gb_genwave_opt(char*buf,int endptr)
-{
-   #define SETTILL(a) \
-     {int bord=w##a,rs;if(bord>endptr)goto last;\
-      rs=sum;if(rs&~0xff){if(rs<0)rs=0;else rs=255;}\
-      memset(buf+(ptr>>8),rs,2+((bord-ptr)>>8));ptr=bord;\
-      ch[a].wvphase=0-ch[a].wvphase;\
-      sum+=(ch[a].wvphase)<<1;\
-      w##a=ptr+ch[a].wvlgt;}
-   #define HANDLE(s0,s1,s2) \
-      {SETTILL(s0); \
-      if(w##s0<=w##s1)goto w##s0##w##s1##w##s2;else \
-      if(w##s0<=w##s2)goto w##s1##w##s0##w##s2;else \
-                      goto w##s1##w##s2##w##s0;}
-
-   int ptr=0,sum=ch[0].wvphase+
-                 ch[1].wvphase+
-                 ch[2].wvphase;
-
-   int w0=ch[0].wvleft,
-       w1=ch[1].wvleft,
-       w2=ch[2].wvleft;
-
-   endptr<<=8;
-
-   w1w2w0:HANDLE(1,2,0);
-   w2w1w0:HANDLE(2,1,0);
-   w0w2w1:HANDLE(0,2,1);
-   w2w0w1:HANDLE(2,0,1);
-   w0w1w2:HANDLE(0,1,2);
-   w1w0w2:HANDLE(1,0,2);
-
-   last:
-     {int rs=sum;
-     if(rs&~0xff){if(rs<0)rs=0;else rs=255;}
-     memset(buf+(ptr>>8),rs,(endptr-ptr)>>8);}
-
-     ch[0].wvleft=w0-endptr;
-     ch[1].wvleft=w1-endptr;
-     ch[2].wvleft=w2-endptr;
-
-   #undef SETTILL
-}
-*/
-
-gb_genwave_opt(char*buf,int endptr)
-{
-   int ptr=0,sum=ch[0].wvphase+
-                 ch[1].wvphase+
-                 ch[2].wvphase;
-
-   #define w0 ch[0].wvleft
-   #define w1 ch[1].wvleft
-   #define w2 ch[2].wvleft
-
-/*   volatile int w0=ch[0].wvleft,
-       w1=ch[1].wvleft,
-       w2=ch[2].wvleft;*/
-
-   endptr<<=8;
-
-   #define SETTILL(a) \
-     {int bord=w##a,rs;if(bord>endptr)goto last;\
-      rs=sum;if(rs&~0xff){if(rs<0)rs=0;else rs=255;}\
-      memset(buf+(ptr>>8),rs,2+((bord-(ptr&~0xff))>>8));ptr=bord;\
-      ch[a].wvphase=0-ch[a].wvphase;\
-      sum+=(ch[a].wvphase)<<1;\
-      w##a=ptr+ch[a].wvlgt;}
-
-   if(w0<=w1){
-      if(w1<=w2)goto w0w1w2;else
-      if(w2<=w0)goto w2w0w1;else
-                goto w0w2w1;
-   }else{
-      if(w0<=w2)goto w1w0w2;else
-      if(w2<=w1)goto w2w1w0;       //.. else w1w2w0 (next)
-   }
 
-   w1w2w0:
-     SETTILL(1);
-     if(w1<=w2)goto w1w2w0;else
-     if(w1<=w0)goto w2w1w0;else   //.. if(w1>w0)goto w2w0w1;
-               goto w2w0w1;
-   w2w1w0:
-     SETTILL(2);
-     if(w2<=w1)goto w2w1w0;else
-     if(w2<=w0)goto w1w2w0;else
-               goto w1w0w2;
-
-   w0w2w1:
-     SETTILL(0);
-     if(w0<=w2)goto w0w2w1;else
-     if(w0<=w1)goto w2w0w1;else   //.. if(w0>w1)goto w2w1w0;
-               goto w2w1w0;
-   w2w0w1:
-     SETTILL(2);
-     if(w2<=w0)goto w2w0w1;else
-     if(w2<=w1)goto w0w2w1;else
-               goto w0w1w2;       //.. not reqd
-
-   w0w1w2:
-     SETTILL(0);
-     if(w0<=w1)goto w0w1w2;else
-     if(w0<=w2)goto w1w0w2;else   //.. if(w0>w2)goto w1w2w0;
-               goto w1w2w0;
-
-   w1w0w2:
-     SETTILL(1);
-     if(w1<=w0)goto w1w0w2;else
-     if(w1<=w2)goto w0w1w2;else
-               goto w0w2w1;
-
-   last:
-     {int rs=sum;
-     if(rs&~0xff){if(rs<0)rs=0;else rs=255;}
-     memset(buf+(ptr>>8),rs,2+((endptr-ptr)>>8));}
+struct {
+   int ord,patt,row;
+   int tick,tempo;
+   int frag, curr, freq;
+} player;
 
-     ch[0].wvleft=w0-endptr;
-     ch[1].wvleft=w1-endptr;
-     ch[2].wvleft=w2-endptr;
 
-   #undef SETTILL
-}
-#define VOLUME 32
-
-playnote(char*buf) /* ==> playtick */
+void player_set_tempo(int tempo)
 {
-  static int ord=0,row=0;
-  int chan=0,pat=tune->patord[ord];
-
-  for(;chan<tune->numchans;chan++){
-    unsigned char b=tune->tracks[(pat*tune->numchans+chan)*64+row];
-
-    if(b==254)gb_ch[chan].wvphase=0;else
-    if(b!=255){
-       b=(b>>4)*12+(b&15);
-       gb_ch[chan].wvlgt=
-         ((double)(400.0*256)/pow(1.059465,b));
-         
-       if(gb_ch[chan].wvlgt<512)
-          gb_ch[chan].wvlgt=512;
-
-       gb_ch[chan].wvleft=gb_ch[chan].wvlgt/(chan+2);
-       gb_ch[chan].wvphase=VOLUME;
-    }
-  }
-
-  gb_genwave(buf,tune->tempo*freq/73);
-  write(fd,buf,tune->tempo*freq/73);
-
-/*  {int j=4;for(;j;j--){
-  gb_beepemu(buf,tune->tempo*freq/(73*4));
-  write(fd,buf,tune->tempo*freq/(73*4));}}*/
-
-  row++;if(row==64){
-    row=0;pat=tune->patord[++ord];
-    if(pat==255)ord=0;
-  }
+   player.tempo = tempo;
+   player.frag = (player.freq * tempo) / 73;
 }
 
-playzax()
+void player_newnote()
 {
-  int i=0;
-  char*buf=malloc(tune->tempo*freq/73);
-  fd=open("/dev/dsp",O_WRONLY);
+   int c=0;
+   
+   for(;c<tune->numchans;c++)
+   {
+      int note=tune->tracks[(player.patt * tune->numchans + c) * 64 + player.row];
+      if(note==254)
+         pwplib_sound_nv(c,0,0);
+      else 
+      if(note!=255)
+         pwplib_sound_nv(c,(note-5)<<8,pwplib_volume);
+   }
+   player.row++;
+   if(player.row==64)
+   {
+      player.row=0;
+      player.ord++;
+      player.patt=tune->patord[player.ord];
+
+      if(player.patt>128)
+      {
+         if(player.patt==255)player.ord=0;else
+         {
+            if(player.patt==254)player.tempo=4;
+            player.ord++;
+         }
+         player.patt=tune->patord[player.ord];
+      }
+   }
+}
 
-  for(;i<3;i++){
-  gb_ch[i].wvlgt=gb_ch[i].wvleft=32000;gb_ch[i].wvphase=0;}
+void player_tick(void)
+{
+   if (player.tick == 0)
+       player_newnote();
+
+   player.tick++;
+   if (player.tick >= player.tempo)
+       player.tick=0;
+}
 
-  for(;;){
-    playnote(buf);
-  }
+void player_render_cb(void *udata, Uint8 * buf, int len)
+{
+    (void) udata;
+    while (len > 0) {
+        if (player.curr > len) {
+            player.curr -= len;
+            gb_genwave((char *)buf, len);
+            len = 0;
+            player_tick();
+        } else {
+            gb_genwave((char *)buf, player.curr);
+            buf += player.curr;
+            len -= player.curr;
+            player.curr = player.frag;
+            player_tick();
+        }
+    }
+}
+
+static void sdlaudio_close(void)
+{
+    fprintf(stderr, "* Closing audio.\n");
+    SDL_CloseAudio();
+    SDL_Quit();
 }
 
 int main(int argc,char**argv)
 {
-   if(argc!=2)
+   SDL_Event event;
+   SDL_AudioSpec fmt;
+   int i;
+
+   /* Settings */
+   fmt.freq = 44100;
+   fmt.format = AUDIO_U8;
+   fmt.channels = 1;
+   fmt.samples = 2048;
+   fmt.callback = player_render_cb;
+
+   if (argc != 2)
    {
       fprintf(stderr,"usage: %s <tunenum 0..%d>\n",
-        argv[0],NUMTUNES-1);
+        argv[0], ntunes - 1);
       return 0;
    }
 
-   {int i=argv[1][0]-'0';
-    if(i<0 || i>=NUMTUNES)i=rand()%NUMTUNES;
-    tune=tunes[i];
+   i = atoi(argv[1]);
+   if (i < 0 || i >= ntunes) i = rand() % ntunes;
+   tune = tunes[i];
+
+   fprintf(stderr,
+     "Tune #%d: '%s'\n"
+     "Tempo: %d\n"
+     "Channels: %d\n",
+     i, tune->title, tune->tempo, tune->numchans);
+
+   if (SDL_Init(SDL_INIT_EVENTTHREAD | SDL_INIT_AUDIO) != 0)
+   {
+       fprintf(stderr, "* SDL could not be initialized.\n");
+       return 1;
+   }
+
+   fprintf(stderr, "* SDL audio request %d, %d, %d -> %d\n",
+       fmt.freq, fmt.format, fmt.channels, fmt.samples);
+
+   if (SDL_OpenAudio(&fmt, NULL) < 0)
+   {
+       fprintf(stderr, "* SDL: Could not get desired audio format.\n");
+       return 1;
    }
 
-   playzax();
+   fprintf(stderr, "* SDL audio initialized %d, %d, %d -> %d\n",
+       fmt.freq, fmt.format, fmt.channels, fmt.samples);
+   
+   atexit(sdlaudio_close);
+
+   gb_init(fmt.freq);
+   player.freq = fmt.freq;
+   player.row = player.ord = 0;
+   player.patt = tune->patord[0];
+   player.tick = 0;
+   player_set_tempo(tune->tempo);
+   player.curr = player.frag;
+
+   SDL_PauseAudio(0);
+
+   
+   while (SDL_WaitEvent(&event) >= 0) {
+       switch (event.type) {
+         case SDL_QUIT:
+            fprintf(stderr, "* Quitting\n");
+            exit(0);
+            break;
+       }
+   }
+   
    return 0;
 }