diff options
Diffstat (limited to 'tutorials/sndkit/sblive')
-rw-r--r-- | tutorials/sndkit/sblive/Makefile | 53 | ||||
-rw-r--r-- | tutorials/sndkit/sblive/README | 12 | ||||
-rw-r--r-- | tutorials/sndkit/sblive/asm10k.c | 1206 | ||||
-rw-r--r-- | tutorials/sndkit/sblive/emu10k.dsp | 378 | ||||
-rw-r--r-- | tutorials/sndkit/sblive/emu10k1.mac | 51 | ||||
-rw-r--r-- | tutorials/sndkit/sblive/emu10k2.mac | 71 | ||||
-rwxr-xr-x | tutorials/sndkit/sblive/emuasm1 | 3 | ||||
-rwxr-xr-x | tutorials/sndkit/sblive/emuasm2 | 3 | ||||
-rw-r--r-- | tutorials/sndkit/sblive/equalizer.mac | 117 | ||||
-rw-r--r-- | tutorials/sndkit/sblive/ld10k.c | 220 | ||||
-rw-r--r-- | tutorials/sndkit/sblive/mkheader.c | 37 | ||||
-rw-r--r-- | tutorials/sndkit/sblive/null.dsp | 23 | ||||
-rw-r--r-- | tutorials/sndkit/sblive/testgen.c | 92 | ||||
-rw-r--r-- | tutorials/sndkit/sblive/vu.mac | 27 | ||||
-rw-r--r-- | tutorials/sndkit/sblive/writegpr.c | 48 |
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", ®) != 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); +} |