summaryrefslogtreecommitdiff
path: root/tutorials/sndkit/sblive
diff options
context:
space:
mode:
Diffstat (limited to 'tutorials/sndkit/sblive')
-rw-r--r--tutorials/sndkit/sblive/Makefile53
-rw-r--r--tutorials/sndkit/sblive/README12
-rw-r--r--tutorials/sndkit/sblive/asm10k.c1206
-rw-r--r--tutorials/sndkit/sblive/emu10k.dsp378
-rw-r--r--tutorials/sndkit/sblive/emu10k1.mac51
-rw-r--r--tutorials/sndkit/sblive/emu10k2.mac71
-rwxr-xr-xtutorials/sndkit/sblive/emuasm13
-rwxr-xr-xtutorials/sndkit/sblive/emuasm23
-rw-r--r--tutorials/sndkit/sblive/equalizer.mac117
-rw-r--r--tutorials/sndkit/sblive/ld10k.c220
-rw-r--r--tutorials/sndkit/sblive/mkheader.c37
-rw-r--r--tutorials/sndkit/sblive/null.dsp23
-rw-r--r--tutorials/sndkit/sblive/testgen.c92
-rw-r--r--tutorials/sndkit/sblive/vu.mac27
-rw-r--r--tutorials/sndkit/sblive/writegpr.c48
15 files changed, 2341 insertions, 0 deletions
diff --git a/tutorials/sndkit/sblive/Makefile b/tutorials/sndkit/sblive/Makefile
new file mode 100644
index 0000000..85efde5
--- /dev/null
+++ b/tutorials/sndkit/sblive/Makefile
@@ -0,0 +1,53 @@
+CC=cc -O
+SRCDIR=../../..
+INCLUDE=-I$(SRCDIR)/include
+LDFLAGS=
+INSTALLDIR=/usr/local/bin
+INSTALLLIB=/usr/lib/oss
+CFLAGS=$(INCLUDE) -DUSERLAND
+
+all: asm10k ld10k emu10k.bin1 emu10k.bin2 emu10k1_dsp.h emu10k2_dsp.h
+
+install: ld10k emu10k.bin1 emu10k.bin2
+ strip asm10k
+ rm -f $(INSTALLDIR)/ld10k $(INSTALLDIR)/emu10k.bin1 $(INSTALLDIR)/emu10k.bin2
+ cp ld10k $(INSTALLDIR)
+ cp emu10k.bin1 $(INSTALLLIB)
+ cp emu10k.bin2 $(INSTALLLIB)
+ cp *.map /tmp
+
+load: ld10k emu10k.bin1
+ cp -f *.map /tmp
+ ./ld10k emu10k.bin1 -a
+
+aload: ld10k emu10k.bin2
+ cp -f *.map /tmp
+ ./ld10k emu10k.bin2 -a
+
+testload: ld10k test.bin2
+ ./ld10k test.bin2 -a
+
+ld10k: ld10k.c
+ $(CC) $(CFLAGS) $(INCLUDE) -o ld10k ld10k.c
+ strip ld10k
+
+asm10k: asm10k.c
+ $(CC) $(CFLAGS) $(INCLUDE) -o asm10k asm10k.c
+
+emu10k.bin1: emu10k.dsp asm10k equalizer.mac emu10k1.mac
+ ./emuasm1 emu10k.dsp
+
+emu10k.bin2: emu10k.dsp asm10k equalizer.mac emu10k2.mac
+ ./emuasm2 emu10k.dsp
+
+test.bin2: test.dsp asm10k equalizer.mac emu10k2.mac
+ ./emuasm2 test.dsp
+
+emu10k1_dsp.h: emu10k.bin1 mkheader
+ ./mkheader emu10k1_dsp < emu10k.bin1 > emu10k1_dsp.h
+
+emu10k2_dsp.h: emu10k.bin2 mkheader
+ ./mkheader emu10k2_dsp < emu10k.bin2 > emu10k2_dsp.h
+
+clean:
+ rm -f *.o asm10k ld10k writegpr *.bin *.bin1 *.bin2 core x y z testgen *.map mkheader *_dsp.h
diff --git a/tutorials/sndkit/sblive/README b/tutorials/sndkit/sblive/README
new file mode 100644
index 0000000..51bbf97
--- /dev/null
+++ b/tutorials/sndkit/sblive/README
@@ -0,0 +1,12 @@
+This directory contains undocumented and unsupported utilities to compile
+DSP code for SB Live! and Audigy/2/4. The sblive driver has used precompiled
+embedded versions of this code (emu10k1_dsp.h and emu10k2_dsp.h) so these tools
+have not been tested for years. However it should still be possible to modify,
+compile and load the code to the card.
+
+Undocumented and unsupported really means that. If you want to use these tools
+then you have to obtain the knowledge about the Live!/audigy DSP architecture
+yourself. Also you need to figure out how these tools work.
+
+Note! The Makefile required to compile this stuff is included in the "source"
+directory of OSS. However this file may not appear in the "build" tree.
diff --git a/tutorials/sndkit/sblive/asm10k.c b/tutorials/sndkit/sblive/asm10k.c
new file mode 100644
index 0000000..b160228
--- /dev/null
+++ b/tutorials/sndkit/sblive/asm10k.c
@@ -0,0 +1,1206 @@
+/*
+ * Assembler for Emu10k1
+ * Copyright (C) 4Front Technologies 2001. All rights reserved
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+
+#include <soundcard.h>
+#ifdef USERLAND
+#define oss_native_word unsigned long
+#define oss_mutex_t unsigned long
+#define oss_device_t unsigned long
+#define ac97_devc unsigned long
+#define oss_midi_inputbyte_t char
+#define uart401_devc unsigned long
+typedef int oss_mutex;
+typedef void *oss_dma_handle_t;
+#else
+#include "../../../kernel/framework/include/os.h"
+#endif /* USERLAND */
+#include "../../../kernel/drv/oss_sblive/sblive.h"
+
+#define MAX_NAME 64
+#define MAX_SYMBOLS 1024
+
+int is_audigy = 0;
+
+int gpr_base = 0x100;
+int input_base = 0x10;
+int output_base = 0x20;
+
+static char line[4096] = "", *lineptr = line;
+static char lastline[4096];
+
+typedef struct
+{
+ char name[MAX_NAME];
+ int type;
+#define SY_DUMMY 0
+#define SY_GPR 1
+#define SY_INPUT 2
+#define SY_OUTPUT 3
+#define SY_CONST 4
+#define SY_FX 5
+#define SY_ACCUM 6
+#define SY_PARM 7
+ int arg;
+}
+sym_t;
+
+typedef struct
+{
+ char *name;
+ int opcode;
+}
+instruction_t;
+
+static instruction_t instructions[] = {
+ {"MACS", 0x0},
+ {"MACS1", 0x1},
+ {"MACW", 0x2},
+ {"MACW1", 0x3},
+ {"MACINTS", 0x4},
+ {"MACIINTW", 0x5},
+ {"SUM", 0x6},
+ {"ACC3", 0x6},
+ {"MACMV", 0x7},
+ {"ANDXOR", 0x8},
+ {"TSTNEG", 0x9},
+ {"LIMIT", 0xa},
+ {"LIMIT1", 0xb},
+ {"LOG", 0xc},
+ {"EXP", 0xd},
+ {"INTERP", 0xe},
+ {"SKIP", 0xf},
+ {NULL, 0}
+};
+
+static sym_t symtab[MAX_SYMBOLS];
+static int nsyms = 0;
+static int group_created = 0;
+
+int lineno = 0, errors = 0;
+static emu10k1_file fle;
+static int pc;
+
+static int ngpr = 0;
+
+static char *
+agetline (char *buf, int len)
+{
+ char *s;
+
+ if (*lineptr == 0)
+ {
+ lineptr = line;
+
+ if (fgets (line, sizeof (line), stdin) == NULL)
+ return NULL;
+
+ if (*line != '#')
+ lineno++;
+
+ strcpy(lastline, line);
+ }
+
+ s = buf;
+
+ while (*lineptr && *lineptr != ';')
+ {
+ *s++ = *lineptr++;
+ }
+
+ *s = 0;
+
+ if (*lineptr == ';')
+ *lineptr++ = 0;
+
+/* printf("%s\n", buf); */
+ return buf;
+}
+
+static void
+error (char *msg)
+{
+ fprintf (stderr, "%s\n", lastline);
+ fprintf (stderr, "Error '%s' on line %d\n", msg, lineno);
+ errors++;
+}
+
+static sym_t *
+find_symbol (char *name)
+{
+ int i;
+
+ for (i = 0; i < nsyms; i++)
+ if (strcmp (symtab[i].name, name) == 0)
+ {
+ return &symtab[i];
+ }
+
+ return NULL;
+}
+
+static void
+add_symbol (char *name, int type, int arg)
+{
+ sym_t *sym;
+
+#if 0
+ /* This is not needed any more */
+ if (is_audigy)
+ {
+ if (type == SY_CONST)
+ arg += 0x80;
+ }
+#endif
+
+ /* printf("'%s' = %d/%x\n", name, type, arg); */
+
+ if (nsyms >= MAX_SYMBOLS)
+ {
+ error ("Symbol table full");
+ exit (-1);
+ }
+
+ if (find_symbol (name) != NULL)
+ {
+ error ("Dublicate symbol");
+ return;
+ }
+
+ if (strlen (name) >= MAX_NAME)
+ {
+ error ("Too long symbol name");
+ exit (-1);
+ }
+
+ sym = &symtab[nsyms++];
+
+ strcpy (sym->name, name);
+ sym->type = type;
+ sym->arg = arg;
+}
+
+static void
+compile_gpr (char *parms)
+{
+ char *p = parms;
+
+ while (*p && *p != ' ')
+ p++;
+ if (*p == ' ')
+ {
+ error ("Too many parameters");
+ return;
+ }
+
+ if (ngpr >= MAX_GPR)
+ error ("Too many GPR variables");
+
+ add_symbol (parms, SY_GPR, gpr_base + ngpr++);
+}
+
+static void
+declare_const (unsigned int gpr, char *value)
+{
+ int n, intv;
+ float v;
+
+ n = fle.consts.nconst;
+
+ if (n >= MAX_CONST_PARMS)
+ {
+ error ("Too many constant parameters");
+ return;
+ }
+
+ if (*value == 'I')
+ {
+ if (sscanf (&value[1], "%g", &v) != 1)
+ {
+ error ("Bad floating point value");
+ return;
+ }
+ intv = (int) v;
+ /* printf("%s/%g -> %08x -> %g\n", value, v, intv, (float)intv); */
+ }
+ else if (*value == '0' && value[1] == 'x')
+ {
+ if (sscanf (&value[2], "%x", &intv) != 1)
+ {
+ error ("Bad hexadecimal value");
+ return;
+ }
+ /* printf("%s/%g -> %08x -> %g\n", value, v, intv, (float)intv); */
+ }
+ else
+ {
+ if (sscanf (value, "%g", &v) != 1)
+ {
+ error ("Bad floating point value");
+ return;
+ }
+ intv = (int) (v * 0x7fffffff);
+ /* printf("%s/%g -> %08x -> %g\n", value, v, intv, (float)intv / (float)0x7fffffff); */
+ }
+
+ fle.consts.consts[n].gpr = gpr;
+ fle.consts.consts[n].value = intv;
+ fle.consts.nconst = n + 1;
+}
+
+static void
+compile_const (char *parms)
+{
+ char *p = parms;
+ char *value;
+
+ while (*p && *p != ' ')
+ p++;
+
+ if (*p == 0)
+ {
+ error ("Too few parameters");
+ return;
+ }
+
+ *p++ = 0;
+ while (*p == ' ')
+ p++;
+
+ if (*p == 0)
+ {
+ error ("Too few parameters");
+ return;
+ }
+
+ value = p;
+
+ while (*p && *p != ' ')
+ p++;
+
+ if (*p == ' ')
+ {
+ error ("Too many parameters");
+ return;
+ }
+
+ if (ngpr >= MAX_GPR)
+ error ("Too many GPR variables");
+
+ declare_const (ngpr, value);
+
+ add_symbol (parms, SY_GPR, gpr_base + ngpr++);
+}
+
+static void
+define_parm (char *parms, char *name, int num, char *typ)
+{
+ int n;
+
+/* printf("Parameter '%s/%s' = GPR %d (%d), typ=%s\n", parms, name, ngpr, num, typ); */
+
+ n = fle.parms.ngpr;
+
+ if (n >= MAX_GPR_PARMS)
+ {
+ error ("Too many GPR parameters");
+ return;
+ }
+
+ if (strcmp (typ, "group") == 0)
+ {
+ strcpy (fle.parms.gpr[n].name, parms);
+ fle.parms.gpr[n].num = 0;
+ fle.parms.gpr[n].type = MIXT_GROUP;
+ fle.parms.gpr[n].def = 0;
+ fle.parms.ngpr = n + 1;
+ group_created = 1;
+ return;
+ }
+
+#if 0
+ if (!group_created)
+ {
+ strcpy (fle.parms.gpr[n].name, "EFX");
+ fle.parms.gpr[n].num = 0;
+ fle.parms.gpr[n].type = MIXT_GROUP;
+ fle.parms.gpr[n].def = 0;
+ fle.parms.ngpr = n + 1;
+ group_created = 1;
+ }
+#endif
+
+ if (strcmp (typ, "stereo") == 0)
+ {
+ char tmp[128];
+
+ strcpy (fle.parms.gpr[n].name, name);
+ fle.parms.gpr[n].num = ngpr;
+ fle.parms.gpr[n].type = MIXT_STEREOSLIDER;
+ fle.parms.gpr[n].def = num | (num << 8);
+ fle.parms.ngpr = n + 1;
+
+ sprintf (tmp, "%s_L", parms);
+ add_symbol (tmp, SY_PARM, gpr_base + ngpr++);
+ sprintf (tmp, "%s_R", parms);
+ add_symbol (tmp, SY_PARM, gpr_base + ngpr++);
+ return;
+ }
+
+ if (strcmp (typ, "stereopeak") == 0)
+ {
+ char tmp[128];
+
+ strcpy (fle.parms.gpr[n].name, name);
+ fle.parms.gpr[n].num = ngpr;
+ fle.parms.gpr[n].type = MIXT_STEREOPEAK;
+ fle.parms.gpr[n].def = num | (num << 8);
+ fle.parms.ngpr = n + 1;
+
+ sprintf (tmp, "%s_L", parms);
+ add_symbol (tmp, SY_PARM, gpr_base + ngpr++);
+ sprintf (tmp, "%s_R", parms);
+ add_symbol (tmp, SY_PARM, gpr_base + ngpr++);
+ return;
+ }
+
+ if (strcmp (typ, "onoff") == 0)
+ {
+ char tmp[128];
+
+ strcpy (fle.parms.gpr[n].name, name);
+ fle.parms.gpr[n].num = ngpr;
+ fle.parms.gpr[n].type = MIXT_ONOFF;
+ fle.parms.gpr[n].def = num;
+ fle.parms.ngpr = n + 1;
+
+ sprintf (tmp, "%s_ON", parms);
+ add_symbol (tmp, SY_PARM, gpr_base + ngpr++);
+ sprintf (tmp, "%s_OFF", parms);
+ add_symbol (tmp, SY_PARM, gpr_base + ngpr++);
+ return;
+ }
+
+ if (strcmp (typ, "eq1") == 0)
+ {
+ char tmp[128];
+
+ strcpy (fle.parms.gpr[n].name, name);
+ fle.parms.gpr[n].num = ngpr;
+ fle.parms.gpr[n].type = EMU_MIXT_EQ1;
+ fle.parms.gpr[n].def = num;
+ fle.parms.ngpr = n + 1;
+
+/* printf("EQ1, GPR=%d\n", ngpr); */
+ sprintf (tmp, "%s_CST_0", parms);
+ add_symbol (tmp, SY_PARM, gpr_base + ngpr++);
+ sprintf (tmp, "%s_CST_1", parms);
+ add_symbol (tmp, SY_PARM, gpr_base + ngpr++);
+ sprintf (tmp, "%s_CST_2", parms);
+ add_symbol (tmp, SY_PARM, gpr_base + ngpr++);
+ sprintf (tmp, "%s_CST_3", parms);
+ add_symbol (tmp, SY_PARM, gpr_base + ngpr++);
+ sprintf (tmp, "%s_CST_4", parms);
+ add_symbol (tmp, SY_PARM, gpr_base + ngpr++);
+ return;
+ }
+
+ if (strcmp (typ, "eq2") == 0)
+ {
+ char tmp[128];
+
+ strcpy (fle.parms.gpr[n].name, name);
+ fle.parms.gpr[n].num = ngpr;
+ fle.parms.gpr[n].type = EMU_MIXT_EQ2;
+ fle.parms.gpr[n].def = num;
+ fle.parms.ngpr = n + 1;
+
+/* printf("EQ2, GPR=%d\n", ngpr); */
+ sprintf (tmp, "%s_CST_0", parms);
+ add_symbol (tmp, SY_PARM, gpr_base + ngpr++);
+ sprintf (tmp, "%s_CST_1", parms);
+ add_symbol (tmp, SY_PARM, gpr_base + ngpr++);
+ sprintf (tmp, "%s_CST_2", parms);
+ add_symbol (tmp, SY_PARM, gpr_base + ngpr++);
+ sprintf (tmp, "%s_CST_3", parms);
+ add_symbol (tmp, SY_PARM, gpr_base + ngpr++);
+ sprintf (tmp, "%s_CST_4", parms);
+ add_symbol (tmp, SY_PARM, gpr_base + ngpr++);
+ return;
+ }
+
+ if (strcmp (typ, "eq3") == 0)
+ {
+ char tmp[128];
+
+ strcpy (fle.parms.gpr[n].name, name);
+ fle.parms.gpr[n].num = ngpr;
+ fle.parms.gpr[n].type = EMU_MIXT_EQ3;
+ fle.parms.gpr[n].def = num;
+ fle.parms.ngpr = n + 1;
+/* printf("EQ3, GPR=%d\n", ngpr); */
+
+ sprintf (tmp, "%s_CST_0", parms);
+ add_symbol (tmp, SY_PARM, gpr_base + ngpr++);
+ sprintf (tmp, "%s_CST_1", parms);
+ add_symbol (tmp, SY_PARM, gpr_base + ngpr++);
+ sprintf (tmp, "%s_CST_2", parms);
+ add_symbol (tmp, SY_PARM, gpr_base + ngpr++);
+ sprintf (tmp, "%s_CST_3", parms);
+ add_symbol (tmp, SY_PARM, gpr_base + ngpr++);
+ sprintf (tmp, "%s_CST_4", parms);
+ add_symbol (tmp, SY_PARM, gpr_base + ngpr++);
+ return;
+ }
+
+ if (strcmp (typ, "eq4") == 0)
+ {
+ char tmp[128];
+
+ strcpy (fle.parms.gpr[n].name, name);
+ fle.parms.gpr[n].num = ngpr;
+ fle.parms.gpr[n].type = EMU_MIXT_EQ4;
+ fle.parms.gpr[n].def = num;
+ fle.parms.ngpr = n + 1;
+/* printf("EQ4, GPR=%d\n", ngpr); */
+
+ sprintf (tmp, "%s_CST_0", parms);
+ add_symbol (tmp, SY_PARM, gpr_base + ngpr++);
+ sprintf (tmp, "%s_CST_1", parms);
+ add_symbol (tmp, SY_PARM, gpr_base + ngpr++);
+ sprintf (tmp, "%s_CST_2", parms);
+ add_symbol (tmp, SY_PARM, gpr_base + ngpr++);
+ sprintf (tmp, "%s_CST_3", parms);
+ add_symbol (tmp, SY_PARM, gpr_base + ngpr++);
+ sprintf (tmp, "%s_CST_4", parms);
+ add_symbol (tmp, SY_PARM, gpr_base + ngpr++);
+ return;
+ }
+
+ strcpy (fle.parms.gpr[n].name, name);
+ fle.parms.gpr[n].num = ngpr;
+ fle.parms.gpr[n].type = MIXT_SLIDER;
+ fle.parms.gpr[n].def = num;
+ fle.parms.ngpr = n + 1;
+ add_symbol (parms, SY_PARM, gpr_base + ngpr++);
+}
+
+static void
+compile_parm (char *parms)
+{
+ char *p = parms, *def, *typ, *name;
+ int n;
+ int num;
+
+ while (*p && *p != ' ')
+ p++;
+ if (*p != ' ')
+ {
+ error ("Too few parameters");
+ return;
+ }
+
+ *p++ = 0;
+ while (*p && *p == ' ')
+ p++;
+
+ if (*p == 0)
+ {
+ error ("Too few parameters");
+ return;
+ }
+
+ def = p;
+ while (*p && *p != ' ')
+ p++;
+
+ if (*p != 0)
+ {
+ *p++ = 0;
+
+ while (*p == ' ' || *p == '\t')
+ p++;
+ }
+
+ if (*p == 0)
+ typ = "";
+ else
+ {
+ typ = p;
+
+ while (*p && *p != ' ' && *p != '\t')
+ p++;
+ if (*p != 0)
+ *p++ = 0;
+ }
+
+ while (*p == ' ' || *p == '\t')
+ p++;
+ name = p;
+ while (*p && *p != ' ' && *p != '\t')
+ p++;
+ *p = 0;
+
+ if (*name == 0)
+ name = parms;
+
+ if (sscanf (def, "%d", &num) != 1)
+ {
+ error ("Bad integer value");
+ return;
+ }
+
+ define_parm (parms, name, num, typ);
+}
+
+static void
+compile_input (char *parms)
+{
+ char *p = parms, *s;
+ int num;
+
+ while (*p && *p != ' ')
+ p++;
+ if (*p != ' ')
+ {
+ error ("Too few parameters");
+ return;
+ }
+
+ *p++ = 0;
+ while (*p && *p == ' ')
+ p++;
+
+ if (*p == 0)
+ {
+ error ("Too few parameters");
+ return;
+ }
+
+ s = p;
+ while (*p && *p != ' ')
+ p++;
+ if (*p == ' ')
+ {
+ error ("Too many parameters");
+ return;
+ }
+
+ if (sscanf (s, "%d", &num) != 1)
+ {
+ error ("Bad integer value");
+ return;
+ }
+
+ add_symbol (parms, SY_INPUT, input_base + num);
+}
+
+static void
+compile_send (char *parms)
+{
+ char *p = parms, *s;
+ int num;
+
+ while (*p && *p != ' ')
+ p++;
+ if (*p != ' ')
+ {
+ error ("Too few parameters");
+ return;
+ }
+
+ *p++ = 0;
+ while (*p && *p == ' ')
+ p++;
+
+ if (*p == 0)
+ {
+ error ("Too few parameters");
+ return;
+ }
+
+ s = p;
+ while (*p && *p != ' ')
+ p++;
+ if (*p == ' ')
+ {
+ error ("Too many parameters");
+ return;
+ }
+
+ if (sscanf (s, "%d", &num) != 1)
+ {
+ error ("Bad integer value");
+ return;
+ }
+
+ add_symbol (parms, SY_FX, num);
+}
+
+static void
+compile_output (char *parms)
+{
+ char *p = parms, *s;
+ int num;
+
+ while (*p && *p != ' ')
+ p++;
+ if (*p != ' ')
+ {
+ error ("Too few parameters");
+ return;
+ }
+
+ *p++ = 0;
+ while (*p && *p == ' ')
+ p++;
+
+ if (*p == 0)
+ {
+ error ("Too few parameters");
+ return;
+ }
+
+ s = p;
+ while (*p && *p != ' ')
+ p++;
+ if (*p == ' ')
+ {
+ error ("Too many parameters");
+ return;
+ }
+
+ if (sscanf (s, "%d", &num) != 1)
+ {
+ error ("Bad integer value");
+ return;
+ }
+
+ add_symbol (parms, SY_OUTPUT, output_base + num);
+}
+
+static void
+compile_directive (char *line)
+{
+ char *p = line;
+
+ while (*p && *p != ' ')
+ p++;
+ if (*p != ' ')
+ {
+ error ("Missing parameter");
+ return;
+ }
+
+ *p++ = 0;
+
+ while (*p == ' ')
+ p++;
+
+ if (strcmp (line, ".gpr") == 0)
+ {
+ compile_gpr (p);
+ return;
+ }
+
+ if (strcmp (line, ".const") == 0)
+ {
+ compile_const (p);
+ return;
+ }
+
+ if (strcmp (line, ".parm") == 0)
+ {
+ compile_parm (p);
+ return;
+ }
+
+ if (strcmp (line, ".input") == 0)
+ {
+ compile_input (p);
+ return;
+ }
+
+ if (strcmp (line, ".send") == 0)
+ {
+ compile_send (p);
+ return;
+ }
+
+ if (strcmp (line, ".output") == 0)
+ {
+ compile_output (p);
+ return;
+ }
+
+ error ("Unknown directive");
+}
+
+static void
+compile_asm (char *iline)
+{
+ char line[4096], *s, *p;
+ char *parms[4];
+ sym_t *symbols[4];
+#define EMIT(o, r, a, x, y) \
+ fle.code[pc*2] = ((x) << 10) | (y); \
+ fle.code[pc*2+1] = ((o) << 20) | ((r) << 10) | a;pc++
+#define EMIT_AUDIGY(o, r, a, x, y) \
+ fle.code[pc*2] = ((x) << 12) | (y); \
+ fle.code[pc*2+1] = ((o) << 24) | ((r) << 12) | a;pc++
+
+ int i, n = 0, nerr = 0;
+ int ninputs = 0;
+
+ s = iline;
+ p = line;
+
+ /* Remove all spaces and the trailing ')' */
+ while (*s)
+ {
+ if (*s != ' ' && *s != ')' && *s != '#')
+ *p++ = *s;
+ s++;
+ }
+
+ *p = 0;
+
+ /* Replace ',' and '(' characters by spaces */
+ p = line;
+ while (*p)
+ {
+ if (*p == ',' || *p == '(')
+ *p = ' ';
+ p++;
+ }
+
+ p = line;
+ while (*p && *p != ' ')
+ p++;
+ if (*p != ' ')
+ {
+ error ("Too few parameters");
+ return;
+ }
+
+ *p++ = 0;
+
+ while (*p && n < 4)
+ {
+ parms[n++] = p;
+
+ while (*p && *p != ' ')
+ p++;
+ if (*p == ' ')
+ *p++ = 0;
+ }
+
+ if (*p != 0)
+ {
+ error ("Too many parameters");
+ return;
+ }
+
+ if (n != 4)
+ {
+ error ("Too few parameters");
+ return;
+ }
+
+
+ for (i = 0; i < 4; i++)
+ {
+ if ((symbols[i] = find_symbol (parms[i])) == NULL)
+ {
+ fprintf (stderr, "%s\n", parms[i]);
+ nerr++;
+ error ("Undefined symbol");
+ continue;
+ }
+
+ if (symbols[i]->type == SY_INPUT)
+ ninputs++;
+
+ if (symbols[i]->type == SY_ACCUM && i != 1)
+ error ("Bad usage of 'accum' operand.");
+ }
+
+ if (nerr > 0)
+ return;
+
+ if (ninputs > 1)
+ {
+ error
+ ("Attempt to access more than one input GPRs by the same instruction");
+ }
+
+ for (i = 0; i < strlen (line); i++)
+ if (line[i] >= 'a' && line[i] <= 'z')
+ line[i] -= 32; /* Upshift */
+
+ for (i = 0; instructions[i].name != NULL; i++)
+ if (strcmp (line, instructions[i].name) == 0)
+ {
+#if 0
+ printf ("Instruction %x: ", instructions[i].opcode);
+ printf ("%03x ", symbols[0]->arg);
+ printf ("%03x ", symbols[1]->arg);
+ printf ("%03x ", symbols[2]->arg);
+ printf ("%03x ", symbols[3]->arg);
+ printf ("\n");
+#endif
+
+ if (is_audigy)
+ {
+ EMIT_AUDIGY (instructions[i].opcode,
+ symbols[0]->arg,
+ symbols[1]->arg, symbols[2]->arg, symbols[3]->arg);
+ }
+ else
+ {
+ EMIT (instructions[i].opcode,
+ symbols[0]->arg,
+ symbols[1]->arg, symbols[2]->arg, symbols[3]->arg);
+ }
+
+ return;
+ }
+
+ fprintf (stderr, "%s\n", line);
+ error ("Unrecognized instruction");
+}
+
+static void
+init_compiler (void)
+{
+ char tmp[100];
+ int i;
+
+ memset (&fle, 0, sizeof (fle));
+/*
+ * Initialize few predefined GPR parameter registers. These definitions
+ * have to be in sync with the GPR_* macros in <sblive.h>.
+ */
+
+/*
+;.parm AC97VOL 0 mono AC97
+;.parm AC97MONVU 0 stereopeak -
+;.parm PCM 100 stereo
+;.parm MAIN 100 stereo VOL
+;.parm VU 0 stereopeak -
+*/
+ add_symbol ("NULL", SY_DUMMY, gpr_base + ngpr++);
+ add_symbol ("NULL_", SY_DUMMY, gpr_base + ngpr++);
+ define_parm ("PCM", "PCM", 100, "stereo");
+ define_parm ("MAIN", "VOL", 100, "stereo");
+
+ pc = 0;
+
+ if (is_audigy)
+ {
+ /* Initialize the code array with NOPs (AUDIGY) */
+ for (i = 0; i < 512; i++)
+ {
+ fle.code[i * 2 + 0] = (0xc0 << 12) | 0xc0;
+ fle.code[i * 2 + 1] = (0x06 << 24) | (0xc0 << 12) | 0xc0;
+ }
+
+ for (i = 0; i < 32; i++)
+ {
+ sprintf (tmp, "fx%d", i);
+ add_symbol (tmp, SY_FX, i);
+ }
+ }
+ else
+ {
+ /* Initialize the code array with NOPs (LIVE) */
+ for (i = 0; i < 512; i++)
+ {
+ fle.code[i * 2 + 0] = 0x10040;
+ fle.code[i * 2 + 1] = 0x610040;
+ }
+
+ for (i = 0; i < 16; i++)
+ {
+ sprintf (tmp, "fx%d", i);
+ add_symbol (tmp, SY_FX, i);
+ }
+ }
+
+/*
+ * Constants
+ */
+
+ if (is_audigy)
+ {
+ /* Audigy symbols */
+ add_symbol ("0", SY_CONST, 0x0c0);
+ add_symbol ("1", SY_CONST, 0x0c1);
+ add_symbol ("2", SY_CONST, 0x0c2);
+ add_symbol ("3", SY_CONST, 0x0c3);
+ add_symbol ("4", SY_CONST, 0x0c4);
+ add_symbol ("8", SY_CONST, 0x0c5);
+ add_symbol ("16", SY_CONST, 0x0c6);
+ add_symbol ("32", SY_CONST, 0x0c7);
+ add_symbol ("256", SY_CONST, 0x0c8);
+ add_symbol ("65536", SY_CONST, 0x0c9);
+
+ add_symbol ("2048", SY_CONST, 0x0ca);
+ add_symbol ("0x800", SY_CONST, 0x0ca);
+
+ add_symbol ("2^28", SY_CONST, 0x0cb);
+ add_symbol ("0x10000000", SY_CONST, 0x0cb);
+
+ add_symbol ("2^29", SY_CONST, 0x0cc);
+ add_symbol ("0x20000000", SY_CONST, 0x0cc);
+
+ add_symbol ("2^30", SY_CONST, 0x0cd);
+ add_symbol ("0x40000000", SY_CONST, 0x0cd);
+
+ add_symbol ("2^31", SY_CONST, 0x0ce);
+ add_symbol ("0x80000000", SY_CONST, 0x0ce);
+
+ add_symbol ("0x7fffffff", SY_CONST, 0x0cf);
+
+ add_symbol ("0xffffffff", SY_CONST, 0x0d0);
+ add_symbol ("-1", SY_CONST, 0x0d0);
+
+ add_symbol ("0xfffffffe", SY_CONST, 0x0d1);
+ add_symbol ("-2", SY_CONST, 0x0d1);
+
+ add_symbol ("0xc0000000", SY_CONST, 0x0d2);
+
+ add_symbol ("0x4f1bbcdc", SY_CONST, 0x0d3);
+
+ add_symbol ("0x5a7ef9db", SY_CONST, 0x0d4);
+
+ add_symbol ("0x100000", SY_CONST, 0x0d5);
+
+ add_symbol ("accum", SY_ACCUM, 0x0d6);
+ add_symbol ("CCR", SY_CONST, 0x0d7);
+
+ add_symbol ("noise_L", SY_CONST, 0x0d8);
+ add_symbol ("noise_R", SY_CONST, 0x0d9);
+ add_symbol ("IRQREQ", SY_CONST, 0x0da);
+ }
+ else
+ {
+ /* SB Live symbols */
+ add_symbol ("0", SY_CONST, 0x040);
+ add_symbol ("1", SY_CONST, 0x041);
+ add_symbol ("2", SY_CONST, 0x042);
+ add_symbol ("3", SY_CONST, 0x043);
+ add_symbol ("4", SY_CONST, 0x044);
+ add_symbol ("8", SY_CONST, 0x045);
+ add_symbol ("16", SY_CONST, 0x046);
+ add_symbol ("32", SY_CONST, 0x047);
+ add_symbol ("256", SY_CONST, 0x048);
+ add_symbol ("65536", SY_CONST, 0x049);
+
+ add_symbol ("2^23", SY_CONST, 0x04a);
+ add_symbol ("0x80000", SY_CONST, 0x04a);
+
+ add_symbol ("2^28", SY_CONST, 0x04b);
+ add_symbol ("0x10000000", SY_CONST, 0x04b);
+
+ add_symbol ("2^29", SY_CONST, 0x04c);
+ add_symbol ("0x20000000", SY_CONST, 0x04c);
+
+ add_symbol ("2^30", SY_CONST, 0x04d);
+ add_symbol ("0x40000000", SY_CONST, 0x04d);
+
+ add_symbol ("2^31", SY_CONST, 0x04e);
+ add_symbol ("0x80000000", SY_CONST, 0x04e);
+
+ add_symbol ("0x7fffffff", SY_CONST, 0x04f);
+
+ add_symbol ("0xffffffff", SY_CONST, 0x050);
+ add_symbol ("-1", SY_CONST, 0x050);
+
+ add_symbol ("0xfffffffe", SY_CONST, 0x051);
+ add_symbol ("-2", SY_CONST, 0x051);
+
+ add_symbol ("accum", SY_ACCUM, 0x056);
+ add_symbol ("CCR", SY_CONST, 0x057);
+
+ add_symbol ("noise_L", SY_CONST, 0x058);
+ add_symbol ("noise_R", SY_CONST, 0x059);
+ add_symbol ("IRQREQ", SY_CONST, 0x05a);
+ }
+}
+
+static void
+produce_map (char *name)
+{
+ char fname[1024];
+ int i;
+ FILE *f;
+
+ sprintf (fname, "%s.map", name);
+
+ if ((f = fopen (fname, "w")) == NULL)
+ {
+ perror (fname);
+ return;
+ }
+
+ fprintf (f, "%d\n", fle.size);
+
+ for (i = 0; i < nsyms; i++)
+ {
+ fprintf (f, "%04x %x %s\n", symtab[i].arg, symtab[i].type,
+ symtab[i].name);
+ }
+
+ fclose (f);
+}
+
+static void
+produce_output (char *fname)
+{
+ int fd;
+
+ if ((fd = creat (fname, 0644)) == -1)
+ {
+ perror (fname);
+ exit (-1);
+ }
+
+ if (is_audigy)
+ {
+ fle.magic = EMU10K2_MAGIC;
+ fle.feature_mask = SB_AUDIGY;
+ }
+ else
+ {
+ fle.magic = EMU10K1_MAGIC;
+ fle.feature_mask = SB_LIVE;
+ }
+ fle.size = pc;
+ fprintf (stderr, "%d instructions out of 512 produced\n", pc);
+
+ if (write (fd, &fle, sizeof (fle)) != sizeof (fle))
+ {
+ perror (fname);
+ exit (-1);
+ }
+
+ close (fd);
+}
+
+int
+main (int argc, char *argv[])
+{
+ char iline[4096], line[4096], *p, *s, *outfile;
+
+ if (argc < 2)
+ {
+ fprintf (stderr, "No output\n");
+ exit (-1);
+ }
+
+ outfile = argv[1];
+
+ if (argc > 2)
+ if (strcmp (argv[2], "-2") == 0)
+ {
+ is_audigy = 1;
+ gpr_base = 0x400;
+ input_base = 0x40;
+ output_base = 0x60;
+ printf ("Compiling for SB Audigy\n");
+ }
+ else
+ printf ("Compiling for SB Live family\n");
+
+ init_compiler ();
+
+ while (agetline (iline, sizeof (iline) - 1) != NULL)
+ {
+ if (*iline == '#')
+ {
+ if (iline[1] == ' ')
+ if (sscanf (&iline[1], "%d", &lineno) == 1)
+ lineno--;
+ continue;
+ }
+/*
+ * Fix for HP-UX cpp. Strip all '#' characters from input.
+ */
+
+ s = iline;
+ p = line;
+
+ while (*s)
+ {
+ if (*s != '#')
+ *p++ = *s;
+ s++;
+ }
+ *p = 0;
+
+ p = line;
+
+ while (*p && *p != '\n' && *p != '/')
+ p++;
+ *p = 0;
+
+ if (*line == 0) /* Empty line */
+ continue;
+
+ p = &line[strlen (line) - 1];
+
+ while (p > line && (*p == ' ' || *p == '\t'))
+ p--;
+ p[1] = 0;
+
+ p = line;
+ while (*p)
+ {
+ if (*p == '\t')
+ *p = ' ';
+ p++;
+ }
+
+ p = line;
+
+ while (*p && (*p == ' ' || *p == '\t'))
+ p++;
+
+ if (*p == 0) /* Empty line */
+ continue;
+
+ if (*p == '.')
+ compile_directive (p);
+ else
+ compile_asm (p);
+ }
+
+ if (lineno < 1)
+ {
+ fprintf (stderr, "Empty input\n");
+ errors++;
+ }
+
+ if (errors == 0)
+ {
+ produce_output (outfile);
+ produce_map (outfile);
+ }
+
+ if (errors > 0)
+ {
+ fprintf (stderr, "%d errors - compile failed\n", errors);
+ exit (-1);
+ }
+
+ fprintf (stderr, "No errors detected - Output written to %s\n", outfile);
+ exit (0);
+}
diff --git a/tutorials/sndkit/sblive/emu10k.dsp b/tutorials/sndkit/sblive/emu10k.dsp
new file mode 100644
index 0000000..5bb6022
--- /dev/null
+++ b/tutorials/sndkit/sblive/emu10k.dsp
@@ -0,0 +1,378 @@
+//
+
+// DSP code for SB Live (C) 4Front Technologies 2001. All rights reserved.
+
+#define HAVE_EQ
+#define HAVE_SURR_EQ
+
+#define COPY(a,b) ACC3(a, b, 0, 0)
+
+// Temporary variables
+
+.gpr TMP_L
+.gpr TMP_R
+.gpr PCMTMP_L
+.gpr PCMTMP_R
+.gpr S_SUM_L
+.gpr S_SUM_R
+.gpr AUX_L
+.gpr AUX_R
+.gpr MIC_L
+.gpr MIC_R
+.gpr VUTMP
+.gpr VUTMP2
+.gpr CENTER_TMP
+.gpr LFE_TMP
+.gpr SURR_TMP_R
+.gpr SURR_TMP_L
+#ifdef AUDIGY
+.gpr SPDIF_TMP_L
+.gpr SPDIF_TMP_R
+#endif
+
+// Some parameters that are currently predefined by the assembler
+//.parm PCM 100 stereo
+//.parm MAIN 100 stereo VOL
+
+#ifdef HAVE_EQ
+#include "equalizer.mac"
+#endif
+
+// Monitor volumes and peak meters
+
+#ifdef HAVE_EQ
+.parm EQUALIZER 0 group
+ INCLUDE_EQPARMS
+#endif
+
+.parm FRONT 0 group
+.parm SPDINVOL 100 mono SPDIF
+.parm SPDINMONVU 0 stereopeak -
+.parm CDSPDINVOL 100 mono DIGCD
+.parm CDSPDINMONVU 0 stereopeak -
+.parm AC97VOL 0 mono AC97
+.parm AC97MONVU 0 stereopeak -
+.parm FRONTPCM 100 mono PCM
+.parm FRONTPCMVU 0 stereopeak -
+.parm FRONTAUX 100 mono AUX
+.parm FRONTAUXVU 0 stereopeak -
+#ifdef AUDIGY
+.parm FRONTMIC 100 mono MIC
+.parm FRONTMICVU 0 stereopeak -
+#endif
+.parm FRONTVOL 100 stereo VOL
+.parm FRONTVU 0 stereopeak -
+
+.parm SURR 0 group
+.parm R_SPDINVOL 0 mono SPDIF
+.parm R_SPDINMONVU 0 stereopeak -
+.parm R_CDSPDINVOL 0 mono DIGCD
+.parm R_CDSPDINMONVU 0 stereopeak -
+.parm R_AC97VOL 0 mono AC97
+.parm R_AC97MONVU 0 stereopeak -
+.parm SURRPCM 100 mono PCM
+.parm SURRPCMVU 0 stereopeak -
+.parm SURRAUX 0 mono AUX
+.parm SURRAUXVU 0 stereopeak -
+#ifdef AUDIGY
+.parm SURRMIC 100 mono MIC
+.parm SURRMICVU 0 stereopeak -
+#endif
+.parm SURRVOL 100 stereo VOL
+.parm SURRVU 0 stereopeak -
+
+// Recording volumes and VU meters
+.parm RECORD 0 group
+.parm SPDIFREC 100 mono SPDIF
+.parm SPDIFVU 0 stereopeak -
+.parm CDSPDIFREC 100 mono DIGCD
+.parm CDVU 0 stereopeak -
+.parm AC97REC 100 mono AC97
+.parm AC97VU 0 stereopeak -
+.parm LOOP 0 mono PCM
+.parm LOOPVU 0 stereopeak -
+.parm RECAUX 100 mono AUX
+.parm RECAUXVU 0 stereopeak -
+#ifdef AUDIGY
+.parm RECMIC 0 mono MIC
+.parm RECMICVU 0 stereopeak -
+#endif
+.parm RECVOL 100 stereo VOL
+.parm RECVU 0 stereopeak -
+
+// Dummy placeholders for the main VU meter.
+.gpr VU_L
+.gpr VU_R
+
+#ifdef AUDIGY
+#include "emu10k2.mac"
+#else
+#include "emu10k1.mac"
+#endif
+
+#ifdef AUDIGY
+.parm _PASSTHROUGH 0 onoff;
+#endif
+
+#ifdef HAVE_EQ
+ INCLUDE_EQVARS
+ INCLUDE_DELAYS(L)
+ INCLUDE_DELAYS(R)
+# ifdef HAVE_SURR_EQ
+ INCLUDE_DELAYS(SL)
+ INCLUDE_DELAYS(SR)
+# endif
+#endif
+
+#include "vu.mac"
+
+#ifdef AUDIGY
+// Take wavetable engine front sends (0,1)
+ MACINTS(TMP_L, 0, SEND_L, 1)
+ MACINTS(TMP_R, 0, SEND_R, 1)
+ MACS(PCMTMP_L, 0, TMP_L, PCM_L)
+ MACS(PCMTMP_R, 0, TMP_R, PCM_R)
+
+// Take raw S/PDIF from the dedicated sends
+ COPY(SPDIF_TMP_L, SPDIF_L)
+ COPY(SPDIF_TMP_R, SPDIF_R)
+
+// Do the same for surround and rear speaker outputs (sum them together)
+ SUM(S_SUM_L, SEND_SL, SEND_RL, 0)
+ SUM(S_SUM_R, SEND_SR, SEND_RR, 0)
+ MACINTS(CENTER_TMP, 0, SEND_C, 1)
+ MACINTS(LFE_TMP, 0, SEND_W, 1)
+ MACS(S_SUM_L, 0, S_SUM_L, PCM_L)
+ MACS(S_SUM_R, 0, S_SUM_R, PCM_R)
+#else
+// Take wavetable engine front sends (0,1) and multiply them by 4 to boost volume
+ MACINTS(TMP_L, 0, SEND_L, 4)
+ MACINTS(TMP_R, 0, SEND_R, 4)
+ MACS(PCMTMP_L, 0, TMP_L, PCM_L)
+ MACS(PCMTMP_R, 0, TMP_R, PCM_R)
+
+// Do the same for rear outputs (2,3)
+ MACINTS(S_SUM_L, 0, SEND_SL, 4)
+ MACINTS(S_SUM_R, 0, SEND_SR, 4)
+ MACS(S_SUM_L, 0, S_SUM_L, PCM_L)
+ MACS(S_SUM_R, 0, S_SUM_R, PCM_R)
+#endif
+
+//
+// Auxiliary input monitors (front channel)
+//
+
+ MACS(AUX_L, 0, PCMTMP_L, FRONTPCM)
+ MACS(AUX_R, 0, PCMTMP_R, FRONTPCM)
+ VU(FRONTPCMVU_L, AUX_L)
+ VU(FRONTPCMVU_R, AUX_R)
+ MACS(AUX_L, AUX_L, CDSPDIFIN_L, CDSPDINVOL)
+ MACS(AUX_R, AUX_R, CDSPDIFIN_R, CDSPDINVOL)
+ // CD S/PDIF input monitor VU
+ VUSCALE(CDSPDINMONVU_L, CDSPDIFIN_L, CDSPDINVOL)
+ VUSCALE(CDSPDINMONVU_R, CDSPDIFIN_R, CDSPDINVOL)
+
+ MACS(AUX_L, AUX_L, AC97IN_L, AC97VOL)
+ MACS(AUX_R, AUX_R, AC97IN_R, AC97VOL)
+ // AC97 monitor VU
+ VUSCALE(AC97MONVU_L, AC97IN_L, AC97VOL)
+ VUSCALE(AC97MONVU_R, AC97IN_R, AC97VOL)
+
+ MACS(AUX_L, AUX_L, GPSPDIFIN_L, SPDINVOL)
+ MACS(AUX_R, AUX_R, GPSPDIFIN_R, SPDINVOL)
+ // S/PDIF input monitor VU
+ VUSCALE(SPDINMONVU_L, GPSPDIFIN_L, SPDINVOL)
+ VUSCALE(SPDINMONVU_R, GPSPDIFIN_R, SPDINVOL)
+ // Boost S/PDIF input level by summing it twice
+ MACS(AUX_L, AUX_L, GPSPDIFIN_L, SPDINVOL)
+ MACS(AUX_R, AUX_R, GPSPDIFIN_R, SPDINVOL)
+
+ // Auxiliary inputs (Live Drive)
+ MACS(AUX_L, AUX_L, AUXIN_L, FRONTAUX)
+ MACS(AUX_R, AUX_R, AUXIN_R, FRONTAUX)
+ VUSCALE(FRONTAUXVU_L, AUXIN_L, FRONTAUX)
+ VUSCALE(FRONTAUXVU_R, AUXIN_R, FRONTAUX)
+
+// Apply main volume to the aux input front volume
+ MACS(AUX_L, 0, AUX_L, MAIN_L)
+ MACS(AUX_R, 0, AUX_R, MAIN_R)
+
+#ifdef AUDIGY
+ // Livedrive mic inputs
+ MACS(MIC_L, MIC_L, MICIN_L, FRONTMIC)
+ MACS(MIC_R, MIC_R, MICIN_R, FRONTMIC)
+ VUSCALE(FRONTMICVU_L, MICIN_L, FRONTMIC)
+ VUSCALE(FRONTMICVU_R, MICIN_R, FRONTMIC)
+
+// Apply main volume to the aux input front volume
+ MACS(MIC_L, 0, AUX_L, MAIN_L)
+ MACS(MIC_R, 0, AUX_R, MAIN_R)
+#endif
+
+#ifdef HAVE_EQ
+ EQUALIZER(L, L, AUX_L)
+ EQUALIZER(R, R, AUX_R)
+#endif
+
+// Secondary sends before applying front volume
+#ifdef AUDIGY
+ MACINTS(SPDOUT1_L, 0, AUX_L, _PASSTHROUGH_OFF)
+ MACINTS(SPDOUT1_R, 0, AUX_R, _PASSTHROUGH_OFF)
+
+// S/PDIF passthrough
+.const 0x1008 0x1008
+.const 0xffff0000 0xffff0000
+.gpr TMP0
+.gpr TMP1
+.gpr TMP2
+
+// Left channel
+ COPY(TMP2, SPDIF_TMP_L)
+ SKIP(CCR, CCR, 0x1008, 1)
+ ACC3(TMP2, 0, 65536, TMP2)
+ ANDXOR(TMP2, TMP2, 0xffff0000, 0)
+ MACINTS(TMP0, 0, TMP2, _PASSTHROUGH_ON)
+ ANDXOR(TMP1, _PASSTHROUGH_ON, 1, 1)
+ MACINTS(TMP1, 0, AUX_L, TMP1)
+ ACC3(SPDOUT1_L, TMP0, TMP1, 0)
+
+// Right channel
+ COPY(TMP2, SPDIF_TMP_R)
+ SKIP(CCR, CCR, 0x1008, 1)
+ ACC3(TMP2, 0, 65536, TMP2)
+ ANDXOR(TMP2, TMP2, 0xffff0000, 0)
+ MACINTS(TMP0, 0, TMP2, _PASSTHROUGH_ON)
+ ANDXOR(TMP1, _PASSTHROUGH_ON, 1, 1)
+ MACINTS(TMP1, 0, AUX_R, TMP1)
+ ACC3(SPDOUT1_R, TMP0, TMP1, 0)
+#else
+ COPY(SPDOUT1_L, AUX_L)
+ COPY(SPDOUT1_R, AUX_R)
+#endif
+
+// Update main peak meters
+ VU(VU_L, AUX_L)
+ VU(VU_R, AUX_R)
+
+// Mix the PCM sends with monitor inputs in and write to front output
+ MACS(FRONT_L, 0, AUX_L, FRONTVOL_L)
+ MACS(FRONT_R, 0, AUX_R, FRONTVOL_R)
+
+ MACS(HEADPH_L, 0, AUX_L, FRONTVOL_L)
+ MACS(HEADPH_R, 0, AUX_R, FRONTVOL_R)
+ VUSCALE(FRONTVU_L, AUX_L, FRONTVOL_L)
+ VUSCALE(FRONTVU_R, AUX_R, FRONTVOL_R)
+
+//
+// Auxiliary input monitors (rear channel)
+//
+
+ MACS(S_SUM_L, 0, S_SUM_L, SURRPCM)
+ MACS(S_SUM_R, 0, S_SUM_R, SURRPCM)
+ VU(SURRPCMVU_L, S_SUM_L)
+ VU(SURRPCMVU_R, S_SUM_R)
+ MACS(S_SUM_L, S_SUM_L, CDSPDIFIN_L, R_CDSPDINVOL)
+ MACS(S_SUM_R, S_SUM_R, CDSPDIFIN_R, R_CDSPDINVOL)
+ // CD S/PDIF input monitor VU
+ VUSCALE(R_CDSPDINMONVU_L, CDSPDIFIN_L, R_CDSPDINVOL)
+ VUSCALE(R_CDSPDINMONVU_R, CDSPDIFIN_R, R_CDSPDINVOL)
+
+ MACS(S_SUM_L, S_SUM_L, AC97IN_L, R_AC97VOL)
+ MACS(S_SUM_R, S_SUM_R, AC97IN_R, R_AC97VOL)
+ // AC97 monitor VU
+ VUSCALE(R_AC97MONVU_L, AC97IN_L, R_AC97VOL)
+ VUSCALE(R_AC97MONVU_R, AC97IN_R, R_AC97VOL)
+
+ MACS(S_SUM_L, S_SUM_L, GPSPDIFIN_L, R_SPDINVOL)
+ MACS(S_SUM_R, S_SUM_R, GPSPDIFIN_R, R_SPDINVOL)
+ // S/PDIF input monitor VU
+ VUSCALE(R_SPDINMONVU_L, GPSPDIFIN_L, R_SPDINVOL)
+ VUSCALE(R_SPDINMONVU_R, GPSPDIFIN_R, R_SPDINVOL)
+
+ MACS(S_SUM_L, S_SUM_L, AUXIN_L, SURRAUX)
+ MACS(S_SUM_R, S_SUM_R, AUXIN_R, SURRAUX)
+ VUSCALE(SURRAUXVU_L, AUXIN_L, SURRAUX)
+ VUSCALE(SURRAUXVU_R, AUXIN_R, SURRAUX)
+#ifdef AUDIGY
+ MACS(S_SUM_L, S_SUM_L, MICIN_L, SURRMIC)
+ MACS(S_SUM_R, S_SUM_R, MICIN_R, SURRMIC)
+ VUSCALE(SURRMICVU_L, MICIN_L, SURRMIC)
+ VUSCALE(SURRMICVU_R, MICIN_R, SURRMIC)
+#endif
+#if 0
+ // Boost S/PDIF input level by summing it twice
+ MACS(S_SUM_L, S_SUM_L, GPSPDIFIN_L, R_SPDINVOL)
+ MACS(S_SUM_R, S_SUM_R, GPSPDIFIN_R, R_SPDINVOL)
+#endif
+
+ MACS(TMP_L, 0, S_SUM_L, MAIN_L)
+ MACS(TMP_R, 0, S_SUM_R, MAIN_R)
+#if defined(HAVE_EQ) && defined(HAVE_SURR_EQ)
+ EQUALIZER(L, SL, TMP_L)
+ EQUALIZER(R, SR, TMP_R)
+#endif
+ MACS(SURR_L, 0, TMP_L, SURRVOL_L)
+ MACS(SURR_R, 0, TMP_R, SURRVOL_R)
+
+#ifdef AUDIGY
+ MACS(DSURR_L, 0, TMP_L, SURRVOL_L)
+ MACS(DSURR_R, 0, TMP_R, SURRVOL_R)
+#else
+ MACS(AC97SURR_L, 0, TMP_L, SURRVOL_L)
+ MACS(AC97SURR_R, 0, TMP_R, SURRVOL_R)
+ MACINTS(CENTER_TMP, 0, SEND_C, 1)
+ MACINTS(LFE_TMP, 0, SEND_W, 1)
+
+#endif
+ VUSCALE(SURRVU_L, TMP_L, SURRVOL_L)
+ VUSCALE(SURRVU_R, TMP_R, SURRVOL_R)
+
+//
+// Misc outputs
+//
+
+ SUM(DCENTER, CENTER_TMP, 0, 0)
+ SUM(DLFE, LFE_TMP, 0, 0)
+ SUM(ACENTER, CENTER_TMP, 0, 0)
+ SUM(ALFE, LFE_TMP, 0, 0)
+
+//
+// Recording sources and VU meters
+//
+
+ MACS(TMP_L, 0, AC97IN_L, AC97REC)
+ MACS(TMP_R, 0, AC97IN_R, AC97REC)
+ VUSCALE(AC97VU_L, AC97IN_L, AC97REC)
+ VUSCALE(AC97VU_R, AC97IN_R, AC97REC)
+
+ MACS(TMP_L, TMP_L, GPSPDIFIN_L, SPDIFREC)
+ MACS(TMP_R, TMP_R, GPSPDIFIN_R, SPDIFREC)
+ VUSCALE(SPDIFVU_L, GPSPDIFIN_L, SPDIFREC)
+ VUSCALE(SPDIFVU_R, GPSPDIFIN_R, SPDIFREC)
+
+ MACS(TMP_L, TMP_L, CDSPDIFIN_L, CDSPDIFREC)
+ MACS(TMP_R, TMP_R, CDSPDIFIN_R, CDSPDIFREC)
+ VUSCALE(CDVU_L, CDSPDIFIN_L, CDSPDIFREC)
+ VUSCALE(CDVU_R, CDSPDIFIN_R, CDSPDIFREC)
+
+ MACS(TMP_L, TMP_L, PCMTMP_L, LOOP)
+ MACS(TMP_R, TMP_R, PCMTMP_R, LOOP)
+ VUSCALE(LOOPVU_L, PCMTMP_L, LOOP)
+ VUSCALE(LOOPVU_R, PCMTMP_R, LOOP)
+
+ MACS(TMP_L, TMP_L, AUXIN_L, RECAUX)
+ MACS(TMP_R, TMP_R, AUXIN_R, RECAUX)
+ VUSCALE(RECAUXVU_L, AUXIN_L, RECAUX)
+ VUSCALE(RECAUXVU_R, AUXIN_R, RECAUX)
+
+#ifdef AUDIGY
+ MACS(TMP_L, TMP_L, MICIN_L, RECMIC)
+ MACS(TMP_R, TMP_R, MICIN_R, RECMIC)
+ VUSCALE(RECMICVU_L, MICIN_L, RECMIC)
+ VUSCALE(RECMICVU_R, MICIN_R, RECMIC)
+#endif
+
+ MACS(ADC_L, 0, TMP_L, RECVOL_L)
+ MACS(ADC_R, 0, TMP_R, RECVOL_R)
+ VUSCALE(RECVU_L, TMP_L, RECVOL_L)
+ VUSCALE(RECVU_R, TMP_R, RECVOL_R)
diff --git a/tutorials/sndkit/sblive/emu10k1.mac b/tutorials/sndkit/sblive/emu10k1.mac
new file mode 100644
index 0000000..157bcad
--- /dev/null
+++ b/tutorials/sndkit/sblive/emu10k1.mac
@@ -0,0 +1,51 @@
+// Constants for EMU 10k1 (SB Live)
+// Sends
+
+.send SEND_L 0
+.send SEND_R 1
+.send SEND_SL 2
+.send SEND_SR 3
+.send SEND_C 4
+.send SEND_W 5
+.send SEND_RL 6
+.send SEND_RR 7
+
+// NOTE! 5 and 6 reserved for S/PDIF (AC3) passthrough with Audigy
+
+// Inputs
+
+.input AC97IN_L 0
+.input AC97IN_R 1
+.input CDSPDIFIN_L 2
+.input CDSPDIFIN_R 3
+.input ZVIN_L 4
+.input ZVIN_R 5
+.input GPSPDIFIN_L 6 // TOSLink
+.input GPSPDIFIN_R 7
+.input MICIN_L 8 // LiveDrive (Line/Mic In 1)
+.input MICIN_R 9
+.input CXSPDIFIN_L 10 // LiveDrive (Coax S/PDIF input)
+.input CXSPDIFIN_R 11
+.input AUXIN_L 12 // LiveDrive (Line/Mic 2)
+.input AUXIN_R 13
+
+// Outputs
+
+.output FRONT_L 0
+.output FRONT_R 1
+.output SPDOUT1_L 2
+.output SPDOUT1_R 3
+.output DCENTER 4 // Digital Center channel
+.output DLFE 5 // Digital LFE
+.output HEADPH_L 6 // LiveDrive headphone out
+.output HEADPH_R 7
+.output SURR_L 8 // Rear output
+.output SURR_R 9
+.output ADC_L 10 // Send to the ADC recording channel
+.output ADC_R 11
+.output MICREC 12 // Send to the microphone recording buffer
+.output AC97SURR_L 13 // AC97 Surround L
+.output AC97SURR_R 14 // AC97 Surround R
+
+.output ACENTER 17 // Analog center channel
+.output ALFE 18 // Analog LFE output
diff --git a/tutorials/sndkit/sblive/emu10k2.mac b/tutorials/sndkit/sblive/emu10k2.mac
new file mode 100644
index 0000000..851f9c2
--- /dev/null
+++ b/tutorials/sndkit/sblive/emu10k2.mac
@@ -0,0 +1,71 @@
+// Constants for EMU 10k2 (SB Audigy)
+// Sends
+
+.send SEND_L 0
+.send SEND_R 1
+.send SEND_SL 2
+.send SEND_SR 3
+.send SEND_C 4
+.send SEND_W 5
+.send SEND_RL 6
+.send SEND_RR 7
+
+// Raw S/PDIF output stream
+
+.send SPDIF_L 20
+.send SPDIF_R 21
+
+// Inputs
+
+.input AC97IN_L 0
+.input AC97IN_R 1
+.input CDSPDIFIN_L 2
+.input CDSPDIFIN_R 3
+.input GPSPDIFIN_L 4 // TOSLink
+.input GPSPDIFIN_R 5
+.input CXSPDIFIN_L 6 // LiveDrive (Coax S/PDIF input)
+.input CXSPDIFIN_R 7
+.input MICIN_L 8 // LiveDrive (Line/Mic In 1)
+.input MICIN_R 9
+.input ANACD_L 10 // Analog CD input?
+.input ANACD_R 11
+.input AUXIN_L 12 // LiveDrive (Line/Mic 2)
+.input AUXIN_R 13
+
+// Outputs
+/*
+audigy's Mic In is not connected to AC97;
+known Audigy output map:
+[digital/analog]:
+0x60, 0x68 - front left
+0x61, 0x69 - front right
+0x66, 0x6e - rear left
+0x67, 0x6f - rear right
+0x62, 0x6a - center
+0x63, 0x6b - subwoofer
+
+0x7c,0x7d - in Creative DSP code this is the same as Digital Front; can be
+LiveDrive SPDIF out
+*/
+
+.output SPDOUT1_L 0
+.output SPDOUT1_R 1
+.output DCENTER 2 // Digital Center channel
+.output DLFE 3 // Digital LFE
+.output HEADPH_L 4 // LiveDrive headphone out
+.output HEADPH_R 5
+.output DSURR_L 6 // Surround output
+.output DSURR_R 7
+.output FRONT_L 8
+.output FRONT_R 9
+.output ACENTER 10 // Analog center channel
+.output ALFE 11 // Analog LFE output
+.output SURR_L 14 // Surround output
+.output SURR_R 15
+.output AC97_L 16 // Send to the AC97 front channel
+.output AC97_R 17
+.output ADC_L 22 // Send to the ADC recording channel
+.output ADC_R 23
+.output MICREC_L 24 // Send to the microphone recording buffer
+.output MICREC_R 25 // ??????? (maybe not in use at all)
+
diff --git a/tutorials/sndkit/sblive/emuasm1 b/tutorials/sndkit/sblive/emuasm1
new file mode 100755
index 0000000..26629df
--- /dev/null
+++ b/tutorials/sndkit/sblive/emuasm1
@@ -0,0 +1,3 @@
+#!/bin/sh
+PATH=/opt/langtools/lbin:/usr/local/lib/gcc-lib/sparc-sun-solaris2.6/2.8.1:$PATH
+cpp < $1|./asm10k `basename $1 .dsp`.bin1 -1
diff --git a/tutorials/sndkit/sblive/emuasm2 b/tutorials/sndkit/sblive/emuasm2
new file mode 100755
index 0000000..554c8c7
--- /dev/null
+++ b/tutorials/sndkit/sblive/emuasm2
@@ -0,0 +1,3 @@
+#!/bin/sh
+PATH=/opt/langtools/lbin:/usr/local/lib/gcc-lib/sparc-sun-solaris2.6/2.8.1:$PATH
+cpp -DAUDIGY < $1|./asm10k `basename $1 .dsp`.bin2 -2
diff --git a/tutorials/sndkit/sblive/equalizer.mac b/tutorials/sndkit/sblive/equalizer.mac
new file mode 100644
index 0000000..f9498ac
--- /dev/null
+++ b/tutorials/sndkit/sblive/equalizer.mac
@@ -0,0 +1,117 @@
+//
+// Equalizer macros.
+//
+/*
+ *
+ * This file is part of Open Sound System.
+ *
+ * Copyright (C) 4Front Technologies 1996-2008.
+ *
+ * This this source file is released under GPL v2 license (no other versions).
+ * See the COPYING file included in the main directory of this source
+ * distribution for the license terms and conditions.
+ *
+ */
+
+#if 0
+// Constant 50% (128) gain tables
+#define INCLUDE_EQPARMS \
+.const EQb1_CST_0 0x10000000;\
+.const EQb1_CST_1 0xE042DE20;\
+.const EQb1_CST_2 0x1FBD21E0;\
+.const EQb1_CST_3 0x0FBD8640;\
+.const EQb1_CST_4 0xF04279C0;\
+.const EQb2_CST_0 0x10000000;\
+.const EQb2_CST_1 0xE2E5DDC0;\
+.const EQb2_CST_2 0x1D1A2240;\
+.const EQb2_CST_3 0x0D48B550;\
+.const EQb2_CST_4 0xF2B74AB0;\
+.const EQb3_CST_0 0x10000000;\
+.const EQb3_CST_1 0xEC7021C0;\
+.const EQb3_CST_2 0x138FDE40;\
+.const EQb3_CST_3 0x069696A0;\
+.const EQb3_CST_4 0xF9696960;\
+.const EQb4_CST_0 0x10000000;\
+.const EQb4_CST_1 0x094B0F90;\
+.const EQb4_CST_2 0xF6B4F070;\
+.const EQb4_CST_3 0x02961F24;\
+.const EQb4_CST_4 0xFD69E0DC;\
+.parm BYPASS 0 onoff ;
+#else
+#define INCLUDE_EQPARMS \
+.parm EQ_GAIN 100 mono PRESCALE;\
+.parm EQb1 128 eq1 LO;\
+.parm EQb2 128 eq2 MID;\
+.parm EQb3 128 eq3 HI;\
+.parm EQb4 128 eq4 XHI;\
+.parm BYPASS 0 onoff ;
+#endif
+
+#define INCLUDE_EQVARS \
+.gpr eq_save;\
+.gpr eq_value;\
+.const 0x1000 0x1000;\
+.const 44 I44;\
+.const EQ_ADJUST I8;\
+.const EQ_AFTERSCALE I32;\
+.const EQ_PRESCALE 0.03125 /* 1/32 */
+
+#define INCLUDE_DELAYS(PREFIX) \
+.gpr PREFIX##b1_x0;\
+.gpr PREFIX##b1_x1;\
+.gpr PREFIX##b1_x2;\
+.gpr PREFIX##b1_y0;\
+.gpr PREFIX##b1_y1;\
+.gpr PREFIX##b1_y2;\
+.gpr PREFIX##b2_x0;\
+.gpr PREFIX##b2_x1;\
+.gpr PREFIX##b2_x2;\
+.gpr PREFIX##b2_y0;\
+.gpr PREFIX##b2_y1;\
+.gpr PREFIX##b2_y2;\
+.gpr PREFIX##b3_x0;\
+.gpr PREFIX##b3_x1;\
+.gpr PREFIX##b3_x2;\
+.gpr PREFIX##b3_y0;\
+.gpr PREFIX##b3_y1;\
+.gpr PREFIX##b3_y2;\
+.gpr PREFIX##b4_x0;\
+.gpr PREFIX##b4_x1;\
+.gpr PREFIX##b4_x2;\
+.gpr PREFIX##b4_y0;\
+.gpr PREFIX##b4_y1;\
+.gpr PREFIX##b4_y2
+
+#define MOVE(a,b) ACC3(b, a, 0, 0)
+
+#define PASS_BAND(N, BAND)\
+\
+ MOVE(N##_x1,N##_x2);\
+ MOVE(N##_x0,N##_x1);\
+ MOVE(eq_value, N##_x0);\
+\
+ MOVE(N##_y1,N##_y2);\
+ MOVE(N##_y0,N##_y1);\
+ MOVE(0,N##_y0);\
+\
+ MACS(N##_y0, 0, N##_x0,EQ##BAND##_CST_0);\
+ MACS(N##_y0, N##_y0, N##_x1,EQ##BAND##_CST_1);\
+ MACS(N##_y0, N##_y0, N##_y1,EQ##BAND##_CST_2);\
+ MACS(N##_y0, N##_y0, N##_x2,EQ##BAND##_CST_3);\
+ MACS(N##_y0, N##_y0, N##_y2,EQ##BAND##_CST_4);\
+\
+ MACINTS(N##_y0, 0, N##_y0, EQ_ADJUST);\
+ ACC3(eq_value, N##_y0, 0, 0)
+
+#define EQUALIZER(SUFFIX, PREFIX, INOUT) \
+ ACC3(eq_value, INOUT, 0, 0); \
+ ACC3(eq_save, INOUT, 0, 0); \
+ MACS(eq_value, 0, eq_value, EQ_GAIN);\
+ MACS(eq_value, 0, eq_value, EQ_PRESCALE);\
+ PASS_BAND(PREFIX##b4, b4); \
+ PASS_BAND(PREFIX##b3, b3); \
+ PASS_BAND(PREFIX##b2, b2); \
+ PASS_BAND(PREFIX##b1, b1); \
+ MACINTS(eq_value, 44, eq_value, EQ_AFTERSCALE);\
+ MACINTS(INOUT, 0, eq_value, BYPASS_OFF);\
+ MACINTS(INOUT, INOUT, eq_save, BYPASS_ON)
diff --git a/tutorials/sndkit/sblive/ld10k.c b/tutorials/sndkit/sblive/ld10k.c
new file mode 100644
index 0000000..d01dc2c
--- /dev/null
+++ b/tutorials/sndkit/sblive/ld10k.c
@@ -0,0 +1,220 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+#include <sys/ioctl.h>
+
+#include <soundcard.h>
+#ifdef USERLAND
+#define oss_native_word unsigned long
+#define oss_mutex_t unsigned long
+#define oss_device_t unsigned long
+#define ac97_devc unsigned long
+#define oss_midi_inputbyte_t char
+#define uart401_devc unsigned long
+typedef int oss_mutex;
+typedef void *oss_dma_handle_t;
+#else
+#include "../../../kernel/framework/include/os.h"
+#endif /* USERLAND */
+#include "../../../kernel/drv/oss_sblive/sblive.h"
+
+int work_done = 0;
+int ossfd;
+emu10k1_file fle;
+
+static int
+find_last_device (void)
+{
+ oss_sysinfo info;
+ int mixerfd;
+
+ if ((mixerfd = open ("/dev/mixer0", O_RDWR, 0)) == -1)
+ {
+ perror ("/dev/mixer0");
+ return 0;
+ }
+
+ if (ioctl (mixerfd, SNDCTL_SYSINFO, &info) == -1)
+ {
+ perror ("SNDCTL_SYSINFO");
+ exit (-1);
+ }
+
+ close (mixerfd);
+ return info.numaudios - 1;
+}
+
+static void
+touch_all_mixers (int ossfd)
+{
+ int i, n;
+
+ for (i = 0; i < 16; i++)
+ {
+ n = i;
+ if (ioctl (ossfd, SNDCTL_MIX_NREXT, &n) == -1)
+ return;
+ }
+}
+
+static void
+do_download (void)
+{
+ int card_type;
+
+ if (ioctl (ossfd, SBLIVE_GETCHIPTYPE, &card_type) == -1)
+ {
+ perror ("???");
+ return;
+ }
+
+ if (card_type != fle.feature_mask)
+ {
+ fprintf (stderr, "Device/file incompatibility (%x/%x)\n", card_type,
+ fle.feature_mask);
+ return;
+ }
+
+ if (ioctl (ossfd, SBLIVE_WRITECODE1, fle.code) == -1)
+ {
+ perror ("code1");
+ return;
+ }
+
+ if (ioctl (ossfd, SBLIVE_WRITECODE2, fle.code + 512) == -1)
+ {
+ perror ("code2");
+ return;
+ }
+
+ if (fle.parms.ngpr > 0)
+ {
+ if (ioctl (ossfd, SBLIVE_WRITEPARMS, &fle.parms) == -1)
+ {
+ perror ("parms");
+ return;
+ }
+
+ touch_all_mixers (ossfd);
+ }
+
+ if (fle.consts.nconst > 0)
+ {
+ if (ioctl (ossfd, SBLIVE_WRITECONST, &fle.consts) == -1)
+ {
+ perror ("consts");
+ return;
+ }
+
+ }
+ work_done = 1;
+}
+
+static void
+do_all_devices (void)
+{
+ int i, mixerfd;
+ oss_sysinfo info;
+ char dspname[100];
+
+ if ((mixerfd = open ("/dev/mixer0", O_RDWR, 0)) == -1)
+ {
+ perror ("/dev/mixer");
+ exit (-1);
+ }
+
+ if (ioctl (mixerfd, SNDCTL_SYSINFO, &info) == -1)
+ {
+ perror ("SNDCTL_SYSINFO");
+ exit (-1);
+ }
+
+ for (i = 0; i < info.numaudios; i++)
+ {
+ oss_audioinfo ainfo;
+ int acc;
+
+ ainfo.dev = i;
+ if (ioctl (mixerfd, SNDCTL_AUDIOINFO, &ainfo) == -1)
+ {
+ perror ("SNDCTL_AUDIOINFO");
+ exit (-1);
+ }
+
+ if (ainfo.magic == fle.magic)
+ {
+
+ sprintf (dspname, "/dev/dsp%d", i);
+ if ((ossfd = open (dspname, O_RDWR, 0)) == -1)
+ {
+ perror (dspname);
+ exit (-1);
+ }
+
+ do_download ();
+ close (ossfd);
+ }
+ }
+ close (mixerfd);
+}
+
+int
+main (int argc, char *argv[])
+{
+ int fd, dspnum = 0;
+ char *dspname = "/dev/dsp", namebuf[32];
+
+ if (argc < 2)
+ {
+ fprintf (stderr, "Usage: %s dspcodefile\n", argv[0]);
+ exit (-1);
+ }
+
+ if ((fd = open (argv[1], O_RDONLY, 0)) == -1)
+ {
+ perror (argv[1]);
+ exit (-1);
+ }
+
+ if (argc > 2)
+ dspname = argv[2];
+
+ if (read (fd, &fle, sizeof (fle)) != sizeof (fle))
+ {
+ fprintf (stderr, "Short file\n");
+ exit (-1);
+ }
+
+ if (fle.magic != EMU10K1_MAGIC && fle.magic != EMU10K2_MAGIC)
+ {
+ fprintf (stderr, "Bad microcode file %s\n", argv[1]);
+ exit (-1);
+ }
+
+ if (strcmp (dspname, "-a") == 0)
+ {
+ do_all_devices ();
+ exit (0);
+ }
+
+ if (strcmp (dspname, "-l") == 0)
+ { /* Last /dev/dsp# file requested */
+ dspnum = find_last_device ();
+ sprintf (namebuf, "/dev/dsp%d", dspnum);
+ dspname = namebuf;
+ }
+
+ if ((ossfd = open (dspname, O_RDWR, 0)) == -1)
+ {
+ perror (dspname);
+ exit (-1);
+ }
+
+ do_download ();
+
+ if (!work_done)
+ exit (-1);
+ exit (0);
+}
diff --git a/tutorials/sndkit/sblive/mkheader.c b/tutorials/sndkit/sblive/mkheader.c
new file mode 100644
index 0000000..4081a56
--- /dev/null
+++ b/tutorials/sndkit/sblive/mkheader.c
@@ -0,0 +1,37 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+int
+main (int argc, char *argv[])
+{
+ unsigned char buffer[1024];
+ int i, l, n = 0;
+
+ if (argc != 2)
+ {
+ fprintf (stderr, "Bad usage\n");
+ exit (-1);
+ }
+
+ printf ("static unsigned char %s[] =\n", argv[1]);
+ printf ("{\n");
+
+ while ((l = read (0, buffer, sizeof (buffer))) > 0)
+ {
+ for (i = 0; i < l; i++)
+ {
+ if (n > 0)
+ printf (", ");
+
+ if (n && (n % 16) == 0)
+ printf ("\n");
+ printf ("0x%02x", buffer[i]);
+ n++;
+ }
+ }
+
+ printf ("\n};\n");
+
+ exit (0);
+}
diff --git a/tutorials/sndkit/sblive/null.dsp b/tutorials/sndkit/sblive/null.dsp
new file mode 100644
index 0000000..ccba794
--- /dev/null
+++ b/tutorials/sndkit/sblive/null.dsp
@@ -0,0 +1,23 @@
+#include "emu10k2.mac"
+
+.gpr AUX_L
+.gpr AUX_R
+.gpr SPDIF_TMP_L
+.gpr SPDIF_TMP_R
+.parm _PASSTHROUGH 0 onoff;
+
+ACC3(AUX_L, SEND_L, 0, 0)
+ACC3(FRONT_L, AUX_L, 0, 0)
+
+ACC3(AUX_R, SEND_L, 0, 0)
+ACC3(FRONT_R, AUX_L, 0, 0)
+
+ACC3(SURR_R, 0, 0, 0)
+ACC3(SURR_L, 0, 0, 0)
+ACC3(SPDIF_TMP_L, SPDIF_L, 0, 0)
+ACC3(SPDIF_TMP_R, SPDIF_R, 0, 0)
+
+ MACINTS(SPDOUT1_L, 0, AUX_L, _PASSTHROUGH_OFF)
+ MACINTS(SPDOUT1_R, 0, AUX_R, _PASSTHROUGH_OFF)
+ MACINTS(SPDOUT1_L, SPDOUT1_L, SPDIF_TMP_L, _PASSTHROUGH_ON)
+ MACINTS(SPDOUT1_R, SPDOUT1_R, SPDIF_TMP_R, _PASSTHROUGH_ON)
diff --git a/tutorials/sndkit/sblive/testgen.c b/tutorials/sndkit/sblive/testgen.c
new file mode 100644
index 0000000..e41d2b7
--- /dev/null
+++ b/tutorials/sndkit/sblive/testgen.c
@@ -0,0 +1,92 @@
+#include <stdio.h>
+#include <stdlib.h>
+
+#define N 64
+
+static void
+gen_inputtest (void)
+{
+ int i;
+
+ printf ("// Input test program\n");
+ printf ("#include \"vu.mac\"\n");
+ printf (".gpr VUTMP\n");
+ printf (".gpr TMP\n");
+
+ for (i = 0; i < N; i += 2)
+ {
+ printf (".input I%d_L %d\n", i, i);
+ printf (".input I%d_R %d\n", i, i + 1);
+ }
+
+ for (i = 0; i < N; i += 2)
+ {
+ if (!(i % 16))
+ printf (".parm G%x 0 group\n", i);
+ printf (".parm IVU%d 0 stereopeak\n", i);
+ }
+
+ for (i = 0; i < N; i += 2)
+ {
+ printf ("ACC3(TMP, I%d_L, 0, 0)\n", i);
+ printf ("VU(IVU%d_L, TMP)\n", i);
+ printf ("ACC3(TMP, I%d_R, 0, 0)\n", i);
+ printf ("VU(IVU%d_R, TMP)\n", i);
+ }
+
+}
+
+static void
+gen_outputtest (void)
+{
+ int i;
+
+ printf ("// Output test program\n");
+ printf ("#include \"vu.mac\"\n");
+ printf (".parm VU 0 stereopeak\n");
+ printf (".gpr VUTMP\n");
+ printf (".gpr TMP\n");
+ printf (".gpr TMP_L\n");
+ printf (".gpr TMP_R\n");
+ printf (".send TEST_L 0\n");
+ printf (".send TEST_R 1\n");
+
+ for (i = 0; i < N; i += 2)
+ {
+ printf (".output O%d_L %d\n", i, i);
+ printf (".output O%d_R %d\n", i, i + 1);
+ }
+
+ for (i = 0; i < N; i += 2)
+ {
+ if (!(i % 16))
+ printf (".parm G%x 0 group\n", i);
+ printf (".parm OUT%d 0 stereo\n", i);
+ }
+
+ printf ("ACC3(TMP_L, TEST_L, 0, 0)\n");
+ printf ("ACC3(TMP_R, TEST_R, 0, 0)\n");
+ printf ("VU(VU_L, TMP_L)\n");
+ printf ("VU(VU_R, TMP_R)\n");
+
+ for (i = 0; i < N; i += 2)
+ {
+ printf ("MACS(O%d_L, 0, TMP_L, OUT%d_L)\n", i, i);
+ printf ("MACS(O%d_R, 0, TMP_R, OUT%d_R)\n", i, i);
+ }
+
+}
+
+int
+main (int argc, char *argv[])
+{
+ if (argc < 2)
+ exit (-1);
+
+ if (strcmp (argv[1], "in") == 0)
+ gen_inputtest ();
+
+ if (strcmp (argv[1], "out") == 0)
+ gen_outputtest ();
+ exit (0);
+}
diff --git a/tutorials/sndkit/sblive/vu.mac b/tutorials/sndkit/sblive/vu.mac
new file mode 100644
index 0000000..c563d98
--- /dev/null
+++ b/tutorials/sndkit/sblive/vu.mac
@@ -0,0 +1,27 @@
+/*
+ *
+ * This file is part of Open Sound System.
+ *
+ * Copyright (C) 4Front Technologies 1996-2008.
+ *
+ * This this source file is released under GPL v2 license (no other versions).
+ * See the COPYING file included in the main directory of this source
+ * distribution for the license terms and conditions.
+ *
+ */
+// VU meter computation macros
+//
+// Simple VU
+#define VU(vuvar, input) \
+ TSTNEG(VUTMP, input, input, 0);\
+ LIMIT(vuvar, vuvar, vuvar, VUTMP)
+/* VU meter with volume scaling */
+#define VUSCALE(vuvar, input, scale) \
+ MACS(VUTMP2, 0, input, scale) ;\
+ TSTNEG(VUTMP, VUTMP2, VUTMP2, 0);\
+ LIMIT(vuvar, vuvar, vuvar, VUTMP)
+/* VU meter with volume scaling and summing with a 'base' signal */
+#define VUSCALESUM(vuvar, basevar, input, scale) \
+ MACS(VUTMP2, basevar, input, scale) ;\
+ TSTNEG(VUTMP, VUTMP2, VUTMP2, 0);\
+ LIMIT(vuvar, vuvar, vuvar, VUTMP)
diff --git a/tutorials/sndkit/sblive/writegpr.c b/tutorials/sndkit/sblive/writegpr.c
new file mode 100644
index 0000000..c70e191
--- /dev/null
+++ b/tutorials/sndkit/sblive/writegpr.c
@@ -0,0 +1,48 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#define oss_native_ulong unsigned long
+#define sound_os_info unsigned long
+#define ac97_devc unsigned long
+typedef int oss_mutex;
+#include <soundcard.h>
+#include <sblive.h>
+
+int
+main (int argc, char *argv[])
+{
+ int ossfd, reg, value;
+ char *dspname = "/dev/dsp";
+ sblive_reg rg;
+
+ if (argc < 3)
+ {
+ fprintf (stderr, "Usage: %s GPR hexvalue\n", argv[0]);
+ exit (-1);
+ }
+
+ if (sscanf (argv[1], "%d", &reg) != 1)
+ exit (-1);
+
+ if (sscanf (argv[2], "%x", &value) != 1)
+ exit (-1);
+
+ if ((ossfd = open (dspname, O_WRONLY, 0)) == -1)
+ {
+ perror (dspname);
+ exit (-1);
+ }
+
+ rg.reg = GPR0 + reg;
+ rg.chn = 0;
+ rg.value = value;
+
+ if (ioctl (ossfd, SBLIVE_WRITEREG, &rg) == -1)
+ perror (dspname);
+
+
+ exit (0);
+}