From c51b1189e3d5353e842991f5859ddcea0f73e426 Mon Sep 17 00:00:00 2001 From: theuni Date: Mon, 24 Jan 2011 16:05:21 -0500 Subject: Merged cptspiff's code-reshuffle branch. Squashed commit due to build breakage during code-reshuffle history. Conflicts: xbmc/Util.cpp xbmc/cdrip/CDDARipper.cpp xbmc/filesystem/Directory.cpp xbmc/filesystem/File.cpp --- lib/stsound/StSoundLibrary/Depacker.cpp | 92 + lib/stsound/StSoundLibrary/Depacker.h | 37 + lib/stsound/StSoundLibrary/LZH/lzh.h | 86 + lib/stsound/StSoundLibrary/LZH/lzhlib.txt | 132 + lib/stsound/StSoundLibrary/LZH/lzhxlib.c | 440 ++++ lib/stsound/StSoundLibrary/Makefile.in | 30 + lib/stsound/StSoundLibrary/StSoundLibrary.h | 71 + lib/stsound/StSoundLibrary/StSoundLibrary.vcproj | 407 +++ lib/stsound/StSoundLibrary/StSoundLibrary.vcxproj | 215 ++ .../StSoundLibrary/StSoundLibrary.vcxproj.filters | 71 + lib/stsound/StSoundLibrary/XBMCYM.cpp | 96 + lib/stsound/StSoundLibrary/Ym2149Ex.cpp | 603 +++++ lib/stsound/StSoundLibrary/Ym2149Ex.h | 160 ++ lib/stsound/StSoundLibrary/YmMusic.cpp | 731 ++++++ lib/stsound/StSoundLibrary/YmMusic.h | 261 ++ lib/stsound/StSoundLibrary/YmTypes.h | 91 + lib/stsound/StSoundLibrary/YmUserInterface.cpp | 132 + lib/stsound/StSoundLibrary/Ymload.cpp | 690 ++++++ lib/stsound/StSoundLibrary/Ymload.h | 62 + lib/stsound/StSoundLibrary/digidrum.cpp | 2584 ++++++++++++++++++++ lib/stsound/StSoundLibrary/digidrum.h | 39 + lib/stsound/license.txt | 341 +++ lib/stsound/readme.html | 151 ++ lib/stsound/revision.txt | 20 + 24 files changed, 7542 insertions(+) create mode 100644 lib/stsound/StSoundLibrary/Depacker.cpp create mode 100644 lib/stsound/StSoundLibrary/Depacker.h create mode 100644 lib/stsound/StSoundLibrary/LZH/lzh.h create mode 100644 lib/stsound/StSoundLibrary/LZH/lzhlib.txt create mode 100644 lib/stsound/StSoundLibrary/LZH/lzhxlib.c create mode 100644 lib/stsound/StSoundLibrary/Makefile.in create mode 100644 lib/stsound/StSoundLibrary/StSoundLibrary.h create mode 100644 lib/stsound/StSoundLibrary/StSoundLibrary.vcproj create mode 100644 lib/stsound/StSoundLibrary/StSoundLibrary.vcxproj create mode 100644 lib/stsound/StSoundLibrary/StSoundLibrary.vcxproj.filters create mode 100644 lib/stsound/StSoundLibrary/XBMCYM.cpp create mode 100644 lib/stsound/StSoundLibrary/Ym2149Ex.cpp create mode 100644 lib/stsound/StSoundLibrary/Ym2149Ex.h create mode 100644 lib/stsound/StSoundLibrary/YmMusic.cpp create mode 100644 lib/stsound/StSoundLibrary/YmMusic.h create mode 100644 lib/stsound/StSoundLibrary/YmTypes.h create mode 100644 lib/stsound/StSoundLibrary/YmUserInterface.cpp create mode 100644 lib/stsound/StSoundLibrary/Ymload.cpp create mode 100644 lib/stsound/StSoundLibrary/Ymload.h create mode 100644 lib/stsound/StSoundLibrary/digidrum.cpp create mode 100644 lib/stsound/StSoundLibrary/digidrum.h create mode 100644 lib/stsound/license.txt create mode 100644 lib/stsound/readme.html create mode 100644 lib/stsound/revision.txt (limited to 'lib/stsound') diff --git a/lib/stsound/StSoundLibrary/Depacker.cpp b/lib/stsound/StSoundLibrary/Depacker.cpp new file mode 100644 index 0000000000..bcd9e33ab3 --- /dev/null +++ b/lib/stsound/StSoundLibrary/Depacker.cpp @@ -0,0 +1,92 @@ +/*----------------------------------------------------------------------------- + + ST-Sound ( YM files player library ) + + Copyright (C) 1995-1999 Arnaud Carre ( http://leonard.oxg.free.fr ) + + LzhXLib wrapper. + +-----------------------------------------------------------------------------*/ + +/*----------------------------------------------------------------------------- + + This file is part of ST-Sound + + ST-Sound is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + ST-Sound is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with ST-Sound; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +-----------------------------------------------------------------------------*/ + +#include "LZH/lzh.h" +#include "YmMusic.h" +#include "Depacker.h" +#include + + +static const ymu8 * s_pSrc = 0; +static ymu8 * s_pDst = 0; +static ymint s_depackedSize = 0; +static ymint s_depackedPos = 0; + + +static ymint ReadCallback(void *pBuffer,ymint size) +{ + memcpy(pBuffer,s_pSrc,size); + s_pSrc += size; + return size; +} + +static ymint WriteCallback(void *pBuffer,ymint size) +{ + ymint safeSize = (s_depackedPos + size <= s_depackedSize) ? size : s_depackedSize - s_depackedPos; + + if (safeSize > 0) + { + memcpy(s_pDst,pBuffer,safeSize); + s_depackedPos += safeSize; + s_pDst += safeSize; + return safeSize; + } + else + return -1; +} + +static void * MallocCallback(unsigned int size) +{ + ymu8 *p = new ymu8[size]; + return (void*)p; +} + +static void FreeCallback(void *p) +{ + if (p) + { + ymu8 *cp = (ymu8 *)p; + delete [] cp; + } +} + +ymbool LzhDepackBlock(const ymu8 *pSrc,ymu8 *pDst,ymint depackedSize) +{ + + s_pSrc = pSrc; + s_pDst = pDst; + s_depackedPos = 0; + s_depackedSize = depackedSize; + + ymint error = lzh_melt(ReadCallback,WriteCallback,MallocCallback,FreeCallback,s_depackedSize); + + return ((0 == error) ? YMTRUE : YMFALSE); +} + diff --git a/lib/stsound/StSoundLibrary/Depacker.h b/lib/stsound/StSoundLibrary/Depacker.h new file mode 100644 index 0000000000..66e99b8446 --- /dev/null +++ b/lib/stsound/StSoundLibrary/Depacker.h @@ -0,0 +1,37 @@ +/*----------------------------------------------------------------------------- + + ST-Sound ( YM files player library ) + + Copyright (C) 1995-1999 Arnaud Carre ( http://leonard.oxg.free.fr ) + + LzhXLib wrapper. + +-----------------------------------------------------------------------------*/ + +/*----------------------------------------------------------------------------- + + This file is part of ST-Sound + + ST-Sound is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + ST-Sound is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with ST-Sound; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +-----------------------------------------------------------------------------*/ + +#ifndef __DEPACKER__ +#define __DEPACKER__ + +extern ymbool LzhDepackBlock(const ymu8 *pSrc,ymu8 *pDst,ymint depackedSize); + +#endif + diff --git a/lib/stsound/StSoundLibrary/LZH/lzh.h b/lib/stsound/StSoundLibrary/LZH/lzh.h new file mode 100644 index 0000000000..009266d205 --- /dev/null +++ b/lib/stsound/StSoundLibrary/LZH/lzh.h @@ -0,0 +1,86 @@ +/** + * + * LZHXLib.C - Decompression module + * + * Compression Library (LZH) from Haruhiko Okumura's "ar". + * + * Copyright(c) 1996 Kerwin F. Medina + * Copyright(c) 1991 Haruhiko Okumura + * + * In MSDOS, this MUST be compiled using compact, large, + * or huge memory models + * + * To test, compile as below to create a stand-alone decompressor (will + * decompress standard input to standard output): + * bcc -O2 -mc -D__TEST__ lzhxlib.c + * or + * gcc -O2 -D__TEST__ lzhxlib.c + * then run as: lzhxlib outfile + * + * To use as a library for your application, __TEST__ must + * not be defined. + * + */ + + +#ifndef LZH_H +#define LZH_H + +#ifndef __TURBOC__ +#define far +#endif + +typedef unsigned char uchar; /* 8 bits or more */ +typedef unsigned int uint; /* 16 bits or more */ +typedef unsigned short ushort; /* 16 bits or more */ +typedef unsigned long ulong; /* 32 bits or more */ + +#ifndef CHAR_BIT + #define CHAR_BIT 8 +#endif + +#ifndef UCHAR_MAX + #define UCHAR_MAX 255 +#endif + +#define BITBUFTYPE ushort + +#define BITBUFSIZ (CHAR_BIT * sizeof (BITBUFTYPE)) +#define DICBIT 13 /* 12(-lh4-) or 13(-lh5-) */ +#define DICSIZ (1U << DICBIT) +#define MAXMATCH 256 /* formerly F (not more than UCHAR_MAX + 1) */ +#define THRESHOLD 3 /* choose optimal value */ +#define NC (UCHAR_MAX + MAXMATCH + 2 - THRESHOLD) /* alphabet = {0, 1, 2, ..., NC - 1} */ +#define CBIT 9 /* $\lfloor \log_2 NC \rfloor + 1$ */ +#define CODE_BIT 16 /* codeword length */ + +#define MAX_HASH_VAL (3 * DICSIZ + (DICSIZ / 512 + 1) * UCHAR_MAX) + +typedef void far * void_far_pointer; +typedef int (*type_fnc_read) (void far *data, int n); +typedef int (*type_fnc_write) (void far *data, int n); +typedef void_far_pointer (*type_fnc_malloc) (unsigned n); +typedef void (*type_fnc_free) (void far *p); + +#ifdef __cplusplus +extern "C" +{ +#endif + +int lzh_freeze (type_fnc_read pfnc_read, + type_fnc_write pfnc_write, + type_fnc_malloc pfnc_malloc, + type_fnc_free pfnc_free); + +int lzh_melt (type_fnc_read pfnc_read, + type_fnc_write pfnc_write, + type_fnc_malloc pfnc_malloc, + type_fnc_free pfnc_free, + ulong origsize); + +#ifdef __cplusplus +} +#endif + + +#endif /* ifndef LZH_H */ diff --git a/lib/stsound/StSoundLibrary/LZH/lzhlib.txt b/lib/stsound/StSoundLibrary/LZH/lzhlib.txt new file mode 100644 index 0000000000..2de8554792 --- /dev/null +++ b/lib/stsound/StSoundLibrary/LZH/lzhlib.txt @@ -0,0 +1,132 @@ +LZHLIB.TXT + +Copyright(c) 1996 Kerwin F. Medina +Kerwin F. Medina +kerwin@infoserve.net +kerwin@digi.co.jp + +I took the source of Haruhiko Okumura's "ar" and extracted only the +necessary codes to create a compression library so an application can +make use of compression through a function call and without having to +spawn an external compression program. + +The library has only two API functions: "lzh_freeze" (to compress) and +"lzh_melt" (to decompress). In both cases, the caller only has to +provide the I/O functions and memory allocation functions. The +following is an example of a minimal compressor and decompressor. + + Sample Compressor: + + #ifdef __TURBOC__ + #include + #include + #else + #include + #endif + #include + + /* My I/O functions */ + int read0 (void far *p, int n) {return read (0, p, n);} + int write1 (void far *p, int n) {return write (1, p, n);} + + /* My Memory functions */ + void *mymalloc (unsigned n) {return malloc (n);} + void myfree (void far *p) {free (p);} + + void main (void) + { + long n; + #ifdef __TURBOC__ + setmode (0, O_BINARY); setmode (1, O_BINARY); + #endif + /* Get the length of the input file */ + n = lseek (0, 0, 2); + lseek (0, 0, 0); + + /* Write this length to the output file */ + write (1, &n, sizeof (n)); + + /* Now, Call the compression function */ + lzh_freeze (read0, write1, mymalloc, myfree); + } + + Sample Decompressor: + + #ifdef __TURBOC__ + #include + #include + #else + #include + #endif + #include + + /* My I/O functions */ + int read0 (void far *p, int n) {return read (0, p, n);} + int write1 (void far *p, int n) {return write (1, p, n);} + + /* My Memory functions */ + void *mymalloc (unsigned n) {return malloc (n);} + void myfree (void far *p) {free (p);} + + void main (void) + { + long n; + #ifdef __TURBOC__ + setmode (0, O_BINARY); setmode (1, O_BINARY); + #endif + /* Get the original file length */ + read (0, &n, sizeof (n)); + + /* Now, Call the decompression function */ + lzh_melt (read0, write1, malloc, free, n); + } + +The description of the library API is given in more detail below: + + Prototypes: + + int lzh_freeze (type_fnc_read pfnc_read, + type_fnc_write pfnc_write, + type_fnc_malloc pfnc_malloc, + type_fnc_free pfnc_free); + + int lzh_melt (type_fnc_read pfnc_read, + type_fnc_write pfnc_write, + type_fnc_malloc pfnc_malloc, + type_fnc_free pfnc_free, + unsigned long origsize); + + Remarks: "lzh_freeze" will perform an LZH compression on input + data that the caller provides through the + "fnc_read" callback function, and will output the + compressed result through a call to "fnc_write". + + "lzh_melt" will perform decompression of input + data that the caller provides through the + "fnc_read" callback function, and will output the + decompressed result through a call to "fnc_write". + + Argumets What it does + -------- ------------ + + fnc_read a callback function that library will call when + needing input data. "fnc_read" must return the + number of input bytes or -1 if there is an error. + + fnc_write a callback function that library will call when + needing to output data. "fnc_write" must return + the number of outputed bytes (or -1 if there is an + error). + + fnc_malloc a callback function that library will call when + needing to allocate memory. "fnc_malloc" must + return the address of the allocated memory or NULL + if there is an error. + + fnc_free a callback function that library will call when + needing to free a memory that was allocated using + "fnc_malloc". + + origsize the original number of bytes of the uncompressed + data. + diff --git a/lib/stsound/StSoundLibrary/LZH/lzhxlib.c b/lib/stsound/StSoundLibrary/LZH/lzhxlib.c new file mode 100644 index 0000000000..08fa22e611 --- /dev/null +++ b/lib/stsound/StSoundLibrary/LZH/lzhxlib.c @@ -0,0 +1,440 @@ +/** + * + * LZHXLib.C - Decompression module + * + * Compression Library (LZH) from Haruhiko Okumura's "ar". + * + * Copyright(c) 1996 Kerwin F. Medina + * Copyright(c) 1991 Haruhiko Okumura + * + * In MSDOS, this MUST be compiled using compact, large, + * or huge memory models + * + * To test, compile as below to create a stand-alone decompressor (will + * decompress standard input to standard output): + * bcc -O2 -mc -D__TEST__ lzhxlib.c + * or + * gcc -O2 -D__TEST__ lzhxlib.c + * then run as: lzhxlib outfile + * + * To use as a library for your application, __TEST__ must + * not be defined. + * + */ + +#include "lzh.h" + +/* + * Additions + */ + +static type_fnc_read fnc_read; +static type_fnc_write fnc_write; +static type_fnc_malloc fnc_malloc; +static type_fnc_free fnc_free; +static int with_error; + +#define BUFSIZE (1024 * 4) +static int fillbufsize; +static uchar far* buf; + +/* + * io.c + */ + +static ushort far left [2 * NC - 1], far right[2 * NC - 1]; + +static BITBUFTYPE bitbuf; +static uint subbitbuf; +static int bitcount; + +/** Shift bitbuf n bits left, read n bits */ +static void fillbuf (int n) +{ + static uint i; + bitbuf = (bitbuf << n) & 0xffff; + while (n > bitcount) + { + bitbuf |= subbitbuf << (n -= bitcount); + if (fillbufsize == 0) + { + i = 0; + fillbufsize = fnc_read (buf, BUFSIZE - 32); + } + if (fillbufsize > 0) + fillbufsize--, subbitbuf = buf[i++]; + else + subbitbuf = 0; + bitcount = CHAR_BIT; + } + bitbuf |= subbitbuf >> (bitcount -= n); +} + +static ushort getbits (int n) +{ + ushort x; + x = bitbuf >> (BITBUFSIZ - n); + fillbuf (n); + return x; +} + +static void init_getbits (void) +{ + bitbuf = 0; + subbitbuf = 0; + bitcount = 0; + fillbuf (BITBUFSIZ); +} + +/* + * maketbl.c + */ + +static int make_table (int nchar, uchar far *bitlen, + int tablebits, ushort far *table) +{ + ushort count[17], weight[17], start[18], *p; + uint i, k, len, ch, jutbits, avail, nextcode, mask; + + for (i = 1; i <= 16; i++) + count[i] = 0; + for (i = 0; i < nchar; i++) + count[bitlen[i]]++; + + start[1] = 0; + for (i = 1; i <= 16; i++) + start[i + 1] = start[i] + (count[i] << (16 - i)); + if (start[17] != (ushort) (1U << 16)) + return (1); /* error: bad table */ + + jutbits = 16 - tablebits; + for (i = 1; i <= tablebits; i++) + { + start[i] >>= jutbits; + weight[i] = 1U << (tablebits - i); + } + while (i <= 16) + weight[i++] = 1U << (16 - i); + + i = start[tablebits + 1] >> jutbits; + if (i != (ushort) (1U << 16)) + { + k = 1U << tablebits; + while (i != k) + table[i++] = 0; + } + + avail = nchar; + mask = 1U << (15 - tablebits); + for (ch = 0; ch < nchar; ch++) + { + if ((len = bitlen[ch]) == 0) + continue; + nextcode = start[len] + weight[len]; + if (len <= tablebits) + { + for (i = start[len]; i < nextcode; i++) + table[i] = ch; + } + else + { + k = start[len]; + p = &table[k >> jutbits]; + i = len - tablebits; + while (i != 0) + { + if (*p == 0) + { + right[avail] = left[avail] = 0; + *p = avail++; + } + if (k & mask) + p = &right[*p]; + else + p = &left[*p]; + k <<= 1; + i--; + } + *p = ch; + } + start[len] = nextcode; + } + return (0); +} + +/* + * huf.c + */ + +#define NP (DICBIT + 1) +#define NT (CODE_BIT + 3) +#define PBIT 4 /* smallest integer such that (1U << PBIT) > NP */ +#define TBIT 5 /* smallest integer such that (1U << TBIT) > NT */ +#if NT > NP + #define NPT NT +#else + #define NPT NP +#endif + +static uchar far c_len[NC], far pt_len[NPT]; +static uint blocksize; +static ushort far c_table[4096], far pt_table[256]; + +static void read_pt_len (int nn, int nbit, int i_special) +{ + int i, n; + short c; + ushort mask; + + n = getbits (nbit); + if (n == 0) + { + c = getbits (nbit); + for (i = 0; i < nn; i++) + pt_len[i] = 0; + for (i = 0; i < 256; i++) + pt_table[i] = c; + } + else + { + i = 0; + while (i < n) + { + c = bitbuf >> (BITBUFSIZ - 3); + if (c == 7) + { + mask = 1U << (BITBUFSIZ - 1 - 3); + while (mask & bitbuf) + { + mask >>= 1; + c++; + } + } + fillbuf ((c < 7) ? 3 : c - 3); + pt_len[i++] = c; + if (i == i_special) + { + c = getbits (2); + while (--c >= 0) + pt_len[i++] = 0; + } + } + while (i < nn) + pt_len[i++] = 0; + make_table (nn, pt_len, 8, pt_table); + } +} + +static void read_c_len (void) +{ + short i, c, n; + ushort mask; + + n = getbits (CBIT); + if (n == 0) + { + c = getbits (CBIT); + for (i = 0; i < NC; i++) + c_len[i] = 0; + for (i = 0; i < 4096; i++) + c_table[i] = c; + } + else + { + i = 0; + while (i < n) + { + c = pt_table[bitbuf >> (BITBUFSIZ - 8)]; + if (c >= NT) + { + mask = 1U << (BITBUFSIZ - 1 - 8); + do + { + if (bitbuf & mask) + c = right[c]; + else + c = left[c]; + mask >>= 1; + } while (c >= NT); + } + fillbuf (pt_len[c]); + if (c <= 2) + { + if (c == 0) + c = 1; + else if (c == 1) + c = getbits (4) + 3; + else + c = getbits (CBIT) + 20; + while (--c >= 0) + c_len[i++] = 0; + } + else + c_len[i++] = c - 2; + } + while (i < NC) + c_len[i++] = 0; + make_table (NC, c_len, 12, c_table); + } +} + +ushort decode_c (void) +{ + ushort j, mask; + + if (blocksize == 0) + { + blocksize = getbits (16); + read_pt_len (NT, TBIT, 3); + read_c_len (); + read_pt_len (NP, PBIT, -1); + } + blocksize--; + j = c_table[bitbuf >> (BITBUFSIZ - 12)]; + if (j >= NC) + { + mask = 1U << (BITBUFSIZ - 1 - 12); + do + { + if (bitbuf & mask) + j = right[j]; + else + j = left[j]; + mask >>= 1; + } + while (j >= NC); + } + fillbuf (c_len[j]); + return j; +} + +ushort decode_p (void) +{ + ushort j, mask; + + j = pt_table[bitbuf >> (BITBUFSIZ - 8)]; + if (j >= NP) + { + mask = 1U << (BITBUFSIZ - 1 - 8); + do + { + if (bitbuf & mask) + j = right[j]; + else + j = left[j]; + mask >>= 1; + } while (j >= NP); + } + fillbuf (pt_len[j]); + if (j != 0) + j = (1U << (j - 1)) + getbits (j - 1); + return j; +} + +void huf_decode_start (void) +{ + init_getbits (); + blocksize = 0; +} + +/* + * decode.c + */ + +static int decode_j; /* remaining bytes to copy */ + +static void decode_start (void) +{ + fillbufsize = 0; + huf_decode_start (); + decode_j = 0; +} + +/* + * The calling function must keep the number of bytes to be processed. This + * function decodes either 'count' bytes or 'DICSIZ' bytes, whichever is + * smaller, into the array 'buffer[]' of size 'DICSIZ' or more. Call + * decode_start() once for each new file before calling this function. + */ +static void decode (uint count, uchar buffer[]) +{ + static uint i; + uint r, c; + + r = 0; + while (--decode_j >= 0) + { + buffer[r] = buffer[i]; + i = (i + 1) & (DICSIZ - 1); + if (++r == count) + return; + } + for (;;) + { + c = decode_c (); + if (c <= UCHAR_MAX) + { + buffer[r] = c; + if (++r == count) + return; + } + else + { + decode_j = c - (UCHAR_MAX + 1 - THRESHOLD); + i = (r - decode_p () - 1) & (DICSIZ - 1); + while (--decode_j >= 0) + { + buffer[r] = buffer[i]; + i = (i + 1) & (DICSIZ - 1); + if (++r == count) + return; + } + } + } +} + +int lzh_melt (type_fnc_write pfnc_read, + type_fnc_read pfnc_write, + type_fnc_malloc pfnc_malloc, + type_fnc_free pfnc_free, + ulong origsize) +{ + int n; + uchar *outbuf; + + fnc_write = pfnc_write; + fnc_read = pfnc_read; + fnc_malloc = pfnc_malloc; + fnc_free = pfnc_free; + + with_error = 0; + + if ((buf = (uchar*)fnc_malloc (BUFSIZE)) == 0L) + return (1); + if ((outbuf = (uchar*)fnc_malloc (DICSIZ)) == 0L) + { + fnc_free (buf); + return (1); + } + + decode_start (); + while (origsize != 0) + { + n = (uint) ((origsize > DICSIZ) ? DICSIZ : origsize); + decode (n, outbuf); + if (with_error) + break; + + fnc_write (outbuf, n); + origsize -= n; + if (with_error) + break; + } + + fnc_free(outbuf); + fnc_free(buf); + + return (with_error ? 1 : 0); +} + +/* end of LZHXLib.C */ diff --git a/lib/stsound/StSoundLibrary/Makefile.in b/lib/stsound/StSoundLibrary/Makefile.in new file mode 100644 index 0000000000..6f0b5ed3e9 --- /dev/null +++ b/lib/stsound/StSoundLibrary/Makefile.in @@ -0,0 +1,30 @@ +ARCH=@ARCH@ + +CFLAGS +=-D_LINUX -fPIC +CXXFLAGS +=-D_LINUX -fPIC +ifeq ($(findstring osx,$(ARCH)), osx) + CFLAGS +=-D__linux__ + CXXFLAGS +=-D__linux__ +endif + +OBJS=Depacker.o \ + digidrum.o \ + LZH/lzhxlib.o \ + XBMCYM.o \ + Ym2149Ex.o \ + Ymload.o \ + YmMusic.o \ + YmUserInterface.o \ + +SLIB=@abs_top_srcdir@/system/players/paplayer/stsoundlibrary-@ARCH@.so + +$(SLIB): $(OBJS) +ifeq ($(findstring osx,$(ARCH)), osx) + ld -bundle -flat_namespace -undefined suppress -o $@ $(OBJS) $(BUNDLE1_O) + @abs_top_srcdir@/tools/Mach5/wrapper.rb $@;mv output.so $@ + chmod +x $@ +else + $(CXX) $(CXXFLAGS) $(LDFLAGS) -shared -o $@ $(OBJS) `cat @abs_top_srcdir@/xbmc/cores/DllLoader/exports/wrapper.def` @abs_top_srcdir@/xbmc/cores/DllLoader/exports/wrapper.o +endif + +include @abs_top_srcdir@/Makefile.include diff --git a/lib/stsound/StSoundLibrary/StSoundLibrary.h b/lib/stsound/StSoundLibrary/StSoundLibrary.h new file mode 100644 index 0000000000..c79f5431a6 --- /dev/null +++ b/lib/stsound/StSoundLibrary/StSoundLibrary.h @@ -0,0 +1,71 @@ +/*----------------------------------------------------------------------------- + + ST-Sound ( YM files player library ) + + Copyright (C) 1995-1999 Arnaud Carre ( http://leonard.oxg.free.fr ) + + Main header to use the StSound "C" like API in your production. + +-----------------------------------------------------------------------------*/ + +/*----------------------------------------------------------------------------- + + This file is part of ST-Sound + + ST-Sound is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + ST-Sound is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with ST-Sound; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +-----------------------------------------------------------------------------*/ + + +#ifndef __STSOUNDLIBRARY__ +#define __STSOUNDLIBRARY__ + +#include "YmTypes.h" + +typedef void YMMUSIC; + +typedef struct +{ + ymchar * pSongName; + ymchar * pSongAuthor; + ymchar * pSongComment; + ymchar * pSongType; + ymchar * pSongPlayer; + yms32 musicTimeInSec; +} ymMusicInfo_t; + +// Create object +extern YMMUSIC * ymMusicCreate(); + +// Release object +extern void ymMusicDestroy(YMMUSIC *pMusic); + +// Functions +extern ymbool ymMusicLoad(YMMUSIC *pMusic,const char *fName); +extern ymbool ymMusicLoadMemory(YMMUSIC *pMusic,void *pBlock,ymu32 size); +extern ymbool ymMusicCompute(YMMUSIC *pMusic,ymsample *pBuffer,ymint nbSample); +extern void ymMusicSetLoopMode(YMMUSIC *pMusic,ymbool bLoop); +extern const char * ymMusicGetLastError(YMMUSIC *pMusic); +extern int ymMusicGetRegister(YMMUSIC *pMusic,ymint reg); +extern void ymMusicGetInfo(YMMUSIC *pMusic,ymMusicInfo_t *pInfo); +extern void ymMusicPlay(YMMUSIC *pMusic); +extern void ymMusicPause(YMMUSIC *pMusic); +extern void ymMusicStop(YMMUSIC *pMusic); + +extern ymbool ymMusicIsSeekable(YMMUSIC *pMusic); +extern ymu32 ymMusicGetPos(YMMUSIC *pMusic); +extern void ymMusicSeek(YMMUSIC *pMusic,ymu32 timeInMs); + +#endif diff --git a/lib/stsound/StSoundLibrary/StSoundLibrary.vcproj b/lib/stsound/StSoundLibrary/StSoundLibrary.vcproj new file mode 100644 index 0000000000..ff6be2b62b --- /dev/null +++ b/lib/stsound/StSoundLibrary/StSoundLibrary.vcproj @@ -0,0 +1,407 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/lib/stsound/StSoundLibrary/StSoundLibrary.vcxproj b/lib/stsound/StSoundLibrary/StSoundLibrary.vcxproj new file mode 100644 index 0000000000..b7ae067d61 --- /dev/null +++ b/lib/stsound/StSoundLibrary/StSoundLibrary.vcxproj @@ -0,0 +1,215 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + libStSoundLibrary_dll + {D9885434-4B9D-41FB-B5FC-5E89D41AEFF0} + libStSoundLibrary_dll + + + + DynamicLibrary + false + MultiByte + + + DynamicLibrary + false + MultiByte + + + + + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30319.1 + $(SolutionDir)libs\$(TargetName)\$(Configuration)\ + $(SolutionDir)objs\$(TargetName)\$(Configuration)\ + $(SolutionDir)libs\$(TargetName)\$(Configuration)\ + $(SolutionDir)objs\$(TargetName)\$(Configuration)\ + StSoundLibrary + StSoundLibrary + Build + Build + + + + Disabled + ..\..\..\..\win32\;%(AdditionalIncludeDirectories) + WIN32;_DEBUG;_LIB;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + EnableFastChecks + MultiThreadedDebugDLL + + + .\Debug/StSoundLibrary.pch + $(Configuration)\vs2010\ + $(Configuration)\vs2010\ + $(Configuration)\vs2010\ + Level3 + true + ProgramDatabase + 4018;%(DisableSpecificWarnings) + + + _DEBUG;%(PreprocessorDefinitions) + 0x040c + + + $(OutDir)$(TargetName)$(TargetExt) + + + false + + + $(Configuration)\vs2010\$(TargetName).lib + + + + + + + copy /B /Y "$(TargetPath)" "$(SolutionDir)..\..\system\players\paplayer\$(TargetFileName)" + + + Copy output + + + $(SolutionDir)..\..\system\players\paplayer\$(TargetFileName) + $(TargetPath) + + + + + MaxSpeed + OnlyExplicitInline + ..\..\..\..\win32\;%(AdditionalIncludeDirectories) + WIN32;NDEBUG;_LIB;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + true + MultiThreadedDLL + true + + + .\Release/StSoundLibrary.pch + $(Configuration)\vs2010\ + $(Configuration)\vs2010\ + $(Configuration)\vs2010\ + Level3 + true + 4018;%(DisableSpecificWarnings) + + + NDEBUG;%(PreprocessorDefinitions) + 0x040c + + + $(OutDir)$(TargetName)$(TargetExt) + + + false + + + $(Configuration)\vs2010\$(TargetName).lib + + + + + + + copy /B /Y "$(TargetPath)" "$(SolutionDir)..\..\system\players\paplayer\$(TargetFileName)" + + + Copy output + + + $(SolutionDir)..\..\system\players\paplayer\$(TargetFileName) + $(TargetPath) + + + + + Disabled + %(PreprocessorDefinitions) + EnableFastChecks + MaxSpeed + %(PreprocessorDefinitions) + + + Disabled + %(PreprocessorDefinitions) + EnableFastChecks + MaxSpeed + %(PreprocessorDefinitions) + + + + Disabled + %(PreprocessorDefinitions) + EnableFastChecks + MaxSpeed + %(PreprocessorDefinitions) + + + Disabled + %(PreprocessorDefinitions) + EnableFastChecks + MaxSpeed + %(PreprocessorDefinitions) + + + Disabled + %(PreprocessorDefinitions) + EnableFastChecks + MaxSpeed + %(PreprocessorDefinitions) + + + Disabled + %(PreprocessorDefinitions) + EnableFastChecks + MaxSpeed + %(PreprocessorDefinitions) + + + Disabled + %(PreprocessorDefinitions) + EnableFastChecks + MaxSpeed + %(PreprocessorDefinitions) + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/lib/stsound/StSoundLibrary/StSoundLibrary.vcxproj.filters b/lib/stsound/StSoundLibrary/StSoundLibrary.vcxproj.filters new file mode 100644 index 0000000000..957cdc5d1b --- /dev/null +++ b/lib/stsound/StSoundLibrary/StSoundLibrary.vcxproj.filters @@ -0,0 +1,71 @@ + + + + + {d963d882-1c80-43af-8a68-d78c2f161582} + cpp;c;cxx;rc;def;r;odl;idl;hpj;bat + + + {c15018a6-d07e-4698-afb6-235c6ffb50a1} + + + {e230fcc5-dec0-4939-914c-a0153802d866} + h;hpp;hxx;hm;inl + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files\LZH + + + + + Source Files\LZH + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + + + + \ No newline at end of file diff --git a/lib/stsound/StSoundLibrary/XBMCYM.cpp b/lib/stsound/StSoundLibrary/XBMCYM.cpp new file mode 100644 index 0000000000..a85acf85c6 --- /dev/null +++ b/lib/stsound/StSoundLibrary/XBMCYM.cpp @@ -0,0 +1,96 @@ +/* + * Copyright (C) 2008-2010 Team XBMC + * http://www.xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ + +#include "StSoundLibrary.h" +#include "YmMusic.h" + +#include +#include + +#ifdef __linux__ +#define __declspec(x) +#endif + +extern "C" +{ + __declspec(dllexport) void* DLL_LoadYM(const char* szFileName) + { + YMMUSIC *pMusic = ymMusicCreate(); + + if (ymMusicLoad(pMusic,szFileName)) + { + ymMusicSetLoopMode(pMusic,YMFALSE); + ymMusicPlay(pMusic); + return pMusic; + } + + ymMusicDestroy(pMusic); + + return 0; + } + + void __declspec(dllexport) DLL_FreeYM(void* ym) + { + ymMusicStop((YMMUSIC*)ym); + ymMusicDestroy((YMMUSIC*)ym); + } + + int __declspec(dllexport) DLL_FillBuffer(void* ym, char* szBuffer, int iSize) + { + if (ymMusicCompute((YMMUSIC*)ym,(ymsample*)szBuffer,iSize/2)) + return iSize; + else + return 0; + } + + unsigned long __declspec(dllexport) DLL_Seek(void* ym, unsigned long timepos) + { + if (ymMusicIsSeekable((YMMUSIC*)ym)) + { + ymMusicSeek((YMMUSIC*)ym,timepos); + return timepos; + } + + return 0; + } + + const char __declspec(dllexport) *DLL_GetTitle(void* ym) + { + ymMusicInfo_t info; + ymMusicGetInfo((YMMUSIC*)ym,&info); + return info.pSongName; + } + + const char __declspec(dllexport) *DLL_GetArtist(void* ym) + { + ymMusicInfo_t info; + ymMusicGetInfo((YMMUSIC*)ym,&info); + return info.pSongAuthor; + } + + unsigned long __declspec(dllexport) DLL_GetLength(void* ym) + { + ymMusicInfo_t info; + ymMusicGetInfo((YMMUSIC*)ym,&info); + return info.musicTimeInSec; + } +} + diff --git a/lib/stsound/StSoundLibrary/Ym2149Ex.cpp b/lib/stsound/StSoundLibrary/Ym2149Ex.cpp new file mode 100644 index 0000000000..c8bf5f5686 --- /dev/null +++ b/lib/stsound/StSoundLibrary/Ym2149Ex.cpp @@ -0,0 +1,603 @@ +/*----------------------------------------------------------------------------- + + ST-Sound ( YM files player library ) + + Copyright (C) 1995-1999 Arnaud Carre ( http://leonard.oxg.free.fr ) + + Extended YM-2149 Emulator, with ATARI music demos effects. + (SID-Like, Digidrum, Sync Buzzer, Sinus SID and Pattern SID) + +-----------------------------------------------------------------------------*/ + +/*----------------------------------------------------------------------------- + + This file is part of ST-Sound + + ST-Sound is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + ST-Sound is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with ST-Sound; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +-----------------------------------------------------------------------------*/ + +#include "YmTypes.h" +#include +#include +#include +#include +#include "Ym2149Ex.h" + +//------------------------------------------------------------------- +// env shapes. +//------------------------------------------------------------------- +static const ymint Env00xx[8]={ 1,0,0,0,0,0,0,0 }; +static const ymint Env01xx[8]={ 0,1,0,0,0,0,0,0 }; +static const ymint Env1000[8]={ 1,0,1,0,1,0,1,0 }; +static const ymint Env1001[8]={ 1,0,0,0,0,0,0,0 }; +static const ymint Env1010[8]={ 1,0,0,1,1,0,0,1 }; +static const ymint Env1011[8]={ 1,0,1,1,1,1,1,1 }; +static const ymint Env1100[8]={ 0,1,0,1,0,1,0,1 }; +static const ymint Env1101[8]={ 0,1,1,1,1,1,1,1 }; +static const ymint Env1110[8]={ 0,1,1,0,0,1,1,0 }; +static const ymint Env1111[8]={ 0,1,0,0,0,0,0,0 }; +static const ymint * EnvWave[16] = { Env00xx,Env00xx,Env00xx,Env00xx, + Env01xx,Env01xx,Env01xx,Env01xx, + Env1000,Env1001,Env1010,Env1011, + Env1100,Env1101,Env1110,Env1111}; + +static ymint ymVolumeTable[16] = +{ 62,161,265,377,580,774,1155,1575,2260,3088,4570,6233,9330,13187,21220,32767}; + + +//---------------------------------------------------------------------- +// Very cool and fast DC Adjuster ! This is the *new* stuff of that +// package coz I get that idea working on SainT in 2004 ! +// ( almost everything here is from 1995 !) +//---------------------------------------------------------------------- +CDcAdjuster::CDcAdjuster() +{ + Reset(); +} + +void CDcAdjuster::Reset(void) +{ + for (ymint i=0;iinternalInputLen) + { + if (pInternalInput) free(pInternalInput); + pInternalInput = (ymsample*)malloc(len*sizeof(ymsample)); + internalInputLen = len; + } + memcpy(pInternalInput,pIn,len*sizeof(ymsample)); + return pInternalInput; +} + +#define DSP_FILTER(a,b,c) (((ymint)(a)+((ymint)b+(ymint)b)+(ymint)(c))>>2) + + +// Cheap but efficient low pass filter ( 0.25,0.5,0.25 ) +// filter: out -> out +void lowpFilterProcess(ymsample *pOut,ymint len) // private +{ +ymsample *pIn; +ymint i; + + pIn = getBufferCopy(pOut,len); + if (len>0) *pOut++ = DSP_FILTER(oldFilter[0],oldFilter[1],pIn[0]); + if (len>1) *pOut++ = DSP_FILTER(oldFilter[1],pIn[0],pIn[1]); + oldFilter[0] = pIn[len-2]; + oldFilter[1] = pIn[len-1]; + for (i=2;i>2)&1); + rndRack = (rndRack>>1) | (rBit<<16); + return (rBit ? 0 : 0xffff); +} + +ymu32 CYm2149Ex::envStepCompute(ymint rHigh,ymint rLow) +{ + + + ymint per = rHigh; + per = (per<<8)+rLow; + if (per<3) + return 0; + +#ifdef YM_INTEGER_ONLY + yms64 step = internalClock; + step <<= (16+16-9); + step /= (per * replayFrequency); +#else + ymfloat step = internalClock; + step /= ((ymfloat)per*512.0*(ymfloat)replayFrequency); + step *= 65536.0*65536.0; +#endif + + return (ymu32)step; +} + + +void CYm2149Ex::reset(void) +{ + writeRegister(7,0x3f); + writeRegister(8,0); + writeRegister(9,0); + writeRegister(10,0); + currentNoise = 0xffff; + rndRack = 1; + sidStop(0); + sidStop(1); + sidStop(2); + + envShape = 0; + envPhase = 0; + envPos = 0; + + m_dcAdjust.Reset(); + + memset(specialEffect,0,sizeof(specialEffect)); + + syncBuzzerStop(); + +} + + +void CYm2149Ex::sidVolumeCompute(ymint voice,ymint *pVol) +{ + + struct YmSpecialEffect *pVoice = specialEffect+voice; + + if (pVoice->bSid) + { + if (pVoice->sidPos & (1<<31)) + writeRegister(8+voice,pVoice->sidVol); + else + writeRegister(8+voice,0); + } + else if (pVoice->bDrum) + { +// writeRegister(8+voice,pVoice->drumData[pVoice->drumPos>>DRUM_PREC]>>4); + + *pVol = (pVoice->drumData[pVoice->drumPos>>DRUM_PREC] * 255) / 6; + + switch (voice) + { + case 0: + pVolA = &volA; + mixerTA = 0xffff; + mixerNA = 0xffff; + break; + case 1: + pVolB = &volB; + mixerTB = 0xffff; + mixerNB = 0xffff; + break; + case 2: + pVolC = &volC; + mixerTC = 0xffff; + mixerNC = 0xffff; + break; + } + + pVoice->drumPos += pVoice->drumStep; + if ((pVoice->drumPos>>DRUM_PREC) >= pVoice->drumSize) + { + pVoice->bDrum = YMFALSE; + } + + } +} + +ymsample CYm2149Ex::nextSample(void) +{ +ymint vol; +ymint bt,bn; + + if (noisePos&0xffff0000) + { + currentNoise ^= rndCompute(); + noisePos &= 0xffff; + } + bn = currentNoise; + + volE = ymVolumeTable[envData[envShape][envPhase][envPos>>(32-5)]]; + + sidVolumeCompute(0,&volA); + sidVolumeCompute(1,&volB); + sidVolumeCompute(2,&volC); + + //--------------------------------------------------- + // Tone+noise+env+DAC for three voices ! + //--------------------------------------------------- + bt = ((((yms32)posA)>>31) | mixerTA) & (bn | mixerNA); + vol = (*pVolA)&bt; + bt = ((((yms32)posB)>>31) | mixerTB) & (bn | mixerNB); + vol += (*pVolB)&bt; + bt = ((((yms32)posC)>>31) | mixerTC) & (bn | mixerNC); + vol += (*pVolC)&bt; + + //--------------------------------------------------- + // Inc + //--------------------------------------------------- + posA += stepA; + posB += stepB; + posC += stepC; + noisePos += noiseStep; + envPos += envStep; + if (0 == envPhase) + { + if (envPos=0) && (reg<=13)) return registers[reg]; + else return -1; +} + +void CYm2149Ex::writeRegister(ymint reg,ymint data) +{ + + switch (reg) + { + case 0: + registers[0] = data&255; + stepA = toneStepCompute(registers[1],registers[0]); + if (!stepA) posA = (1<<31); // Assume output always 1 if 0 period (for Digi-sample !) + break; + + case 2: + registers[2] = data&255; + stepB = toneStepCompute(registers[3],registers[2]); + if (!stepB) posB = (1<<31); // Assume output always 1 if 0 period (for Digi-sample !) + break; + + case 4: + registers[4] = data&255; + stepC = toneStepCompute(registers[5],registers[4]); + if (!stepC) posC = (1<<31); // Assume output always 1 if 0 period (for Digi-sample !) + break; + + case 1: + registers[1] = data&15; + stepA = toneStepCompute(registers[1],registers[0]); + if (!stepA) posA = (1<<31); // Assume output always 1 if 0 period (for Digi-sample !) + break; + + case 3: + registers[3] = data&15; + stepB = toneStepCompute(registers[3],registers[2]); + if (!stepB) posB = (1<<31); // Assume output always 1 if 0 period (for Digi-sample !) + break; + + case 5: + registers[5] = data&15; + stepC = toneStepCompute(registers[5],registers[4]); + if (!stepC) posC = (1<<31); // Assume output always 1 if 0 period (for Digi-sample !) + break; + + case 6: + registers[6] = data&0x1f; + noiseStep = noiseStepCompute(registers[6]); + if (!noiseStep) + { + noisePos = 0; + currentNoise = 0xffff; + } + break; + + case 7: + registers[7] = data&255; + mixerTA = (data&(1<<0)) ? 0xffff : 0; + mixerTB = (data&(1<<1)) ? 0xffff : 0; + mixerTC = (data&(1<<2)) ? 0xffff : 0; + mixerNA = (data&(1<<3)) ? 0xffff : 0; + mixerNB = (data&(1<<4)) ? 0xffff : 0; + mixerNC = (data&(1<<5)) ? 0xffff : 0; + break; + + case 8: + registers[8] = data&31; + volA = ymVolumeTable[data&15]; + if (data&0x10) + pVolA = &volE; + else + pVolA = &volA; + break; + + case 9: + registers[9] = data&31; + volB = ymVolumeTable[data&15]; + if (data&0x10) + pVolB = &volE; + else + pVolB = &volB; + break; + + case 10: + registers[10] = data&31; + volC = ymVolumeTable[data&15]; + if (data&0x10) + pVolC = &volE; + else + pVolC = &volC; + break; + + case 11: + registers[11] = data&255; + envStep = envStepCompute(registers[12],registers[11]); + break; + + case 12: + registers[12] = data&255; + envStep = envStepCompute(registers[12],registers[11]); + break; + + case 13: + registers[13] = data&0xf; + envPos = 0; + envPhase = 0; + envShape = data&0xf; + break; + + } +} + +void CYm2149Ex::update(ymsample *pSampleBuffer,ymint nbSample) +{ + + + ymsample *pBuffer = pSampleBuffer; + ymint nbs = nbSample; + + + if (nbSample>0) + { + do + { + *pSampleBuffer++ = nextSample(); + } + while (--nbSample); + } + + lowpFilterProcess((ymsample*)pBuffer,nbs); + +} + +void CYm2149Ex::drumStart(ymint voice,ymu8 *pDrumBuffer,ymu32 drumSize,ymint drumFreq) +{ + specialEffect[voice].drumData = pDrumBuffer; + specialEffect[voice].drumPos = 0; + specialEffect[voice].drumSize = drumSize; + specialEffect[voice].drumStep = (drumFreq< +#include +#include "YmMusic.h" + +#define _LINEAR_OVRS // Activate linear oversampling (best quality) Only used for DigiMix and UniversalTracker YM file type + + +// ATARI-ST MFP chip predivisor +static const ymint mfpPrediv[8] = {0,4,10,16,50,64,100,200}; + + + +CYmMusic::CYmMusic(ymint _replayRate) +{ + + pBigMalloc = NULL; + pSongName = NULL; + pSongAuthor = NULL; + pSongComment = NULL; + pSongType = NULL; + pSongPlayer = NULL; + + pBigSampleBuffer = NULL; + pMixBlock = NULL; + + replayRate = _replayRate; + innerSamplePos = 0; + nbDrum = 0; + pDrumTab = NULL; + setLoopMode(YMFALSE); +} + +void CYmMusic::setTimeControl(ymbool bTime) +{ + if (bTime) + attrib |= A_TIMECONTROL; + else + attrib &= (~A_TIMECONTROL); +} + +CYmMusic::~CYmMusic() +{ + stop(); + unLoad(); +} + +void CYmMusic::setLoopMode(ymbool bLoopMode) +{ + bLoop = bLoopMode; +} + +void CYmMusic::setPlayerRate(ymint rate) +{ + playerRate = rate; +} + +ymu32 CYmMusic::getPos() +{ + if (!isSeekable()) return 0; + if ((nbFrame>0) && (playerRate>0)) + { + return ((ymu32)currentFrame*1000)/(ymu32)playerRate; + } + else + return 0; + +} + +ymu32 CYmMusic::getMusicTime(void) +{ + if ((nbFrame>0) && (playerRate>0)) + { + return ((ymu32)nbFrame*1000)/(ymu32)playerRate; + } + else + return 0; + +} + +ymu32 CYmMusic::setMusicTime(ymu32 time) +{ + if (!isSeekable()) return 0; + ymu32 newTime = 0; + + if ((songType>=YM_V2) && (songType=getMusicTime()) newTime = 0; + currentFrame = (newTime*(ymu32)playerRate)/1000; + } + else if ((songType>=YM_TRACKER1) && (songType=getMusicTime()) newTime = 0; + currentFrame = (newTime*(ymu32)playerRate)/1000; + } + + return newTime; +} + +void CYmMusic::getMusicInfo(ymMusicInfo_t *pInfo) +{ + if (pInfo) + { + pInfo->pSongName = pSongName; + pInfo->pSongAuthor = pSongAuthor; + pInfo->pSongComment = pSongComment; + pInfo->pSongType = pSongType; + pInfo->pSongPlayer = pSongPlayer; + + if (playerRate>0) + pInfo->musicTimeInSec = (ymu32)nbFrame/(ymu32)playerRate; + else + pInfo->musicTimeInSec = 0; + } +} + + +void CYmMusic::setAttrib(ymint _attrib) +{ + attrib = _attrib; +} + +ymint CYmMusic::getAttrib(void) +{ + return attrib; +} + +ymbool CYmMusic::isSeekable(void) +{ + return getAttrib()&A_TIMECONTROL; +} + +void CYmMusic::setLastError(char *pError) +{ + pLastError = pError; +} + +char *CYmMusic::getLastError(void) +{ + return pLastError; +} + +void bufferClear(ymsample *pBuffer,ymint nbSample) +{ + memset((void*)pBuffer,0,nbSample*sizeof(ymsample)); +} + +ymbool CYmMusic::update(ymsample *sampleBuffer,ymint nbSample) +{ +ymint sampleToCompute; +ymint vblNbSample; + + + if ((!bMusicOk) || + (bPause) || + (bMusicOver)) + { + bufferClear(sampleBuffer,nbSample); + if (bMusicOver) + return YMFALSE; + else + return YMTRUE; + } + + if ((songType >= YM_MIX1) && (songType < YM_MIXMAX)) + { + stDigitMix(sampleBuffer,nbSample); + } + else if ((songType >= YM_TRACKER1) && (songTypenbs) sampleToCompute = nbs; + innerSamplePos += sampleToCompute; + if (innerSamplePos>=vblNbSample) + { + player(); // Lecture de la partition (playerRate Hz) + innerSamplePos -= vblNbSample; + } + if (sampleToCompute>0) + { + ymChip.update(pOut,sampleToCompute); // YM Emulation. + pOut += sampleToCompute; + } + nbs -= sampleToCompute; + } + while (nbs>0); + } + + + return YMTRUE; +} + + + +void CYmMusic::readYm6Effect(unsigned char *pReg,ymint code,ymint prediv,ymint count) +{ +ymint voice; +ymint ndrum; + + code = pReg[code]&0xf0; + prediv = (pReg[prediv]>>5)&7; + count = pReg[count]; + + if (code&0x30) + { + ymu32 tmpFreq; + // Ici il y a un effet sur la voie: + + voice = ((code&0x30)>>4)-1; + switch (code&0xc0) + { + case 0x00: // SID + case 0x80: // Sinus-SID + + prediv = mfpPrediv[prediv]; + prediv *= count; + tmpFreq = 0; + if (prediv) + { + tmpFreq = 2457600L / prediv; + if ((code&0xc0)==0x00) + ymChip.sidStart(voice,tmpFreq,pReg[voice+8]&15); + else + ymChip.sidSinStart(voice,tmpFreq,pReg[voice+8]&15); + } + break; + + case 0x40: // DigiDrum + ndrum = pReg[voice+8]&31; + if ((ndrum>=0) && (ndrum0) + { + tmpFreq = 2457600L / prediv; + ymChip.drumStart(voice,pDrumTab[ndrum].pData,pDrumTab[ndrum].size,tmpFreq); + } + } + break; + + case 0xc0: // Sync-Buzzer. + + prediv = mfpPrediv[prediv]; + prediv *= count; + tmpFreq = 0; + if (prediv) + { + tmpFreq = 2457600L / prediv; + ymChip.syncBuzzerStart(tmpFreq,pReg[voice+8]&15); + } + break; + + + } + + } +} + +void CYmMusic::setVolume(ymint volume) +{ +// ymChip.setGlobalVolume(volume); +} + +void CYmMusic::player(void) + { + ymu8 *ptr; + ymu32 prediv; + ymint voice; + ymint ndrum; + + + if (currentFrame<0) currentFrame = 0; + + if (currentFrame>=nbFrame) + { + if (bLoop) + { + currentFrame = loopFrame; + } + else + { + bMusicOver = YMTRUE; + ymChip.reset(); + return; + } + } + + ptr = pDataStream+currentFrame*streamInc; + + for (ymint i=0;i<=10;i++) + ymChip.writeRegister(i,ptr[i]); + + ymChip.sidStop(0); + ymChip.sidStop(1); + ymChip.sidStop(2); + ymChip.syncBuzzerStop(); + + //--------------------------------------------- + // Check digi-drum + //--------------------------------------------- + if (songType == YM_V2) // MADMAX specific ! + { + if (ptr[13]!=0xff) + { + ymChip.writeRegister(11,ptr[11]); + ymChip.writeRegister(12,0); + ymChip.writeRegister(13,10); // MADMAX specific !! + } + if (ptr[10]&0x80) // bit 7 volume canal C pour annoncer une digi-drum madmax. + { + ymint sampleNum; + ymu32 sampleFrq; + ymChip.writeRegister(7,ymChip.readRegister(7)|0x24) ; // Coupe TONE + NOISE canal C. + sampleNum = ptr[10]&0x7f; // Numero du sample + + if (ptr[12]) + { + sampleFrq = (MFP_CLOCK / ptr[12]); + ymChip.drumStart( 2, // Voice C + sampleAdress[sampleNum], + sampleLen[sampleNum], + sampleFrq); + } + } + } + else if (songType >= YM_V3) + { + ymChip.writeRegister(11,ptr[11]); + ymChip.writeRegister(12,ptr[12]); + if (ptr[13]!=0xff) + { + ymChip.writeRegister(13,ptr[13]); + } + + if (songType >= YM_V5) + { + ymint code; + + if (songType == YM_V6) + { + readYm6Effect(ptr,1,6,14); + readYm6Effect(ptr,3,8,15); + } + else + { // YM5 effect decoding + + //------------------------------------------------------ + // Sid Voice !! + //------------------------------------------------------ + code = (ptr[1]>>4)&3; + if (code!=0) + { + ymu32 tmpFreq; + voice = code-1; + prediv = mfpPrediv[(ptr[6]>>5)&7]; + prediv *= ptr[14]; + tmpFreq = 0; + if (prediv) + { + tmpFreq = 2457600L / prediv; + ymChip.sidStart(voice,tmpFreq,ptr[voice+8]&15); + } + } + + //------------------------------------------------------ + // YM5 Digi Drum. + //------------------------------------------------------ + code = (ptr[3]>>4)&3; + if (code!=0) + { // Ici un digidrum demarre sur la voie voice. + voice = code-1; + ndrum = ptr[8+voice]&31; + if ((ndrum>=0) && (ndrum>5)&7]; + prediv *= ptr[15]; + if (prediv) + { + sampleFrq = MFP_CLOCK / prediv; + ymChip.drumStart(voice,pDrumTab[ndrum].pData,pDrumTab[ndrum].size,sampleFrq); + } + } + } + } + } + } + currentFrame++; + } + +/* + + x x x x x x x x r0 + 0 0 0 0 x x x x r1 // Special FX 1a + x x x x x x x x r2 + 0 0 0 0 x x x x r3 // Special FX 2a + x x x x x x x x r4 + 0 0 0 0 x x x x r5 + 0 0 0 x x x x x r6 // Special FX 1b + 0 0 x x x x x x r7 + 0 0 0 x x x x x r8 // Special FX 2b + 0 0 0 x x x x x r9 + 0 0 0 x x x x x r10 + x x x x x x x x r11 + x x x x x x x x r12 + 0 0 0 0 x x x x r13 + 0 0 0 0 0 0 0 0 r14 // Special FX 1c + 0 0 0 0 0 0 0 0 r15 // Special FX 2c + + + Special Fx ?a + 0 0 0 0 : No special FX running + 0 0 0 1 : Sid Voice A + 0 0 1 0 : Sid Voice B + 0 0 1 1 : Sid Voice C + 0 1 0 0 : Extended Fx voice A + 0 1 0 1 : Digidrum voice A + 0 1 1 0 : Digidrum voice B + 0 1 1 1 : Digidrum voice C + 1 0 0 0 : Extended Fx voice B + 1 0 0 1 : Sinus SID voice A + 1 0 1 0 : Sinus SID voice B + 1 0 1 1 : Sinus SID voice C + 1 1 0 0 : Extended Fx voice C + 1 1 0 1 : Sync Buzzer voice A + 1 1 1 0 : Sync Buzzer voice B + 1 1 1 1 : Sync Buzzer voice C + + + +*/ + +void CYmMusic::readNextBlockInfo(void) +{ + nbRepeat--; + if (nbRepeat<=0) + { + mixPos++; + if (mixPos >= nbMixBlock) + { + mixPos = 0; + if (!bLoop) bMusicOver = YMTRUE; + } + nbRepeat = pMixBlock[mixPos].nbRepeat; + } + pCurrentMixSample = pBigSampleBuffer + pMixBlock[mixPos].sampleStart; + currentSampleLength = (pMixBlock[mixPos].sampleLength)<<12; + currentPente = (((ymu32)pMixBlock[mixPos].replayFreq)<<12) / PC_DAC_FREQ; + currentPos &= ((1<<12)-1); +} + +void CYmMusic::stDigitMix(ymsample *pWrite16,ymint nbs) +{ + + + if (bMusicOver) return; + + if (mixPos == -1) + { + nbRepeat = -1; + readNextBlockInfo(); + } + + if (nbs) do + { + + ymint sa = (ymint)(ymsample)(pCurrentMixSample[currentPos>>12]<<8); +#ifdef _LINEAR_OVRS + ymint sb = sa; + if ((currentPos>>12)<((currentSampleLength>>12)-1)) + sb = (ymint)(ymsample)(pCurrentMixSample[(currentPos>>12)+1]<<8); + ymint frac = currentPos&((1<<12)-1); + sa += (((sb-sa)*frac)>>12); +#endif + *pWrite16++ = sa; + + currentPos += currentPente; + if (currentPos>=currentSampleLength) + { + readNextBlockInfo(); + if (bMusicOver) return; + } + } + while (--nbs); +} + +void CYmMusic::ymTrackerDesInterleave(void) +{ +unsigned char *a0,*a1,*a2; +unsigned char *pNewBuffer; +ymint step; +ymu32 n1,n2; + + + if (attrib&A_STREAMINTERLEAVED) + { + a0 = pDataStream; + ymint size = sizeof(ymTrackerLine_t)*nbVoice*nbFrame; + pNewBuffer = (unsigned char*)malloc(size); + step = sizeof(ymTrackerLine_t)*nbVoice; + n1 = step; + a2 = pNewBuffer; + do + { + n2 = nbFrame; + a1 = a2; + do + { + *a1 = *a0++; + a1 += step; + } + while (--n2); + a2++; + } + while (--n1); + memcpy(pDataStream,pNewBuffer,size); + free(pNewBuffer); + attrib &= (~A_STREAMINTERLEAVED); + } +} + + +void CYmMusic::ymTrackerInit(ymint volMaxPercent) +{ +ymint i,s; +ymint vol; +ymint scale; +ymsample *pTab; + + + + for (i=0;ifreqHigh<<8) | pLine->freqLow; + if (pVoice[i].sampleFreq) + { + pVoice[i].sampleVolume = pLine->volume&63; + pVoice[i].bLoop = (pLine->volume&0x40); + n = pLine->noteOn; + if (n != 0xff) // Note ON. + { + pVoice[i].bRunning = 1; + pVoice[i].pSample = pDrumTab[n].pData; + pVoice[i].sampleSize = pDrumTab[n].size; + pVoice[i].repLen = pDrumTab[n].repLen; + pVoice[i].samplePos = 0; + } + } + else + { + pVoice[i].bRunning = 0; + } + pLine++; + } + + currentFrame++; + if (currentFrame >= nbFrame) + { + if (!bLoop) + { + bMusicOver = YMTRUE; + } + currentFrame = 0; + } +} + + +void CYmMusic::ymTrackerVoiceAdd(ymTrackerVoice_t *pVoice,ymsample *pBuffer,ymint nbs) +{ +ymsample *pVolumeTab; +ymu8 *pSample; +ymu32 samplePos; +ymu32 sampleEnd; +ymu32 sampleInc; +ymu32 repLen; +double step; + + + if (!(pVoice->bRunning)) return; + + pVolumeTab = &ymTrackerVolumeTable[256*(pVoice->sampleVolume&63)]; + pSample = pVoice->pSample; + samplePos = pVoice->samplePos; + + step = (double)(pVoice->sampleFreq<sampleSize<repLen<0) do + { + ymint va = pVolumeTab[pSample[samplePos>>YMTPREC]]; +#ifdef _LINEAR_OVRS + ymint vb = va; + if (samplePos < (sampleEnd-(1<>YMTPREC)+1]]; + ymint frac = samplePos & ((1<>YMTPREC); +#endif + (*pBuffer++) += va; + + samplePos += sampleInc; + if (samplePos>=sampleEnd) + { + if (pVoice->bLoop) + { + samplePos -= repLen; + } + else + { + pVoice->bRunning = 0; + return; + } + } + } + while (--nbs); + pVoice->samplePos = samplePos; +} + +void CYmMusic::ymTrackerUpdate(ymsample *pBuffer,ymint nbSample) +{ +ymint i; +ymint _nbs; + + // Clear les buffers. + memset(pBuffer,0,sizeof(ymsample)*nbSample); + if (bMusicOver) return; + + do + { + if (ymTrackerNbSampleBefore == 0) + { + // Lit la partition ymTracker + ymTrackerPlayer(ymTrackerVoice); + if (bMusicOver) return; + ymTrackerNbSampleBefore = YMTNBSRATE; + } + _nbs = ymTrackerNbSampleBefore; // nb avant playerUpdate. + if (_nbs>nbSample) _nbs = nbSample; + ymTrackerNbSampleBefore -= _nbs; + if (_nbs>0) + { + // Genere les samples. + for (i=0;i0); +} diff --git a/lib/stsound/StSoundLibrary/YmMusic.h b/lib/stsound/StSoundLibrary/YmMusic.h new file mode 100644 index 0000000000..cb59af39d5 --- /dev/null +++ b/lib/stsound/StSoundLibrary/YmMusic.h @@ -0,0 +1,261 @@ +/*----------------------------------------------------------------------------- + + ST-Sound ( YM files player library ) + + Copyright (C) 1995-1999 Arnaud Carre ( http://leonard.oxg.free.fr ) + + YM Music Driver + +-----------------------------------------------------------------------------*/ + +/*----------------------------------------------------------------------------- + + This file is part of ST-Sound + + ST-Sound is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + ST-Sound is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with ST-Sound; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +-----------------------------------------------------------------------------*/ + + +#ifndef __YMMUSIC__ +#define __YMMUSIC__ + +#include "YmTypes.h" +#include "StSoundLibrary.h" +#include "Ym2149Ex.h" +#include "Ymload.h" +#include "digidrum.h" + +#define MAX_DIGIDRUM 128 + +#define YMTPREC 16 +#define MAX_VOICE 8 +#define PC_DAC_FREQ 44100 +#define YMTNBSRATE (PC_DAC_FREQ/50) + +typedef enum +{ + YM_V2, + YM_V3, + YM_V4, + YM_V5, + YM_V6, + YM_VMAX, + + YM_TRACKER1=32, + YM_TRACKER2, + YM_TRACKERMAX, + + YM_MIX1=64, + YM_MIX2, + YM_MIXMAX, +} ymFile_t; + +typedef struct +{ + ymu32 sampleStart; + ymu32 sampleLength; + ymu16 nbRepeat; + ymu16 replayFreq; +} mixBlock_t; + +typedef struct +{ + ymu32 size; + ymu8 * pData; + ymu32 repLen; +} digiDrum_t; + +typedef struct +{ + ymint nbVoice; + ymu32 nbVbl; + ymu8 * pDataBufer; + ymu32 currentVbl; + ymu32 flags; + ymbool bLoop; +} ymTrackerPartoche_t; + + +typedef struct +{ + ymu8 * pSample; + ymu32 sampleSize; + ymu32 samplePos; + ymu32 repLen; + yms32 sampleVolume; + ymu32 sampleFreq; + ymbool bLoop; + ymbool bRunning; +} ymTrackerVoice_t; + +typedef struct +{ + ymu8 noteOn; + ymu8 volume; + ymu8 freqHigh; + ymu8 freqLow; +} ymTrackerLine_t; + + +enum +{ + A_STREAMINTERLEAVED = 1, + A_DRUMSIGNED = 2, + A_DRUM4BITS = 4, + A_TIMECONTROL = 8, + A_LOOPMODE = 16, +}; + + +class CYmMusic +{ + +public: + CYmMusic(ymint _replayRate=44100); + ~CYmMusic(); + + ymbool load(const char *pName); + ymbool loadMemory(void *pBlock,ymu32 size); + + void unLoad(void); + ymbool isSeekable(void); + ymbool update(ymsample *pBuffer,ymint nbSample); + ymu32 getPos(void); + ymu32 getMusicTime(void); + ymu32 setMusicTime(ymu32 time); + void play(void); + void pause(void); + void stop(void); + void setVolume(ymint volume); + int getAttrib(void); + void getMusicInfo(ymMusicInfo_t *pInfo); + void setLoopMode(ymbool bLoop); + char *getLastError(void); + int readYmRegister(ymint reg) { return ymChip.readRegister(reg); } + +//------------------------------------------------------------- +// WAVE Generator +//------------------------------------------------------------- + int waveCreate(char *fName); + + ymbool bMusicOver; + +private: + + ymbool checkCompilerTypes(); + + void setPlayerRate(int rate); + void setAttrib(int _attrib); + void setLastError(char *pError); + ymu8 *depackFile(void); + ymbool deInterleave(void); + void readYm6Effect(ymu8 *pReg,int code,int prediv,int count); + void player(void); + void setTimeControl(ymbool bFlag); + + + CYm2149Ex ymChip; + char *pLastError; + ymFile_t songType; + int nbFrame; + int loopFrame; + int currentFrame; + int nbDrum; + digiDrum_t *pDrumTab; + int musicTime; + ymu8 *pBigMalloc; + ymu8 *pDataStream; + ymbool bLoop; + ymint fileSize; + ymbool ymDecode(void); + ymint playerRate; + ymint attrib; + volatile ymbool bMusicOk; + volatile ymbool bPause; + ymint streamInc; + ymint innerSamplePos; + ymint replayRate; + + ymchar *pSongName; + ymchar *pSongAuthor; + ymchar *pSongComment; + ymchar *pSongType; + ymchar *pSongPlayer; + +//------------------------------------------------------------- +// ATARI Digi Mix Music. +//------------------------------------------------------------- + void readNextBlockInfo(void); + void stDigitMix(signed short *pWrite16,int nbs); + ymint nbRepeat; + ymint nbMixBlock; + mixBlock_t *pMixBlock; + ymint mixPos; + ymu8 *pBigSampleBuffer; + ymu8 *pCurrentMixSample; + ymu32 currentSampleLength; + ymu32 currentPente; + ymu32 currentPos; + +//------------------------------------------------------------- +// YM-Universal-Tracker +//------------------------------------------------------------- + void ymTrackerInit(int volMaxPercent); + void ymTrackerUpdate(signed short *pBuffer,int nbSample); + void ymTrackerDesInterleave(void); + void ymTrackerPlayer(ymTrackerVoice_t *pVoice); + void ymTrackerVoiceAdd(ymTrackerVoice_t *pVoice,signed short *pBuffer,int nbs); + + int nbVoice; + ymTrackerVoice_t ymTrackerVoice[MAX_VOICE]; + int ymTrackerNbSampleBefore; + signed short ymTrackerVolumeTable[256*64]; + int ymTrackerFreqShift; + + +}; + +/* + int version; + SD pos; + UD inc; + UD timeSec; + UD timeMin; + UD loopSec; + UD loopMin; + UD nbVbl; + UD vblRestart; + UD ymFreq; + UD playerFreq; + UB *pRegister; + UB *pFileBuffer; + UD fileSize; + UD attrib; + char *pSongName; + char *pSongComment; + char *pSongAuthor; + mixBlock_t *pMixBlock; + long nbMixBlock; + UD nbDrum; + digiDrum_t *pDrumTab; + int nbVoice; + ymu32 currentVbl; + int bTimeControl; + int timeTotal; + int ymtFreqShift; +*/ + +#endif diff --git a/lib/stsound/StSoundLibrary/YmTypes.h b/lib/stsound/StSoundLibrary/YmTypes.h new file mode 100644 index 0000000000..90b89831d9 --- /dev/null +++ b/lib/stsound/StSoundLibrary/YmTypes.h @@ -0,0 +1,91 @@ +/*----------------------------------------------------------------------------- + + ST-Sound ( YM files player library ) + + Copyright (C) 1995-1999 Arnaud Carre ( http://leonard.oxg.free.fr ) + + Define YM types for multi-platform compilcation. + Change that file depending of your platform. Please respect the right size + for each type. + +-----------------------------------------------------------------------------*/ + +/*----------------------------------------------------------------------------- + + This file is part of ST-Sound + + ST-Sound is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + ST-Sound is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with ST-Sound; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +-----------------------------------------------------------------------------*/ + +#ifndef __YMTYPES__ +#define __YMTYPES__ + +#define YM_INTEGER_ONLY + +//----------------------------------------------------------- +// Platform specific stuff +//----------------------------------------------------------- + +#if defined(_WIN32) || defined(__linux__) + +// These settings are ok for Windows 32bits platform. + +#ifdef YM_INTEGER_ONLY +#ifdef __linux__ +#include +typedef int64_t yms64; +#else +typedef __int64 yms64; +#endif +#else +typedef float ymfloat; +#endif + +typedef signed char yms8; // 8 bits signed integer +typedef signed short yms16; // 16 bits signed integer +typedef signed long yms32; // 32 bits signed integer + +typedef unsigned char ymu8; // 8 bits unsigned integer +typedef unsigned short ymu16; // 16 bits unsigned integer +typedef unsigned long ymu32; // 32 bits unsigned integer + +typedef int ymint; // Native "int" for speed purpose. StSound suppose int is signed and at least 32bits. If not, change it to match to yms32 + +typedef char ymchar; // 8 bits char character (used for null terminated strings) + +#else + + fail + + Please make the right definition for your platform ( for 8,16,32 signed and unsigned integer) + +#endif + +#ifndef NULL +#define NULL (0L) +#endif + +//----------------------------------------------------------- +// Multi-platform +//----------------------------------------------------------- +typedef int ymbool; // boolean ( theorically nothing is assumed for its size in StSound,so keep using int) +typedef yms16 ymsample; // StSound emulator render mono 16bits signed PCM samples + +#define YMFALSE (0) +#define YMTRUE (!YMFALSE) + +#endif + diff --git a/lib/stsound/StSoundLibrary/YmUserInterface.cpp b/lib/stsound/StSoundLibrary/YmUserInterface.cpp new file mode 100644 index 0000000000..14f26e9a74 --- /dev/null +++ b/lib/stsound/StSoundLibrary/YmUserInterface.cpp @@ -0,0 +1,132 @@ +/*----------------------------------------------------------------------------- + + ST-Sound ( YM files player library ) + + Copyright (C) 1995-1999 Arnaud Carre ( http://leonard.oxg.free.fr ) + + ST-Sound library "C-like" interface wrapper + +-----------------------------------------------------------------------------*/ + +/*----------------------------------------------------------------------------- + + This file is part of ST-Sound + + ST-Sound is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + ST-Sound is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with ST-Sound; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +-----------------------------------------------------------------------------*/ + + +#include "YmMusic.h" +#include "StSoundLibrary.h" + + +// Static assert to check various type len + +YMMUSIC * ymMusicCreate() +{ + return (YMMUSIC*)(new CYmMusic); +} + + +ymbool ymMusicLoad(YMMUSIC *pMus,const char *fName) +{ + CYmMusic *pMusic = (CYmMusic*)pMus; + return pMusic->load(fName); +} + +ymbool ymMusicLoadMemory(YMMUSIC *pMus,void *pBlock,ymu32 size) +{ + CYmMusic *pMusic = (CYmMusic*)pMus; + return pMusic->loadMemory(pBlock,size); +} + +void ymMusicDestroy(YMMUSIC *pMus) +{ + CYmMusic *pMusic = (CYmMusic*)pMus; + delete pMusic; +} + +ymbool ymMusicCompute(YMMUSIC *_pMus,ymsample *pBuffer,int nbSample) +{ + CYmMusic *pMusic = (CYmMusic*)_pMus; + return pMusic->update(pBuffer,nbSample); +} + +void ymMusicSetLoopMode(YMMUSIC *_pMus,ymbool bLoop) +{ + CYmMusic *pMusic = (CYmMusic*)_pMus; + pMusic->setLoopMode(bLoop); +} + +const char *ymMusicGetLastError(YMMUSIC *_pMus) +{ + CYmMusic *pMusic = (CYmMusic*)_pMus; + return pMusic->getLastError(); +} + +int ymMusicGetRegister(YMMUSIC *_pMus,ymint reg) +{ + CYmMusic *pMusic = (CYmMusic*)_pMus; + return pMusic->readYmRegister(reg); +} + +void ymMusicGetInfo(YMMUSIC *_pMus,ymMusicInfo_t *pInfo) +{ + CYmMusic *pMusic = (CYmMusic*)_pMus; + pMusic->getMusicInfo(pInfo); +} + +void ymMusicPlay(YMMUSIC *_pMus) +{ + CYmMusic *pMusic = (CYmMusic*)_pMus; + pMusic->play(); +} + +void ymMusicPause(YMMUSIC *_pMus) +{ + CYmMusic *pMusic = (CYmMusic*)_pMus; + pMusic->pause(); +} + +void ymMusicStop(YMMUSIC *_pMus) +{ + CYmMusic *pMusic = (CYmMusic*)_pMus; + pMusic->stop(); +} + +ymbool ymMusicIsSeekable(YMMUSIC *_pMus) +{ + CYmMusic *pMusic = (CYmMusic*)_pMus; + return pMusic->isSeekable() ? YMTRUE : YMFALSE; +} + +unsigned long ymMusicGetPos(YMMUSIC *_pMus) +{ + CYmMusic *pMusic = (CYmMusic*)_pMus; + if (!pMusic->isSeekable()) + return 0; + + return pMusic->getPos(); +} + +void ymMusicSeek(YMMUSIC *_pMus,ymu32 timeInMs) +{ + CYmMusic *pMusic = (CYmMusic*)_pMus; + if (pMusic->isSeekable()) + { + pMusic->setMusicTime(timeInMs); + } +} diff --git a/lib/stsound/StSoundLibrary/Ymload.cpp b/lib/stsound/StSoundLibrary/Ymload.cpp new file mode 100644 index 0000000000..87b6bc5455 --- /dev/null +++ b/lib/stsound/StSoundLibrary/Ymload.cpp @@ -0,0 +1,690 @@ +/*----------------------------------------------------------------------------- + + ST-Sound ( YM files player library ) + + Copyright (C) 1995-1999 Arnaud Carre ( http://leonard.oxg.free.fr ) + + Manage YM file depacking and parsing + +-----------------------------------------------------------------------------*/ + +/*----------------------------------------------------------------------------- + + This file is part of ST-Sound + + ST-Sound is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + ST-Sound is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with ST-Sound; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +-----------------------------------------------------------------------------*/ + +#include +#include +#include +#include "YmMusic.h" +#include "Depacker.h" + +static ymu16 ymVolumeTable[16] = +{ 62,161,265,377,580,774,1155,1575,2260,3088,4570,6233,9330,13187,21220,32767}; + + +static void signeSample(ymu8 *ptr,yms32 size) +{ + + if (size>0) + { + do + { + *ptr++ ^= 0x80; + } + while (--size); + } +} + +char *mstrdup(char *in) +{ + char *out = (char*)malloc(strlen(in)+1); + if (out) strcpy(out,in); + return out; +} + +ymu32 readMotorolaDword(ymu8 **ptr) +{ +ymu32 n; +ymu8 *p = *ptr; + + n = (p[0]<<24)|(p[1]<<16)|(p[2]<<8)|p[3]; + p+=4; + *ptr = p; + return n; +} + +ymu16 readMotorolaWord(ymu8 **ptr) +{ +ymu16 n; +ymu8 *p = *ptr; + + n = (p[0]<<8)|p[1]; + p+=2; + *ptr = p; + return n; +} + +ymchar *readNtString(ymchar **ptr) +{ +ymchar *p; + + p = mstrdup(*ptr); + (*ptr) += strlen(*ptr)+1; + return p; +} + +yms32 ReadLittleEndian32(ymu8 *pLittle) +{ + yms32 v = ( (pLittle[0]<<0) | + (pLittle[1]<<8) | + (pLittle[2]<<16) | + (pLittle[3]<<24)); + + return v; +} + +yms32 ReadBigEndian32(ymu8 *pBig) +{ + yms32 v = ( (pBig[0]<<24) | + (pBig[1]<<16) | + (pBig[2]<<8) | + (pBig[3]<<0)); + + return v; +} + +unsigned char *CYmMusic::depackFile(void) + { + lzhHeader_t *pHeader; + ymu8 *pNew; + ymu8 *pSrc; + + pHeader = (lzhHeader_t*)pBigMalloc; + if ((pHeader->size==0) || // NOTE: Endianness works because value is 0 + (strncmp(pHeader->id,"-lh5-",5))) + { // Le fichier n'est pas compresse, on retourne l'original. + return pBigMalloc; + } + + fileSize = (ymu32)-1; + + if (pHeader->level != 0) // NOTE: Endianness works because value is 0 + { // Compression LH5, header !=0 : Error. + free(pBigMalloc); + pBigMalloc = NULL; + setLastError("LHARC Header must be 0 !"); + return NULL; + } + + fileSize = ReadLittleEndian32((ymu8*)&pHeader->original); + pNew = (ymu8*)malloc(fileSize); + if (!pNew) + { + setLastError("MALLOC Failed !"); + free(pBigMalloc); + pBigMalloc = NULL; + return NULL; + } + + pSrc = pBigMalloc+sizeof(lzhHeader_t)+pHeader->name_lenght; // NOTE: Endianness works because name_lenght is a byte + + pSrc += 2; // skip CRC16 + + if (!LzhDepackBlock(pSrc,pNew,fileSize)) + { + setLastError("LH5 Depacking Error !"); + free(pNew); + free(pBigMalloc); + pNew = NULL; + pBigMalloc = NULL; + return NULL; + } + + // Tout est bon, le fichier est depack‚, on free le bloque + // pack‚ et on retourne le nouveau... + free(pBigMalloc); + return pNew; + } + + + + + +static ymint fileSizeGet(FILE *h) + { + ymint size; + ymint old; + + old = ftell(h); + fseek(h,0,SEEK_END); + size = ftell(h); + fseek(h,old,SEEK_SET); + return size; + } + + +ymbool CYmMusic::deInterleave(void) + { + yms32 nextPlane[32]; + ymu8 *pW,*tmpBuff; + yms32 j,k; + + + if (attrib&A_STREAMINTERLEAVED) + { + + tmpBuff = (ymu8*)malloc(nbFrame*streamInc); + if (!tmpBuff) + { + setLastError("Malloc error in deInterleave()\n"); + return YMFALSE; + } + + // Precalcul les offsets. + for (j=0;j0) + { + pDrumTab=(digiDrum_t*)malloc(nbDrum*sizeof(digiDrum_t)); + for (i=0;i>7; + } + } + ptr += pDrumTab[i].size; + } + else + { + pDrumTab[i].pData = NULL; + } + } + attrib &= (~A_DRUM4BITS); + } + pSongName = readNtString((char**)&ptr); + pSongAuthor = readNtString((char**)&ptr); + pSongComment = readNtString((char**)&ptr); + songType = YM_V5; + if (id=='YM6!') + { + songType = YM_V6; + pSongType = mstrdup("YM 6"); + } + else + { + pSongType = mstrdup("YM 5"); + } + pDataStream = ptr; + streamInc = 16; + setAttrib(A_STREAMINTERLEAVED|A_TIMECONTROL); + pSongPlayer = mstrdup("YM-Chip driver."); + break; + + case 'MIX1': // ATARI Remix digit format. + + if (strncmp((const char*)(pBigMalloc+4),"LeOnArD!",8)) + { + setLastError("Not a valid YM format !"); + return YMFALSE; + } + ptr = pBigMalloc+12; + songType = YM_MIX1; + tmp = readMotorolaDword(&ptr); + setAttrib(0); + if (tmp&1) setAttrib(A_DRUMSIGNED); + sampleSize = readMotorolaDword(&ptr); + nbMixBlock = readMotorolaDword(&ptr); + pMixBlock = (mixBlock_t*)malloc(nbMixBlock*sizeof(mixBlock_t)); + for (i=0;i0) + { + pDrumTab=(digiDrum_t*)malloc(nbDrum*sizeof(digiDrum_t)); + for (i=0;i<(ymint)nbDrum;i++) + { + pDrumTab[i].size = readMotorolaWord(&ptr); + pDrumTab[i].repLen = pDrumTab[i].size; + if ('YMT2' == id) + { + pDrumTab[i].repLen = readMotorolaWord(&ptr); // repLen + readMotorolaWord(&ptr); // flag + } + if (pDrumTab[i].repLen>pDrumTab[i].size) + { + pDrumTab[i].repLen = pDrumTab[i].size; + } + + if (pDrumTab[i].size) + { + pDrumTab[i].pData = (ymu8*)malloc(pDrumTab[i].size); + memcpy(pDrumTab[i].pData,ptr,pDrumTab[i].size); + ptr += pDrumTab[i].size; + } + else + { + pDrumTab[i].pData = NULL; + } + } + } + + ymTrackerFreqShift = 0; + if ('YMT2' == id) + { + ymTrackerFreqShift = (attrib>>28)&15; + attrib &= 0x0fffffff; + pSongType = mstrdup("YM-T2"); + } + else + { + pSongType = mstrdup("YM-T1"); + } + + + pDataStream = ptr; + ymChip.setClock(ATARI_CLOCK); + + ymTrackerInit(100); // 80% de volume maxi. + streamInc = 16; + setTimeControl(YMTRUE); + pSongPlayer = mstrdup("Universal Tracker"); + break; + + default: + setLastError("Unknow YM format !"); + return YMFALSE; + break; + } + + if (!deInterleave()) + { + return YMFALSE; + } + + return YMTRUE; + } + + +ymbool CYmMusic::checkCompilerTypes() +{ + setLastError("Basic types size are not correct (check ymTypes.h)"); + + if (1 != sizeof(ymu8)) return YMFALSE; + if (1 != sizeof(yms8)) return YMFALSE; + if (1 != sizeof(ymchar)) return YMFALSE; + + if (2 != sizeof(ymu16)) return YMFALSE; + if (2 != sizeof(yms16)) return YMFALSE; + if (4 != sizeof(ymu32)) return YMFALSE; + if (4 != sizeof(yms32)) return YMFALSE; + + if (2 != sizeof(ymsample)) return YMFALSE; + +#ifdef YM_INTEGER_ONLY + if (8 != sizeof(yms64)) return YMFALSE; +#endif + + if (sizeof(ymint) < 4) return YMFALSE; // ymint should be at least 32bits + + setLastError(""); + return YMTRUE; +} + + +ymbool CYmMusic::load(const char *fileName) +{ +FILE *in; + + + stop(); + unLoad(); + + if (!checkCompilerTypes()) + return YMFALSE; + + in = fopen(fileName,"rb"); + if (!in) + { + setLastError("File not Found"); + return YMFALSE; + } + + //--------------------------------------------------- + // Allocation d'un buffer pour lire le fichier. + //--------------------------------------------------- + fileSize = fileSizeGet(in); + pBigMalloc = (unsigned char*)malloc(fileSize); + if (!pBigMalloc) + { + setLastError("MALLOC Error"); + fclose(in); + return YMFALSE; + } + + //--------------------------------------------------- + // Chargement du fichier complet. + //--------------------------------------------------- + if (fread(pBigMalloc,fileSize,1,in)!=(size_t)1) + { + free(pBigMalloc); + setLastError("File is corrupted."); + fclose(in); + return YMFALSE; + } + fclose(in); + + //--------------------------------------------------- + // Transforme les donn‚es en donn‚es valides. + //--------------------------------------------------- + pBigMalloc = depackFile(); + if (!pBigMalloc) + { + return YMFALSE; + } + + //--------------------------------------------------- + // Lecture des donn‚es YM: + //--------------------------------------------------- + if (!ymDecode()) + { + free(pBigMalloc); + pBigMalloc = NULL; + return YMFALSE; + } + + ymChip.reset(); + bMusicOk = YMTRUE; + bPause = YMFALSE; + return YMTRUE; + } + +ymbool CYmMusic::loadMemory(void *pBlock,ymu32 size) +{ + + + stop(); + unLoad(); + + if (!checkCompilerTypes()) + return YMFALSE; + + //--------------------------------------------------- + // Allocation d'un buffer pour lire le fichier. + //--------------------------------------------------- + fileSize = size; + pBigMalloc = (unsigned char*)malloc(fileSize); + if (!pBigMalloc) + { + setLastError("MALLOC Error"); + return YMFALSE; + } + + //--------------------------------------------------- + // Chargement du fichier complet. + //--------------------------------------------------- + memcpy(pBigMalloc,pBlock,size); + + //--------------------------------------------------- + // Transforme les donn‚es en donn‚es valides. + //--------------------------------------------------- + pBigMalloc = depackFile(); + if (!pBigMalloc) + { + return YMFALSE; + } + + //--------------------------------------------------- + // Lecture des donn‚es YM: + //--------------------------------------------------- + if (!ymDecode()) + { + free(pBigMalloc); + pBigMalloc = NULL; + return YMFALSE; + } + + ymChip.reset(); + bMusicOk = YMTRUE; + bPause = YMFALSE; + return YMTRUE; + } + +void myFree(void **pPtr) +{ + if (*pPtr) free(*pPtr); + *pPtr = NULL; +} + +void CYmMusic::unLoad(void) +{ + + bMusicOk = YMFALSE; + bPause = YMTRUE; + bMusicOver = YMFALSE; +// myFree((void**)&pSongName); + myFree((void**)&pSongAuthor); + myFree((void**)&pSongComment); + myFree((void**)&pSongType); + myFree((void**)&pSongPlayer); + myFree((void**)&pBigMalloc); + if (nbDrum>0) + { + for (ymint i=0;i + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/lib/stsound/readme.html b/lib/stsound/readme.html new file mode 100644 index 0000000000..5c64b70345 --- /dev/null +++ b/lib/stsound/readme.html @@ -0,0 +1,151 @@ + + +Open Source ST-Sound + + + + + + + + + + + + + + +
+ +
+

Open + Source ST-Sound Library by + Arnaud Carré
+
v1.2
+ 10 years later !! :-)

+
+
 
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
History...
+

In + 1995 I created the YM + file format and wrote ST-Sound, a program to play ATARI-ST on + your PC. I was very happy to see how ST-Sound was popular. MS-Dos + player at first, I write a Windows player, a winamp and a netscape + plugin. ( then some website use Atari tunes !).

+

And + then time passed and I worked on other stuff. Quite often, some + people asked me to release the source code, and I always answered + that I should clean some code and add license stuff, so I never + take time..

+

Now + it's done ! 2005, ten years after the first ST-Sound creation, here + is the ST-Sound library with sample project, all under GPL license. + The code is not as clean as I hope but no time to change it. Don't + forget almost all that stuff was written in 1995 :-)

+
Package + details
+

ST-Sound + library package comes with four main directories.:

+

StSoundLibrary

+
+

This + is the most important directory. Portable ( I hope !! :-)) C++ + code to play YM files into your own production. There is a simple + "C like" user API, and you just need to include "StSoundLibrary.h" + to work with YM files. See tutorial projects for details. Theorically + should compile under windows, linux, etc.

+
+

YmToWav

+
+

Tutorial + code. Portable ( I hope !! :-)) code to render an YM file into + a WAV file. Works in command line. theorically should compile + under windows, linux, etc.

+
+

SmallYmPlayer

+
+

Tutorial + code. Non portable (windows only) real time YM player using StSoundLibrary. + Works under windows (use the waveOut sound API)

+
+

YmSampleFiles

+
+

Only + contains a set of YM sample files to fastly test the library without + browsing the whole world wide web ! :-)

+
+
Compiling
+

The + package is done to work very nicely with Microsoft Visual C++ 6.0 + ( Visual .NET is pure bullshit! )

+

For + Visual C++ 6.0 users: Load StSoundGPL.dsw file into your lovely + IDE and just build one of the tutorial sample or the main library. + Everything should work like a charm without pain.

+

For + other users ( .NET, Linux, Gameboy color or other strange system), + just search in your head some very, very oldschool knowledge and + build a nice makefile :-) ( should be easy for StSoundLibrary)

+
Legal + infos
+

ST-Sound + library, Copyright (C) 1995-1999 Arnaud Carré ( http://leonard.oxg.free.fr + )

+

ST-Sound + library is distributed under GNU + GPL license. If you use it in your own production, please include + at least that ZIP package and make me a little credits :-). You + can find the GPL legal file within that package ( license.txt ).

+

As + almost all YM files on the web are packed with LZH method, ST-Sound + includes LZH depacking code written by Haruhiko Okumura and modifyed/improved + by Kerwin F. Medina.

+
+

Enjoy ATARI-ST sound !!

+

http://leonard.oxg.free.fr

+
+

 

+

 

+ + diff --git a/lib/stsound/revision.txt b/lib/stsound/revision.txt new file mode 100644 index 0000000000..b56ad8a4e4 --- /dev/null +++ b/lib/stsound/revision.txt @@ -0,0 +1,20 @@ +v1.1b +---------------------------------------------------- +- runtime build in basic types size checking +- some "short" types converted to ymsample + +v1.1 +---------------------------------------------------- +- YmTypes.h added to help multiplatform port +- Added Sync-Buzzer sound effect support +- Integer only version (no float or double used by default) +- Small changes in C interface (ymMusicCreate and ymMusicDestroy added) +- little/big endian fixed for bigendian platform (depacking and Ym3b format) +- Memory leak fixed in LZHXLIB library +- printf fixed in the YM to WAV sample code + + + +v1.0 +---------------------------------------------------- +- First release. -- cgit v1.2.3