Update DUMB to version 2.0.0.

This commit is contained in:
Christopher Snowhill 2017-09-26 16:11:54 -07:00
parent 78b69b010d
commit 47a6afe62c
106 changed files with 19176 additions and 19508 deletions

View file

@ -1,3 +1,4 @@
```
/* _______ ____ __ ___ ___ /* _______ ____ __ ___ ___
* \ _ \ \ / \ / \ \ / / ' ' ' * \ _ \ \ / \ / \ \ / / ' ' '
* | | \ \ | | || | \/ | . . * | | \ \ | | || | \/ | . .
@ -8,7 +9,7 @@
* /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque * /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
* / \ * / \
* / . \ * / . \
* release.txt - Release notes for DUMB. / / \ \ * CHANGELOG.md - Release notes for DUMB. / / \ \
* | < / \_ * | < / \_
* | \/ /\ / * | \/ /\ /
* \_ / > / * \_ / > /
@ -16,11 +17,35 @@
* | ' / * | ' /
* \__/ * \__/
*/ */
```
# DUMB Changelog
******************************************* ## v2.0.0, released 26 September 2017
*** DUMB v0.9.3, released 7 August 2005 ***
******************************************* * Memory leak and bug fixes
* Audio playback quality improvements for STM
* Added support for FEST MOD files
* Default resampling quality is now cubic
* Allegro 4 support
* New dumbplay, dumbout examples
* Multiple cmake fixes
* Deprecated `duh_render()`, use `duh_render_float()` and `duh_render_int()`
* Removed API deprecated since 0.9.3, see the
[DUMB 0.9.3 deprecation reference](http://dumb.sourceforge.net/index.php?page=docs&doc=deprec)
## v1.0.0, released 17 January 2015
* Support newer compilers
* Better audio playback quality
* More supported formats
* SSE optimizations support
* CMake support
* New resamplers
* Seek support
* Fixes, cleanups, speedups.
## v0.9.3, released 7 August 2005
Hello! Welcome to a long-awaited-or-probably-just-given-up-on-by-everybody Hello! Welcome to a long-awaited-or-probably-just-given-up-on-by-everybody
release! New to this release are lower memory usage, faster mixing loops, release! New to this release are lower memory usage, faster mixing loops,
@ -173,9 +198,7 @@ That's it! I hope you enjoy this long-awaited-or-probably-just-given-up-on-
by-everybody release of DUMB! by-everybody release of DUMB!
****************************************** ## v0.9.2, released 2 April 2003
*** DUMB v0.9.2, released 2 April 2003 ***
******************************************
Yes, there really has been a release. This is not a day-late April fools' Yes, there really has been a release. This is not a day-late April fools'
joke. joke.
@ -272,9 +295,7 @@ explained in licence.txt. However, the request is still there ...
As usual, enjoy! As usual, enjoy!
********************************************** ## v0.9.1, released 19 December 2002
*** DUMB v0.9.1, released 19 December 2002 ***
**********************************************
Hi again! Lots to say this time, so I shall cut right to the chase. Hi again! Lots to say this time, so I shall cut right to the chase.
@ -355,9 +376,7 @@ the last release; they are relevant for this release too.
That's all folks! Until next time. That's all folks! Until next time.
******************************************* ## v0.9, released 16 October 2002
*** DUMB v0.9, released 16 October 2002 ***
*******************************************
MOD support is here! DUMB now supports all four of the common module formats. MOD support is here! DUMB now supports all four of the common module formats.
As usual, there have also been some improvements to the way modules are As usual, there have also been some improvements to the way modules are
@ -431,9 +450,7 @@ Off you go.
Bye. Bye.
******************************************** ## v0.8.1, released 11 August 2002
*** DUMB v0.8.1, released 11 August 2002 ***
********************************************
This is a minor release that fixes a few bugs. One of these bugs, however, This is a minor release that fixes a few bugs. One of these bugs, however,
was pretty serious. dumb_register_dat_xm() was never coded! It was prototyped was pretty serious. dumb_register_dat_xm() was never coded! It was prototyped
@ -487,9 +504,7 @@ The point about length not being calculated also applies to XM files.
Enjoy :) Enjoy :)
**************************************** ## v0.8, released 14 June 2002
*** DUMB v0.8, released 14 June 2002 ***
****************************************
Welcome to the second release of DUMB! Welcome to the second release of DUMB!
@ -530,9 +545,7 @@ going myself (72 GBP, and I'd have to wear a suit, ugh), but with all the
noise outside I shall enjoy pumping up the speakers tonight! noise outside I shall enjoy pumping up the speakers tonight!
**************************************** ## DUMB v0.7, released 2 March 2002
*** DUMB v0.7, released 2 March 2002 ***
****************************************
This is the first release of DUMB, and parts of the library are not This is the first release of DUMB, and parts of the library are not
crystallised. Don't let this put you off! Provided you don't try to use any crystallised. Don't let this put you off! Provided you don't try to use any

View file

@ -0,0 +1,35 @@
# Compiling
## 1. CMake
### 1.1. Example
In libdumb project root, run:
```
mkdir -p build
cd build
cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=/usr/local -DBUILD_SHARED_LIBS:BOOL=ON -DBUILD_ALLEGRO4:BOOL=ON ..
make
make install
```
### 1.2. Steps
1. Create a new temporary build directory and cd into it
2. Run libdumb cmake file with cmake (eg. `cmake -DCMAKE_INSTALL_PREFIX=/install/dir -DBUILD_SHARED_LIBS:BOOL=ON -DCMAKE_BUILD_TYPE=Release path/to/dumb/cmake/dir`).
3. Run make (eg. just `make` or `mingw32-make` or something).
4. If needed, run make install.
### 1.3. Flags
* `CMAKE_INSTALL_PREFIX` sets the installation path prefix.
* `CMAKE_BUILD_TYPE` chooses the build type: `Release`, `Debug`, `RelWithDebInfo`, or `MinSizeRel`. Debug libraries will be named `libdumbd`, release libraries `libdumb`. Default is `Release`.
* `BUILD_SHARED_LIBS` selects whether cmake should build a dynamic (`ON`) or static (`OFF`) library. Default is `OFF`.
* `BUILD_ALLEGRO4` enables (`ON`) or disables (`OFF`) the optional Allegro 4 support. This requires Allegro 4 installed on the system. Default is `ON`.
* `BUILD_EXAMPLES` selects example binaries. These example binaries require argtable2 and SDL2 libraries. Default is `ON`.
* `USE_SSE` enables or disables SSE support. Default is `ON`.
* You may also need to tell cmake what kind of makefiles to create with the "-G" flag. Eg. for MSYS one would say something like `cmake -G "MSYS Makefiles" .`.
## 2. Visual Studio
TODO

View file

@ -0,0 +1,226 @@
Specification of DUMBFILE_SYSTEM
================================
DUMB is designed filesystem-agnostic, even though the C standard library
already defines an abstraction over files on a disk. This is useful because
Allegro 4 and 5 define their own abstractions.
To register your own filesystem abstraction with DUMB, you must create an
instance of struct `DUMBFILE_SYSTEM`, fill in your own function pointers
according to the specification below, and call `register_dumbfile_system` on
your instance.
The header `dumb.h` defines `DUMBFILE_SYSTEM` as a struct of function pointers:
```
typedef struct DUMBFILE_SYSTEM
{
void *(*open)(const char *filename);
int (*skip)(void *f, dumb_off_t n);
int (*getc)(void *f);
dumb_ssize_t (*getnc)(char *ptr, size_t n, void *f);
void (*close)(void *f);
int (*seek)(void *f, dumb_off_t n);
dumb_off_t (*get_size)(void *f);
}
DUMBFILE_SYSTEM;
```
Here, `dumb_off_t` is a signed integer at least 64 bits wide, it is intended
to measure file offsets. The return type `dumb_ssize_t` is a signed integer
exactly as wide as `size_t`, it is intended to store either a `size_t` or a
negative error code. Both `dumb_*_t` are defined in `dumb.h`.
The function pointers `skip` and `getnc` are optional, i.e., you may set
some of these to `NULL` in your struct instance. DUMB will then try to
mimick the missing functions' behavior by calling your `getc` several times.
If DUMB is built with debugging flags, it will assert that all other
functions are not `NULL`. In release mode, DUMB will silently fail.
Your non-`NULL` function pointers must conform to the following specification.
open
----
```
void *(*open)(const char *filename);
```
Open a file for reading.
Arguments:
* `const char *filename`: A normal filename as understood by the operating
system. Will be opened for reading.
Returns as `void *`:
* the address of a file handle on successfully opening the file.
DUMB will pass this file handle as argument to other functions of
the `DUMBFILE_SYSTEM`.
* `NULL` on error during opening the file.
Each file has a *position* internally managed by DUMB. A newly opened file
has a position of 0. Other functions from the `DUMBFILE_SYSTEM` can move
this position around.
DUMB allocates memory for the successfully opened file, and will store opaque
information in that memory, e.g., the DUMB-internal file position. This memory
be freed when DUMB calls `close` on the file's handle. The memory is separate
from your own filesystem implementation: You are responsible for supplying the
data, and DUMB is responsible for storing anything about interpreting that
data.
skip
----
```
int (*skip)(void *f, dumb_off_t n);
```
Advance the position in the file.
Arguments:
* `void *f`: A file handle that `open` returned. Guaranteed non-`NULL`.
* `dumb_off_t n`: Number of bytes to advance in the file. DUMB will only
call this with `n >= 0`. For `n < 0`, the behavior of `skip` is undefined.
Returns as `int`:
* `0` on successfully skipping ahead by `n` bytes.
* `-1` on error.
It is legal to set `skip = NULL` in a `DUMBFILE_SYSTEM`. DUMB will then call
`getc` a total of `n` times to skip ahead in a file. For speed, it is
advisable to supply a proper `skip` implementation.
getc
----
```
int (*getc)(void *f);
```
Read a byte from the file.
Arguments:
* `void *f`: A file handle that `open` returned. Guaranteed non-`NULL`.
Returns as `int`:
* the value of the byte read, on successfully reading one byte.
* `-1` on error.
After a succesful read, DUMB will treat the file as advanced by one byte.
getnc
-----
```
dumb_ssize_t (*getnc)(char *ptr, size_t n, void *f);
```
Read up to the given number of bytes from the file into a given buffer.
* `char *ptr`: The start of a buffer provided by DUMB.
* `size_t n`: The length of the number of bytes to be read.
* `void *f`: A file handle that `open` returned. Guaranteed non-`NULL`.
Returns as `dumb_ssize_t`:
* the number of bytes successfully read, if it was possible to read at least
one byte.
* `-1` on error.
This function shall bytes from the file `f` and store them in sequence in the
buffer beginning at `ptr`. It shall read fewer than `n` bytes if end of file
is encountered before `n` bytes could have been read, otherwise it should read
`n` bytes.
It is legal to set `skip = NULL` in a `DUMBFILE_SYSTEM`. DUMB will then call
`getc` a total of `n` times and store the results in its buffer.
close
-----
```
void (*close)(void *f);
```
Closes a file that has been opened before with `open`.
Arguments:
* `void *f`: A file handle that `open` returned. Guaranteed non-`NULL`.
DUMB will deallocate the memory that it used to interpret the file. You are
free to treat your resource however you would like: You may deallocate it, or
keep it around for other things. For example, Allegro 5's implementation
of `close` takes a void pointer and does nothing with it at all.
seek
----
```
int (*seek)(void *f, dumb_off_t n);
```
Jump to an arbitrary position in the file.
Arguments:
* `void *f`: A file handle that `open` returned. Guaranteed non-`NULL`.
* `dumb_off_t n`: The position in the file, relative to the beginning.
There is no guarantee whether `n >= 0`.
Returns as `int`:
* `0` on successfully seeking in the file.
* `-1` on error.
DUMB will modify its internal position of the file accordingly.
A value of `n < 0` shall set the file into an erroneous state from which no
bytes can be read.
get_size
--------
```
dumb_off_t (*get_size)(void *f);
```
Get the length in bytes, i.e., the position after the final byte, of a file.
Arguments:
* `void *f`: A file handle that `open` returned. Guaranteed non-`NULL`.
Returns as `dumb_off_t`:
* the length of the file in bytes.

View file

@ -0,0 +1,96 @@
# Dynamic Universal Music Bibliotheque (libdumb)
_______ ____ __ ___ ___
\ _ \ \ / \ / \ \ / / ' ' '
| | \ \ | | || | \/ | . .
| | | | | | || ||\ /| |
| | | | | | || || \/ | | ' ' '
| | | | | | || || | | . .
| |_/ / \ \__// || | |
/_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
/ \
/ . \
/ / \ \
| < / \_
| \/ /\ /
\_ / > /
| \ / /
| ' /
\__/
## Introduction
DUMB is a module audio renderer library. It reads module files and
outputs audio that can be dumped to the actual audio playback library.
This is a fork of the original dumb (http://dumb.sf.net/) by Ben Davis.
## Features
- Supports playback of the following module formats. The tracker software or
library the format is known for is given in parentheses. This does not mean
that DUMB does not support files created by other trackers provided that they
output files in one of those formats.
* IT (Impulse Tracker)
* XM (Fasttracker II)
* MOD (Ultimate SoundTracker, ProTracker)
* STM (Scream Tracker)
* S3M (Scream Tracker 3)
* 669 (Composer 669)
* AMF Asylum Music Format
* AMF Digital Sound and Music Interface Advanced Music Format
* DSM Digital Sound Interface Kit module format
* MTM (MultiTracker)
* OKT (Oktalyzer)
* PSM (Protracker Studio)
Both the older PSM16 and the newer PSM format is supported.
* PTM (PolyTracker)
* RIFF AM/AMFF (Galaxy Music System internal format)
- Audio generated can be used in any way; DUMB does not necessarily send it
straight to a sound output system
- Portable
- Faithful to the original trackers, especially IT; if it plays a module
wrongly, it is considered a bug
- Accurate support for low-pass resonant filters for IT files
- Very accurate timing and pitching; completely deterministic playback
- Click removal
- Six resampling quality settings: aliasing, aliasing with bandwidth limiting,
linear interpolation, linear interpolation with bandwidth limiting, cubic
interpolation, and a compile-time-configurable fast sinc resampler
- Number of samples playing at once can be limited to reduce processor usage,
but samples will come back in when other louder ones stop
- Option to take longer loading but seek fast to any point before the music
first loops (seeking time increases beyond this point)
- All notes will be present and correct even if a module's playback is started
in the middle
- Optional Allegro 4 or Allegro 5 integration support
- Facility to embed music files in other files (e.g. Allegro datafiles)
## Installation
Currently you need to compile libdumb yourself. For more details, please see
the file [COMPILING.md](COMPILING.md).
## License
See [LICENSE](LICENSE) for license details.
## Contributing
Bugs, feature requests and patches can be submitted at https://github.com/kode54/dumb/.

View file

@ -20,7 +20,6 @@
#ifndef DUMB_H #ifndef DUMB_H
#define DUMB_H #define DUMB_H
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h> #include <stdio.h>
@ -32,51 +31,23 @@
#endif #endif
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
/*
#define DUMB_MAJOR_VERSION 1 * When you bump major, minor, or patch, bump both the number and the string.
* When you bump major or minor version, bump them in CMakeLists.txt, too.
*/
#define DUMB_MAJOR_VERSION 2
#define DUMB_MINOR_VERSION 0 #define DUMB_MINOR_VERSION 0
#define DUMB_REVISION_VERSION 0 #define DUMB_REVISION_VERSION 0
#define DUMB_VERSION_STR "2.0.0"
#define DUMB_VERSION (DUMB_MAJOR_VERSION*10000 + DUMB_MINOR_VERSION*100 + DUMB_REVISION_VERSION) #define DUMB_VERSION \
(DUMB_MAJOR_VERSION * 10000 + DUMB_MINOR_VERSION * 100 + \
#define DUMB_VERSION_STR "1.0.0" DUMB_REVISION_VERSION)
#define DUMB_NAME "DUMB v" DUMB_VERSION_STR #define DUMB_NAME "DUMB v" DUMB_VERSION_STR
#define DUMB_YEAR 2015
#define DUMB_MONTH 1
#define DUMB_DAY 17
#define DUMB_YEAR_STR2 "15"
#define DUMB_YEAR_STR4 "2015"
#define DUMB_MONTH_STR1 "1"
#define DUMB_DAY_STR1 "17"
#if DUMB_MONTH < 10
#define DUMB_MONTH_STR2 "0" DUMB_MONTH_STR1
#else
#define DUMB_MONTH_STR2 DUMB_MONTH_STR1
#endif
#if DUMB_DAY < 10
#define DUMB_DAY_STR2 "0" DUMB_DAY_STR1
#else
#define DUMB_DAY_STR2 DUMB_DAY_STR1
#endif
/* WARNING: The month and day were inadvertently swapped in the v0.8 release.
* Please do not compare this constant against any date in 2002. In
* any case, DUMB_VERSION is probably more useful for this purpose.
*/
#define DUMB_DATE (DUMB_YEAR*10000 + DUMB_MONTH*100 + DUMB_DAY)
#define DUMB_DATE_STR DUMB_DAY_STR1 "." DUMB_MONTH_STR1 "." DUMB_YEAR_STR4
#ifdef DEBUGMODE #ifdef DEBUGMODE
#ifndef ASSERT #ifndef ASSERT
@ -97,27 +68,11 @@
#define TRACE 1 ? (void)0 : (void)printf #define TRACE 1 ? (void)0 : (void)printf
#endif #endif
#endif #endif // DEBUGMODE
#define DUMB_ID(a, b, c, d) \
#define DUMB_ID(a,b,c,d) (((unsigned int)(a) << 24) | \ (((unsigned int)(a) << 24) | ((unsigned int)(b) << 16) | \
((unsigned int)(b) << 16) | \ ((unsigned int)(c) << 8) | ((unsigned int)(d)))
((unsigned int)(c) << 8) | \
((unsigned int)(d) ))
#ifndef LONG_LONG
#if defined __GNUC__ || defined __INTEL_COMPILER || defined __MWERKS__
#define LONG_LONG long long
#elif defined _MSC_VER || defined __WATCOMC__
#define LONG_LONG __int64
#elif defined __sgi
#define LONG_LONG long long
#else
#error 64-bit integer type unknown
#endif
#endif
#if __GNUC__ * 100 + __GNUC_MINOR__ >= 301 /* GCC 3.1+ */ #if __GNUC__ * 100 + __GNUC_MINOR__ >= 301 /* GCC 3.1+ */
#ifndef DUMB_DECLARE_DEPRECATED #ifndef DUMB_DECLARE_DEPRECATED
@ -128,32 +83,101 @@
#define DUMB_DEPRECATED #define DUMB_DEPRECATED
#endif #endif
/* Basic Sample Type. Normal range is -0x800000 to 0x7FFFFF. */ /* Basic Sample Type. Normal range is -0x800000 to 0x7FFFFF. */
typedef int sample_t; typedef int sample_t;
/* Library Clean-up Management */ /* Library Clean-up Management */
int dumb_atexit(void (*proc)(void)); int dumb_atexit(void (*proc)(void));
void dumb_exit(void); void dumb_exit(void);
/* File Input Functions */ /* File Input Functions */
#ifdef DUMB_OFF_T_CUSTOM
typedef dumb_off_t DUMB_OFF_T_CUSTOM;
#elif defined _MSC_VER || defined __WATCOMC__
typedef __int64 dumb_off_t;
#elif defined __DJGPP__
typedef off64_t dumb_off_t;
#elif _POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 500 || defined __MINGW32__
typedef off_t dumb_off_t;
#else
typedef long long dumb_off_t;
#endif
typedef struct DUMBFILE_SYSTEM /*
{ * If the build fails here, it does so, because we need a 64-bit-type for
* defining offsets. To fix this do either of the following:
*
* 1. Compile your code with -D_FILE_OFFSET_BITS=64, so that off_t is 64-bit
* (recommended, but make sure the rest of your code can handle it)
* 2. Supply your own definition of a signed 64-bit integer
* such as off64_t or int64_t before including dumb.h as follows:
* #define DUMB_OFF_T_CUSTOM int64_t
*/
#if (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) && \
!defined __cplusplus
_Static_assert(sizeof(dumb_off_t) >= 8, "fuse: off_t must be 64bit");
#else
struct dumb_off_t_needs_to_be_at_least_8_bytes {
unsigned int dumb_off_t_needs_to_be_at_least_8_bytes
: ((sizeof(dumb_off_t) >= 8) ? 1 : -42);
};
#endif
/*
* ssize_t is defined in POSIX to hold either a size_t or an error.
* We will use dumb_ssize_t on all platforms for (either size_t or error) in
* all getnc-type functions. See DUMBFILE_SYSTEM.md for that function's spec.
*/
#if defined(_MSC_VER)
#include <BaseTsd.h>
typedef SSIZE_T dumb_ssize_t;
#else
#include <sys/types.h>
typedef ssize_t dumb_ssize_t;
#endif
/*
* DUMB provides an abstraction over files, to work with memory-mapped files,
* files on disk, files read into memory by other libraries in their own
* custom formats, ...
*
* Register your own file-handling functions as callbacks via this struct.
* DUMB 2.0 doesn't use long anymore. The 64-bit dumb_*_t are defined above.
*
* See DUMBFILE_SYSTEM.md in project's root for a complete spec.
*/
typedef struct DUMBFILE_SYSTEM {
/* open */
/* Open filename. Returned file may be of any custom type. */
void *(*open)(const char *filename); void *(*open)(const char *filename);
int (*skip)(void *f, long n);
/* skip */
/* Ignore the next n bytes in file f. Returns 0 on succes, -1 on error. */
int (*skip)(void *f, dumb_off_t n);
/* getc */
/* Read the next byte. Returns byte as unsigned, or -1 on error. */
int (*getc)(void *f); int (*getc)(void *f);
long (*getnc)(char *ptr, long n, void *f);
/* getnc */
/* Read n bytes into buffer ptr. Returns number of bytes read or -1. */
dumb_ssize_t (*getnc)(char *ptr, size_t n, void *f);
/* close */
/* Called when DUMB is done with the file. User code may do anything. */
void (*close)(void *f); void (*close)(void *f);
int (*seek)(void *f, long n);
long (*get_size)(void *f); /* seek */
} /* Jump to offset in bytes from beginning. Returns 0 if OK, -1 on error. */
DUMBFILE_SYSTEM; int (*seek)(void *f, dumb_off_t offset);
/* get_size */
/* Returns the size in bytes of the file. */
dumb_off_t (*get_size)(void *f);
} DUMBFILE_SYSTEM;
typedef struct DUMBFILE DUMBFILE; typedef struct DUMBFILE DUMBFILE;
@ -162,16 +186,16 @@ void register_dumbfile_system(const DUMBFILE_SYSTEM *dfs);
DUMBFILE *dumbfile_open(const char *filename); DUMBFILE *dumbfile_open(const char *filename);
DUMBFILE *dumbfile_open_ex(void *file, const DUMBFILE_SYSTEM *dfs); DUMBFILE *dumbfile_open_ex(void *file, const DUMBFILE_SYSTEM *dfs);
long dumbfile_pos(DUMBFILE *f); dumb_off_t dumbfile_pos(DUMBFILE *f);
int dumbfile_skip(DUMBFILE *f, long n); int dumbfile_skip(DUMBFILE *f, dumb_off_t n);
#define DFS_SEEK_SET 0 #define DFS_SEEK_SET 0
#define DFS_SEEK_CUR 1 #define DFS_SEEK_CUR 1
#define DFS_SEEK_END 2 #define DFS_SEEK_END 2
int dumbfile_seek(DUMBFILE *f, long n, int origin); int dumbfile_seek(DUMBFILE *f, dumb_off_t n, int origin);
long dumbfile_get_size(DUMBFILE *f); dumb_off_t dumbfile_get_size(DUMBFILE *f);
int dumbfile_getc(DUMBFILE *f); int dumbfile_getc(DUMBFILE *f);
@ -184,199 +208,95 @@ long dumbfile_mgetl(DUMBFILE *f);
unsigned long dumbfile_cgetul(DUMBFILE *f); unsigned long dumbfile_cgetul(DUMBFILE *f);
signed long dumbfile_cgetsl(DUMBFILE *f); signed long dumbfile_cgetsl(DUMBFILE *f);
long dumbfile_getnc(char *ptr, long n, DUMBFILE *f); dumb_ssize_t dumbfile_getnc(char *ptr, size_t n, DUMBFILE *f);
int dumbfile_error(DUMBFILE *f); int dumbfile_error(DUMBFILE *f);
int dumbfile_close(DUMBFILE *f); int dumbfile_close(DUMBFILE *f);
/* stdio File Input Module */ /* stdio File Input Module */
void dumb_register_stdfiles(void); void dumb_register_stdfiles(void);
DUMBFILE *dumbfile_open_stdfile(FILE *p); DUMBFILE *dumbfile_open_stdfile(FILE *p);
/* Memory File Input Module */ /* Memory File Input Module */
DUMBFILE *dumbfile_open_memory(const char *data, long size); DUMBFILE *dumbfile_open_memory(const char *data, size_t size);
/* DUH Management */ /* DUH Management */
typedef struct DUH DUH; typedef struct DUH DUH;
#define DUH_SIGNATURE DUMB_ID('D','U','H','!') #define DUH_SIGNATURE DUMB_ID('D', 'U', 'H', '!')
void unload_duh(DUH *duh); void unload_duh(DUH *duh);
DUH *load_duh(const char *filename); DUH *load_duh(const char *filename);
DUH *read_duh(DUMBFILE *f); DUH *read_duh(DUMBFILE *f);
long duh_get_length(DUH *duh); dumb_off_t duh_get_length(DUH *duh);
const char *duh_get_tag(DUH *duh, const char *key); const char *duh_get_tag(DUH *duh, const char *key);
int duh_get_tag_iterator_size(DUH *duh); int duh_get_tag_iterator_size(DUH *duh);
int duh_get_tag_iterator_get(DUH *duh, const char **key, const char **tag, int i); int duh_get_tag_iterator_get(DUH *duh, const char **key, const char **tag,
int i);
/* Signal Rendering Functions */ /* Signal Rendering Functions */
typedef struct DUH_SIGRENDERER DUH_SIGRENDERER; typedef struct DUH_SIGRENDERER DUH_SIGRENDERER;
DUH_SIGRENDERER *duh_start_sigrenderer(DUH *duh, int sig, int n_channels, long pos); DUH_SIGRENDERER *duh_start_sigrenderer(DUH *duh, int sig, int n_channels,
long pos);
#ifdef DUMB_DECLARE_DEPRECATED typedef void (*DUH_SIGRENDERER_SAMPLE_ANALYSER_CALLBACK)(
typedef void (*DUH_SIGRENDERER_CALLBACK)(void *data, sample_t **samples, int n_channels, long length); void *data, const sample_t *const *samples, int n_channels, long length);
/* This is deprecated, but is not marked as such because GCC tends to
* complain spuriously when the typedef is used later. See comments below.
*/
void duh_sigrenderer_set_callback(
DUH_SIGRENDERER *sigrenderer,
DUH_SIGRENDERER_CALLBACK callback, void *data
) DUMB_DEPRECATED;
/* The 'callback' argument's type has changed for const-correctness. See the
* DUH_SIGRENDERER_CALLBACK definition just above. Also note that the samples
* in the buffer are now 256 times as large; the normal range is -0x800000 to
* 0x7FFFFF. The function has been renamed partly because its functionality
* has changed slightly and partly so that its name is more meaningful. The
* new one is duh_sigrenderer_set_analyser_callback(), and the typedef for
* the function pointer has also changed, from DUH_SIGRENDERER_CALLBACK to
* DUH_SIGRENDERER_ANALYSER_CALLBACK. (If you wanted to use this callback to
* apply a DSP effect, don't worry; there is a better way of doing this. It
* is undocumented, so contact me and I shall try to help. Contact details
* are in readme.txt.)
*/
typedef void (*DUH_SIGRENDERER_ANALYSER_CALLBACK)(void *data, const sample_t *const *samples, int n_channels, long length);
/* This is deprecated, but is not marked as such because GCC tends to
* complain spuriously when the typedef is used later. See comments below.
*/
void duh_sigrenderer_set_analyser_callback(
DUH_SIGRENDERER *sigrenderer,
DUH_SIGRENDERER_ANALYSER_CALLBACK callback, void *data
) DUMB_DEPRECATED;
/* This is deprecated because the meaning of the 'samples' parameter in the
* callback needed to change. For stereo applications, the array used to be
* indexed with samples[channel][pos]. It is now indexed with
* samples[0][pos*2+channel]. Mono sample data are still indexed with
* samples[0][pos]. The array is still 2D because samples will probably only
* ever be interleaved in twos. In order to fix your code, adapt it to the
* new sample layout and then call
* duh_sigrenderer_set_sample_analyser_callback below instead of this
* function.
*/
#endif
typedef void (*DUH_SIGRENDERER_SAMPLE_ANALYSER_CALLBACK)(void *data, const sample_t *const *samples, int n_channels, long length);
void duh_sigrenderer_set_sample_analyser_callback( void duh_sigrenderer_set_sample_analyser_callback(
DUH_SIGRENDERER *sigrenderer, DUH_SIGRENDERER *sigrenderer,
DUH_SIGRENDERER_SAMPLE_ANALYSER_CALLBACK callback, void *data DUH_SIGRENDERER_SAMPLE_ANALYSER_CALLBACK callback, void *data);
);
int duh_sigrenderer_get_n_channels(DUH_SIGRENDERER *sigrenderer); int duh_sigrenderer_get_n_channels(DUH_SIGRENDERER *sigrenderer);
long duh_sigrenderer_get_position(DUH_SIGRENDERER *sigrenderer); long duh_sigrenderer_get_position(DUH_SIGRENDERER *sigrenderer);
void duh_sigrenderer_set_sigparam(DUH_SIGRENDERER *sigrenderer, unsigned char id, long value); void duh_sigrenderer_set_sigparam(DUH_SIGRENDERER *sigrenderer,
unsigned char id, long value);
#ifdef DUMB_DECLARE_DEPRECATED long duh_sigrenderer_generate_samples(DUH_SIGRENDERER *sigrenderer,
long duh_sigrenderer_get_samples( float volume, float delta, long size,
DUH_SIGRENDERER *sigrenderer, sample_t **samples);
float volume, float delta,
long size, sample_t **samples
) DUMB_DEPRECATED;
/* The sample format has changed, so if you were using this function,
* you should switch to duh_sigrenderer_generate_samples() and change
* how you interpret the samples array. See the comments for
* duh_sigrenderer_set_analyser_callback().
*/
#endif
long duh_sigrenderer_generate_samples( void duh_sigrenderer_get_current_sample(DUH_SIGRENDERER *sigrenderer,
DUH_SIGRENDERER *sigrenderer, float volume, sample_t *samples);
float volume, float delta,
long size, sample_t **samples
);
void duh_sigrenderer_get_current_sample(DUH_SIGRENDERER *sigrenderer, float volume, sample_t *samples);
void duh_end_sigrenderer(DUH_SIGRENDERER *sigrenderer); void duh_end_sigrenderer(DUH_SIGRENDERER *sigrenderer);
/* DUH Rendering Functions */ /* DUH Rendering Functions */
/* For packed integers: 8, 16, 24-bit wide. /* For packed integers: 8, 16, 24-bit wide.
* Intermediary buffer sig_samples must be freed with destroy_sample_buffer() * Intermediary buffer sig_samples must be freed with destroy_sample_buffer()
* in the end of the rendering loop. * in the end of the rendering loop.
*/ */
long duh_render_int( long duh_render_int(DUH_SIGRENDERER *sigrenderer, sample_t ***sig_samples,
DUH_SIGRENDERER *sigrenderer, long *sig_samples_size, int bits, int unsign, float volume,
sample_t ***sig_samples, float delta, long size, void *sptr);
long *sig_samples_size,
int bits, int unsign,
float volume, float delta,
long size, void *sptr
);
/* For floats: 32, 64-bit wide. /* For floats: 32, 64-bit wide.
* Intermediary buffer sig_samples must be freed with destroy_sample_buffer() * Intermediary buffer sig_samples must be freed with destroy_sample_buffer()
* in the end of the rendering loop. * in the end of the rendering loop.
*/ */
long duh_render_float( long duh_render_float(DUH_SIGRENDERER *sigrenderer, sample_t ***sig_samples,
DUH_SIGRENDERER *sigrenderer, long *sig_samples_size, int bits, float volume,
sample_t ***sig_samples, float delta, long size, void *sptr);
long *sig_samples_size,
int bits,
float volume, float delta,
long size, void *sptr
);
#ifdef DUMB_DECLARE_DEPRECATED #ifdef DUMB_DECLARE_DEPRECATED
long duh_render( /* DEPRECATED since 2.0.0. Please use duh_render_int or duh_render_float. */
DUH_SIGRENDERER *sigrenderer, long duh_render(DUH_SIGRENDERER *sigrenderer, int bits, int unsign,
int bits, int unsign, float volume, float delta, long size,
float volume, float delta, void *sptr) DUMB_DEPRECATED;
long size, void *sptr
) DUMB_DEPRECATED;
long duh_render_signal(
DUH_SIGRENDERER *sigrenderer,
float volume, float delta,
long size, sample_t **samples
) DUMB_DEPRECATED;
/* Please use duh_sigrenderer_generate_samples(), and see the
* comments for the deprecated duh_sigrenderer_get_samples() too.
*/
typedef DUH_SIGRENDERER DUH_RENDERER DUMB_DEPRECATED;
/* Please use DUH_SIGRENDERER instead of DUH_RENDERER. */
DUH_SIGRENDERER *duh_start_renderer(DUH *duh, int n_channels, long pos) DUMB_DEPRECATED;
/* Please use duh_start_sigrenderer() instead. Pass 0 for 'sig'. */
int duh_renderer_get_n_channels(DUH_SIGRENDERER *dr) DUMB_DEPRECATED;
long duh_renderer_get_position(DUH_SIGRENDERER *dr) DUMB_DEPRECATED;
/* Please use the duh_sigrenderer_*() equivalents of these two functions. */
void duh_end_renderer(DUH_SIGRENDERER *dr) DUMB_DEPRECATED;
/* Please use duh_end_sigrenderer() instead. */
DUH_SIGRENDERER *duh_renderer_encapsulate_sigrenderer(DUH_SIGRENDERER *sigrenderer) DUMB_DEPRECATED;
DUH_SIGRENDERER *duh_renderer_get_sigrenderer(DUH_SIGRENDERER *dr) DUMB_DEPRECATED;
DUH_SIGRENDERER *duh_renderer_decompose_to_sigrenderer(DUH_SIGRENDERER *dr) DUMB_DEPRECATED;
/* These functions have become no-ops that just return the parameter.
* So, for instance, replace
* duh_renderer_encapsulate_sigrenderer(my_sigrenderer)
* with
* my_sigrenderer
*/
#endif #endif
/* Impulse Tracker Support */ /* Impulse Tracker Support */
extern int dumb_it_max_to_mix; extern int dumb_it_max_to_mix;
@ -385,34 +305,54 @@ typedef struct DUMB_IT_SIGDATA DUMB_IT_SIGDATA;
typedef struct DUMB_IT_SIGRENDERER DUMB_IT_SIGRENDERER; typedef struct DUMB_IT_SIGRENDERER DUMB_IT_SIGRENDERER;
DUMB_IT_SIGDATA *duh_get_it_sigdata(DUH *duh); DUMB_IT_SIGDATA *duh_get_it_sigdata(DUH *duh);
DUH_SIGRENDERER *duh_encapsulate_it_sigrenderer(DUMB_IT_SIGRENDERER *it_sigrenderer, int n_channels, long pos); DUH_SIGRENDERER *
duh_encapsulate_it_sigrenderer(DUMB_IT_SIGRENDERER *it_sigrenderer,
int n_channels, long pos);
DUMB_IT_SIGRENDERER *duh_get_it_sigrenderer(DUH_SIGRENDERER *sigrenderer); DUMB_IT_SIGRENDERER *duh_get_it_sigrenderer(DUH_SIGRENDERER *sigrenderer);
int dumb_it_trim_silent_patterns(DUH * duh); int dumb_it_trim_silent_patterns(DUH *duh);
typedef int (*dumb_scan_callback)(void *, int, long); typedef int (*dumb_scan_callback)(void *, int, long);
int dumb_it_scan_for_playable_orders(DUMB_IT_SIGDATA *sigdata, dumb_scan_callback callback, void * callback_data); int dumb_it_scan_for_playable_orders(DUMB_IT_SIGDATA *sigdata,
dumb_scan_callback callback,
void *callback_data);
DUH_SIGRENDERER *dumb_it_start_at_order(DUH *duh, int n_channels, int startorder); DUH_SIGRENDERER *dumb_it_start_at_order(DUH *duh, int n_channels,
int startorder);
enum enum {
{
DUMB_IT_RAMP_NONE = 0, DUMB_IT_RAMP_NONE = 0,
DUMB_IT_RAMP_ONOFF_ONLY = 1, DUMB_IT_RAMP_ONOFF_ONLY = 1,
DUMB_IT_RAMP_FULL = 2 DUMB_IT_RAMP_FULL = 2
}; };
void dumb_it_set_ramp_style(DUMB_IT_SIGRENDERER * sigrenderer, int ramp_style); void dumb_it_set_ramp_style(DUMB_IT_SIGRENDERER *sigrenderer, int ramp_style);
void dumb_it_set_loop_callback(DUMB_IT_SIGRENDERER *sigrenderer, int (*callback)(void *data), void *data); void dumb_it_set_loop_callback(DUMB_IT_SIGRENDERER *sigrenderer,
void dumb_it_set_xm_speed_zero_callback(DUMB_IT_SIGRENDERER *sigrenderer, int (*callback)(void *data), void *data); int (*callback)(void *data), void *data);
void dumb_it_set_midi_callback(DUMB_IT_SIGRENDERER *sigrenderer, int (*callback)(void *data, int channel, unsigned char midi_byte), void *data); void dumb_it_set_xm_speed_zero_callback(DUMB_IT_SIGRENDERER *sigrenderer,
void dumb_it_set_global_volume_zero_callback(DUMB_IT_SIGRENDERER *sigrenderer, int (*callback)(void *data), void *data); int (*callback)(void *data),
void *data);
void dumb_it_set_midi_callback(DUMB_IT_SIGRENDERER *sigrenderer,
int (*callback)(void *data, int channel,
unsigned char midi_byte),
void *data);
void dumb_it_set_global_volume_zero_callback(DUMB_IT_SIGRENDERER *sigrenderer,
int (*callback)(void *data),
void *data);
int dumb_it_callback_terminate(void *data); int dumb_it_callback_terminate(void *data);
int dumb_it_callback_midi_block(void *data, int channel, unsigned char midi_byte); int dumb_it_callback_midi_block(void *data, int channel,
unsigned char midi_byte);
/* dumb_*_mod*: restrict_ |= 1-Don't read 15 sample files / 2-Use old pattern counting method */ /* dumb_*_mod*: restrict_ - OR these together */
enum {
DUMB_MOD_RESTRICT_NO_15_SAMPLE = (1 << 0), /* Don't load 15 sample files,
which have no identifying
signature */
DUMB_MOD_RESTRICT_OLD_PATTERN_COUNT =
(1 << 1) /* Use old pattern counting method */
};
DUH *dumb_load_it(const char *filename); DUH *dumb_load_it(const char *filename);
DUH *dumb_load_xm(const char *filename); DUH *dumb_load_xm(const char *filename);
@ -422,7 +362,7 @@ DUH *dumb_load_mod(const char *filename, int restrict_);
DUH *dumb_load_ptm(const char *filename); DUH *dumb_load_ptm(const char *filename);
DUH *dumb_load_669(const char *filename); DUH *dumb_load_669(const char *filename);
DUH *dumb_load_psm(const char *filename, int subsong); DUH *dumb_load_psm(const char *filename, int subsong);
DUH *dumb_load_old_psm(const char * filename); DUH *dumb_load_old_psm(const char *filename);
DUH *dumb_load_mtm(const char *filename); DUH *dumb_load_mtm(const char *filename);
DUH *dumb_load_riff(const char *filename); DUH *dumb_load_riff(const char *filename);
DUH *dumb_load_asy(const char *filename); DUH *dumb_load_asy(const char *filename);
@ -452,7 +392,7 @@ DUH *dumb_load_mod_quick(const char *filename, int restrict_);
DUH *dumb_load_ptm_quick(const char *filename); DUH *dumb_load_ptm_quick(const char *filename);
DUH *dumb_load_669_quick(const char *filename); DUH *dumb_load_669_quick(const char *filename);
DUH *dumb_load_psm_quick(const char *filename, int subsong); DUH *dumb_load_psm_quick(const char *filename, int subsong);
DUH *dumb_load_old_psm_quick(const char * filename); DUH *dumb_load_old_psm_quick(const char *filename);
DUH *dumb_load_mtm_quick(const char *filename); DUH *dumb_load_mtm_quick(const char *filename);
DUH *dumb_load_riff_quick(const char *filename); DUH *dumb_load_riff_quick(const char *filename);
DUH *dumb_load_asy_quick(const char *filename); DUH *dumb_load_asy_quick(const char *filename);
@ -494,7 +434,8 @@ int dumb_it_sd_get_n_instruments(DUMB_IT_SIGDATA *sd);
const unsigned char *dumb_it_sd_get_sample_name(DUMB_IT_SIGDATA *sd, int i); const unsigned char *dumb_it_sd_get_sample_name(DUMB_IT_SIGDATA *sd, int i);
const unsigned char *dumb_it_sd_get_sample_filename(DUMB_IT_SIGDATA *sd, int i); const unsigned char *dumb_it_sd_get_sample_filename(DUMB_IT_SIGDATA *sd, int i);
const unsigned char *dumb_it_sd_get_instrument_name(DUMB_IT_SIGDATA *sd, int i); const unsigned char *dumb_it_sd_get_instrument_name(DUMB_IT_SIGDATA *sd, int i);
const unsigned char *dumb_it_sd_get_instrument_filename(DUMB_IT_SIGDATA *sd, int i); const unsigned char *dumb_it_sd_get_instrument_filename(DUMB_IT_SIGDATA *sd,
int i);
int dumb_it_sd_get_initial_global_volume(DUMB_IT_SIGDATA *sd); int dumb_it_sd_get_initial_global_volume(DUMB_IT_SIGDATA *sd);
void dumb_it_sd_set_initial_global_volume(DUMB_IT_SIGDATA *sd, int gv); void dumb_it_sd_set_initial_global_volume(DUMB_IT_SIGDATA *sd, int gv);
@ -509,7 +450,8 @@ int dumb_it_sd_get_initial_tempo(DUMB_IT_SIGDATA *sd);
void dumb_it_sd_set_initial_tempo(DUMB_IT_SIGDATA *sd, int tempo); void dumb_it_sd_set_initial_tempo(DUMB_IT_SIGDATA *sd, int tempo);
int dumb_it_sd_get_initial_channel_volume(DUMB_IT_SIGDATA *sd, int channel); int dumb_it_sd_get_initial_channel_volume(DUMB_IT_SIGDATA *sd, int channel);
void dumb_it_sd_set_initial_channel_volume(DUMB_IT_SIGDATA *sd, int channel, int volume); void dumb_it_sd_set_initial_channel_volume(DUMB_IT_SIGDATA *sd, int channel,
int volume);
int dumb_it_sr_get_current_order(DUMB_IT_SIGRENDERER *sr); int dumb_it_sr_get_current_order(DUMB_IT_SIGRENDERER *sr);
int dumb_it_sr_get_current_row(DUMB_IT_SIGRENDERER *sr); int dumb_it_sr_get_current_row(DUMB_IT_SIGRENDERER *sr);
@ -529,15 +471,16 @@ void dumb_it_sr_set_speed(DUMB_IT_SIGRENDERER *sr, int speed);
/* Channels passed to any of these functions are 0-based */ /* Channels passed to any of these functions are 0-based */
int dumb_it_sr_get_channel_volume(DUMB_IT_SIGRENDERER *sr, int channel); int dumb_it_sr_get_channel_volume(DUMB_IT_SIGRENDERER *sr, int channel);
void dumb_it_sr_set_channel_volume(DUMB_IT_SIGRENDERER *sr, int channel, int volume); void dumb_it_sr_set_channel_volume(DUMB_IT_SIGRENDERER *sr, int channel,
int volume);
int dumb_it_sr_get_channel_muted(DUMB_IT_SIGRENDERER *sr, int channel); int dumb_it_sr_get_channel_muted(DUMB_IT_SIGRENDERER *sr, int channel);
void dumb_it_sr_set_channel_muted(DUMB_IT_SIGRENDERER *sr, int channel, int muted); void dumb_it_sr_set_channel_muted(DUMB_IT_SIGRENDERER *sr, int channel,
int muted);
typedef struct DUMB_IT_CHANNEL_STATE DUMB_IT_CHANNEL_STATE; typedef struct DUMB_IT_CHANNEL_STATE DUMB_IT_CHANNEL_STATE;
struct DUMB_IT_CHANNEL_STATE struct DUMB_IT_CHANNEL_STATE {
{
int channel; /* 0-based; meaningful for NNA channels */ int channel; /* 0-based; meaningful for NNA channels */
int sample; /* 1-based; 0 if nothing playing, then other fields undef */ int sample; /* 1-based; 0 if nothing playing, then other fields undef */
int freq; /* in Hz */ int freq; /* in Hz */
@ -555,8 +498,8 @@ struct DUMB_IT_CHANNEL_STATE
}; };
/* Values of 64 or more will access NNA channels here. */ /* Values of 64 or more will access NNA channels here. */
void dumb_it_sr_get_channel_state(DUMB_IT_SIGRENDERER *sr, int channel, DUMB_IT_CHANNEL_STATE *state); void dumb_it_sr_get_channel_state(DUMB_IT_SIGRENDERER *sr, int channel,
DUMB_IT_CHANNEL_STATE *state);
/* Signal Design Helper Values */ /* Signal Design Helper Values */
@ -576,7 +519,6 @@ void dumb_it_sr_get_channel_state(DUMB_IT_SIGRENDERER *sr, int channel, DUMB_IT_
*/ */
#define DUMB_PITCH_BASE 1.000225659305069791926712241547647863626 #define DUMB_PITCH_BASE 1.000225659305069791926712241547647863626
/* Signal Design Function Types */ /* Signal Design Function Types */
typedef void sigdata_t; typedef void sigdata_t;
@ -584,43 +526,29 @@ typedef void sigrenderer_t;
typedef sigdata_t *(*DUH_LOAD_SIGDATA)(DUH *duh, DUMBFILE *file); typedef sigdata_t *(*DUH_LOAD_SIGDATA)(DUH *duh, DUMBFILE *file);
typedef sigrenderer_t *(*DUH_START_SIGRENDERER)( typedef sigrenderer_t *(*DUH_START_SIGRENDERER)(DUH *duh, sigdata_t *sigdata,
DUH *duh, int n_channels, long pos);
sigdata_t *sigdata,
int n_channels,
long pos
);
typedef void (*DUH_SIGRENDERER_SET_SIGPARAM)( typedef void (*DUH_SIGRENDERER_SET_SIGPARAM)(sigrenderer_t *sigrenderer,
sigrenderer_t *sigrenderer, unsigned char id, long value);
unsigned char id, long value
);
typedef long (*DUH_SIGRENDERER_GENERATE_SAMPLES)( typedef long (*DUH_SIGRENDERER_GENERATE_SAMPLES)(sigrenderer_t *sigrenderer,
sigrenderer_t *sigrenderer,
float volume, float delta, float volume, float delta,
long size, sample_t **samples long size, sample_t **samples);
);
typedef void (*DUH_SIGRENDERER_GET_CURRENT_SAMPLE)( typedef void (*DUH_SIGRENDERER_GET_CURRENT_SAMPLE)(sigrenderer_t *sigrenderer,
sigrenderer_t *sigrenderer,
float volume, float volume,
sample_t *samples sample_t *samples);
);
typedef long (*DUH_SIGRENDERER_GET_POSITION)( typedef long (*DUH_SIGRENDERER_GET_POSITION)(sigrenderer_t *sigrenderer);
sigrenderer_t *sigrenderer
);
typedef void (*DUH_END_SIGRENDERER)(sigrenderer_t *sigrenderer); typedef void (*DUH_END_SIGRENDERER)(sigrenderer_t *sigrenderer);
typedef void (*DUH_UNLOAD_SIGDATA)(sigdata_t *sigdata); typedef void (*DUH_UNLOAD_SIGDATA)(sigdata_t *sigdata);
/* Signal Design Function Registration */ /* Signal Design Function Registration */
typedef struct DUH_SIGTYPE_DESC typedef struct DUH_SIGTYPE_DESC {
{
long type; long type;
DUH_LOAD_SIGDATA load_sigdata; DUH_LOAD_SIGDATA load_sigdata;
DUH_START_SIGRENDERER start_sigrenderer; DUH_START_SIGRENDERER start_sigrenderer;
@ -630,63 +558,56 @@ typedef struct DUH_SIGTYPE_DESC
DUH_SIGRENDERER_GET_POSITION sigrenderer_get_position; DUH_SIGRENDERER_GET_POSITION sigrenderer_get_position;
DUH_END_SIGRENDERER end_sigrenderer; DUH_END_SIGRENDERER end_sigrenderer;
DUH_UNLOAD_SIGDATA unload_sigdata; DUH_UNLOAD_SIGDATA unload_sigdata;
} } DUH_SIGTYPE_DESC;
DUH_SIGTYPE_DESC;
void dumb_register_sigtype(DUH_SIGTYPE_DESC *desc); void dumb_register_sigtype(DUH_SIGTYPE_DESC *desc);
int duh_add_signal(DUH *duh, DUH_SIGTYPE_DESC *desc, sigdata_t *sigdata); int duh_add_signal(DUH *duh, DUH_SIGTYPE_DESC *desc, sigdata_t *sigdata);
// Decide where to put these functions; new heading? // Decide where to put these functions; new heading?
sigdata_t *duh_get_raw_sigdata(DUH *duh, int sig, long type); sigdata_t *duh_get_raw_sigdata(DUH *duh, int sig, long type);
DUH_SIGRENDERER *duh_encapsulate_raw_sigrenderer(sigrenderer_t *vsigrenderer, DUH_SIGTYPE_DESC *desc, int n_channels, long pos); DUH_SIGRENDERER *duh_encapsulate_raw_sigrenderer(sigrenderer_t *vsigrenderer,
DUH_SIGTYPE_DESC *desc,
int n_channels, long pos);
sigrenderer_t *duh_get_raw_sigrenderer(DUH_SIGRENDERER *sigrenderer, long type); sigrenderer_t *duh_get_raw_sigrenderer(DUH_SIGRENDERER *sigrenderer, long type);
/* Standard Signal Types */ /* Standard Signal Types */
//void dumb_register_sigtype_sample(void); // void dumb_register_sigtype_sample(void);
/* Sample Buffer Allocation Helpers */ /* Sample Buffer Allocation Helpers */
#ifdef DUMB_DECLARE_DEPRECATED
sample_t **create_sample_buffer(int n_channels, long length) DUMB_DEPRECATED;
/* DUMB has been changed to interleave stereo samples. Use
* allocate_sample_buffer() instead, and see the comments for
* duh_sigrenderer_set_analyser_callback().
*/
#endif
sample_t **allocate_sample_buffer(int n_channels, long length); sample_t **allocate_sample_buffer(int n_channels, long length);
void destroy_sample_buffer(sample_t **samples); void destroy_sample_buffer(sample_t **samples);
/* Silencing Helper */ /* Silencing Helper */
void dumb_silence(sample_t *samples, long length); void dumb_silence(sample_t *samples, long length);
/* Click Removal Helpers */ /* Click Removal Helpers */
typedef struct DUMB_CLICK_REMOVER DUMB_CLICK_REMOVER; typedef struct DUMB_CLICK_REMOVER DUMB_CLICK_REMOVER;
DUMB_CLICK_REMOVER *dumb_create_click_remover(void); DUMB_CLICK_REMOVER *dumb_create_click_remover(void);
void dumb_record_click(DUMB_CLICK_REMOVER *cr, long pos, sample_t step); void dumb_record_click(DUMB_CLICK_REMOVER *cr, long pos, sample_t step);
void dumb_remove_clicks(DUMB_CLICK_REMOVER *cr, sample_t *samples, long length, int step, float halflife); void dumb_remove_clicks(DUMB_CLICK_REMOVER *cr, sample_t *samples, long length,
int step, float halflife);
sample_t dumb_click_remover_get_offset(DUMB_CLICK_REMOVER *cr); sample_t dumb_click_remover_get_offset(DUMB_CLICK_REMOVER *cr);
void dumb_destroy_click_remover(DUMB_CLICK_REMOVER *cr); void dumb_destroy_click_remover(DUMB_CLICK_REMOVER *cr);
DUMB_CLICK_REMOVER **dumb_create_click_remover_array(int n); DUMB_CLICK_REMOVER **dumb_create_click_remover_array(int n);
void dumb_record_click_array(int n, DUMB_CLICK_REMOVER **cr, long pos, sample_t *step); void dumb_record_click_array(int n, DUMB_CLICK_REMOVER **cr, long pos,
void dumb_record_click_negative_array(int n, DUMB_CLICK_REMOVER **cr, long pos, sample_t *step); sample_t *step);
void dumb_remove_clicks_array(int n, DUMB_CLICK_REMOVER **cr, sample_t **samples, long length, float halflife); void dumb_record_click_negative_array(int n, DUMB_CLICK_REMOVER **cr, long pos,
void dumb_click_remover_get_offset_array(int n, DUMB_CLICK_REMOVER **cr, sample_t *offset); sample_t *step);
void dumb_remove_clicks_array(int n, DUMB_CLICK_REMOVER **cr,
sample_t **samples, long length, float halflife);
void dumb_click_remover_get_offset_array(int n, DUMB_CLICK_REMOVER **cr,
sample_t *offset);
void dumb_destroy_click_remover_array(int n, DUMB_CLICK_REMOVER **cr); void dumb_destroy_click_remover_array(int n, DUMB_CLICK_REMOVER **cr);
/* Resampling Helpers */ /* Resampling Helpers */
#define DUMB_RQ_ALIASING 0 #define DUMB_RQ_ALIASING 0
@ -698,7 +619,8 @@ void dumb_destroy_click_remover_array(int n, DUMB_CLICK_REMOVER **cr);
#define DUMB_RQ_N_LEVELS 6 #define DUMB_RQ_N_LEVELS 6
extern int dumb_resampling_quality; /* This specifies the default */ extern int dumb_resampling_quality; /* This specifies the default */
void dumb_it_set_resampling_quality(DUMB_IT_SIGRENDERER * sigrenderer, int quality); /* This overrides it */ void dumb_it_set_resampling_quality(DUMB_IT_SIGRENDERER *sigrenderer,
int quality); /* This overrides it */
typedef struct DUMB_RESAMPLER DUMB_RESAMPLER; typedef struct DUMB_RESAMPLER DUMB_RESAMPLER;
@ -706,8 +628,7 @@ typedef struct DUMB_VOLUME_RAMP_INFO DUMB_VOLUME_RAMP_INFO;
typedef void (*DUMB_RESAMPLE_PICKUP)(DUMB_RESAMPLER *resampler, void *data); typedef void (*DUMB_RESAMPLE_PICKUP)(DUMB_RESAMPLER *resampler, void *data);
struct DUMB_RESAMPLER struct DUMB_RESAMPLER {
{
void *src; void *src;
long pos; long pos;
int subpos; int subpos;
@ -718,17 +639,16 @@ struct DUMB_RESAMPLER
int quality; int quality;
/* Everything below this point is internal: do not use. */ /* Everything below this point is internal: do not use. */
union { union {
sample_t x24[3*2]; sample_t x24[3 * 2];
short x16[3*2]; short x16[3 * 2];
signed char x8[3*2]; signed char x8[3 * 2];
} x; } x;
int overshot; int overshot;
double fir_resampler_ratio; double fir_resampler_ratio;
void* fir_resampler[2]; void *fir_resampler[2];
}; };
struct DUMB_VOLUME_RAMP_INFO struct DUMB_VOLUME_RAMP_INFO {
{
float volume; float volume;
float delta; float delta;
float target; float target;
@ -736,52 +656,138 @@ struct DUMB_VOLUME_RAMP_INFO
unsigned char declick_stage; unsigned char declick_stage;
}; };
void dumb_reset_resampler(DUMB_RESAMPLER *resampler, sample_t *src, int src_channels, long pos, long start, long end, int quality); void dumb_reset_resampler(DUMB_RESAMPLER *resampler, sample_t *src,
DUMB_RESAMPLER *dumb_start_resampler(sample_t *src, int src_channels, long pos, long start, long end, int quality); int src_channels, long pos, long start, long end,
long dumb_resample_1_1(DUMB_RESAMPLER *resampler, sample_t *dst, long dst_size, DUMB_VOLUME_RAMP_INFO * volume, float delta); int quality);
long dumb_resample_1_2(DUMB_RESAMPLER *resampler, sample_t *dst, long dst_size, DUMB_VOLUME_RAMP_INFO * volume_left, DUMB_VOLUME_RAMP_INFO * volume_right, float delta); DUMB_RESAMPLER *dumb_start_resampler(sample_t *src, int src_channels, long pos,
long dumb_resample_2_1(DUMB_RESAMPLER *resampler, sample_t *dst, long dst_size, DUMB_VOLUME_RAMP_INFO * volume_left, DUMB_VOLUME_RAMP_INFO * volume_right, float delta); long start, long end, int quality);
long dumb_resample_2_2(DUMB_RESAMPLER *resampler, sample_t *dst, long dst_size, DUMB_VOLUME_RAMP_INFO * volume_left, DUMB_VOLUME_RAMP_INFO * volume_right, float delta); long dumb_resample_1_1(DUMB_RESAMPLER *resampler, sample_t *dst, long dst_size,
void dumb_resample_get_current_sample_1_1(DUMB_RESAMPLER *resampler, DUMB_VOLUME_RAMP_INFO * volume, sample_t *dst); DUMB_VOLUME_RAMP_INFO *volume, float delta);
void dumb_resample_get_current_sample_1_2(DUMB_RESAMPLER *resampler, DUMB_VOLUME_RAMP_INFO * volume_left, DUMB_VOLUME_RAMP_INFO * volume_right, sample_t *dst); long dumb_resample_1_2(DUMB_RESAMPLER *resampler, sample_t *dst, long dst_size,
void dumb_resample_get_current_sample_2_1(DUMB_RESAMPLER *resampler, DUMB_VOLUME_RAMP_INFO * volume_left, DUMB_VOLUME_RAMP_INFO * volume_right, sample_t *dst); DUMB_VOLUME_RAMP_INFO *volume_left,
void dumb_resample_get_current_sample_2_2(DUMB_RESAMPLER *resampler, DUMB_VOLUME_RAMP_INFO * volume_left, DUMB_VOLUME_RAMP_INFO * volume_right, sample_t *dst); DUMB_VOLUME_RAMP_INFO *volume_right, float delta);
long dumb_resample_2_1(DUMB_RESAMPLER *resampler, sample_t *dst, long dst_size,
DUMB_VOLUME_RAMP_INFO *volume_left,
DUMB_VOLUME_RAMP_INFO *volume_right, float delta);
long dumb_resample_2_2(DUMB_RESAMPLER *resampler, sample_t *dst, long dst_size,
DUMB_VOLUME_RAMP_INFO *volume_left,
DUMB_VOLUME_RAMP_INFO *volume_right, float delta);
void dumb_resample_get_current_sample_1_1(DUMB_RESAMPLER *resampler,
DUMB_VOLUME_RAMP_INFO *volume,
sample_t *dst);
void dumb_resample_get_current_sample_1_2(DUMB_RESAMPLER *resampler,
DUMB_VOLUME_RAMP_INFO *volume_left,
DUMB_VOLUME_RAMP_INFO *volume_right,
sample_t *dst);
void dumb_resample_get_current_sample_2_1(DUMB_RESAMPLER *resampler,
DUMB_VOLUME_RAMP_INFO *volume_left,
DUMB_VOLUME_RAMP_INFO *volume_right,
sample_t *dst);
void dumb_resample_get_current_sample_2_2(DUMB_RESAMPLER *resampler,
DUMB_VOLUME_RAMP_INFO *volume_left,
DUMB_VOLUME_RAMP_INFO *volume_right,
sample_t *dst);
void dumb_end_resampler(DUMB_RESAMPLER *resampler); void dumb_end_resampler(DUMB_RESAMPLER *resampler);
void dumb_reset_resampler_16(DUMB_RESAMPLER *resampler, short *src, int src_channels, long pos, long start, long end, int quality); void dumb_reset_resampler_16(DUMB_RESAMPLER *resampler, short *src,
DUMB_RESAMPLER *dumb_start_resampler_16(short *src, int src_channels, long pos, long start, long end, int quality); int src_channels, long pos, long start, long end,
long dumb_resample_16_1_1(DUMB_RESAMPLER *resampler, sample_t *dst, long dst_size, DUMB_VOLUME_RAMP_INFO * volume, float delta); int quality);
long dumb_resample_16_1_2(DUMB_RESAMPLER *resampler, sample_t *dst, long dst_size, DUMB_VOLUME_RAMP_INFO * volume_left, DUMB_VOLUME_RAMP_INFO * volume_right, float delta); DUMB_RESAMPLER *dumb_start_resampler_16(short *src, int src_channels, long pos,
long dumb_resample_16_2_1(DUMB_RESAMPLER *resampler, sample_t *dst, long dst_size, DUMB_VOLUME_RAMP_INFO * volume_left, DUMB_VOLUME_RAMP_INFO * volume_right, float delta); long start, long end, int quality);
long dumb_resample_16_2_2(DUMB_RESAMPLER *resampler, sample_t *dst, long dst_size, DUMB_VOLUME_RAMP_INFO * volume_left, DUMB_VOLUME_RAMP_INFO * volume_right, float delta); long dumb_resample_16_1_1(DUMB_RESAMPLER *resampler, sample_t *dst,
void dumb_resample_get_current_sample_16_1_1(DUMB_RESAMPLER *resampler, DUMB_VOLUME_RAMP_INFO * volume, sample_t *dst); long dst_size, DUMB_VOLUME_RAMP_INFO *volume,
void dumb_resample_get_current_sample_16_1_2(DUMB_RESAMPLER *resampler, DUMB_VOLUME_RAMP_INFO * volume_left, DUMB_VOLUME_RAMP_INFO * volume_right, sample_t *dst); float delta);
void dumb_resample_get_current_sample_16_2_1(DUMB_RESAMPLER *resampler, DUMB_VOLUME_RAMP_INFO * volume_left, DUMB_VOLUME_RAMP_INFO * volume_right, sample_t *dst); long dumb_resample_16_1_2(DUMB_RESAMPLER *resampler, sample_t *dst,
void dumb_resample_get_current_sample_16_2_2(DUMB_RESAMPLER *resampler, DUMB_VOLUME_RAMP_INFO * volume_left, DUMB_VOLUME_RAMP_INFO * volume_right, sample_t *dst); long dst_size, DUMB_VOLUME_RAMP_INFO *volume_left,
DUMB_VOLUME_RAMP_INFO *volume_right, float delta);
long dumb_resample_16_2_1(DUMB_RESAMPLER *resampler, sample_t *dst,
long dst_size, DUMB_VOLUME_RAMP_INFO *volume_left,
DUMB_VOLUME_RAMP_INFO *volume_right, float delta);
long dumb_resample_16_2_2(DUMB_RESAMPLER *resampler, sample_t *dst,
long dst_size, DUMB_VOLUME_RAMP_INFO *volume_left,
DUMB_VOLUME_RAMP_INFO *volume_right, float delta);
void dumb_resample_get_current_sample_16_1_1(DUMB_RESAMPLER *resampler,
DUMB_VOLUME_RAMP_INFO *volume,
sample_t *dst);
void dumb_resample_get_current_sample_16_1_2(
DUMB_RESAMPLER *resampler, DUMB_VOLUME_RAMP_INFO *volume_left,
DUMB_VOLUME_RAMP_INFO *volume_right, sample_t *dst);
void dumb_resample_get_current_sample_16_2_1(
DUMB_RESAMPLER *resampler, DUMB_VOLUME_RAMP_INFO *volume_left,
DUMB_VOLUME_RAMP_INFO *volume_right, sample_t *dst);
void dumb_resample_get_current_sample_16_2_2(
DUMB_RESAMPLER *resampler, DUMB_VOLUME_RAMP_INFO *volume_left,
DUMB_VOLUME_RAMP_INFO *volume_right, sample_t *dst);
void dumb_end_resampler_16(DUMB_RESAMPLER *resampler); void dumb_end_resampler_16(DUMB_RESAMPLER *resampler);
void dumb_reset_resampler_8(DUMB_RESAMPLER *resampler, signed char *src, int src_channels, long pos, long start, long end, int quality); void dumb_reset_resampler_8(DUMB_RESAMPLER *resampler, signed char *src,
DUMB_RESAMPLER *dumb_start_resampler_8(signed char *src, int src_channels, long pos, long start, long end, int quality); int src_channels, long pos, long start, long end,
long dumb_resample_8_1_1(DUMB_RESAMPLER *resampler, sample_t *dst, long dst_size, DUMB_VOLUME_RAMP_INFO * volume, float delta); int quality);
long dumb_resample_8_1_2(DUMB_RESAMPLER *resampler, sample_t *dst, long dst_size, DUMB_VOLUME_RAMP_INFO * volume_left, DUMB_VOLUME_RAMP_INFO * volume_right, float delta); DUMB_RESAMPLER *dumb_start_resampler_8(signed char *src, int src_channels,
long dumb_resample_8_2_1(DUMB_RESAMPLER *resampler, sample_t *dst, long dst_size, DUMB_VOLUME_RAMP_INFO * volume_left, DUMB_VOLUME_RAMP_INFO * volume_right, float delta); long pos, long start, long end,
long dumb_resample_8_2_2(DUMB_RESAMPLER *resampler, sample_t *dst, long dst_size, DUMB_VOLUME_RAMP_INFO * volume_left, DUMB_VOLUME_RAMP_INFO * volume_right, float delta); int quality);
void dumb_resample_get_current_sample_8_1_1(DUMB_RESAMPLER *resampler, DUMB_VOLUME_RAMP_INFO * volume, sample_t *dst); long dumb_resample_8_1_1(DUMB_RESAMPLER *resampler, sample_t *dst,
void dumb_resample_get_current_sample_8_1_2(DUMB_RESAMPLER *resampler, DUMB_VOLUME_RAMP_INFO * volume_left, DUMB_VOLUME_RAMP_INFO * volume_right, sample_t *dst); long dst_size, DUMB_VOLUME_RAMP_INFO *volume,
void dumb_resample_get_current_sample_8_2_1(DUMB_RESAMPLER *resampler, DUMB_VOLUME_RAMP_INFO * volume_left, DUMB_VOLUME_RAMP_INFO * volume_right, sample_t *dst); float delta);
void dumb_resample_get_current_sample_8_2_2(DUMB_RESAMPLER *resampler, DUMB_VOLUME_RAMP_INFO * volume_left, DUMB_VOLUME_RAMP_INFO * volume_right, sample_t *dst); long dumb_resample_8_1_2(DUMB_RESAMPLER *resampler, sample_t *dst,
long dst_size, DUMB_VOLUME_RAMP_INFO *volume_left,
DUMB_VOLUME_RAMP_INFO *volume_right, float delta);
long dumb_resample_8_2_1(DUMB_RESAMPLER *resampler, sample_t *dst,
long dst_size, DUMB_VOLUME_RAMP_INFO *volume_left,
DUMB_VOLUME_RAMP_INFO *volume_right, float delta);
long dumb_resample_8_2_2(DUMB_RESAMPLER *resampler, sample_t *dst,
long dst_size, DUMB_VOLUME_RAMP_INFO *volume_left,
DUMB_VOLUME_RAMP_INFO *volume_right, float delta);
void dumb_resample_get_current_sample_8_1_1(DUMB_RESAMPLER *resampler,
DUMB_VOLUME_RAMP_INFO *volume,
sample_t *dst);
void dumb_resample_get_current_sample_8_1_2(DUMB_RESAMPLER *resampler,
DUMB_VOLUME_RAMP_INFO *volume_left,
DUMB_VOLUME_RAMP_INFO *volume_right,
sample_t *dst);
void dumb_resample_get_current_sample_8_2_1(DUMB_RESAMPLER *resampler,
DUMB_VOLUME_RAMP_INFO *volume_left,
DUMB_VOLUME_RAMP_INFO *volume_right,
sample_t *dst);
void dumb_resample_get_current_sample_8_2_2(DUMB_RESAMPLER *resampler,
DUMB_VOLUME_RAMP_INFO *volume_left,
DUMB_VOLUME_RAMP_INFO *volume_right,
sample_t *dst);
void dumb_end_resampler_8(DUMB_RESAMPLER *resampler); void dumb_end_resampler_8(DUMB_RESAMPLER *resampler);
void dumb_reset_resampler_n(int n, DUMB_RESAMPLER *resampler, void *src, int src_channels, long pos, long start, long end, int quality); void dumb_reset_resampler_n(int n, DUMB_RESAMPLER *resampler, void *src,
DUMB_RESAMPLER *dumb_start_resampler_n(int n, void *src, int src_channels, long pos, long start, long end, int quality); int src_channels, long pos, long start, long end,
long dumb_resample_n_1_1(int n, DUMB_RESAMPLER *resampler, sample_t *dst, long dst_size, DUMB_VOLUME_RAMP_INFO * volume, float delta); int quality);
long dumb_resample_n_1_2(int n, DUMB_RESAMPLER *resampler, sample_t *dst, long dst_size, DUMB_VOLUME_RAMP_INFO * volume_left, DUMB_VOLUME_RAMP_INFO * volume_right, float delta); DUMB_RESAMPLER *dumb_start_resampler_n(int n, void *src, int src_channels,
long dumb_resample_n_2_1(int n, DUMB_RESAMPLER *resampler, sample_t *dst, long dst_size, DUMB_VOLUME_RAMP_INFO * volume_left, DUMB_VOLUME_RAMP_INFO * volume_right, float delta); long pos, long start, long end,
long dumb_resample_n_2_2(int n, DUMB_RESAMPLER *resampler, sample_t *dst, long dst_size, DUMB_VOLUME_RAMP_INFO * volume_left, DUMB_VOLUME_RAMP_INFO * volume_right, float delta); int quality);
void dumb_resample_get_current_sample_n_1_1(int n, DUMB_RESAMPLER *resampler, DUMB_VOLUME_RAMP_INFO * volume, sample_t *dst); long dumb_resample_n_1_1(int n, DUMB_RESAMPLER *resampler, sample_t *dst,
void dumb_resample_get_current_sample_n_1_2(int n, DUMB_RESAMPLER *resampler, DUMB_VOLUME_RAMP_INFO * volume_left, DUMB_VOLUME_RAMP_INFO * volume_right, sample_t *dst); long dst_size, DUMB_VOLUME_RAMP_INFO *volume,
void dumb_resample_get_current_sample_n_2_1(int n, DUMB_RESAMPLER *resampler, DUMB_VOLUME_RAMP_INFO * volume_left, DUMB_VOLUME_RAMP_INFO * volume_right, sample_t *dst); float delta);
void dumb_resample_get_current_sample_n_2_2(int n, DUMB_RESAMPLER *resampler, DUMB_VOLUME_RAMP_INFO * volume_left, DUMB_VOLUME_RAMP_INFO * volume_right, sample_t *dst); long dumb_resample_n_1_2(int n, DUMB_RESAMPLER *resampler, sample_t *dst,
long dst_size, DUMB_VOLUME_RAMP_INFO *volume_left,
DUMB_VOLUME_RAMP_INFO *volume_right, float delta);
long dumb_resample_n_2_1(int n, DUMB_RESAMPLER *resampler, sample_t *dst,
long dst_size, DUMB_VOLUME_RAMP_INFO *volume_left,
DUMB_VOLUME_RAMP_INFO *volume_right, float delta);
long dumb_resample_n_2_2(int n, DUMB_RESAMPLER *resampler, sample_t *dst,
long dst_size, DUMB_VOLUME_RAMP_INFO *volume_left,
DUMB_VOLUME_RAMP_INFO *volume_right, float delta);
void dumb_resample_get_current_sample_n_1_1(int n, DUMB_RESAMPLER *resampler,
DUMB_VOLUME_RAMP_INFO *volume,
sample_t *dst);
void dumb_resample_get_current_sample_n_1_2(int n, DUMB_RESAMPLER *resampler,
DUMB_VOLUME_RAMP_INFO *volume_left,
DUMB_VOLUME_RAMP_INFO *volume_right,
sample_t *dst);
void dumb_resample_get_current_sample_n_2_1(int n, DUMB_RESAMPLER *resampler,
DUMB_VOLUME_RAMP_INFO *volume_left,
DUMB_VOLUME_RAMP_INFO *volume_right,
sample_t *dst);
void dumb_resample_get_current_sample_n_2_2(int n, DUMB_RESAMPLER *resampler,
DUMB_VOLUME_RAMP_INFO *volume_left,
DUMB_VOLUME_RAMP_INFO *volume_right,
sample_t *dst);
void dumb_end_resampler_n(int n, DUMB_RESAMPLER *resampler); void dumb_end_resampler_n(int n, DUMB_RESAMPLER *resampler);
/* This sets the default panning separation for hard panned formats, /* This sets the default panning separation for hard panned formats,
@ -792,21 +798,13 @@ extern int dumb_it_default_panning_separation; /* in percent, default 25 */
/* DUH Construction */ /* DUH Construction */
DUH *make_duh( DUH *make_duh(dumb_off_t length, int n_tags, const char *const tag[][2],
long length, int n_signals, DUH_SIGTYPE_DESC *desc[], sigdata_t *sigdata[]);
int n_tags,
const char *const tag[][2],
int n_signals,
DUH_SIGTYPE_DESC *desc[],
sigdata_t *sigdata[]
);
void duh_set_length(DUH *duh, long length);
void duh_set_length(DUH *duh, dumb_off_t length);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
#endif /* DUMB_H */ #endif /* DUMB_H */

View file

@ -20,8 +20,6 @@
#ifndef INTERNAL_ALDUMB_H #ifndef INTERNAL_ALDUMB_H
#define INTERNAL_ALDUMB_H #define INTERNAL_ALDUMB_H
void _dat_unload_duh(void *duh); void _dat_unload_duh(void *duh);
#endif /* INTERNAL_DUMB_H */ #endif /* INTERNAL_DUMB_H */

View file

@ -6,38 +6,38 @@
#ifdef BARRAY_DECORATE #ifdef BARRAY_DECORATE
#undef PASTE #undef PASTE
#undef EVALUATE #undef EVALUATE
#define PASTE(a,b) a ## b #define PASTE(a, b) a##b
#define EVALUATE(a,b) PASTE(a,b) #define EVALUATE(a, b) PASTE(a, b)
#define bit_array_create EVALUATE(BARRAY_DECORATE,_bit_array_create) #define bit_array_create EVALUATE(BARRAY_DECORATE, _bit_array_create)
#define bit_array_destroy EVALUATE(BARRAY_DECORATE,_bit_array_destroy) #define bit_array_destroy EVALUATE(BARRAY_DECORATE, _bit_array_destroy)
#define bit_array_dup EVALUATE(BARRAY_DECORATE,_bit_array_dup) #define bit_array_dup EVALUATE(BARRAY_DECORATE, _bit_array_dup)
#define bit_array_reset EVALUATE(BARRAY_DECORATE,_bit_array_reset) #define bit_array_reset EVALUATE(BARRAY_DECORATE, _bit_array_reset)
#define bit_array_set EVALUATE(BARRAY_DECORATE,_bit_array_set) #define bit_array_set EVALUATE(BARRAY_DECORATE, _bit_array_set)
#define bit_array_set_range EVALUATE(BARRAY_DECORATE,_bit_array_set_range) #define bit_array_set_range EVALUATE(BARRAY_DECORATE, _bit_array_set_range)
#define bit_array_test EVALUATE(BARRAY_DECORATE,_bit_array_test) #define bit_array_test EVALUATE(BARRAY_DECORATE, _bit_array_test)
#define bit_array_test_range EVALUATE(BARRAY_DECORATE,_bit_array_test_range) #define bit_array_test_range EVALUATE(BARRAY_DECORATE, _bit_array_test_range)
#define bit_array_clear EVALUATE(BARRAY_DECORATE,_bit_array_clear) #define bit_array_clear EVALUATE(BARRAY_DECORATE, _bit_array_clear)
#define bit_array_clear_range EVALUATE(BARRAY_DECORATE,_bit_array_clear_range) #define bit_array_clear_range EVALUATE(BARRAY_DECORATE, _bit_array_clear_range)
#define bit_array_merge EVALUATE(BARRAY_DECORATE,_bit_array_merge) #define bit_array_merge EVALUATE(BARRAY_DECORATE, _bit_array_merge)
#define bit_array_mask EVALUATE(BARRAY_DECORATE,_bit_array_mask) #define bit_array_mask EVALUATE(BARRAY_DECORATE, _bit_array_mask)
#endif #endif
void * bit_array_create(size_t size); void *bit_array_create(size_t size);
void bit_array_destroy(void * array); void bit_array_destroy(void *array);
void * bit_array_dup(void * array); void *bit_array_dup(void *array);
void bit_array_reset(void * array); void bit_array_reset(void *array);
void bit_array_set(void * array, size_t bit); void bit_array_set(void *array, size_t bit);
void bit_array_set_range(void * array, size_t bit, size_t count); void bit_array_set_range(void *array, size_t bit, size_t count);
int bit_array_test(void * array, size_t bit); int bit_array_test(void *array, size_t bit);
int bit_array_test_range(void * array, size_t bit, size_t count); int bit_array_test_range(void *array, size_t bit, size_t count);
void bit_array_clear(void * array, size_t bit); void bit_array_clear(void *array, size_t bit);
void bit_array_clear_range(void * array, size_t bit, size_t count); void bit_array_clear_range(void *array, size_t bit, size_t count);
void bit_array_merge(void * array, void * source, size_t offset); void bit_array_merge(void *array, void *source, size_t offset);
void bit_array_mask(void * array, void * source, size_t offset); void bit_array_mask(void *array, void *source, size_t offset);
#endif #endif

View file

@ -26,37 +26,42 @@
#ifndef INTERNAL_DUMB_H #ifndef INTERNAL_DUMB_H
#define INTERNAL_DUMB_H #define INTERNAL_DUMB_H
#include "../dumb.h"
#undef MIN #undef MIN
#undef MAX #undef MAX
#undef MID #undef MID
#define MIN(x,y) (((x) < (y)) ? (x) : (y)) #define MIN(x, y) (((x) < (y)) ? (x) : (y))
#define MAX(x,y) (((x) > (y)) ? (x) : (y)) #define MAX(x, y) (((x) > (y)) ? (x) : (y))
#define MID(x,y,z) MAX((x), MIN((y), (z))) #define MID(x, y, z) MAX((x), MIN((y), (z)))
#undef ABS #undef ABS
#define ABS(x) (((x) >= 0) ? (x) : (-(x))) #define ABS(x) (((x) >= 0) ? (x) : (-(x)))
typedef struct DUH_SIGTYPE_DESC_LINK #ifndef LONG_LONG
{ #if defined __GNUC__ || defined __INTEL_COMPILER || defined __MWERKS__ || \
defined __sgi
#define LONG_LONG long long
#elif defined _MSC_VER || defined __WATCOMC__
#define LONG_LONG __int64
#else
#error 64-bit integer type unknown
#endif
#endif
typedef struct DUH_SIGTYPE_DESC_LINK {
struct DUH_SIGTYPE_DESC_LINK *next; struct DUH_SIGTYPE_DESC_LINK *next;
DUH_SIGTYPE_DESC *desc; DUH_SIGTYPE_DESC *desc;
} } DUH_SIGTYPE_DESC_LINK;
DUH_SIGTYPE_DESC_LINK;
typedef struct DUH_SIGNAL {
typedef struct DUH_SIGNAL
{
sigdata_t *sigdata; sigdata_t *sigdata;
DUH_SIGTYPE_DESC *desc; DUH_SIGTYPE_DESC *desc;
} } DUH_SIGNAL;
DUH_SIGNAL;
struct DUH {
struct DUH dumb_off_t length;
{
long length;
int n_tags; int n_tags;
char *(*tag)[2]; char *(*tag)[2];
@ -65,8 +70,6 @@ struct DUH
DUH_SIGNAL **signal; DUH_SIGNAL **signal;
}; };
DUH_SIGTYPE_DESC *_dumb_get_sigtype_desc(long type); DUH_SIGTYPE_DESC *_dumb_get_sigtype_desc(long type);
#endif /* INTERNAL_DUMB_H */ #endif /* INTERNAL_DUMB_H */

View file

@ -3,8 +3,7 @@
#include "../dumb.h" #include "../dumb.h"
struct DUMBFILE struct DUMBFILE {
{
const DUMBFILE_SYSTEM *dfs; const DUMBFILE_SYSTEM *dfs;
void *file; void *file;
long pos; long pos;

View file

@ -1,18 +0,0 @@
#ifndef _FIR_RESAMPLER_H_
#define _FIR_RESAMPLER_H_
void fir_init();
void * fir_resampler_create();
void fir_resampler_delete(void *);
void * fir_resampler_dup(void *);
int fir_resampler_get_free_count(void *);
void fir_resampler_write_sample(void *, short sample);
void fir_resampler_set_rate( void *, double new_factor );
int fir_resampler_ready(void *);
void fir_resampler_clear(void *);
int fir_resampler_get_sample(void *);
void fir_resampler_remove_sample(void *);
#endif

View file

@ -27,7 +27,6 @@
#ifndef INTERNAL_IT_H #ifndef INTERNAL_IT_H
#define INTERNAL_IT_H #define INTERNAL_IT_H
#define BIT_ARRAY_BULLSHIT #define BIT_ARRAY_BULLSHIT
#include <stddef.h> #include <stddef.h>
@ -35,7 +34,6 @@
#include "barray.h" #include "barray.h"
#include "tarray.h" #include "tarray.h"
/** TO DO: THINK ABOUT THE FOLLOWING: /** TO DO: THINK ABOUT THE FOLLOWING:
sigdata->flags & IT_COMPATIBLE_GXX sigdata->flags & IT_COMPATIBLE_GXX
@ -49,8 +47,6 @@ sigdata->flags & IT_COMPATIBLE_GXX
NewFrequency = OldFrequency * NewC5 / OldC5; NewFrequency = OldFrequency * NewC5 / OldC5;
*/ */
/* These #defines are TEMPORARY. They are used to write alternative code to /* These #defines are TEMPORARY. They are used to write alternative code to
* handle ambiguities in the format specification. The correct code in each * handle ambiguities in the format specification. The correct code in each
* case will be determined most likely by experimentation. * case will be determined most likely by experimentation.
@ -60,8 +56,6 @@ sigdata->flags & IT_COMPATIBLE_GXX
#define SUSTAIN_LOOP_OVERRIDES_NORMAL_LOOP #define SUSTAIN_LOOP_OVERRIDES_NORMAL_LOOP
#define VOLUME_OUT_OF_RANGE_SETS_MAXIMUM #define VOLUME_OUT_OF_RANGE_SETS_MAXIMUM
#define SIGTYPE_IT DUMB_ID('I', 'T', ' ', ' ') #define SIGTYPE_IT DUMB_ID('I', 'T', ' ', ' ')
#define IT_SIGNATURE DUMB_ID('I', 'M', 'P', 'M') #define IT_SIGNATURE DUMB_ID('I', 'M', 'P', 'M')
@ -72,13 +66,10 @@ sigdata->flags & IT_COMPATIBLE_GXX
#define IT_MPTX_SIGNATURE DUMB_ID('X', 'T', 'P', 'M') #define IT_MPTX_SIGNATURE DUMB_ID('X', 'T', 'P', 'M')
#define IT_INSM_SIGNATURE DUMB_ID('M', 'S', 'N', 'I') #define IT_INSM_SIGNATURE DUMB_ID('M', 'S', 'N', 'I')
/* This is divided by the tempo times 256 to get the interval between ticks. /* This is divided by the tempo times 256 to get the interval between ticks.
*/ */
#define TICK_TIME_DIVIDEND (65536 * 5 * 128) #define TICK_TIME_DIVIDEND (65536 * 5 * 128)
/* I'm not going to try to explain this, because I didn't derive it very /* I'm not going to try to explain this, because I didn't derive it very
* formally ;) * formally ;)
*/ */
@ -88,8 +79,6 @@ sigdata->flags & IT_COMPATIBLE_GXX
#define AMIGA_CLOCK 3546895 #define AMIGA_CLOCK 3546895
#define AMIGA_DIVISOR ((float)(16.0 * AMIGA_CLOCK)) #define AMIGA_DIVISOR ((float)(16.0 * AMIGA_CLOCK))
typedef struct IT_MIDI IT_MIDI; typedef struct IT_MIDI IT_MIDI;
typedef struct IT_FILTER_STATE IT_FILTER_STATE; typedef struct IT_FILTER_STATE IT_FILTER_STATE;
typedef struct IT_ENVELOPE IT_ENVELOPE; typedef struct IT_ENVELOPE IT_ENVELOPE;
@ -103,10 +92,7 @@ typedef struct IT_CHANNEL IT_CHANNEL;
typedef struct IT_CHECKPOINT IT_CHECKPOINT; typedef struct IT_CHECKPOINT IT_CHECKPOINT;
typedef struct IT_CALLBACKS IT_CALLBACKS; typedef struct IT_CALLBACKS IT_CALLBACKS;
struct IT_MIDI {
struct IT_MIDI
{
unsigned char SFmacro[16][16]; // read these from 0x120 unsigned char SFmacro[16][16]; // read these from 0x120
unsigned char SFmacrolen[16]; unsigned char SFmacrolen[16];
unsigned short SFmacroz[16]; /* Bitfield; bit 0 set = z in first position */ unsigned short SFmacroz[16]; /* Bitfield; bit 0 set = z in first position */
@ -114,23 +100,17 @@ struct IT_MIDI
unsigned char Zmacrolen[128]; unsigned char Zmacrolen[128];
}; };
struct IT_FILTER_STATE {
struct IT_FILTER_STATE
{
sample_t currsample, prevsample; sample_t currsample, prevsample;
}; };
#define IT_ENVELOPE_ON 1 #define IT_ENVELOPE_ON 1
#define IT_ENVELOPE_LOOP_ON 2 #define IT_ENVELOPE_LOOP_ON 2
#define IT_ENVELOPE_SUSTAIN_LOOP 4 #define IT_ENVELOPE_SUSTAIN_LOOP 4
#define IT_ENVELOPE_CARRY 8 #define IT_ENVELOPE_CARRY 8
#define IT_ENVELOPE_PITCH_IS_FILTER 128 #define IT_ENVELOPE_PITCH_IS_FILTER 128
struct IT_ENVELOPE struct IT_ENVELOPE {
{
unsigned char flags; unsigned char flags;
unsigned char n_nodes; unsigned char n_nodes;
unsigned char loop_start; unsigned char loop_start;
@ -141,8 +121,6 @@ struct IT_ENVELOPE
unsigned short node_t[25]; unsigned short node_t[25];
}; };
#define NNA_NOTE_CUT 0 #define NNA_NOTE_CUT 0
#define NNA_NOTE_CONTINUE 1 #define NNA_NOTE_CONTINUE 1
#define NNA_NOTE_OFF 2 #define NNA_NOTE_OFF 2
@ -157,8 +135,7 @@ struct IT_ENVELOPE
#define DCA_NOTE_OFF 1 #define DCA_NOTE_OFF 1
#define DCA_NOTE_FADE 2 #define DCA_NOTE_FADE 2
struct IT_INSTRUMENT struct IT_INSTRUMENT {
{
unsigned char name[27]; unsigned char name[27];
unsigned char filename[14]; unsigned char filename[14];
@ -184,11 +161,9 @@ struct IT_INSTRUMENT
unsigned char map_note[120]; unsigned char map_note[120];
unsigned short map_sample[120]; unsigned short map_sample[120];
//int output; // int output;
}; };
#define IT_SAMPLE_EXISTS 1 #define IT_SAMPLE_EXISTS 1
#define IT_SAMPLE_16BIT 2 #define IT_SAMPLE_16BIT 2
#define IT_SAMPLE_STEREO 4 #define IT_SAMPLE_STEREO 4
@ -205,8 +180,7 @@ struct IT_INSTRUMENT
#define IT_VIBRATO_RAMP_DOWN 5 #define IT_VIBRATO_RAMP_DOWN 5
#define IT_VIBRATO_RAMP_UP 6 #define IT_VIBRATO_RAMP_UP 6
struct IT_SAMPLE struct IT_SAMPLE {
{
unsigned char name[35]; unsigned char name[35];
unsigned char filename[15]; unsigned char filename[15];
unsigned char flags; unsigned char flags;
@ -238,8 +212,6 @@ struct IT_SAMPLE
int max_resampling_quality; int max_resampling_quality;
}; };
#define IT_ENTRY_NOTE 1 #define IT_ENTRY_NOTE 1
#define IT_ENTRY_INSTRUMENT 2 #define IT_ENTRY_INSTRUMENT 2
#define IT_ENTRY_VOLPAN 4 #define IT_ENTRY_VOLPAN 4
@ -282,7 +254,7 @@ struct IT_SAMPLE
#define IT_GLOBAL_VOLUME_SLIDE 23 #define IT_GLOBAL_VOLUME_SLIDE 23
#define IT_SET_PANNING 24 #define IT_SET_PANNING 24
#define IT_PANBRELLO 25 #define IT_PANBRELLO 25
#define IT_MIDI_MACRO 26 //see MIDI.TXT #define IT_MIDI_MACRO 26 // see MIDI.TXT
/* Some effects needed for XM compatibility */ /* Some effects needed for XM compatibility */
#define IT_XM_PORTAMENTO_DOWN 27 #define IT_XM_PORTAMENTO_DOWN 27
@ -369,8 +341,7 @@ SEx Pattern delay for x rows
SFx Set parameterised MIDI Macro SFx Set parameterised MIDI Macro
*/ */
struct IT_ENTRY struct IT_ENTRY {
{
unsigned char channel; /* End of row if channel >= DUMB_IT_N_CHANNELS */ unsigned char channel; /* End of row if channel >= DUMB_IT_N_CHANNELS */
unsigned char mask; unsigned char mask;
unsigned char note; unsigned char note;
@ -380,17 +351,12 @@ struct IT_ENTRY
unsigned char effectvalue; unsigned char effectvalue;
}; };
struct IT_PATTERN {
struct IT_PATTERN
{
int n_rows; int n_rows;
int n_entries; int n_entries;
IT_ENTRY *entry; IT_ENTRY *entry;
}; };
#define IT_STEREO 1 #define IT_STEREO 1
#define IT_USE_INSTRUMENTS 4 #define IT_USE_INSTRUMENTS 4
#define IT_LINEAR_SLIDES 8 /* If not set, use Amiga slides */ #define IT_LINEAR_SLIDES 8 /* If not set, use Amiga slides */
@ -413,13 +379,14 @@ struct IT_PATTERN
#define IT_WAS_AN_STM 4096 #define IT_WAS_AN_STM 4096
#define IT_WAS_PROCESSED 8192 /* Will be set the first time a sigdata passes through a sigrenderer */ #define IT_WAS_PROCESSED \
8192 /* Will be set the first time a sigdata passes through a sigrenderer \
*/
#define IT_ORDER_END 255 #define IT_ORDER_END 255
#define IT_ORDER_SKIP 254 #define IT_ORDER_SKIP 254
struct DUMB_IT_SIGDATA struct DUMB_IT_SIGDATA {
{
unsigned char name[65]; unsigned char name[65];
unsigned char *song_message; unsigned char *song_message;
@ -453,25 +420,19 @@ struct DUMB_IT_SIGDATA
IT_CHECKPOINT *checkpoint; IT_CHECKPOINT *checkpoint;
}; };
struct IT_PLAYING_ENVELOPE {
struct IT_PLAYING_ENVELOPE
{
int next_node; int next_node;
int tick; int tick;
int value; int value;
}; };
#define IT_PLAYING_BACKGROUND 1 #define IT_PLAYING_BACKGROUND 1
#define IT_PLAYING_SUSTAINOFF 2 #define IT_PLAYING_SUSTAINOFF 2
#define IT_PLAYING_FADING 4 #define IT_PLAYING_FADING 4
#define IT_PLAYING_DEAD 8 #define IT_PLAYING_DEAD 8
#define IT_PLAYING_REVERSE 16 #define IT_PLAYING_REVERSE 16
struct IT_PLAYING struct IT_PLAYING {
{
int flags; int flags;
int resampling_quality; int resampling_quality;
@ -504,8 +465,11 @@ struct IT_PLAYING
unsigned char filter_cutoff; unsigned char filter_cutoff;
unsigned char filter_resonance; unsigned char filter_resonance;
unsigned short true_filter_cutoff; /* These incorporate the filter envelope, and will not */ unsigned short
unsigned char true_filter_resonance; /* be changed if they would be set to 127<<8 and 0. */ true_filter_cutoff; /* These incorporate the filter envelope, and will
not */
unsigned char true_filter_resonance; /* be changed if they would be set to
127<<8 and 0. */
unsigned char vibrato_speed; unsigned char vibrato_speed;
unsigned char vibrato_depth; unsigned char vibrato_depth;
@ -553,19 +517,16 @@ struct IT_PLAYING
*/ */
long time_lost; long time_lost;
//int output; // int output;
}; };
#define IT_CHANNEL_MUTED 1 #define IT_CHANNEL_MUTED 1
#define IT_ENV_VOLUME 1 #define IT_ENV_VOLUME 1
#define IT_ENV_PANNING 2 #define IT_ENV_PANNING 2
#define IT_ENV_PITCH 4 #define IT_ENV_PITCH 4
struct IT_CHANNEL struct IT_CHANNEL {
{
int flags; int flags;
unsigned char volume; unsigned char volume;
@ -600,7 +561,7 @@ struct IT_CHANNEL
unsigned char new_note_action; unsigned char new_note_action;
unsigned char const* arpeggio_table; unsigned char const *arpeggio_table;
signed char arpeggio_offsets[3]; signed char arpeggio_offsets[3];
int arpeggio_shift; int arpeggio_shift;
@ -609,7 +570,8 @@ struct IT_CHANNEL
int retrig_tick; int retrig_tick;
unsigned char tremor; unsigned char tremor;
unsigned char tremor_time; /* Bit 6 set if note on; bit 7 set if tremor active. */ unsigned char
tremor_time; /* Bit 6 set if note on; bit 7 set if tremor active. */
unsigned char vibrato_waveform; unsigned char vibrato_waveform;
unsigned char tremolo_waveform; unsigned char tremolo_waveform;
@ -618,13 +580,15 @@ struct IT_CHANNEL
int portamento; int portamento;
int toneporta; int toneporta;
int toneslide; int toneslide;
unsigned char toneslide_tick, last_toneslide_tick, ptm_toneslide, ptm_last_toneslide, okt_toneslide; unsigned char toneslide_tick, last_toneslide_tick, ptm_toneslide,
ptm_last_toneslide, okt_toneslide;
unsigned char destnote; unsigned char destnote;
unsigned char toneslide_retrig; unsigned char toneslide_retrig;
unsigned char glissando; unsigned char glissando;
/** WARNING - for neatness, should one or both of these be in the IT_PLAYING struct? */ /** WARNING - for neatness, should one or both of these be in the IT_PLAYING
* struct? */
unsigned short sample; unsigned short sample;
unsigned char truenote; unsigned char truenote;
@ -667,17 +631,14 @@ struct IT_CHANNEL
IT_PLAYING *playing; IT_PLAYING *playing;
#ifdef BIT_ARRAY_BULLSHIT #ifdef BIT_ARRAY_BULLSHIT
void * played_patjump; void *played_patjump;
int played_patjump_order; int played_patjump_order;
#endif #endif
//int output; // int output;
}; };
struct DUMB_IT_SIGRENDERER {
struct DUMB_IT_SIGRENDERER
{
DUMB_IT_SIGDATA *sigdata; DUMB_IT_SIGDATA *sigdata;
int n_channels; int n_channels;
@ -720,14 +681,13 @@ struct DUMB_IT_SIGRENDERER
IT_CALLBACKS *callbacks; IT_CALLBACKS *callbacks;
#ifdef BIT_ARRAY_BULLSHIT #ifdef BIT_ARRAY_BULLSHIT
/* bit array, which rows are played, only checked by pattern break or loop commands */ /* bit array, which rows are played, only checked by pattern break or loop
void * played; * commands */
void *played;
/* /*
Loop indicator for internal processes, may also be useful for external processes Loop indicator for internal processes, may also be useful for external
0 - Not looped processes 0 - Not looped 1 - Looped -1 - Continued past loop
1 - Looped
-1 - Continued past loop
*/ */
int looped; int looped;
@ -736,7 +696,7 @@ struct DUMB_IT_SIGRENDERER
*/ */
LONG_LONG time_played; LONG_LONG time_played;
void * row_timekeeper; void *row_timekeeper;
#endif #endif
long gvz_time; long gvz_time;
@ -744,22 +704,16 @@ struct DUMB_IT_SIGRENDERER
int ramp_style; int ramp_style;
//int max_output; // int max_output;
}; };
struct IT_CHECKPOINT {
struct IT_CHECKPOINT
{
IT_CHECKPOINT *next; IT_CHECKPOINT *next;
long time; long time;
DUMB_IT_SIGRENDERER *sigrenderer; DUMB_IT_SIGRENDERER *sigrenderer;
}; };
struct IT_CALLBACKS {
struct IT_CALLBACKS
{
int (*loop)(void *data); int (*loop)(void *data);
void *loop_data; void *loop_data;
/* Return 1 to prevent looping; the music will terminate abruptly. If you /* Return 1 to prevent looping; the music will terminate abruptly. If you
@ -786,15 +740,11 @@ struct IT_CALLBACKS
/* Return 1 to terminate the module when global volume is set to zero. */ /* Return 1 to terminate the module when global volume is set to zero. */
}; };
void _dumb_it_end_sigrenderer(sigrenderer_t *sigrenderer); void _dumb_it_end_sigrenderer(sigrenderer_t *sigrenderer);
void _dumb_it_unload_sigdata(sigdata_t *vsigdata); void _dumb_it_unload_sigdata(sigdata_t *vsigdata);
extern DUH_SIGTYPE_DESC _dumb_sigtype_it; extern DUH_SIGTYPE_DESC _dumb_sigtype_it;
#define XM_APPREGIO 0 #define XM_APPREGIO 0
#define XM_PORTAMENTO_UP 1 #define XM_PORTAMENTO_UP 1
#define XM_PORTAMENTO_DOWN 2 #define XM_PORTAMENTO_DOWN 2
@ -819,7 +769,7 @@ extern DUH_SIGTYPE_DESC _dumb_sigtype_it;
#define XM_MULTI_RETRIG 27 /* R */ #define XM_MULTI_RETRIG 27 /* R */
#define XM_TREMOR 29 /* T */ #define XM_TREMOR 29 /* T */
#define XM_X 33 /* X */ #define XM_X 33 /* X */
#define XM_N_EFFECTS (10+26) #define XM_N_EFFECTS (10 + 26)
#define XM_E_SET_FILTER 0x0 #define XM_E_SET_FILTER 0x0
#define XM_E_FINE_PORTA_UP 0x1 #define XM_E_FINE_PORTA_UP 0x1
@ -846,27 +796,25 @@ extern DUH_SIGTYPE_DESC _dumb_sigtype_it;
* way, these effects can be manipulated like regular effects. * way, these effects can be manipulated like regular effects.
*/ */
#define EBASE (XM_N_EFFECTS) #define EBASE (XM_N_EFFECTS)
#define XBASE (EBASE+16) #define XBASE (EBASE + 16)
#define SBASE (IT_N_EFFECTS) #define SBASE (IT_N_EFFECTS)
#define EFFECT_VALUE(x, y) (((x)<<4)|(y)) #define EFFECT_VALUE(x, y) (((x) << 4) | (y))
#define HIGH(v) ((v)>>4) #define HIGH(v) ((v) >> 4)
#define LOW(v) ((v)&0x0F) #define LOW(v) ((v)&0x0F)
#define SET_HIGH(v, x) v = (((x)<<4)|((v)&0x0F)) #define SET_HIGH(v, x) v = (((x) << 4) | ((v)&0x0F))
#define SET_LOW(v, y) v = (((v)&0xF0)|(y)) #define SET_LOW(v, y) v = (((v)&0xF0) | (y))
#define BCD_TO_NORMAL(v) (HIGH(v)*10+LOW(v)) #define BCD_TO_NORMAL(v) (HIGH(v) * 10 + LOW(v))
#if 0 #if 0
unsigned char **_dumb_malloc2(int w, int h); unsigned char **_dumb_malloc2(int w, int h);
void _dumb_free2(unsigned char **line); void _dumb_free2(unsigned char **line);
#endif #endif
void _dumb_it_xm_convert_effect(int effect, int value, IT_ENTRY *entry, int mod); void _dumb_it_xm_convert_effect(int effect, int value, IT_ENTRY *entry,
int mod);
int _dumb_it_fix_invalid_orders(DUMB_IT_SIGDATA *sigdata); int _dumb_it_fix_invalid_orders(DUMB_IT_SIGDATA *sigdata);
#define PTM_APPREGIO 0 #define PTM_APPREGIO 0
#define PTM_PORTAMENTO_UP 1 #define PTM_PORTAMENTO_UP 1
#define PTM_PORTAMENTO_DOWN 2 #define PTM_PORTAMENTO_DOWN 2
@ -918,9 +866,9 @@ long _dumb_it_read_sample_data_adpcm4(IT_SAMPLE *sample, DUMBFILE *f);
void _dumb_it_interleave_stereo_sample(IT_SAMPLE *sample); void _dumb_it_interleave_stereo_sample(IT_SAMPLE *sample);
/* Calling either of these is optional */ /* Calling either of these is optional */
void _dumb_init_cubic(); void _dumb_init_cubic(void);
#ifdef _USE_SSE #ifdef _USE_SSE
void _dumb_init_sse(); void _dumb_init_sse(void);
#endif #endif
#endif /* INTERNAL_IT_H */ #endif /* INTERNAL_IT_H */

View file

@ -5,36 +5,44 @@
#ifdef RESAMPLER_DECORATE #ifdef RESAMPLER_DECORATE
#undef PASTE #undef PASTE
#undef EVALUATE #undef EVALUATE
#define PASTE(a,b) a ## b #define PASTE(a, b) a##b
#define EVALUATE(a,b) PASTE(a,b) #define EVALUATE(a, b) PASTE(a, b)
#define resampler_init EVALUATE(RESAMPLER_DECORATE,_resampler_init) #define resampler_init EVALUATE(RESAMPLER_DECORATE, _resampler_init)
#define resampler_create EVALUATE(RESAMPLER_DECORATE,_resampler_create) #define resampler_create EVALUATE(RESAMPLER_DECORATE, _resampler_create)
#define resampler_delete EVALUATE(RESAMPLER_DECORATE,_resampler_delete) #define resampler_delete EVALUATE(RESAMPLER_DECORATE, _resampler_delete)
#define resampler_dup EVALUATE(RESAMPLER_DECORATE,_resampler_dup) #define resampler_dup EVALUATE(RESAMPLER_DECORATE, _resampler_dup)
#define resampler_dup_inplace EVALUATE(RESAMPLER_DECORATE,_resampler_dup_inplace) #define resampler_dup_inplace \
#define resampler_set_quality EVALUATE(RESAMPLER_DECORATE,_resampler_set_quality) EVALUATE(RESAMPLER_DECORATE, _resampler_dup_inplace)
#define resampler_get_free_count EVALUATE(RESAMPLER_DECORATE,_resampler_get_free_count) #define resampler_set_quality \
#define resampler_write_sample EVALUATE(RESAMPLER_DECORATE,_resampler_write_sample) EVALUATE(RESAMPLER_DECORATE, _resampler_set_quality)
#define resampler_write_sample_fixed EVALUATE(RESAMPLER_DECORATE,_resampler_write_sample_fixed) #define resampler_get_free_count \
#define resampler_write_sample_float EVALUATE(RESAMPLER_DECORATE,_resampler_write_sample_float) EVALUATE(RESAMPLER_DECORATE, _resampler_get_free_count)
#define resampler_set_rate EVALUATE(RESAMPLER_DECORATE,_resampler_set_rate) #define resampler_write_sample \
#define resampler_ready EVALUATE(RESAMPLER_DECORATE,_resampler_ready) EVALUATE(RESAMPLER_DECORATE, _resampler_write_sample)
#define resampler_clear EVALUATE(RESAMPLER_DECORATE,_resampler_clear) #define resampler_write_sample_fixed \
#define resampler_get_sample_count EVALUATE(RESAMPLER_DECORATE,_resampler_get_sample_count) EVALUATE(RESAMPLER_DECORATE, _resampler_write_sample_fixed)
#define resampler_get_sample EVALUATE(RESAMPLER_DECORATE,_resampler_get_sample) #define resampler_write_sample_float \
#define resampler_get_sample_float EVALUATE(RESAMPLER_DECORATE,_resampler_get_sample_float) EVALUATE(RESAMPLER_DECORATE, _resampler_write_sample_float)
#define resampler_remove_sample EVALUATE(RESAMPLER_DECORATE,_resampler_remove_sample) #define resampler_set_rate EVALUATE(RESAMPLER_DECORATE, _resampler_set_rate)
#define resampler_ready EVALUATE(RESAMPLER_DECORATE, _resampler_ready)
#define resampler_clear EVALUATE(RESAMPLER_DECORATE, _resampler_clear)
#define resampler_get_sample_count \
EVALUATE(RESAMPLER_DECORATE, _resampler_get_sample_count)
#define resampler_get_sample EVALUATE(RESAMPLER_DECORATE, _resampler_get_sample)
#define resampler_get_sample_float \
EVALUATE(RESAMPLER_DECORATE, _resampler_get_sample_float)
#define resampler_remove_sample \
EVALUATE(RESAMPLER_DECORATE, _resampler_remove_sample)
#endif #endif
void resampler_init(void); void resampler_init(void);
void * resampler_create(void); void *resampler_create(void);
void resampler_delete(void *); void resampler_delete(void *);
void * resampler_dup(const void *); void *resampler_dup(const void *);
void resampler_dup_inplace(void *, const void *); void resampler_dup_inplace(void *, const void *);
enum enum {
{
RESAMPLER_QUALITY_MIN = 0, RESAMPLER_QUALITY_MIN = 0,
RESAMPLER_QUALITY_ZOH = 0, RESAMPLER_QUALITY_ZOH = 0,
RESAMPLER_QUALITY_BLEP = 1, RESAMPLER_QUALITY_BLEP = 1,
@ -51,7 +59,7 @@ int resampler_get_free_count(void *);
void resampler_write_sample(void *, short sample); void resampler_write_sample(void *, short sample);
void resampler_write_sample_fixed(void *, int sample, unsigned char depth); void resampler_write_sample_fixed(void *, int sample, unsigned char depth);
void resampler_write_sample_float(void *, float sample); void resampler_write_sample_float(void *, float sample);
void resampler_set_rate( void *, double new_factor ); void resampler_set_rate(void *, double new_factor);
int resampler_ready(void *); int resampler_ready(void *);
void resampler_clear(void *); void resampler_clear(void *);
int resampler_get_sample_count(void *); int resampler_get_sample_count(void *);

View file

@ -3,22 +3,20 @@
struct riff; struct riff;
struct riff_chunk struct riff_chunk {
{
unsigned type; unsigned type;
long offset; long offset;
unsigned size; unsigned size;
struct riff * nested; struct riff *nested;
}; };
struct riff struct riff {
{
unsigned type; unsigned type;
unsigned chunk_count; unsigned chunk_count;
struct riff_chunk * chunks; struct riff_chunk *chunks;
}; };
struct riff * riff_parse( DUMBFILE * f, long offset, long size, unsigned proper ); struct riff *riff_parse(DUMBFILE *f, long offset, long size, unsigned proper);
void riff_free( struct riff * ); void riff_free(struct riff *);
#endif #endif

View file

@ -36,13 +36,13 @@
#define STACK_ALLOC_H #define STACK_ALLOC_H
#ifdef WIN32 #ifdef WIN32
# include <malloc.h> #include <malloc.h>
#else #else
# ifdef HAVE_ALLOCA_H #ifdef HAVE_ALLOCA_H
# include <alloca.h> #include <alloca.h>
# else #else
# include <stdlib.h> #include <stdlib.h>
# endif #endif
#endif #endif
/** /**
@ -86,15 +86,21 @@
#include <valgrind/memcheck.h> #include <valgrind/memcheck.h>
#define ALIGN(stack, size) ((stack) += ((size) - (long)(stack)) & ((size) - 1)) #define ALIGN(stack, size) ((stack) += ((size) - (long)(stack)) & ((size)-1))
#define PUSH(stack, size, type) (VALGRIND_MAKE_NOACCESS(stack, 1000),ALIGN((stack),sizeof(type)),VALGRIND_MAKE_WRITABLE(stack, ((size)*sizeof(type))),(stack)+=((size)*sizeof(type)),(type*)((stack)-((size)*sizeof(type)))) #define PUSH(stack, size, type) \
(VALGRIND_MAKE_NOACCESS(stack, 1000), ALIGN((stack), sizeof(type)), \
VALGRIND_MAKE_WRITABLE(stack, ((size) * sizeof(type))), \
(stack) += ((size) * sizeof(type)), \
(type *)((stack) - ((size) * sizeof(type))))
#else #else
#define ALIGN(stack, size) ((stack) += ((size) - (long)(stack)) & ((size) - 1)) #define ALIGN(stack, size) ((stack) += ((size) - (long)(stack)) & ((size)-1))
#define PUSH(stack, size, type) (ALIGN((stack),sizeof(type)),(stack)+=((size)*sizeof(type)),(type*)((stack)-((size)*sizeof(type)))) #define PUSH(stack, size, type) \
(ALIGN((stack), sizeof(type)), (stack) += ((size) * sizeof(type)), \
(type *)((stack) - ((size) * sizeof(type))))
#endif #endif
@ -103,11 +109,10 @@
#define ALLOC(var, size, type) type var[size] #define ALLOC(var, size, type) type var[size]
#elif defined(USE_ALLOCA) #elif defined(USE_ALLOCA)
#define VARDECL(var) var #define VARDECL(var) var
#define ALLOC(var, size, type) var = alloca(sizeof(type)*(size)) #define ALLOC(var, size, type) var = alloca(sizeof(type) * (size))
#else #else
#define VARDECL(var) var #define VARDECL(var) var
#define ALLOC(var, size, type) var = PUSH(stack, size, type) #define ALLOC(var, size, type) var = PUSH(stack, size, type)
#endif #endif
#endif #endif

View file

@ -2,30 +2,19 @@
#define _T_ARRAY_H_ #define _T_ARRAY_H_
#include <stdlib.h> #include <stdlib.h>
#include "internal/dumb.h"
#ifndef LONG_LONG void *timekeeping_array_create(size_t size);
#if defined __GNUC__ || defined __INTEL_COMPILER || defined __MWERKS__ void timekeeping_array_destroy(void *array);
#define LONG_LONG long long void *timekeeping_array_dup(void *array);
#elif defined _MSC_VER || defined __WATCOMC__
#define LONG_LONG __int64
#elif defined __sgi
#define LONG_LONG long long
#else
#error 64-bit integer type unknown
#endif
#endif
void * timekeeping_array_create(size_t size); void timekeeping_array_reset(void *array, size_t loop_start);
void timekeeping_array_destroy(void * array);
void * timekeeping_array_dup(void * array);
void timekeeping_array_reset(void * array, size_t loop_start); void timekeeping_array_push(void *array, size_t index, LONG_LONG time);
void timekeeping_array_bump(void *array, size_t index);
void timekeeping_array_push(void * array, size_t index, LONG_LONG time); unsigned int timekeeping_array_get_count(void *array, size_t index);
void timekeeping_array_bump(void * array, size_t index);
unsigned int timekeeping_array_get_count(void * array, size_t index); LONG_LONG timekeeping_array_get_item(void *array, size_t index);
LONG_LONG timekeeping_array_get_item(void * array, size_t index);
#endif #endif

View file

@ -1,77 +0,0 @@
/* _______ ____ __ ___ ___
* \ _ \ \ / \ / \ \ / / ' ' '
* | | \ \ | | || | \/ | . .
* | | | | | | || ||\ /| |
* | | | | | | || || \/ | | ' ' '
* | | | | | | || || | | . .
* | |_/ / \ \__// || | |
* /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
* / \
* / . \
* licence.txt - Conditions for use of DUMB. / / \ \
* | < / \_
* If you do not agree to these terms, please | \/ /\ /
* do not use DUMB. \_ / > /
* | \ / /
* Information in [brackets] is provided to aid | ' /
* interpretation of the licence. \__/
*/
Dynamic Universal Music Bibliotheque, Version 0.9.3
Copyright (C) 2001-2005 Ben Davis, Robert J Ohannessian and Julien Cugniere
This software is provided 'as-is', without any express or implied warranty.
In no event shall the authors be held liable for any damages arising from the
use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim
that you wrote the original software. If you use this software in a
product, you are requested to acknowledge its use in the product
documentation, along with details on where to get an unmodified version of
this software, but this is not a strict requirement.
[Note that the above point asks for a link to DUMB, not just a mention.
Googling for DUMB doesn't help much! The URL is "http://dumb.sf.net/".]
[The link was originally strictly required. This was changed for two
reasons. Firstly, if many projects request an acknowledgement, the list of
acknowledgements can become quite unmanageable. Secondly, DUMB was placing
a restriction on the code using it, preventing people from using the GNU
General Public Licence which disallows any such restrictions. See
http://www.gnu.org/philosophy/bsd.html for more information on this
subject. However, if DUMB plays a significant part in your project, we do
urge you to acknowledge its use.]
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed from or altered in any source distribution.
4. If you are using the Program in someone else's bedroom on any Monday at
3:05 pm, you are not allowed to modify the Program for ten minutes. [This
clause provided by Inphernic; every licence should contain at least one
clause, the reasoning behind which is far from obvious.]
5. Users who wish to use DUMB for the specific purpose of playing music are
required to feed their dog on every full moon (if deemed appropriate).
[This clause provided by Allefant, who couldn't remember what Inphernic's
clause was.]
6. No clause in this licence shall prevent this software from being depended
upon by a product licensed under the GNU General Public Licence. If such a
clause is deemed to exist, Debian, then it shall be respected in spirit as
far as possible and all other clauses shall continue to apply in full
force.
We regret that we cannot provide any warranty, not even the implied warranty
of merchantability or fitness for a particular purpose.
Some files generated or copied by automake, autoconf and friends are
available in an extra download. These fall under separate licences but are
all free to distribute. Please check their licences as necessary.

View file

@ -1,541 +0,0 @@
/* _______ ____ __ ___ ___
* \ _ \ \ / \ / \ \ / / ' ' '
* | | \ \ | | || | \/ | . .
* | | | | | | || ||\ /| |
* | | | | | | || || \/ | | ' ' '
* | | | | | | || || | | . .
* | |_/ / \ \__// || | |
* /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
* / \
* / . \
* readme.txt - General information on DUMB. / / \ \
* | < / \_
* | \/ /\ /
* \_ / > /
* | \ / /
* | ' /
* \__/
*/
********************
*** Introduction ***
********************
Thank you for downloading DUMB v0.9.3! You should have the following
documentation:
readme.txt - This file
licence.txt - Conditions for the use of this software
release.txt - Release notes and changes for this and past releases
docs/
howto.txt - Step-by-step instructions on adding DUMB to your project
faq.txt - Frequently asked questions and answers to them
dumb.txt - DUMB library reference
deprec.txt - Information about deprecated parts of the API
ptr.txt - Quick introduction to pointers for those who need it
fnptr.txt - Explanation of function pointers for those who need it
modplug.txt - Our official position regarding ModPlug Tracker
This file will help you get DUMB set up. If you have not yet done so, please
read licence.txt and release.txt before proceeding. After you've got DUMB set
up, please refer to the files in the docs/ directory at your convenience. I
recommend you start with howto.txt.
****************
*** Features ***
****************
Here is the statutory feature list:
- Freeware
- Supports playback of IT, XM, S3M and MOD files
- Faithful to the original trackers, especially IT; if it plays your module
wrongly, please tell me so I can fix the bug! (But please don't complain
about differences between DUMB and ModPlug Tracker; see docs/modplug.txt)
- Accurate support for low-pass resonant filters for IT files
- Very accurate timing and pitching; completely deterministic playback
- Click removal
- Facility to embed music files in other files (e.g. Allegro datafiles)
- Three resampling quality settings: aliasing, linear interpolation and cubic
interpolation
- Number of samples playing at once can be limited to reduce processor usage,
but samples will come back in when other louder ones stop
- All notes will be present and correct even if you start a piece of music in
the middle
- Option to take longer loading but seek fast to any point before the music
first loops (seeking time increases beyond this point)
- Audio generated can be used in any way; DUMB does not necessarily send it
straight to a sound output system
- Can be used with Allegro, can be used without (if you'd like to help make
DUMB more approachable to people who aren't using Allegro, please contact
me)
- Makefile provided for DJGPP, MinGW, Linux, BeOS and Mac OS X
- Project files provided for MSVC 6
- Autotools-based configure script available as a separate download for
masochists
- Code should port anywhere that has a 32-bit C compiler; instructions on
compiling it manually are available further down
*********************
*** What you need ***
*********************
To use DUMB, you need a 32-bit C compiler (GCC and MSVC are fine). If you
have Allegro, DUMB can integrate with its audio streams and datafiles, making
your life easier. If you do not wish to use Allegro, you will have to do some
work to get music playing back. The 'dumbplay' example program requires
Allegro.
Allegro - http://alleg.sf.net/
**********************************************
*** How to set DUMB up with DJGPP or MinGW ***
**********************************************
You should have got the .zip version. If for some reason you got the .tar.gz
version instead, you may have to convert make/config.bat to DOS text file
format. WinZip does this automatically by default. Otherwise, loading it into
MS EDIT and saving it again should do the trick (but do not do this to the
Makefiles as it destroys tabs). You will have to do the same for any files
you want to view in Windows Notepad. If you have problems, just go and
download the .zip instead.
Make sure you preserved the directory structure when you extracted DUMB from
the archive. Most unzipping programs will do this by default, but pkunzip
requires you to pass -d. If not, please delete DUMB and extract it again
properly.
If you are using Windows, open an MS-DOS Prompt or a Windows Command Line.
Change to the directory into which you unzipped DUMB.
If you are using MinGW (and you haven't renamed 'mingw32-make'), type:
mingw32-make
Otherwise, type the following:
make
DUMB will ask you whether you wish to compile for DJGPP or MinGW. Then it
will ask you whether you want support for Allegro. (You have to have made and
installed Allegro's optimised library for this to work.) Finally, it will
compile optimised and debugging builds of DUMB, along with the example
programs. When it has finished, run one of the following to install the
libraries:
make install
mingw32-make install
All done! If you ever need the configuration again (e.g. if you compiled for
DJGPP before and you want to compile for MinGW now), run one of the
following:
make config
mingw32-make config
See the comments in the Makefile for other targets.
Note: the Makefile will only work properly if you have COMSPEC or ComSpec set
to point to command.com or cmd.exe. If you set it to point to a Unix-style
shell, the Makefile won't work.
Please let me know if you have any trouble.
As an alternative, MSYS users may attempt to use the configure script,
available in dumb-0.9.3-autotools.tar.gz. This has been found to work without
Allegro, and is untested with Allegro. I should appreciate feedback from
anyone else who tries this. I do not recommend its use, partly because it
creates dynamically linked libraries and I don't know how to stop it from
doing that (see the section on compiling DUMB manually), and partly because
autotools are plain evil.
Scroll down for information on the example programs. Refer to docs/howto.txt
when you are ready to start programming with DUMB. If you use DUMB in a game,
let me know - I might decide to place a link to your game on DUMB's website!
******************************************************
*** How to set DUMB up with Microsoft Visual C++ 6 ***
******************************************************
If you have a newer version of Microsoft Visual C++ or Visual Something that
supports C++, please try these instructions and let me know if it works.
You should have got the .zip version. If for some reason you got the .tar.gz
version instead, you may have to convert some files to DOS text file format.
WinZip does this automatically by default. Otherwise, loading such files into
MS EDIT and saving them again should do the trick. You will have to do this
for any files you want to view in Windows Notepad. If you have problems, just
go and download the .zip instead.
Make sure you preserved the directory structure when you extracted DUMB from
the archive. Most unzipping programs will do this by default, but pkunzip
requires you to pass -d. If not, please delete DUMB and extract it again
properly.
DUMB comes with a workspace Microsoft Visual C++ 6, containing projects for
the DUMB core, the Allegro interface library and each of the examples. The
first thing you might want to do is load the workspace up and have a look
around. You will find it in the dumb\vc6 directory under the name dumb.dsw.
Note that the aldumb and dumbplay projects require Allegro, so they won't
work if you don't have Allegro. Nevertheless, dumbplay is the best-commented
of the examples, so do have a look.
When you are ready to add DUMB to your project, follow these instructions:
1. Open your project in VC++.
2. Select Project|Insert Project into Workspace...
3. Navigate to the dumb\vc6\dumb directory and select dumb.dsp.
Alternatively, if you know that you are statically linking with a library
that uses the statically linked multithreaded runtime (/MT), you may wish
to select dumb_static.dsp in the dumb_static subdirectory instead.
4. Select Build|Set Active Configuration..., and reselect one of your
project's configurations.
5. Select Project|Dependencies... and ensure your project is dependent on
DUMB.
6. Select Project|Settings..., Settings for: All Configurations, C/C++ tab,
Preprocessor category. Add the DUMB include directory to the Additional
Include Directories box.
7. Ensure that for all the projects in the workspace (or more likely just all
the projects in a particular dependency chain) the run-time libraries are
the same. That's in Project|Settings, C/C++ tab, Code generation category,
Use run-time library dropdown. The settings for Release and Debug are
separate, so you'll have to change them one at a time. Exactly which run-
time library you use will depend on what you need; it doesn't appear that
DUMB has any particular requirements, so set it to whatever you're using
now. (It will have to be /MD, the multithreaded DLL library, if you are
statically linking with Allegro. If you are dynamically linking with
Allegro than it doesn't matter.)
8. If you are using Allegro, do some or all of the above for the aldumb.dsp
project in the aldumb directory too.
Good thing you only have to do all that once ... or twice ...
If you have the Intel compiler installed, it will - well, should - be used to
compile DUMB. The only setting I [Tom Seddon] added is /QxiM. This allows the
compiler to use PPro and MMX instructions, and so when compiling with Intel
the resultant EXE will require a Pentium II or greater. I don't think this is
unreasonable. After all, it is 2003 :)
[Note from Ben: the Intel compiler is evil! It makes AMD processors look bad!
Patch it or boycott it or something!]
If you don't have the Intel compiler, VC will compile DUMB as normal.
This project file and these instructions were provided by Tom Seddon (I hope
I got his name right; I had to guess it from his e-mail address!). Chad
Austin has since changed the project files around, and I've just attempted to
hack them to incorporate new source files. I've also tried to update the
instructions using guesswork and some knowledge of Visual J++ (you heard me).
The instructions and the project files are to this day untested by me. If you
have problems, check the download page at http://dumb.sf.net/ to see if they
are addressed; failing that, direct queries to me and I'll try to figure them
out.
If you have any comments at all on how the VC6 projects are laid out, or how
the instructions could be improved, I should be really grateful to hear them.
I am a perfectionist, after all. :)
Scroll down for information on the example programs. When you are ready to
start using DUMB, refer to docs/howto.txt. If you use DUMB in a game, let me
know - I might decide to place a link to your game on DUMB's website!
******************************************************
*** How to set DUMB up on Linux, BeOS and Mac OS X ***
******************************************************
You should have got the .tar.gz version. If for some reason you got the .zip
version instead, you may have to strip all characters with ASCII code 13 from
some of the text files. If you have problems, just go and download the
.tar.gz instead.
You have two options. There is a Makefile which should cope with most
systems. The first option is to use this default Makefile, and the procedure
is explained below. The second option is to download
dumb-0.9.3-autotools.tar.gz, extract it over the installation, run
./configure and use the generated Makefile. Users who choose to do this are
left to their own devices but advised to read the information at the end of
this section. I strongly recommend the first option.
If you are not using the configure script, the procedure is as follows.
First, run the following command as a normal user:
make
You will be asked whether you want Allegro support. Then, unless you are on
BeOS, you will be asked where you'd like DUMB to install its headers,
libraries and examples (which will go in the include/, lib/ and bin/
subdirectories of the prefix you specify). BeOS has fixed locations for these
files. You may use shell variables here, e.g. $HOME or ${HOME}, but ~ will
not work. Once you have specified these pieces of information, the optimised
and debugging builds of DUMB will be compiled, along with the examples. When
it has finished, you can install them with:
make install
You may need to be root for this to work. It depends on the prefix you chose.
Note: the Makefile will only work if COMSPEC and ComSpec are both undefined.
If either of these is defined, the Makefile will try to build for a Windows
system, and will fail.
Please let me know if you have any trouble.
Scroll down for information on the example programs. Refer to docs/howto.txt
when you are ready to start programming with DUMB. If you use DUMB in a game,
let me know - I might decide to place a link to your game on DUMB's website!
Important information for users of the configure script follows.
The Makefile generated by the configure script creates dynamically linked
libraries, and I don't know how to stop it from doing so. See the section
below on building DUMB manually for why I recommend linking DUMB statically.
However, if you choose to use the configure script, note the following.
The default Makefile is a copy of Makefile.rdy (short for 'ready'), and it
must exist with the name Makefile.rdy in order to work. The configure script
will overwrite Makefile, so if you want the default Makefile back, just run:
cp Makefile.rdy Makefile
Do not use a symlink, as that would result in Makefile.rdy getting
overwritten next time the configure script is run!
You can also access the usual build system by passing '-f Makefile.rdy' to
Make.
********************************************************
*** How to build DUMB manually if nothing else works ***
********************************************************
Those porting to platforms without floating point support should be aware
that DUMB does use floating point operations but not in the inner loops. They
are used for volume and note pitch calculations, and they are used when
initialising the filter algorithm for given cut-off and resonance values.
Please let me know if this is a problem for you. If there is enough demand, I
may be able to eliminate one or both of these cases.
All of the library source code may be found in the src/ subdirectory. There
are headers in the include/ subdirectory, and src/helpers/resample.c also
#includes some .inc files in its own directory.
There are four subdirectories under src/. For projects not using Allegro, you
will need all the files in src/core/, src/helpers/ and src/it/. If you are
using Allegro, you will want the src/allegro/ subdirectory too. For
consistency with the other build systems, the contents of src/allegro/ should
be compiled into a separate library.
I recommend static-linking DUMB, since the version information is done via
macros and the API has a tendency to change. If you static-link, then once
your program is in binary form, you can be sure that changes to the installed
version of DUMB won't cause it to malfuction. It is my fault that the API has
been so unstable. Sorry!
Compile each .c file separately. As mentioned above, you will need to specify
two places to look for #include files: the include/ directory and the source
file's own directory. You will also need to define the symbol
DUMB_DECLARE_DEPRECATED on the command line.
Do not compile the .inc files separately.
You may need to edit dumb.h and add your own definition for LONG_LONG. It
should be a 64-bit integer. If you do this, please see if you can add a check
for your compiler so that it still works with other compilers.
DUMB has two build modes. If you define the symbol DEBUGMODE, some checks for
programmer error will be incorporated into the library. Otherwise it will be
built without any such checks. (DUMB will however always thoroughly check the
validity of files it is loading. If you ever find a module file that crashes
DUMB, please let me know!)
I recommend building two versions of the library, one with DEBUGMODE defined
and debugging information included, and the other with compiler optimisation
enabled. If you can install DUMB system-wide so that your projects, and other
people's, can simply #include <dumb.h> or <aldumb.h> and link with libraries
by simple name with no path, then that is ideal.
If you successfully port DUMB to a new platform, please let me know!
****************************
*** The example programs ***
****************************
Three example programs are provided. On DOS and Windows, you can find them in
the examples subdirectory. On other systems they will be installed system-
wide.
dumbplay
This program will only be built if you have Allegro. Pass it the filename
of an IT, XM, S3M or MOD file, and it will play it. It's not a polished
player with real-time threading or anything - so don't complain about it
stuttering while you use other programs - but it does show DUMB's fidelity
nicely. You can control the playback quality by editing dumb.ini, which
must be in the current working directory. (This is a flaw for systems
where the program is installed system-wide, but it is non-fatal.) Have a
look at the examples/dumb.ini file for further information.
dumbout
This program does not need Allegro. You can use it to stream an IT, XM,
S3M or MOD file to raw PCM. This can be used as input to an encoder like
oggenc (with appropriate command-line options), or it can be sent to a
.pcm file which can be read by any respectable waveform editor. This
program is also convenient for timing DUMB. Compare the time it takes to
render a module with the module's playing time! dumbout doesn't try to
read any configuration file; the options are set on the command line.
dumb2wav
This program is much the same as dumbout, but it writes a .wav file with
the appropriate header. Thanks go to Chad Austin for this useful tool.
*********************************************
*** Downloading music or writing your own ***
*********************************************
If you would like to compose your own music modules, then this section should
help get you started.
The best programs for the job are the trackers that pioneered the file
formats:
Impulse Tracker - IT files - http://www.lim.com.au/ImpulseTracker/
Fast Tracker II - XM files - http://www.fasttracker2.com/
Scream Tracker 3 - S3M files - No official site known, please use Google
MOD files come from the Amiga; I do not know what PC tracker to recommend for
editing these. If you know of one, let me know! In the meantime, I would
recommend using a more advanced file format. However, don't convert your
existing MODs just for the sake of it.
Fast Tracker II is Shareware. It offers a very flashy interface and has a
game embedded, but the IT file format is more powerful and better defined. By
all means try them both and see which you prefer; it is largely a matter of
taste (and, in some cases, religion). Impulse Tracker and Scream Tracker 3
are Freeware, although you can donate to Impulse Tracker and receive a
slightly upgraded version. DUMB is likely to be at its best with IT files.
These editors are DOS programs. Users of DOS-incapable operating systems may
like to try ModPlug Tracker, but should read docs/modplug.txt before using it
for any serious work. If you use a different operating system, or if you know
of any module editors for Windows that are more faithful to the original
trackers' playback, please give me some links so I can put them here!
ModPlug Tracker - http://www.modplug.com/
If you have an x86 Linux system with VGA-compatible hardware (which covers
all PC graphics cards I've ever seen), you should be able to get Impulse
Tracker running with DOSEMU. You will have to give it access to the VGA ports
and run it in a true console, as it will not work with the X-based VGA
emulation. I personally added the SB16 emulation to DOSEMU, so you can even
use filters! However, it corrupts samples alarmingly often when saving on my
system - probably a DOSEMU issue. If you set this up, I am curious to know
whether it works for you.
DOSEMU - http://www.dosemu.org/
BEWARE OF WINAMP! Although it's excellent for MP3s, it is notorious for being
one of the worst module players in existence; very many modules play wrongly
with it. There are plug-ins available to improve Winamp's module support, for
example WSP.
Winamp - http://www.winamp.com/
WSP - http://www.spytech.cz/index.php?sec=demo
(There is a Winamp plug-in that uses DUMB, but it is unreliable. If anyone
would like to work on it, please get in touch.)
While I am at it I should also point out that Winamp is notorious for
containing security flaws. Install it at your own risk, and if it is your
work computer, check with your boss first!
Samples and instruments are the building blocks of music modules. You can
download samples at
http://www.tump.net/
If you would like to download module files composed by other people, check
the following sites:
http://www.modarchive.com/
http://www.scene.org/
http://www.tump.net/
http://www.homemusic.cc/main.php
http://www.modplug.com/
Once again, if you know of more sites where samples or module files are
available for download, please let me know.
If you wish to use someone's music in your game, please respect the
composer's wishes. In general, you should ask the composer. Music that has
been placed in the Public Domain can be used by anyone for anything, but it
wouldn't do any harm to ask anyway if you know who the author is. In many
cases the author will be thrilled, so don't hesitate!
A note about converting modules from one format to another, or converting
from MIDI: don't do it, unless you are a musician and are prepared to go
through the file and make sure everything sounds the way it should! The
module formats are all slightly different, and MIDI is very different;
converting from one format to another will usually do some damage.
Instead, it is recommended that you allow DUMB to interpret the original file
as it sees fit. DUMB may make mistakes (it does a lot of conversion on
loading), but future versions of DUMB will be able to rectify these mistakes.
On the other hand, if you convert the file, the damage is permanent.
***********************
*** Contact details ***
***********************
If you have trouble with DUMB, or want to contact me for any other reason, my
e-mail address is given below. Please do get in touch, even if I appear to
have disappeared!
If you wish to chat online about something, perhaps on IRC, that can most
likely be arranged. Send me an e-mail.
******************
*** Conclusion ***
******************
This is the conclusion.
Ben Davis
entheh@users.sf.net

View file

@ -22,27 +22,19 @@
#include "dumb.h" #include "dumb.h"
#include "internal/dumb.h" #include "internal/dumb.h"
typedef struct DUMB_ATEXIT_PROC {
typedef struct DUMB_ATEXIT_PROC
{
struct DUMB_ATEXIT_PROC *next; struct DUMB_ATEXIT_PROC *next;
void (*proc)(void); void (*proc)(void);
} } DUMB_ATEXIT_PROC;
DUMB_ATEXIT_PROC;
static DUMB_ATEXIT_PROC *dumb_atexit_proc = NULL; static DUMB_ATEXIT_PROC *dumb_atexit_proc = NULL;
int dumb_atexit(void (*proc)(void)) {
int dumb_atexit(void (*proc)(void))
{
DUMB_ATEXIT_PROC *dap = dumb_atexit_proc; DUMB_ATEXIT_PROC *dap = dumb_atexit_proc;
while (dap) { while (dap) {
if (dap->proc == proc) return 0; if (dap->proc == proc)
return 0;
dap = dap->next; dap = dap->next;
} }
@ -58,10 +50,7 @@ int dumb_atexit(void (*proc)(void))
return 0; return 0;
} }
void dumb_exit(void) {
void dumb_exit(void)
{
while (dumb_atexit_proc) { while (dumb_atexit_proc) {
DUMB_ATEXIT_PROC *next = dumb_atexit_proc->next; DUMB_ATEXIT_PROC *next = dumb_atexit_proc->next;
(*dumb_atexit_proc->proc)(); (*dumb_atexit_proc->proc)();

View file

@ -26,17 +26,9 @@
#include "dumb.h" #include "dumb.h"
#include "internal/dumb.h" #include "internal/dumb.h"
dumb_off_t duh_get_length(DUH *duh) { return duh ? duh->length : 0; }
void duh_set_length(DUH *duh, dumb_off_t length) {
long duh_get_length(DUH *duh)
{
return duh ? duh->length : 0;
}
void duh_set_length(DUH *duh, long length)
{
if (duh) if (duh)
duh->length = length; duh->length = length;
} }

View file

@ -22,13 +22,11 @@
#include "dumb.h" #include "dumb.h"
#include "internal/dumb.h" #include "internal/dumb.h"
const char *duh_get_tag(DUH *duh, const char *key) {
const char *duh_get_tag(DUH *duh, const char *key)
{
int i; int i;
ASSERT(key); ASSERT(key);
if (!duh || !duh->tag) return NULL; if (!duh || !duh->tag)
return NULL;
for (i = 0; i < duh->n_tags; i++) for (i = 0; i < duh->n_tags; i++)
if (strcmp(key, duh->tag[i][0]) == 0) if (strcmp(key, duh->tag[i][0]) == 0)
@ -37,19 +35,16 @@ const char *duh_get_tag(DUH *duh, const char *key)
return NULL; return NULL;
} }
int duh_get_tag_iterator_size(DUH *duh) {
int duh_get_tag_iterator_size(DUH *duh)
{
return (duh && duh->tag ? duh->n_tags : 0); return (duh && duh->tag ? duh->n_tags : 0);
} }
int duh_get_tag_iterator_get(DUH *duh, const char **key, const char **tag,
int duh_get_tag_iterator_get(DUH *duh, const char **key, const char **tag, int i) int i) {
{
ASSERT(key); ASSERT(key);
ASSERT(tag); ASSERT(tag);
if (!duh || !duh->tag || i >= duh->n_tags) return -1; if (!duh || !duh->tag || i >= duh->n_tags)
return -1;
*key = duh->tag[i][0]; *key = duh->tag[i][0];
*tag = duh->tag[i][1]; *tag = duh->tag[i][1];

View file

@ -22,14 +22,9 @@
#include "dumb.h" #include "dumb.h"
#include "internal/dumb.h" #include "internal/dumb.h"
static const DUMBFILE_SYSTEM *the_dfs = NULL; static const DUMBFILE_SYSTEM *the_dfs = NULL;
void register_dumbfile_system(const DUMBFILE_SYSTEM *dfs) {
void register_dumbfile_system(const DUMBFILE_SYSTEM *dfs)
{
ASSERT(dfs); ASSERT(dfs);
ASSERT(dfs->open); ASSERT(dfs->open);
ASSERT(dfs->getc); ASSERT(dfs->getc);
@ -39,19 +34,14 @@ void register_dumbfile_system(const DUMBFILE_SYSTEM *dfs)
the_dfs = dfs; the_dfs = dfs;
} }
#include "internal/dumbfile.h" #include "internal/dumbfile.h"
DUMBFILE *dumbfile_open(const char *filename) {
DUMBFILE *dumbfile_open(const char *filename)
{
DUMBFILE *f; DUMBFILE *f;
ASSERT(the_dfs); ASSERT(the_dfs);
f = (DUMBFILE *) malloc(sizeof(*f)); f = (DUMBFILE *)malloc(sizeof(*f));
if (!f) if (!f)
return NULL; return NULL;
@ -70,17 +60,14 @@ DUMBFILE *dumbfile_open(const char *filename)
return f; return f;
} }
DUMBFILE *dumbfile_open_ex(void *file, const DUMBFILE_SYSTEM *dfs) {
DUMBFILE *dumbfile_open_ex(void *file, const DUMBFILE_SYSTEM *dfs)
{
DUMBFILE *f; DUMBFILE *f;
ASSERT(dfs); ASSERT(dfs);
ASSERT(dfs->getc); ASSERT(dfs->getc);
ASSERT(file); ASSERT(file);
f = (DUMBFILE *) malloc(sizeof(*f)); f = (DUMBFILE *)malloc(sizeof(*f));
if (!f) { if (!f) {
if (dfs->close) if (dfs->close)
@ -96,19 +83,14 @@ DUMBFILE *dumbfile_open_ex(void *file, const DUMBFILE_SYSTEM *dfs)
return f; return f;
} }
dumb_off_t dumbfile_pos(DUMBFILE *f) {
long dumbfile_pos(DUMBFILE *f)
{
ASSERT(f); ASSERT(f);
return f->pos; return f->pos;
} }
/* Move forward in the file from the current position by n bytes. */
int dumbfile_skip(DUMBFILE *f, dumb_off_t n) {
int dumbfile_skip(DUMBFILE *f, long n)
{
int rv; int rv;
ASSERT(f); ASSERT(f);
@ -139,10 +121,7 @@ int dumbfile_skip(DUMBFILE *f, long n)
return 0; return 0;
} }
int dumbfile_getc(DUMBFILE *f) {
int dumbfile_getc(DUMBFILE *f)
{
int rv; int rv;
ASSERT(f); ASSERT(f);
@ -162,10 +141,7 @@ int dumbfile_getc(DUMBFILE *f)
return rv; return rv;
} }
int dumbfile_igetw(DUMBFILE *f) {
int dumbfile_igetw(DUMBFILE *f)
{
int l, h; int l, h;
ASSERT(f); ASSERT(f);
@ -190,10 +166,7 @@ int dumbfile_igetw(DUMBFILE *f)
return l | (h << 8); return l | (h << 8);
} }
int dumbfile_mgetw(DUMBFILE *f) {
int dumbfile_mgetw(DUMBFILE *f)
{
int l, h; int l, h;
ASSERT(f); ASSERT(f);
@ -218,10 +191,7 @@ int dumbfile_mgetw(DUMBFILE *f)
return l | (h << 8); return l | (h << 8);
} }
long dumbfile_igetl(DUMBFILE *f) {
long dumbfile_igetl(DUMBFILE *f)
{
unsigned long rv, b; unsigned long rv, b;
ASSERT(f); ASSERT(f);
@ -261,10 +231,7 @@ long dumbfile_igetl(DUMBFILE *f)
return rv; return rv;
} }
long dumbfile_mgetl(DUMBFILE *f) {
long dumbfile_mgetl(DUMBFILE *f)
{
unsigned long rv, b; unsigned long rv, b;
ASSERT(f); ASSERT(f);
@ -305,10 +272,7 @@ long dumbfile_mgetl(DUMBFILE *f)
return rv; return rv;
} }
unsigned long dumbfile_cgetul(DUMBFILE *f) {
unsigned long dumbfile_cgetul(DUMBFILE *f)
{
unsigned long rv = 0; unsigned long rv = 0;
int v; int v;
@ -325,10 +289,7 @@ unsigned long dumbfile_cgetul(DUMBFILE *f)
return rv; return rv;
} }
signed long dumbfile_cgetsl(DUMBFILE *f) {
signed long dumbfile_cgetsl(DUMBFILE *f)
{
unsigned long rv = dumbfile_cgetul(f); unsigned long rv = dumbfile_cgetul(f);
if (f->pos < 0) if (f->pos < 0)
@ -337,11 +298,8 @@ signed long dumbfile_cgetsl(DUMBFILE *f)
return (rv >> 1) | (rv << 31); return (rv >> 1) | (rv << 31);
} }
dumb_ssize_t dumbfile_getnc(char *ptr, size_t n, DUMBFILE *f) {
dumb_ssize_t rv;
long dumbfile_getnc(char *ptr, long n, DUMBFILE *f)
{
long rv;
ASSERT(f); ASSERT(f);
ASSERT(n >= 0); ASSERT(n >= 0);
@ -351,12 +309,12 @@ long dumbfile_getnc(char *ptr, long n, DUMBFILE *f)
if (f->dfs->getnc) { if (f->dfs->getnc) {
rv = (*f->dfs->getnc)(ptr, n, f->file); rv = (*f->dfs->getnc)(ptr, n, f->file);
if (rv < n) { if (rv < (dumb_ssize_t)n) {
f->pos = -1; f->pos = -1;
return MAX(rv, 0); return MAX(rv, 0);
} }
} else { } else {
for (rv = 0; rv < n; rv++) { for (rv = 0; rv < (dumb_ssize_t)n; rv++) {
int c = (*f->dfs->getc)(f->file); int c = (*f->dfs->getc)(f->file);
if (c < 0) { if (c < 0) {
f->pos = -1; f->pos = -1;
@ -371,39 +329,35 @@ long dumbfile_getnc(char *ptr, long n, DUMBFILE *f)
return rv; return rv;
} }
/* Move to an arbitrary position n in the file, specified relative to origin,
* where origin shall be one of the DFS_SEEK_* constants.
int dumbfile_seek(DUMBFILE *f, long n, int origin) */
{ int dumbfile_seek(DUMBFILE *f, dumb_off_t n, int origin) {
switch ( origin ) switch (origin) {
{ case DFS_SEEK_CUR:
case DFS_SEEK_CUR: n += f->pos; break; n += f->pos;
case DFS_SEEK_END: n += (*f->dfs->get_size)(f->file); break; break;
case DFS_SEEK_END:
n += (*f->dfs->get_size)(f->file);
break;
default:
break; /* keep n, seek position from beginning of file */
} }
f->pos = n; f->pos = n;
return (*f->dfs->seek)(f->file, n); return (*f->dfs->seek)(f->file, n);
} }
dumb_off_t dumbfile_get_size(DUMBFILE *f) {
long dumbfile_get_size(DUMBFILE *f)
{
return (*f->dfs->get_size)(f->file); return (*f->dfs->get_size)(f->file);
} }
int dumbfile_error(DUMBFILE *f) {
int dumbfile_error(DUMBFILE *f)
{
ASSERT(f); ASSERT(f);
return f->pos < 0; return f->pos < 0;
} }
int dumbfile_close(DUMBFILE *f) {
int dumbfile_close(DUMBFILE *f)
{
int rv; int rv;
ASSERT(f); ASSERT(f);

View file

@ -20,14 +20,11 @@
#include "dumb.h" #include "dumb.h"
#include "internal/dumb.h" #include "internal/dumb.h"
/* load_duh(): loads a .duh file, returning a pointer to a DUH struct. /* load_duh(): loads a .duh file, returning a pointer to a DUH struct.
* When you have finished with it, you must pass the pointer to unload_duh() * When you have finished with it, you must pass the pointer to unload_duh()
* so that the memory can be freed. * so that the memory can be freed.
*/ */
DUH *load_duh(const char *filename) DUH *load_duh(const char *filename) {
{
DUH *duh; DUH *duh;
DUMBFILE *f = dumbfile_open(filename); DUMBFILE *f = dumbfile_open(filename);

View file

@ -23,14 +23,13 @@
#include "dumb.h" #include "dumb.h"
#include "internal/dumb.h" #include "internal/dumb.h"
static DUH_SIGNAL *make_signal(DUH_SIGTYPE_DESC *desc, sigdata_t *sigdata) {
static DUH_SIGNAL *make_signal(DUH_SIGTYPE_DESC *desc, sigdata_t *sigdata)
{
DUH_SIGNAL *signal; DUH_SIGNAL *signal;
ASSERT((desc->start_sigrenderer && desc->end_sigrenderer) || (!desc->start_sigrenderer && !desc->end_sigrenderer)); ASSERT((desc->start_sigrenderer && desc->end_sigrenderer) ||
ASSERT(desc->sigrenderer_generate_samples && desc->sigrenderer_get_current_sample); (!desc->start_sigrenderer && !desc->end_sigrenderer));
ASSERT(desc->sigrenderer_generate_samples &&
desc->sigrenderer_get_current_sample);
signal = malloc(sizeof(*signal)); signal = malloc(sizeof(*signal));
@ -47,17 +46,8 @@ static DUH_SIGNAL *make_signal(DUH_SIGTYPE_DESC *desc, sigdata_t *sigdata)
return signal; return signal;
} }
DUH *make_duh(dumb_off_t length, int n_tags, const char *const tags[][2],
int n_signals, DUH_SIGTYPE_DESC *desc[], sigdata_t *sigdata[]) {
DUH *make_duh(
long length,
int n_tags,
const char *const tags[][2],
int n_signals,
DUH_SIGTYPE_DESC *desc[],
sigdata_t *sigdata[]
)
{
DUH *duh = malloc(sizeof(*duh)); DUH *duh = malloc(sizeof(*duh));
int i; int i;
int fail; int fail;
@ -106,10 +96,12 @@ DUH *make_duh(
for (i = 0; i < n_tags; i++) for (i = 0; i < n_tags; i++)
mem += strlen(tags[i][0]) + strlen(tags[i][1]); mem += strlen(tags[i][0]) + strlen(tags[i][1]);
if (mem <= 0) return duh; if (mem <= 0)
return duh;
duh->tag = malloc(n_tags * sizeof(*duh->tag)); duh->tag = malloc(n_tags * sizeof(*duh->tag));
if (!duh->tag) return duh; if (!duh->tag)
return duh;
duh->tag[0][0] = malloc(mem); duh->tag[0][0] = malloc(mem);
if (!duh->tag[0][0]) { if (!duh->tag[0][0]) {
free(duh->tag); free(duh->tag);
@ -131,21 +123,24 @@ DUH *make_duh(
return duh; return duh;
} }
int duh_add_signal(DUH *duh, DUH_SIGTYPE_DESC *desc, sigdata_t *sigdata) int duh_add_signal(DUH *duh, DUH_SIGTYPE_DESC *desc, sigdata_t *sigdata) {
{
DUH_SIGNAL **signal; DUH_SIGNAL **signal;
if ( !duh || !desc || !sigdata ) return -1; if (!duh || !desc || !sigdata)
return -1;
signal = ( DUH_SIGNAL ** ) realloc( duh->signal, ( duh->n_signals + 1 ) * sizeof( *duh->signal ) ); signal = (DUH_SIGNAL **)realloc(duh->signal, (duh->n_signals + 1) *
if ( !signal ) return -1; sizeof(*duh->signal));
if (!signal)
return -1;
duh->signal = signal; duh->signal = signal;
memmove( signal + 1, signal, duh->n_signals * sizeof( *signal ) ); memmove(signal + 1, signal, duh->n_signals * sizeof(*signal));
duh->n_signals++; duh->n_signals++;
signal[ 0 ] = make_signal( desc, sigdata ); signal[0] = make_signal(desc, sigdata);
if ( !signal[ 0 ] ) return -1; if (!signal[0])
return -1;
return 0; return 0;
} }

View file

@ -22,31 +22,26 @@
#include "dumb.h" #include "dumb.h"
#include "internal/dumb.h" #include "internal/dumb.h"
/* You have to specify the type of sigdata, proving you know what to do with /* You have to specify the type of sigdata, proving you know what to do with
* the pointer. If you get it wrong, you can expect NULL back. * the pointer. If you get it wrong, you can expect NULL back.
*/ */
sigdata_t *duh_get_raw_sigdata(DUH *duh, int sig, long type) sigdata_t *duh_get_raw_sigdata(DUH *duh, int sig, long type) {
{
int i; int i;
DUH_SIGNAL *signal; DUH_SIGNAL *signal;
if (!duh) return NULL; if (!duh)
return NULL;
if ( sig >= 0 ) if (sig >= 0) {
{ if ((unsigned int)sig >= (unsigned int)duh->n_signals)
if ((unsigned int)sig >= (unsigned int)duh->n_signals) return NULL; return NULL;
signal = duh->signal[sig]; signal = duh->signal[sig];
if (signal && signal->desc->type == type) if (signal && signal->desc->type == type)
return signal->sigdata; return signal->sigdata;
} } else {
else for (i = 0; i < duh->n_signals; i++) {
{
for ( i = 0; i < duh->n_signals; i++ )
{
signal = duh->signal[i]; signal = duh->signal[i];
if (signal && signal->desc->type == type) if (signal && signal->desc->type == type)

View file

@ -22,10 +22,7 @@
#include "dumb.h" #include "dumb.h"
#include "internal/dumb.h" #include "internal/dumb.h"
static DUH_SIGNAL *read_signal(DUH *duh, DUMBFILE *f) {
static DUH_SIGNAL *read_signal(DUH *duh, DUMBFILE *f)
{
DUH_SIGNAL *signal; DUH_SIGNAL *signal;
long type; long type;
@ -58,13 +55,10 @@ static DUH_SIGNAL *read_signal(DUH *duh, DUMBFILE *f)
return signal; return signal;
} }
/* read_duh(): reads a DUH from an already open DUMBFILE, and returns its /* read_duh(): reads a DUH from an already open DUMBFILE, and returns its
* pointer, or null on error. The file is not closed. * pointer, or null on error. The file is not closed.
*/ */
DUH *read_duh(DUMBFILE *f) DUH *read_duh(DUMBFILE *f) {
{
DUH *duh; DUH *duh;
int i; int i;
@ -81,7 +75,7 @@ DUH *read_duh(DUMBFILE *f)
return NULL; return NULL;
} }
duh->n_signals = dumbfile_igetl(f); duh->n_signals = (int)dumbfile_igetl(f);
if (dumbfile_error(f) || duh->n_signals <= 0) { if (dumbfile_error(f) || duh->n_signals <= 0) {
free(duh); free(duh);
return NULL; return NULL;

View file

@ -22,18 +22,13 @@
#include "dumb.h" #include "dumb.h"
#include "internal/dumb.h" #include "internal/dumb.h"
static DUH_SIGTYPE_DESC_LINK *sigtype_desc = NULL; static DUH_SIGTYPE_DESC_LINK *sigtype_desc = NULL;
static DUH_SIGTYPE_DESC_LINK **sigtype_desc_tail = &sigtype_desc; static DUH_SIGTYPE_DESC_LINK **sigtype_desc_tail = &sigtype_desc;
/* destroy_sigtypes(): frees all memory allocated while registering signal /* destroy_sigtypes(): frees all memory allocated while registering signal
* types. This function is set up to be called by dumb_exit(). * types. This function is set up to be called by dumb_exit().
*/ */
static void destroy_sigtypes(void) static void destroy_sigtypes(void) {
{
DUH_SIGTYPE_DESC_LINK *desc_link = sigtype_desc, *next; DUH_SIGTYPE_DESC_LINK *desc_link = sigtype_desc, *next;
sigtype_desc = NULL; sigtype_desc = NULL;
sigtype_desc_tail = &sigtype_desc; sigtype_desc_tail = &sigtype_desc;
@ -45,8 +40,6 @@ static void destroy_sigtypes(void)
} }
} }
/* dumb_register_sigtype(): registers a new signal type with DUMB. The signal /* dumb_register_sigtype(): registers a new signal type with DUMB. The signal
* type is identified by a four-character string (e.g. "WAVE"), which you can * type is identified by a four-character string (e.g. "WAVE"), which you can
* encode using the the DUMB_ID() macro (e.g. DUMB_ID('W','A','V','E')). The * encode using the the DUMB_ID() macro (e.g. DUMB_ID('W','A','V','E')). The
@ -56,13 +49,15 @@ static void destroy_sigtypes(void)
* If a DUH tries to use a signal that has not been registered using this * If a DUH tries to use a signal that has not been registered using this
* function, then the library will fail to load the DUH. * function, then the library will fail to load the DUH.
*/ */
void dumb_register_sigtype(DUH_SIGTYPE_DESC *desc) void dumb_register_sigtype(DUH_SIGTYPE_DESC *desc) {
{
DUH_SIGTYPE_DESC_LINK *desc_link = sigtype_desc; DUH_SIGTYPE_DESC_LINK *desc_link = sigtype_desc;
ASSERT((desc->load_sigdata && desc->unload_sigdata) || (!desc->load_sigdata && !desc->unload_sigdata)); ASSERT((desc->load_sigdata && desc->unload_sigdata) ||
ASSERT((desc->start_sigrenderer && desc->end_sigrenderer) || (!desc->start_sigrenderer && !desc->end_sigrenderer)); (!desc->load_sigdata && !desc->unload_sigdata));
ASSERT(desc->sigrenderer_generate_samples && desc->sigrenderer_get_current_sample); ASSERT((desc->start_sigrenderer && desc->end_sigrenderer) ||
(!desc->start_sigrenderer && !desc->end_sigrenderer));
ASSERT(desc->sigrenderer_generate_samples &&
desc->sigrenderer_get_current_sample);
if (desc_link) { if (desc_link) {
do { do {
@ -86,15 +81,12 @@ void dumb_register_sigtype(DUH_SIGTYPE_DESC *desc)
desc_link->desc = desc; desc_link->desc = desc;
} }
/* _dumb_get_sigtype_desc(): searches the registered functions for a signal /* _dumb_get_sigtype_desc(): searches the registered functions for a signal
* type matching the parameter. If such a sigtype is found, it returns a * type matching the parameter. If such a sigtype is found, it returns a
* pointer to a sigtype descriptor containing the necessary functions to * pointer to a sigtype descriptor containing the necessary functions to
* manage the signal. If none is found, it returns NULL. * manage the signal. If none is found, it returns NULL.
*/ */
DUH_SIGTYPE_DESC *_dumb_get_sigtype_desc(long type) DUH_SIGTYPE_DESC *_dumb_get_sigtype_desc(long type) {
{
DUH_SIGTYPE_DESC_LINK *desc_link = sigtype_desc; DUH_SIGTYPE_DESC_LINK *desc_link = sigtype_desc;
while (desc_link && desc_link->desc->type != type) while (desc_link && desc_link->desc->type != type)

View file

@ -23,85 +23,77 @@
#include "dumb.h" #include "dumb.h"
#include "internal/dumb.h" #include "internal/dumb.h"
/* On the x86, we can use some tricks to speed stuff up */ /* On the x86, we can use some tricks to speed stuff up */
#if (defined _MSC_VER) || (defined __DJGPP__) || (defined __MINGW__) #if (defined _MSC_VER) || (defined __DJGPP__) || (defined __MINGW__)
// Can't we detect Linux and other x86 platforms here? :/ // Can't we detect Linux and other x86 platforms here? :/
#define FAST_MID(var, min, max) { \ #define FAST_MID(var, min, max) \
{ \
var -= (min); \ var -= (min); \
var &= (~var) >> (sizeof(var) * CHAR_BIT - 1); \ var &= (~var) >> (sizeof(var) * CHAR_BIT - 1); \
var += (min); \ var += (min); \
var -= (max); \ var -= (max); \
var &= var >> (sizeof(var) * CHAR_BIT - 1); \ var &= var >> (sizeof(var) * CHAR_BIT - 1); \
var += (max); \ var += (max); \
} }
#define CONVERT8(src, pos, signconv) { \ #define CONVERT8(src, pos, signconv) \
{ \
signed int f = (src + 0x8000) >> 16; \ signed int f = (src + 0x8000) >> 16; \
FAST_MID(f, -128, 127); \ FAST_MID(f, -128, 127); \
((char*)sptr)[pos] = (char)f ^ signconv; \ ((char *)sptr)[pos] = (char)f ^ signconv; \
} }
#define CONVERT16(src, pos, signconv) { \ #define CONVERT16(src, pos, signconv) \
{ \
signed int f = (src + 0x80) >> 8; \ signed int f = (src + 0x80) >> 8; \
FAST_MID(f, -32768, 32767); \ FAST_MID(f, -32768, 32767); \
((short*)sptr)[pos] = (short)(f ^ signconv); \ ((short *)sptr)[pos] = (short)(f ^ signconv); \
} }
#else #else
#define CONVERT8(src, pos, signconv) \ #define CONVERT8(src, pos, signconv) \
{ \ { \
signed int f = (src + 0x8000) >> 16; \ signed int f = (src + 0x8000) >> 16; \
f = MID(-128, f, 127); \ f = MID(-128, f, 127); \
((char *)sptr)[pos] = (char)f ^ signconv; \ ((char *)sptr)[pos] = (char)f ^ signconv; \
} }
#define CONVERT16(src, pos, signconv) \ #define CONVERT16(src, pos, signconv) \
{ \ { \
signed int f = (src + 0x80) >> 8; \ signed int f = (src + 0x80) >> 8; \
f = MID(-32768, f, 32767); \ f = MID(-32768, f, 32767); \
((short *)sptr)[pos] = (short)(f ^ signconv); \ ((short *)sptr)[pos] = (short)(f ^ signconv); \
} }
#endif #endif
#define CONVERT24(src, pos) { \ #define CONVERT24(src, pos) \
{ \
signed int f = src; \ signed int f = src; \
f = MID(-8388608, f, 8388607); \ f = MID(-8388608, f, 8388607); \
((unsigned char*)sptr)[pos ] = (f) & 0xFF; \ ((unsigned char *)sptr)[pos] = (f)&0xFF; \
((unsigned char*)sptr)[pos+1] = (f >> 8) & 0xFF; \ ((unsigned char *)sptr)[pos + 1] = (f >> 8) & 0xFF; \
((unsigned char*)sptr)[pos+2] = (f >> 16) & 0xFF; \ ((unsigned char *)sptr)[pos + 2] = (f >> 16) & 0xFF; \
} }
#define CONVERT32F(src, pos) { \ #define CONVERT32F(src, pos) \
((float*)sptr)[pos] = (float)((signed int)src) * (1.0f/(float)(0xffffff/2+1)); \ { \
} ((float *)sptr)[pos] = \
(float)((signed int)src) * (1.0f / (float)(0xffffff / 2 + 1)); \
#define CONVERT64F(src, pos) { \ }
((double*)sptr)[pos] = (double)((signed int)src) * (1.0/(double)(0xffffff/2+1)); \
}
#define CONVERT64F(src, pos) \
{ \
((double *)sptr)[pos] = \
(double)((signed int)src) * (1.0 / (double)(0xffffff / 2 + 1)); \
}
/* This is the only deprecated function in 2.0.0. */
/* DEPRECATED */ /* DEPRECATED */
DUH_SIGRENDERER *duh_start_renderer(DUH *duh, int n_channels, long pos) long duh_render(DUH_SIGRENDERER *sigrenderer, int bits, int unsign,
{ float volume, float delta, long size, void *sptr) {
return duh_start_sigrenderer(duh, 0, n_channels, pos);
}
/* DEPRECATED */
long duh_render(
DUH_SIGRENDERER *sigrenderer,
int bits, int unsign,
float volume, float delta,
long size, void *sptr
)
{
long n; long n;
sample_t **sampptr; sample_t **sampptr;
@ -129,7 +121,8 @@ long duh_render(
dumb_silence(sampptr[0], n_channels * size); dumb_silence(sampptr[0], n_channels * size);
size = duh_sigrenderer_generate_samples(sigrenderer, volume, delta, size, sampptr); size = duh_sigrenderer_generate_samples(sigrenderer, volume, delta, size,
sampptr);
if (bits == 16) { if (bits == 16) {
int signconv = unsign ? 0x8000 : 0x0000; int signconv = unsign ? 0x8000 : 0x0000;
@ -150,16 +143,9 @@ long duh_render(
return size; return size;
} }
long duh_render_int(DUH_SIGRENDERER *sigrenderer, sample_t ***sig_samples,
long duh_render_int( long *sig_samples_size, int bits, int unsign, float volume,
DUH_SIGRENDERER *sigrenderer, float delta, long size, void *sptr) {
sample_t ***sig_samples,
long *sig_samples_size,
int bits, int unsign,
float volume, float delta,
long size, void *sptr
)
{
long n; long n;
sample_t **sampptr; sample_t **sampptr;
@ -182,8 +168,7 @@ long duh_render_int(
*/ */
ASSERT(n_channels <= 2); ASSERT(n_channels <= 2);
if ((*sig_samples == NULL) || (*sig_samples_size != size)) if ((*sig_samples == NULL) || (*sig_samples_size != size)) {
{
destroy_sample_buffer(*sig_samples); destroy_sample_buffer(*sig_samples);
*sig_samples = allocate_sample_buffer(n_channels, size); *sig_samples = allocate_sample_buffer(n_channels, size);
*sig_samples_size = size; *sig_samples_size = size;
@ -195,7 +180,8 @@ long duh_render_int(
dumb_silence(sampptr[0], n_channels * size); dumb_silence(sampptr[0], n_channels * size);
size = duh_sigrenderer_generate_samples(sigrenderer, volume, delta, size, sampptr); size = duh_sigrenderer_generate_samples(sigrenderer, volume, delta, size,
sampptr);
if (bits == 24) { if (bits == 24) {
long i = 0; long i = 0;
@ -204,8 +190,7 @@ long duh_render_int(
for (n = 0; n < size * n_channels; n++, i += 3) { for (n = 0; n < size * n_channels; n++, i += 3) {
CONVERT24(sampptr[0][n], i); CONVERT24(sampptr[0][n], i);
} }
} else } else if (bits == 16) {
if (bits == 16) {
int signconv = unsign ? 0x8000 : 0x0000; int signconv = unsign ? 0x8000 : 0x0000;
for (n = 0; n < size * n_channels; n++) { for (n = 0; n < size * n_channels; n++) {
@ -222,16 +207,9 @@ long duh_render_int(
return size; return size;
} }
long duh_render_float(DUH_SIGRENDERER *sigrenderer, sample_t ***sig_samples,
long duh_render_float( long *sig_samples_size, int bits, float volume,
DUH_SIGRENDERER *sigrenderer, float delta, long size, void *sptr) {
sample_t ***sig_samples,
long *sig_samples_size,
int bits,
float volume, float delta,
long size, void *sptr
)
{
long n; long n;
sample_t **sampptr; sample_t **sampptr;
@ -254,8 +232,7 @@ long duh_render_float(
*/ */
ASSERT(n_channels <= 2); ASSERT(n_channels <= 2);
if ((*sig_samples == NULL) || (*sig_samples_size != size)) if ((*sig_samples == NULL) || (*sig_samples_size != size)) {
{
destroy_sample_buffer(*sig_samples); destroy_sample_buffer(*sig_samples);
*sig_samples = allocate_sample_buffer(n_channels, size); *sig_samples = allocate_sample_buffer(n_channels, size);
*sig_samples_size = size; *sig_samples_size = size;
@ -267,14 +244,14 @@ long duh_render_float(
dumb_silence(sampptr[0], n_channels * size); dumb_silence(sampptr[0], n_channels * size);
size = duh_sigrenderer_generate_samples(sigrenderer, volume, delta, size, sampptr); size = duh_sigrenderer_generate_samples(sigrenderer, volume, delta, size,
sampptr);
if (bits == 64) { if (bits == 64) {
for (n = 0; n < size * n_channels; n++) { for (n = 0; n < size * n_channels; n++) {
CONVERT64F(sampptr[0][n], n); CONVERT64F(sampptr[0][n], n);
} }
} else } else if (bits == 32) {
if (bits == 32) {
for (n = 0; n < size * n_channels; n++) { for (n = 0; n < size * n_channels; n++) {
CONVERT32F(sampptr[0][n], n); CONVERT32F(sampptr[0][n], n);
} }
@ -282,50 +259,3 @@ long duh_render_float(
return size; return size;
} }
/* DEPRECATED */
int duh_renderer_get_n_channels(DUH_SIGRENDERER *dr)
{
return duh_sigrenderer_get_n_channels(dr);
}
/* DEPRECATED */
long duh_renderer_get_position(DUH_SIGRENDERER *dr)
{
return duh_sigrenderer_get_position(dr);
}
/* DEPRECATED */
void duh_end_renderer(DUH_SIGRENDERER *dr)
{
duh_end_sigrenderer(dr);
}
/* DEPRECATED */
DUH_SIGRENDERER *duh_renderer_encapsulate_sigrenderer(DUH_SIGRENDERER *sigrenderer)
{
return sigrenderer;
}
/* DEPRECATED */
DUH_SIGRENDERER *duh_renderer_get_sigrenderer(DUH_SIGRENDERER *dr)
{
return dr;
}
/* DEPRECATED */
DUH_SIGRENDERER *duh_renderer_decompose_to_sigrenderer(DUH_SIGRENDERER *dr)
{
return dr;
}

View file

@ -22,10 +22,7 @@
#include "dumb.h" #include "dumb.h"
#include "internal/dumb.h" #include "internal/dumb.h"
struct DUH_SIGRENDERER {
struct DUH_SIGRENDERER
{
DUH_SIGTYPE_DESC *desc; DUH_SIGTYPE_DESC *desc;
sigrenderer_t *sigrenderer; sigrenderer_t *sigrenderer;
@ -39,10 +36,8 @@ struct DUH_SIGRENDERER
void *callback_data; void *callback_data;
}; };
DUH_SIGRENDERER *duh_start_sigrenderer(DUH *duh, int sig, int n_channels,
long pos) {
DUH_SIGRENDERER *duh_start_sigrenderer(DUH *duh, int sig, int n_channels, long pos)
{
DUH_SIGRENDERER *sigrenderer; DUH_SIGRENDERER *sigrenderer;
DUH_SIGNAL *signal; DUH_SIGNAL *signal;
@ -68,7 +63,8 @@ DUH_SIGRENDERER *duh_start_sigrenderer(DUH *duh, int sig, int n_channels, long p
if (proc) { if (proc) {
duh->signal[sig] = NULL; duh->signal[sig] = NULL;
sigrenderer->sigrenderer = (*proc)(duh, signal->sigdata, n_channels, pos); sigrenderer->sigrenderer =
(*proc)(duh, signal->sigdata, n_channels, pos);
duh->signal[sig] = signal; duh->signal[sig] = signal;
if (!sigrenderer->sigrenderer) { if (!sigrenderer->sigrenderer) {
@ -88,64 +84,24 @@ DUH_SIGRENDERER *duh_start_sigrenderer(DUH *duh, int sig, int n_channels, long p
return sigrenderer; return sigrenderer;
} }
#include <stdio.h>
void duh_sigrenderer_set_callback(
DUH_SIGRENDERER *sigrenderer,
DUH_SIGRENDERER_CALLBACK callback, void *data
)
{
(void)sigrenderer;
(void)callback;
(void)data;
/*fprintf(stderr,
"Call to deprecated function duh_sigrenderer_set_callback(). The callback\n"
"was not installed. See dumb/docs/deprec.txt for how to fix this.\n");*/
}
void duh_sigrenderer_set_analyser_callback(
DUH_SIGRENDERER *sigrenderer,
DUH_SIGRENDERER_ANALYSER_CALLBACK callback, void *data
)
{
(void)sigrenderer;
(void)callback;
(void)data;
fprintf(stderr,
"Call to deprecated function duh_sigrenderer_set_analyser_callback(). The\n"
"callback was not installed. See dumb/docs/deprec.txt for how to fix this.\n");
}
void duh_sigrenderer_set_sample_analyser_callback( void duh_sigrenderer_set_sample_analyser_callback(
DUH_SIGRENDERER *sigrenderer, DUH_SIGRENDERER *sigrenderer,
DUH_SIGRENDERER_SAMPLE_ANALYSER_CALLBACK callback, void *data DUH_SIGRENDERER_SAMPLE_ANALYSER_CALLBACK callback, void *data) {
)
{
if (sigrenderer) { if (sigrenderer) {
sigrenderer->callback = callback; sigrenderer->callback = callback;
sigrenderer->callback_data = data; sigrenderer->callback_data = data;
} }
} }
int duh_sigrenderer_get_n_channels(DUH_SIGRENDERER *sigrenderer) {
int duh_sigrenderer_get_n_channels(DUH_SIGRENDERER *sigrenderer)
{
return sigrenderer ? sigrenderer->n_channels : 0; return sigrenderer ? sigrenderer->n_channels : 0;
} }
long duh_sigrenderer_get_position(DUH_SIGRENDERER *sigrenderer) {
long duh_sigrenderer_get_position(DUH_SIGRENDERER *sigrenderer)
{
DUH_SIGRENDERER_GET_POSITION proc; DUH_SIGRENDERER_GET_POSITION proc;
if (!sigrenderer) return -1; if (!sigrenderer)
return -1;
proc = sigrenderer->desc->sigrenderer_get_position; proc = sigrenderer->desc->sigrenderer_get_position;
if (proc) if (proc)
@ -154,50 +110,42 @@ long duh_sigrenderer_get_position(DUH_SIGRENDERER *sigrenderer)
return sigrenderer->pos; return sigrenderer->pos;
} }
void duh_sigrenderer_set_sigparam(DUH_SIGRENDERER *sigrenderer,
unsigned char id, long value) {
void duh_sigrenderer_set_sigparam(
DUH_SIGRENDERER *sigrenderer,
unsigned char id, long value
)
{
DUH_SIGRENDERER_SET_SIGPARAM proc; DUH_SIGRENDERER_SET_SIGPARAM proc;
if (!sigrenderer) return; if (!sigrenderer)
return;
proc = sigrenderer->desc->sigrenderer_set_sigparam; proc = sigrenderer->desc->sigrenderer_set_sigparam;
if (proc) if (proc)
(*proc)(sigrenderer->sigrenderer, id, value); (*proc)(sigrenderer->sigrenderer, id, value);
else else
TRACE("Parameter #%d = %ld for signal %c%c%c%c, which does not take parameters.\n", TRACE("Parameter #%d = %ld for signal %c%c%c%c, which does not take "
(int)id, "parameters.\n",
value, (int)id, value, (int)(sigrenderer->desc->type >> 24),
(int)(sigrenderer->desc->type >> 24),
(int)(sigrenderer->desc->type >> 16), (int)(sigrenderer->desc->type >> 16),
(int)(sigrenderer->desc->type >> 8), (int)(sigrenderer->desc->type >> 8),
(int)(sigrenderer->desc->type)); (int)(sigrenderer->desc->type));
} }
long duh_sigrenderer_generate_samples(DUH_SIGRENDERER *sigrenderer,
float volume, float delta, long size,
long duh_sigrenderer_generate_samples( sample_t **samples) {
DUH_SIGRENDERER *sigrenderer,
float volume, float delta,
long size, sample_t **samples
)
{
long rendered; long rendered;
LONG_LONG t; LONG_LONG t;
if (!sigrenderer) return 0; if (!sigrenderer)
return 0;
rendered = (*sigrenderer->desc->sigrenderer_generate_samples) rendered = (*sigrenderer->desc->sigrenderer_generate_samples)(
(sigrenderer->sigrenderer, volume, delta, size, samples); sigrenderer->sigrenderer, volume, delta, size, samples);
if (rendered) { if (rendered) {
if (sigrenderer->callback) if (sigrenderer->callback)
(*sigrenderer->callback)(sigrenderer->callback_data, (*sigrenderer->callback)(sigrenderer->callback_data,
(const sample_t *const *)samples, sigrenderer->n_channels, rendered); (const sample_t *const *)samples,
sigrenderer->n_channels, rendered);
t = sigrenderer->subpos + (LONG_LONG)(delta * 65536.0 + 0.5) * rendered; t = sigrenderer->subpos + (LONG_LONG)(delta * 65536.0 + 0.5) * rendered;
@ -208,68 +156,14 @@ long duh_sigrenderer_generate_samples(
return rendered; return rendered;
} }
void duh_sigrenderer_get_current_sample(DUH_SIGRENDERER *sigrenderer,
float volume, sample_t *samples) {
/* DEPRECATED */
long duh_sigrenderer_get_samples(
DUH_SIGRENDERER *sigrenderer,
float volume, float delta,
long size, sample_t **samples
)
{
sample_t **s;
long rendered;
long i;
int j;
if (!samples) return duh_sigrenderer_generate_samples(sigrenderer, volume, delta, size, NULL);
s = allocate_sample_buffer(sigrenderer->n_channels, size);
if (!s) return 0;
dumb_silence(s[0], sigrenderer->n_channels * size);
rendered = duh_sigrenderer_generate_samples(sigrenderer, volume, delta, size, s);
for (j = 0; j < sigrenderer->n_channels; j++)
for (i = 0; i < rendered; i++)
samples[j][i] += s[0][i*sigrenderer->n_channels+j];
destroy_sample_buffer(s);
return rendered;
}
/* DEPRECATED */
long duh_render_signal(
DUH_SIGRENDERER *sigrenderer,
float volume, float delta,
long size, sample_t **samples
)
{
sample_t **s;
long rendered;
long i;
int j;
if (!samples) return duh_sigrenderer_generate_samples(sigrenderer, volume, delta, size, NULL);
s = allocate_sample_buffer(sigrenderer->n_channels, size);
if (!s) return 0;
dumb_silence(s[0], sigrenderer->n_channels * size);
rendered = duh_sigrenderer_generate_samples(sigrenderer, volume, delta, size, s);
for (j = 0; j < sigrenderer->n_channels; j++)
for (i = 0; i < rendered; i++)
samples[j][i] += s[0][i*sigrenderer->n_channels+j] >> 8;
destroy_sample_buffer(s);
return rendered;
}
void duh_sigrenderer_get_current_sample(DUH_SIGRENDERER *sigrenderer, float volume, sample_t *samples)
{
if (sigrenderer) if (sigrenderer)
(*sigrenderer->desc->sigrenderer_get_current_sample)(sigrenderer->sigrenderer, volume, samples); (*sigrenderer->desc->sigrenderer_get_current_sample)(
sigrenderer->sigrenderer, volume, samples);
} }
void duh_end_sigrenderer(DUH_SIGRENDERER *sigrenderer) {
void duh_end_sigrenderer(DUH_SIGRENDERER *sigrenderer)
{
if (sigrenderer) { if (sigrenderer) {
if (sigrenderer->desc->end_sigrenderer) if (sigrenderer->desc->end_sigrenderer)
if (sigrenderer->sigrenderer) if (sigrenderer->sigrenderer)
@ -279,13 +173,13 @@ void duh_end_sigrenderer(DUH_SIGRENDERER *sigrenderer)
} }
} }
DUH_SIGRENDERER *duh_encapsulate_raw_sigrenderer(sigrenderer_t *vsigrenderer,
DUH_SIGTYPE_DESC *desc,
DUH_SIGRENDERER *duh_encapsulate_raw_sigrenderer(sigrenderer_t *vsigrenderer, DUH_SIGTYPE_DESC *desc, int n_channels, long pos) int n_channels, long pos) {
{
DUH_SIGRENDERER *sigrenderer; DUH_SIGRENDERER *sigrenderer;
if (desc->start_sigrenderer && !vsigrenderer) return NULL; if (desc->start_sigrenderer && !vsigrenderer)
return NULL;
sigrenderer = malloc(sizeof(*sigrenderer)); sigrenderer = malloc(sizeof(*sigrenderer));
if (!sigrenderer) { if (!sigrenderer) {
@ -308,18 +202,14 @@ DUH_SIGRENDERER *duh_encapsulate_raw_sigrenderer(sigrenderer_t *vsigrenderer, DU
return sigrenderer; return sigrenderer;
} }
sigrenderer_t *duh_get_raw_sigrenderer(DUH_SIGRENDERER *sigrenderer,
long type) {
sigrenderer_t *duh_get_raw_sigrenderer(DUH_SIGRENDERER *sigrenderer, long type)
{
if (sigrenderer && sigrenderer->desc->type == type) if (sigrenderer && sigrenderer->desc->type == type)
return sigrenderer->sigrenderer; return sigrenderer->sigrenderer;
return NULL; return NULL;
} }
#if 0 #if 0
// This function is disabled because we don't know whether we want to destroy // This function is disabled because we don't know whether we want to destroy
// the sigrenderer if the type doesn't match. We don't even know if we need // the sigrenderer if the type doesn't match. We don't even know if we need

View file

@ -22,10 +22,7 @@
#include "dumb.h" #include "dumb.h"
#include "internal/dumb.h" #include "internal/dumb.h"
static void destroy_signal(DUH_SIGNAL *signal) {
static void destroy_signal(DUH_SIGNAL *signal)
{
if (signal) { if (signal) {
if (signal->desc) if (signal->desc)
if (signal->desc->unload_sigdata) if (signal->desc->unload_sigdata)
@ -36,13 +33,10 @@ static void destroy_signal(DUH_SIGNAL *signal)
} }
} }
/* unload_duh(): destroys a DUH struct. You must call this for every DUH /* unload_duh(): destroys a DUH struct. You must call this for every DUH
* struct created, when you've finished with it. * struct created, when you've finished with it.
*/ */
void unload_duh(DUH *duh) void unload_duh(DUH *duh) {
{
int i; int i;
if (duh) { if (duh) {

View file

@ -2,65 +2,54 @@
#include <string.h> #include <string.h>
void *bit_array_create(size_t size) {
void * bit_array_create(size_t size)
{
size_t bsize = ((size + 7) >> 3) + sizeof(size_t); size_t bsize = ((size + 7) >> 3) + sizeof(size_t);
void * ret = calloc(1, bsize); void *ret = calloc(1, bsize);
if (ret) *(size_t *)ret = size; if (ret)
*(size_t *)ret = size;
return ret; return ret;
} }
void bit_array_destroy(void * array) void bit_array_destroy(void *array) {
{ if (array)
if (array) free(array); free(array);
} }
void * bit_array_dup(void * array) void *bit_array_dup(void *array) {
{ if (array) {
if (array) size_t *size = (size_t *)array;
{
size_t * size = (size_t *) array;
size_t bsize = ((*size + 7) >> 3) + sizeof(*size); size_t bsize = ((*size + 7) >> 3) + sizeof(*size);
void * ret = malloc(bsize); void *ret = malloc(bsize);
if (ret) memcpy(ret, array, bsize); if (ret)
memcpy(ret, array, bsize);
return ret; return ret;
} }
return NULL; return NULL;
} }
void bit_array_reset(void * array) void bit_array_reset(void *array) {
{ if (array) {
if (array) size_t *size = (size_t *)array;
{
size_t * size = (size_t *) array;
size_t bsize = (*size + 7) >> 3; size_t bsize = (*size + 7) >> 3;
memset(size + 1, 0, bsize); memset(size + 1, 0, bsize);
} }
} }
void bit_array_set(void *array, size_t bit) {
void bit_array_set(void * array, size_t bit) if (array) {
{ size_t *size = (size_t *)array;
if (array) if (bit < *size) {
{ unsigned char *ptr = (unsigned char *)(size + 1);
size_t * size = (size_t *) array;
if (bit < *size)
{
unsigned char * ptr = (unsigned char *)(size + 1);
ptr[bit >> 3] |= (1U << (bit & 7)); ptr[bit >> 3] |= (1U << (bit & 7));
} }
} }
} }
void bit_array_set_range(void * array, size_t bit, size_t count) void bit_array_set_range(void *array, size_t bit, size_t count) {
{ if (array && count) {
if (array && count) size_t *size = (size_t *)array;
{ if (bit < *size) {
size_t * size = (size_t *) array; unsigned char *ptr = (unsigned char *)(size + 1);
if (bit < *size)
{
unsigned char * ptr = (unsigned char *)(size + 1);
size_t i; size_t i;
for (i = bit; i < *size && i < bit + count; ++i) for (i = bit; i < *size && i < bit + count; ++i)
ptr[i >> 3] |= (1U << (i & 7)); ptr[i >> 3] |= (1U << (i & 7));
@ -68,16 +57,12 @@ void bit_array_set_range(void * array, size_t bit, size_t count)
} }
} }
int bit_array_test(void * array, size_t bit) int bit_array_test(void *array, size_t bit) {
{ if (array) {
if (array) size_t *size = (size_t *)array;
{ if (bit < *size) {
size_t * size = (size_t *) array; unsigned char *ptr = (unsigned char *)(size + 1);
if (bit < *size) if (ptr[bit >> 3] & (1U << (bit & 7))) {
{
unsigned char * ptr = (unsigned char *)(size + 1);
if (ptr[bit >> 3] & (1U << (bit & 7)))
{
return 1; return 1;
} }
} }
@ -85,35 +70,30 @@ int bit_array_test(void * array, size_t bit)
return 0; return 0;
} }
int bit_array_test_range(void * array, size_t bit, size_t count) int bit_array_test_range(void *array, size_t bit, size_t count) {
{ if (array) {
if (array) size_t *size = (size_t *)array;
{ if (bit < *size) {
size_t * size = (size_t *) array; unsigned char *ptr = (unsigned char *)(size + 1);
if (bit < *size) if ((bit & 7) && (count > 8)) {
{ while ((bit < *size) && count && (bit & 7)) {
unsigned char * ptr = (unsigned char *)(size + 1); if (ptr[bit >> 3] & (1U << (bit & 7)))
if ((bit & 7) && (count > 8)) return 1;
{
while ((bit < *size) && count && (bit & 7))
{
if (ptr[bit >> 3] & (1U << (bit & 7))) return 1;
bit++; bit++;
count--; count--;
} }
} }
if (!(bit & 7)) if (!(bit & 7)) {
{ while (((*size - bit) >= 8) && (count >= 8)) {
while (((*size - bit) >= 8) && (count >= 8)) if (ptr[bit >> 3])
{ return 1;
if (ptr[bit >> 3]) return 1;
bit += 8; bit += 8;
count -= 8; count -= 8;
} }
} }
while ((bit < *size) && count) while ((bit < *size) && count) {
{ if (ptr[bit >> 3] & (1U << (bit & 7)))
if (ptr[bit >> 3] & (1U << (bit & 7))) return 1; return 1;
bit++; bit++;
count--; count--;
} }
@ -122,27 +102,21 @@ int bit_array_test_range(void * array, size_t bit, size_t count)
return 0; return 0;
} }
void bit_array_clear(void * array, size_t bit) void bit_array_clear(void *array, size_t bit) {
{ if (array) {
if (array) size_t *size = (size_t *)array;
{ if (bit < *size) {
size_t * size = (size_t *) array; unsigned char *ptr = (unsigned char *)(size + 1);
if (bit < *size)
{
unsigned char * ptr = (unsigned char *)(size + 1);
ptr[bit >> 3] &= ~(1U << (bit & 7)); ptr[bit >> 3] &= ~(1U << (bit & 7));
} }
} }
} }
void bit_array_clear_range(void * array, size_t bit, size_t count) void bit_array_clear_range(void *array, size_t bit, size_t count) {
{ if (array && count) {
if (array && count) size_t *size = (size_t *)array;
{ if (bit < *size) {
size_t * size = (size_t *) array; unsigned char *ptr = (unsigned char *)(size + 1);
if (bit < *size)
{
unsigned char * ptr = (unsigned char *)(size + 1);
size_t i; size_t i;
for (i = bit; i < *size && i < bit + count; ++i) for (i = bit; i < *size && i < bit + count; ++i)
ptr[i >> 3] &= ~(1U << (i & 7)); ptr[i >> 3] &= ~(1U << (i & 7));
@ -150,17 +124,13 @@ void bit_array_clear_range(void * array, size_t bit, size_t count)
} }
} }
void bit_array_merge(void * dest, void * source, size_t offset) void bit_array_merge(void *dest, void *source, size_t offset) {
{ if (dest && source) {
if (dest && source) size_t *dsize = (size_t *)dest;
{ size_t *ssize = (size_t *)source;
size_t * dsize = (size_t *) dest;
size_t * ssize = (size_t *) source;
size_t soffset = 0; size_t soffset = 0;
while (offset < *dsize && soffset < *ssize) while (offset < *dsize && soffset < *ssize) {
{ if (bit_array_test(source, soffset)) {
if (bit_array_test(source, soffset))
{
bit_array_set(dest, offset); bit_array_set(dest, offset);
} }
soffset++; soffset++;
@ -169,17 +139,13 @@ void bit_array_merge(void * dest, void * source, size_t offset)
} }
} }
void bit_array_mask(void * dest, void * source, size_t offset) void bit_array_mask(void *dest, void *source, size_t offset) {
{ if (dest && source) {
if (dest && source) size_t *dsize = (size_t *)dest;
{ size_t *ssize = (size_t *)source;
size_t * dsize = (size_t *) dest;
size_t * ssize = (size_t *) source;
size_t soffset = 0; size_t soffset = 0;
while (offset < *dsize && soffset < *ssize) while (offset < *dsize && soffset < *ssize) {
{ if (bit_array_test(source, soffset)) {
if (bit_array_test(source, soffset))
{
bit_array_clear(dest, offset); bit_array_clear(dest, offset);
} }
soffset++; soffset++;

View file

@ -20,34 +20,27 @@
#include <stdlib.h> #include <stdlib.h>
#include <math.h> #include <math.h>
#include "dumb.h" #include "dumb.h"
#include "internal/dumb.h"
typedef struct DUMB_CLICK DUMB_CLICK; typedef struct DUMB_CLICK DUMB_CLICK;
struct DUMB_CLICK_REMOVER {
struct DUMB_CLICK_REMOVER
{
DUMB_CLICK *click; DUMB_CLICK *click;
int n_clicks; int n_clicks;
int offset; int offset;
}; };
struct DUMB_CLICK {
struct DUMB_CLICK
{
DUMB_CLICK *next; DUMB_CLICK *next;
long pos; long pos;
sample_t step; sample_t step;
}; };
DUMB_CLICK_REMOVER *dumb_create_click_remover(void) {
DUMB_CLICK_REMOVER *dumb_create_click_remover(void)
{
DUMB_CLICK_REMOVER *cr = malloc(sizeof(*cr)); DUMB_CLICK_REMOVER *cr = malloc(sizeof(*cr));
if (!cr) return NULL; if (!cr)
return NULL;
cr->click = NULL; cr->click = NULL;
cr->n_clicks = 0; cr->n_clicks = 0;
@ -57,15 +50,13 @@ DUMB_CLICK_REMOVER *dumb_create_click_remover(void)
return cr; return cr;
} }
void dumb_record_click(DUMB_CLICK_REMOVER *cr, long pos, sample_t step) {
void dumb_record_click(DUMB_CLICK_REMOVER *cr, long pos, sample_t step)
{
DUMB_CLICK *click; DUMB_CLICK *click;
ASSERT(pos >= 0); ASSERT(pos >= 0);
if (!cr || !step) return; if (!cr || !step)
return;
if (pos == 0) { if (pos == 0) {
cr->offset -= step; cr->offset -= step;
@ -73,7 +64,8 @@ void dumb_record_click(DUMB_CLICK_REMOVER *cr, long pos, sample_t step)
} }
click = malloc(sizeof(*click)); click = malloc(sizeof(*click));
if (!click) return; if (!click)
return;
click->pos = pos; click->pos = pos;
click->step = step; click->step = step;
@ -83,19 +75,18 @@ void dumb_record_click(DUMB_CLICK_REMOVER *cr, long pos, sample_t step)
cr->n_clicks++; cr->n_clicks++;
} }
static DUMB_CLICK *dumb_click_mergesort(DUMB_CLICK *click, int n_clicks) {
static DUMB_CLICK *dumb_click_mergesort(DUMB_CLICK *click, int n_clicks)
{
int i; int i;
DUMB_CLICK *c1, *c2, **cp; DUMB_CLICK *c1, *c2, **cp;
if (n_clicks <= 1) return click; if (n_clicks <= 1)
return click;
/* Split the list into two */ /* Split the list into two */
c1 = click; c1 = click;
cp = &c1; cp = &c1;
for (i = 0; i < n_clicks; i += 2) cp = &(*cp)->next; for (i = 0; i < n_clicks; i += 2)
cp = &(*cp)->next;
c2 = *cp; c2 = *cp;
*cp = NULL; *cp = NULL;
@ -123,18 +114,17 @@ static DUMB_CLICK *dumb_click_mergesort(DUMB_CLICK *click, int n_clicks)
return click; return click;
} }
void dumb_remove_clicks(DUMB_CLICK_REMOVER *cr, sample_t *samples, long length,
int step, float halflife) {
void dumb_remove_clicks(DUMB_CLICK_REMOVER *cr, sample_t *samples, long length, int step, float halflife)
{
DUMB_CLICK *click; DUMB_CLICK *click;
long pos = 0; long pos = 0;
int offset; int offset;
int factor; int factor;
if (!cr) return; if (!cr)
return;
factor = (int)floor(pow(0.5, 1.0/halflife) * (1U << 31)); factor = (int)floor(pow(0.5, 1.0 / halflife) * (1U << 31));
click = dumb_click_mergesort(cr->click, cr->n_clicks); click = dumb_click_mergesort(cr->click, cr->n_clicks);
cr->click = NULL; cr->click = NULL;
@ -144,7 +134,7 @@ void dumb_remove_clicks(DUMB_CLICK_REMOVER *cr, sample_t *samples, long length,
while (click) { while (click) {
DUMB_CLICK *next = click->next; DUMB_CLICK *next = click->next;
int end = click->pos * step; long end = click->pos * step;
ASSERT(end <= length); ASSERT(end <= length);
offset = cr->offset; offset = cr->offset;
if (offset < 0) { if (offset < 0) {
@ -186,17 +176,11 @@ void dumb_remove_clicks(DUMB_CLICK_REMOVER *cr, sample_t *samples, long length,
cr->offset = offset; cr->offset = offset;
} }
sample_t dumb_click_remover_get_offset(DUMB_CLICK_REMOVER *cr) {
sample_t dumb_click_remover_get_offset(DUMB_CLICK_REMOVER *cr)
{
return cr ? cr->offset : 0; return cr ? cr->offset : 0;
} }
void dumb_destroy_click_remover(DUMB_CLICK_REMOVER *cr) {
void dumb_destroy_click_remover(DUMB_CLICK_REMOVER *cr)
{
if (cr) { if (cr) {
DUMB_CLICK *click = cr->click; DUMB_CLICK *click = cr->click;
while (click) { while (click) {
@ -208,23 +192,21 @@ void dumb_destroy_click_remover(DUMB_CLICK_REMOVER *cr)
} }
} }
DUMB_CLICK_REMOVER **dumb_create_click_remover_array(int n) {
DUMB_CLICK_REMOVER **dumb_create_click_remover_array(int n)
{
int i; int i;
DUMB_CLICK_REMOVER **cr; DUMB_CLICK_REMOVER **cr;
if (n <= 0) return NULL; if (n <= 0)
return NULL;
cr = malloc(n * sizeof(*cr)); cr = malloc(n * sizeof(*cr));
if (!cr) return NULL; if (!cr)
for (i = 0; i < n; i++) cr[i] = dumb_create_click_remover(); return NULL;
for (i = 0; i < n; i++)
cr[i] = dumb_create_click_remover();
return cr; return cr;
} }
void dumb_record_click_array(int n, DUMB_CLICK_REMOVER **cr, long pos,
sample_t *step) {
void dumb_record_click_array(int n, DUMB_CLICK_REMOVER **cr, long pos, sample_t *step)
{
if (cr) { if (cr) {
int i; int i;
for (i = 0; i < n; i++) for (i = 0; i < n; i++)
@ -232,10 +214,8 @@ void dumb_record_click_array(int n, DUMB_CLICK_REMOVER **cr, long pos, sample_t
} }
} }
void dumb_record_click_negative_array(int n, DUMB_CLICK_REMOVER **cr, long pos,
sample_t *step) {
void dumb_record_click_negative_array(int n, DUMB_CLICK_REMOVER **cr, long pos, sample_t *step)
{
if (cr) { if (cr) {
int i; int i;
for (i = 0; i < n; i++) for (i = 0; i < n; i++)
@ -243,39 +223,35 @@ void dumb_record_click_negative_array(int n, DUMB_CLICK_REMOVER **cr, long pos,
} }
} }
void dumb_remove_clicks_array(int n, DUMB_CLICK_REMOVER **cr,
sample_t **samples, long length, float halflife) {
void dumb_remove_clicks_array(int n, DUMB_CLICK_REMOVER **cr, sample_t **samples, long length, float halflife)
{
if (cr) { if (cr) {
int i; int i;
for (i = 0; i < n >> 1; i++) { for (i = 0; i<n>> 1; i++) {
dumb_remove_clicks(cr[i << 1], samples[i], length, 2, halflife); dumb_remove_clicks(cr[i << 1], samples[i], length, 2, halflife);
dumb_remove_clicks(cr[(i << 1) + 1], samples[i] + 1, length, 2, halflife); dumb_remove_clicks(cr[(i << 1) + 1], samples[i] + 1, length, 2,
halflife);
} }
if (n & 1) if (n & 1)
dumb_remove_clicks(cr[i << 1], samples[i], length, 1, halflife); dumb_remove_clicks(cr[i << 1], samples[i], length, 1, halflife);
} }
} }
void dumb_click_remover_get_offset_array(int n, DUMB_CLICK_REMOVER **cr,
sample_t *offset) {
void dumb_click_remover_get_offset_array(int n, DUMB_CLICK_REMOVER **cr, sample_t *offset)
{
if (cr) { if (cr) {
int i; int i;
for (i = 0; i < n; i++) for (i = 0; i < n; i++)
if (cr[i]) offset[i] += cr[i]->offset; if (cr[i])
offset[i] += cr[i]->offset;
} }
} }
void dumb_destroy_click_remover_array(int n, DUMB_CLICK_REMOVER **cr) {
void dumb_destroy_click_remover_array(int n, DUMB_CLICK_REMOVER **cr)
{
if (cr) { if (cr) {
int i; int i;
for (i = 0; i < n; i++) dumb_destroy_click_remover(cr[i]); for (i = 0; i < n; i++)
dumb_destroy_click_remover(cr[i]);
free(cr); free(cr);
} }
} }

View file

@ -1,281 +0,0 @@
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include "internal/fir_resampler.h"
enum { fir_width = 16 };
enum { fir_max_res = 1024 };
enum { fir_min_width = (fir_width < 4 ? 4 : fir_width) };
enum { fir_adj_width = fir_min_width / 4 * 4 + 2 };
enum { fir_stereo = 1 }; /* channel count, not boolean value */
enum { fir_write_offset = fir_adj_width * fir_stereo };
enum { fir_buffer_size = fir_width * 2 };
typedef short fir_impulse[fir_adj_width];
/* exp slope to 31/32 of ln(8) */
static const double fir_ratios[32] = {
1.000, 1.067, 1.139, 1.215, 1.297, 1.384, 1.477, 1.576,
1.682, 1.795, 1.915, 2.044, 2.181, 2.327, 2.484, 2.650,
2.828, 3.018, 3.221, 3.437, 3.668, 3.914, 4.177, 4.458,
4.757, 5.076, 5.417, 5.781, 6.169, 6.583, 7.025, 7.497
};
static fir_impulse fir_impulses[32][fir_max_res];
#undef PI
#define PI 3.1415926535897932384626433832795029
static void gen_sinc( double rolloff, int width, double offset, double spacing, double scale,
int count, short* out )
{
double const maxh = 256;
double const step = PI / maxh * spacing;
double const to_w = maxh * 2 / width;
double const pow_a_n = pow( rolloff, maxh );
double angle = (count / 2 - 1 + offset) * -step;
scale /= maxh * 2;
while ( count-- )
{
double w;
*out++ = 0;
w = angle * to_w;
if ( fabs( w ) < PI )
{
double rolloff_cos_a = rolloff * cos( angle );
double num = 1 - rolloff_cos_a -
pow_a_n * cos( maxh * angle ) +
pow_a_n * rolloff * cos( (maxh - 1) * angle );
double den = 1 - rolloff_cos_a - rolloff_cos_a + rolloff * rolloff;
double sinc = scale * num / den - scale;
out [-1] = (short) (cos( w ) * sinc + sinc);
}
angle += step;
}
}
typedef struct fir_resampler
{
int write_pos, write_filled;
int read_pos, read_filled;
unsigned short phase;
unsigned int phase_inc;
unsigned int ratio_set;
int buffer_in[fir_buffer_size * 2];
int buffer_out[fir_buffer_size];
} fir_resampler;
void * fir_resampler_create()
{
fir_resampler * r = ( fir_resampler * ) malloc( sizeof(fir_resampler) );
if ( !r ) return 0;
r->write_pos = 0;
r->write_filled = 0;
r->read_pos = 0;
r->read_filled = 0;
r->phase = 0;
r->phase_inc = 0;
r->ratio_set = 0;
memset( r->buffer_in, 0, sizeof(r->buffer_in) );
memset( r->buffer_out, 0, sizeof(r->buffer_out) );
return r;
}
void fir_resampler_delete(void * _r)
{
free( _r );
}
void * fir_resampler_dup(void * _r)
{
fir_resampler * r_in = ( fir_resampler * ) _r;
fir_resampler * r_out = ( fir_resampler * ) malloc( sizeof(fir_resampler) );
if ( !r_out ) return 0;
r_out->write_pos = r_in->write_pos;
r_out->write_filled = r_in->write_filled;
r_out->read_pos = r_in->read_pos;
r_out->read_filled = r_in->read_filled;
r_out->phase = r_in->phase;
r_out->phase_inc = r_in->phase_inc;
r_out->ratio_set = r_in->ratio_set;
memcpy( r_out->buffer_in, r_in->buffer_in, sizeof(r_in->buffer_in) );
memcpy( r_out->buffer_out, r_in->buffer_out, sizeof(r_in->buffer_out) );
return r_out;
}
int fir_resampler_get_free_count(void *_r)
{
fir_resampler * r = ( fir_resampler * ) _r;
return fir_buffer_size - r->write_filled;
}
int fir_resampler_ready(void *_r)
{
fir_resampler * r = ( fir_resampler * ) _r;
return r->write_filled > fir_adj_width;
}
void fir_resampler_clear(void *_r)
{
fir_resampler * r = ( fir_resampler * ) _r;
r->write_pos = 0;
r->write_filled = 0;
r->read_pos = 0;
r->read_filled = 0;
r->phase = 0;
memset( r->buffer_in, 0, sizeof(r->buffer_in) );
}
void fir_resampler_set_rate(void *_r, double new_factor)
{
fir_resampler * r = ( fir_resampler * ) _r;
r->phase_inc = (int)( new_factor * 65536.0 );
r->ratio_set = 0;
while ( r->ratio_set < 31 && new_factor > fir_ratios[ r->ratio_set ] ) r->ratio_set++;
}
void fir_resampler_write_sample(void *_r, short s)
{
fir_resampler * r = ( fir_resampler * ) _r;
if ( r->write_filled < fir_buffer_size )
{
int s32 = s;
r->buffer_in[ r->write_pos ] = s32;
r->buffer_in[ r->write_pos + fir_buffer_size ] = s32;
++r->write_filled;
r->write_pos = ( r->write_pos + 1 ) % fir_buffer_size;
}
}
void fir_init()
{
double const rolloff = 0.999;
double const gain = 1.0;
int const res = fir_max_res;
int i;
for (i = 0; i < 32; i++)
{
double const ratio_ = fir_ratios[ i ];
double fraction = 1.0 / (double)fir_max_res;
double const filter = (ratio_ < 1.0) ? 1.0 : 1.0 / ratio_;
double pos = 0.0;
short* out = (short*) fir_impulses[ i ];
int n;
for ( n = res; --n >= 0; )
{
gen_sinc( rolloff, (int) (fir_adj_width * filter + 1) & ~1, pos, filter,
(double) (0x7FFF * gain * filter), (int) fir_adj_width, out );
out += fir_adj_width;
pos += fraction;
}
}
}
int fir_resampler_run(void *_r, int ** out_, int * out_end)
{
fir_resampler * r = ( fir_resampler * ) _r;
int in_size = r->write_filled;
int const* in_ = r->buffer_in + fir_buffer_size + r->write_pos - r->write_filled;
int used = 0;
in_size -= fir_write_offset;
if ( in_size > 0 )
{
int* out = *out_;
int const* in = in_;
int const* const in_end = in + in_size;
int phase = r->phase;
int phase_inc = r->phase_inc;
int ratio_set = r->ratio_set;
do
{
// accumulate in extended precision
short const* imp = fir_impulses[ratio_set][(phase & 0xFFC0) >> 6];
int pt = imp [0];
int s = pt * in [0];
int n;
if ( out >= out_end )
break;
for ( n = (fir_adj_width - 2) / 2; n; --n )
{
pt = imp [1];
s += pt * in [1];
// pre-increment more efficient on some RISC processors
imp += 2;
pt = imp [0];
in += 2;
s += pt * in [0];
}
pt = imp [1];
s += pt * in [1];
phase += phase_inc;
in += (phase >> 16) - fir_adj_width + 2;
phase &= 65535;
*out++ = (int) (s >> 7);
}
while ( in < in_end );
r->phase = phase;
*out_ = out;
used = in - in_;
r->write_filled -= used;
}
return used;
}
int fir_resampler_get_sample(void *_r)
{
fir_resampler * r = ( fir_resampler * ) _r;
if ( r->read_filled < 1 )
{
int write_pos = ( r->read_pos + r->read_filled ) % fir_buffer_size;
int write_size = fir_buffer_size - write_pos;
int * out = r->buffer_out + write_pos;
if ( write_size > ( fir_buffer_size - r->read_filled ) )
write_size = fir_buffer_size - r->read_filled;
fir_resampler_run( r, &out, out + write_size );
r->read_filled += out - r->buffer_out - write_pos;
}
if ( r->read_filled < 1 )
return 0;
return r->buffer_out[ r->read_pos ];
}
void fir_resampler_remove_sample(void *_r)
{
fir_resampler * r = ( fir_resampler * ) _r;
if ( r->read_filled > 0 )
{
--r->read_filled;
r->read_pos = ( r->read_pos + 1 ) % fir_buffer_size;
}
}

View file

@ -55,32 +55,33 @@ Carsten Bormann
/* Input : n elements of time doamin data /* Input : n elements of time doamin data
Output: m lpc coefficients, excitation energy */ Output: m lpc coefficients, excitation energy */
static float vorbis_lpc_from_data(float *data,float *lpci,long n,long m){ static float vorbis_lpc_from_data(float *data, float *lpci, long n, long m) {
double *aut=alloca(sizeof(*aut)*(m+1)); double *aut = alloca(sizeof(*aut) * (m + 1));
double *lpc=alloca(sizeof(*lpc)*(m)); double *lpc = alloca(sizeof(*lpc) * (m));
double error; double error;
double epsilon; double epsilon;
long i,j; long i, j;
/* autocorrelation, p+1 lag coefficients */ /* autocorrelation, p+1 lag coefficients */
j=m+1; j = m + 1;
while(j--){ while (j--) {
double d=0; /* double needed for accumulator depth */ double d = 0; /* double needed for accumulator depth */
for(i=j;i<n;i++)d+=(double)data[i]*data[(i-j)]; for (i = j; i < n; i++)
aut[j]=d; d += (double)data[i] * data[(i - j)];
aut[j] = d;
} }
/* Generate lpc coefficients from autocorr values */ /* Generate lpc coefficients from autocorr values */
/* set our noise floor to about -100dB */ /* set our noise floor to about -100dB */
error=aut[0] * (1. + 1e-10); error = aut[0] * (1. + 1e-10);
epsilon=1e-9*aut[0]+1e-10; epsilon = 1e-9 * aut[0] + 1e-10;
for(i=0;i<m;i++){ for (i = 0; i < m; i++) {
double r= -aut[i+1]; double r = -aut[i + 1];
if(error<epsilon){ if (error < epsilon) {
memset(lpc+i,0,(m-i)*sizeof(*lpc)); memset(lpc + i, 0, (m - i) * sizeof(*lpc));
goto done; goto done;
} }
@ -89,37 +90,39 @@ static float vorbis_lpc_from_data(float *data,float *lpci,long n,long m){
and needs reflection coefficients, save the results of 'r' from and needs reflection coefficients, save the results of 'r' from
each iteration. */ each iteration. */
for(j=0;j<i;j++)r-=lpc[j]*aut[i-j]; for (j = 0; j < i; j++)
r/=error; r -= lpc[j] * aut[i - j];
r /= error;
/* Update LPC coefficients and total error */ /* Update LPC coefficients and total error */
lpc[i]=r; lpc[i] = r;
for(j=0;j<i/2;j++){ for (j = 0; j < i / 2; j++) {
double tmp=lpc[j]; double tmp = lpc[j];
lpc[j]+=r*lpc[i-1-j]; lpc[j] += r * lpc[i - 1 - j];
lpc[i-1-j]+=r*tmp; lpc[i - 1 - j] += r * tmp;
} }
if(i&1)lpc[j]+=lpc[j]*r; if (i & 1)
lpc[j] += lpc[j] * r;
error*=1.-r*r;
error *= 1. - r * r;
} }
done: done:
/* slightly damp the filter */ /* slightly damp the filter */
{ {
double g = .99; double g = .99;
double damp = g; double damp = g;
for(j=0;j<m;j++){ for (j = 0; j < m; j++) {
lpc[j]*=damp; lpc[j] *= damp;
damp*=g; damp *= g;
} }
} }
for(j=0;j<m;j++)lpci[j]=(float)lpc[j]; for (j = 0; j < m; j++)
lpci[j] = (float)lpc[j];
/* we need the error value to know how big an impulse to hit the /* we need the error value to know how big an impulse to hit the
filter with later */ filter with later */
@ -127,32 +130,32 @@ static float vorbis_lpc_from_data(float *data,float *lpci,long n,long m){
return error; return error;
} }
static void vorbis_lpc_predict(float *coeff,float *prime,long m, static void vorbis_lpc_predict(float *coeff, float *prime, long m, float *data,
float *data,long n){ long n) {
/* in: coeff[0...m-1] LPC coefficients /* in: coeff[0...m-1] LPC coefficients
prime[0...m-1] initial values (allocated size of n+m-1) prime[0...m-1] initial values (allocated size of n+m-1)
out: data[0...n-1] data samples */ out: data[0...n-1] data samples */
long i,j,o,p; long i, j, o, p;
float y; float y;
float *work=alloca(sizeof(*work)*(m+n)); float *work = alloca(sizeof(*work) * (m + n));
if(!prime) if (!prime)
for(i=0;i<m;i++) for (i = 0; i < m; i++)
work[i]=0.f; work[i] = 0.f;
else else
for(i=0;i<m;i++) for (i = 0; i < m; i++)
work[i]=prime[i]; work[i] = prime[i];
for(i=0;i<n;i++){ for (i = 0; i < n; i++) {
y=0; y = 0;
o=i; o = i;
p=m; p = m;
for(j=0;j<m;j++) for (j = 0; j < m; j++)
y-=work[o++]*coeff[--p]; y -= work[o++] * coeff[--p];
data[i]=work[o]=y; data[i] = work[o] = y;
} }
} }
@ -160,66 +163,72 @@ static void vorbis_lpc_predict(float *coeff,float *prime,long m,
#include "internal/dumb.h" #include "internal/dumb.h"
#include "internal/it.h" #include "internal/it.h"
enum { lpc_max = 256 }; /* Maximum number of input samples to train the function */ enum {
lpc_max = 256
}; /* Maximum number of input samples to train the function */
enum { lpc_order = 32 }; /* Order of the filter */ enum { lpc_order = 32 }; /* Order of the filter */
enum { lpc_extra = 64 }; /* How many samples of padding to predict or silence */ enum { lpc_extra = 64 }; /* How many samples of padding to predict or silence */
/* This extra sample padding is really only needed by the FIR resampler, but it
* helps the other resamplers as well. */
/* This extra sample padding is really only needed by the FIR resampler, but it helps the other resamplers as well. */ int dumb_it_add_lpc(struct DUMB_IT_SIGDATA *sigdata) {
int dumb_it_add_lpc(struct DUMB_IT_SIGDATA *sigdata){
float lpc[lpc_order * 2]; float lpc[lpc_order * 2];
float lpc_input[lpc_max * 2]; float lpc_input[lpc_max * 2];
float lpc_output[lpc_extra * 2]; float lpc_output[lpc_extra * 2];
signed char * s8; signed char *s8;
signed short * s16; signed short *s16;
long n, o, offset, lpc_samples; long n, o, offset, lpc_samples;
for ( n = 0; n < sigdata->n_samples; n++ ) { for (n = 0; n < sigdata->n_samples; n++) {
IT_SAMPLE * sample = sigdata->sample + n; IT_SAMPLE *sample = sigdata->sample + n;
if ( ( sample->flags & ( IT_SAMPLE_EXISTS | IT_SAMPLE_LOOP) ) == IT_SAMPLE_EXISTS && if ((sample->flags & (IT_SAMPLE_EXISTS | IT_SAMPLE_LOOP)) ==
sample->data != NULL ) { IT_SAMPLE_EXISTS &&
/* If we have enough sample data to train the filter, use the filter to generate the padding */ sample->data != NULL) {
if ( sample->length >= lpc_order ) { /* If we have enough sample data to train the filter, use the filter
* to generate the padding */
if (sample->length >= lpc_order) {
lpc_samples = sample->length; lpc_samples = sample->length;
if (lpc_samples > lpc_max) lpc_samples = lpc_max; if (lpc_samples > lpc_max)
lpc_samples = lpc_max;
offset = sample->length - lpc_samples; offset = sample->length - lpc_samples;
if ( sample->flags & IT_SAMPLE_STEREO ) if (sample->flags & IT_SAMPLE_STEREO) {
{ if (sample->flags & IT_SAMPLE_16BIT) {
if ( sample->flags & IT_SAMPLE_16BIT ) s16 = (signed short *)sample->data;
{
s16 = ( signed short * ) sample->data;
s16 += offset * 2; s16 += offset * 2;
for ( o = 0; o < lpc_samples; o++ ) for (o = 0; o < lpc_samples; o++) {
{ lpc_input[o] = s16[o * 2 + 0];
lpc_input[ o ] = s16[ o * 2 + 0 ]; lpc_input[o + lpc_max] = s16[o * 2 + 1];
lpc_input[ o + lpc_max ] = s16[ o * 2 + 1 ];
} }
} } else {
else s8 = (signed char *)sample->data;
{
s8 = ( signed char * ) sample->data;
s8 += offset * 2; s8 += offset * 2;
for ( o = 0; o < lpc_samples; o++ ) for (o = 0; o < lpc_samples; o++) {
{ lpc_input[o] = s8[o * 2 + 0];
lpc_input[ o ] = s8[ o * 2 + 0 ]; lpc_input[o + lpc_max] = s8[o * 2 + 1];
lpc_input[ o + lpc_max ] = s8[ o * 2 + 1 ];
} }
} }
vorbis_lpc_from_data( lpc_input, lpc, lpc_samples, lpc_order ); vorbis_lpc_from_data(lpc_input, lpc, lpc_samples,
vorbis_lpc_from_data( lpc_input + lpc_max, lpc + lpc_order, lpc_samples, lpc_order ); lpc_order);
vorbis_lpc_from_data(lpc_input + lpc_max, lpc + lpc_order,
lpc_samples, lpc_order);
vorbis_lpc_predict( lpc, lpc_input + lpc_samples - lpc_order, lpc_order, lpc_output, lpc_extra ); vorbis_lpc_predict(lpc, lpc_input + lpc_samples - lpc_order,
vorbis_lpc_predict( lpc + lpc_order, lpc_input + lpc_max + lpc_samples - lpc_order, lpc_order, lpc_output + lpc_extra, lpc_extra ); lpc_order, lpc_output, lpc_extra);
vorbis_lpc_predict(
lpc + lpc_order,
lpc_input + lpc_max + lpc_samples - lpc_order,
lpc_order, lpc_output + lpc_extra, lpc_extra);
if ( sample->flags & IT_SAMPLE_16BIT ) if (sample->flags & IT_SAMPLE_16BIT) {
{ s16 = (signed short *)realloc(
s16 = ( signed short * ) realloc( sample->data, ( sample->length + lpc_extra ) * 2 * sizeof(short) ); sample->data,
if ( !s16 ) (sample->length + lpc_extra) * 2 * sizeof(short));
if (!s16)
return -1; return -1;
sample->data = s16; sample->data = s16;
@ -227,16 +236,14 @@ int dumb_it_add_lpc(struct DUMB_IT_SIGDATA *sigdata){
s16 += sample->length * 2; s16 += sample->length * 2;
sample->length += lpc_extra; sample->length += lpc_extra;
for ( o = 0; o < lpc_extra; o++ ) for (o = 0; o < lpc_extra; o++) {
{ s16[o * 2 + 0] = lpc_output[o];
s16[ o * 2 + 0 ] = lpc_output[ o ]; s16[o * 2 + 1] = lpc_output[o + lpc_extra];
s16[ o * 2 + 1 ] = lpc_output[ o + lpc_extra ];
} }
} } else {
else s8 = (signed char *)realloc(
{ sample->data, (sample->length + lpc_extra) * 2);
s8 = ( signed char * ) realloc( sample->data, ( sample->length + lpc_extra ) * 2 ); if (!s8)
if ( !s8 )
return -1; return -1;
sample->data = s8; sample->data = s8;
@ -244,41 +251,36 @@ int dumb_it_add_lpc(struct DUMB_IT_SIGDATA *sigdata){
s8 += sample->length * 2; s8 += sample->length * 2;
sample->length += lpc_extra; sample->length += lpc_extra;
for ( o = 0; o < lpc_extra; o++ ) for (o = 0; o < lpc_extra; o++) {
{ s8[o * 2 + 0] = lpc_output[o];
s8[ o * 2 + 0 ] = lpc_output[ o ]; s8[o * 2 + 1] = lpc_output[o + lpc_extra];
s8[ o * 2 + 1 ] = lpc_output[ o + lpc_extra ];
} }
} }
} } else {
else if (sample->flags & IT_SAMPLE_16BIT) {
{ s16 = (signed short *)sample->data;
if ( sample->flags & IT_SAMPLE_16BIT )
{
s16 = ( signed short * ) sample->data;
s16 += offset; s16 += offset;
for ( o = 0; o < lpc_samples; o++ ) for (o = 0; o < lpc_samples; o++) {
{ lpc_input[o] = s16[o];
lpc_input[ o ] = s16[ o ];
} }
} } else {
else s8 = (signed char *)sample->data;
{
s8 = ( signed char * ) sample->data;
s8 += offset; s8 += offset;
for ( o = 0; o < lpc_samples; o++ ) for (o = 0; o < lpc_samples; o++) {
{ lpc_input[o] = s8[o];
lpc_input[ o ] = s8[ o ];
} }
} }
vorbis_lpc_from_data( lpc_input, lpc, lpc_samples, lpc_order ); vorbis_lpc_from_data(lpc_input, lpc, lpc_samples,
lpc_order);
vorbis_lpc_predict( lpc, lpc_input + lpc_samples - lpc_order, lpc_order, lpc_output, lpc_extra ); vorbis_lpc_predict(lpc, lpc_input + lpc_samples - lpc_order,
lpc_order, lpc_output, lpc_extra);
if ( sample->flags & IT_SAMPLE_16BIT ) if (sample->flags & IT_SAMPLE_16BIT) {
{ s16 = (signed short *)realloc(
s16 = ( signed short * ) realloc( sample->data, ( sample->length + lpc_extra ) * sizeof(short) ); sample->data,
(sample->length + lpc_extra) * sizeof(short));
if (!s16) if (!s16)
return -1; return -1;
@ -287,15 +289,13 @@ int dumb_it_add_lpc(struct DUMB_IT_SIGDATA *sigdata){
s16 += sample->length; s16 += sample->length;
sample->length += lpc_extra; sample->length += lpc_extra;
for ( o = 0; o < lpc_extra; o++ ) for (o = 0; o < lpc_extra; o++) {
{ s16[o] = lpc_output[o];
s16[ o ] = lpc_output[ o ];
} }
} } else {
else s8 = (signed char *)realloc(sample->data,
{ sample->length + lpc_extra);
s8 = ( signed char * ) realloc( sample->data, sample->length + lpc_extra ); if (!s8)
if ( !s8 )
return -1; return -1;
sample->data = s8; sample->data = s8;
@ -303,14 +303,12 @@ int dumb_it_add_lpc(struct DUMB_IT_SIGDATA *sigdata){
s8 += sample->length; s8 += sample->length;
sample->length += lpc_extra; sample->length += lpc_extra;
for ( o = 0; o < lpc_extra; o++ ) for (o = 0; o < lpc_extra; o++) {
{ s8[o] = lpc_output[o];
s8[ o ] = lpc_output[ o ];
} }
} }
} }
} } else
else
/* Otherwise, pad with silence. */ /* Otherwise, pad with silence. */
{ {
void *data; void *data;
@ -320,18 +318,20 @@ int dumb_it_add_lpc(struct DUMB_IT_SIGDATA *sigdata){
sample->length += lpc_samples; sample->length += lpc_samples;
n = 1; n = 1;
if ( sample->flags & IT_SAMPLE_STEREO ) n *= 2; if (sample->flags & IT_SAMPLE_STEREO)
if ( sample->flags & IT_SAMPLE_16BIT ) n *= 2; n *= 2;
if (sample->flags & IT_SAMPLE_16BIT)
n *= 2;
offset *= n; offset *= n;
lpc_samples *= n; lpc_samples *= n;
data = realloc( sample->data, offset + lpc_samples ); data = realloc(sample->data, offset + lpc_samples);
if (!data) if (!data)
return -1; return -1;
sample->data = data; sample->data = data;
memset( (char*)data + offset, 0, lpc_samples ); memset((char *)data + offset, 0, lpc_samples);
} }
} }
} }

View file

@ -22,59 +22,43 @@
#include "dumb.h" #include "dumb.h"
typedef struct MEMFILE MEMFILE; typedef struct MEMFILE MEMFILE;
struct MEMFILE struct MEMFILE {
{
const char *ptr, *ptr_begin; const char *ptr, *ptr_begin;
long left, size; size_t left, size;
}; };
static int dumb_memfile_skip(void *f, dumb_off_t n) {
static int dumb_memfile_skip(void *f, long n)
{
MEMFILE *m = f; MEMFILE *m = f;
if (n > m->left) return -1; if (n > (dumb_off_t)m->left)
return -1;
m->ptr += n; m->ptr += n;
m->left -= n; m->left -= n;
return 0; return 0;
} }
static int dumb_memfile_getc(void *f) {
static int dumb_memfile_getc(void *f)
{
MEMFILE *m = f; MEMFILE *m = f;
if (m->left <= 0) return -1; if (m->left <= 0)
return -1;
m->left--; m->left--;
return *(const unsigned char *)m->ptr++; return *(const unsigned char *)m->ptr++;
} }
static dumb_ssize_t dumb_memfile_getnc(char *ptr, size_t n, void *f) {
static long dumb_memfile_getnc(char *ptr, long n, void *f)
{
MEMFILE *m = f; MEMFILE *m = f;
if (n > m->left) n = m->left; if (n > m->left)
n = m->left;
memcpy(ptr, m->ptr, n); memcpy(ptr, m->ptr, n);
m->ptr += n; m->ptr += n;
m->left -= n; m->left -= n;
return n; return n;
} }
static void dumb_memfile_close(void *f) { free(f); }
static int dumb_memfile_seek(void *f, dumb_off_t n) {
static void dumb_memfile_close(void *f)
{
free(f);
}
static int dumb_memfile_seek(void *f, long n)
{
MEMFILE *m = f; MEMFILE *m = f;
m->ptr = m->ptr_begin + n; m->ptr = m->ptr_begin + n;
@ -83,30 +67,23 @@ static int dumb_memfile_seek(void *f, long n)
return 0; return 0;
} }
static dumb_off_t dumb_memfile_get_size(void *f) {
static long dumb_memfile_get_size(void *f)
{
MEMFILE *m = f; MEMFILE *m = f;
return m->size; return m->size;
} }
static const DUMBFILE_SYSTEM memfile_dfs = {NULL,
static const DUMBFILE_SYSTEM memfile_dfs = {
NULL,
&dumb_memfile_skip, &dumb_memfile_skip,
&dumb_memfile_getc, &dumb_memfile_getc,
&dumb_memfile_getnc, &dumb_memfile_getnc,
&dumb_memfile_close, &dumb_memfile_close,
&dumb_memfile_seek, &dumb_memfile_seek,
&dumb_memfile_get_size &dumb_memfile_get_size};
};
DUMBFILE *dumbfile_open_memory(const char *data, size_t size) {
DUMBFILE *dumbfile_open_memory(const char *data, long size)
{
MEMFILE *m = malloc(sizeof(*m)); MEMFILE *m = malloc(sizeof(*m));
if (!m) return NULL; if (!m)
return NULL;
m->ptr_begin = data; m->ptr_begin = data;
m->ptr = data; m->ptr = data;

View file

@ -42,16 +42,14 @@
* FIXME: these comments are somewhat out of date now. * FIXME: these comments are somewhat out of date now.
*/ */
#define SUFFIX3 _1 #define SUFFIX3 _1
/* For convenience, returns nonzero on stop. */ /* For convenience, returns nonzero on stop. */
static int process_pickup(DUMB_RESAMPLER *resampler) static int process_pickup(DUMB_RESAMPLER *resampler) {
{
if (resampler->overshot < 0) { if (resampler->overshot < 0) {
resampler->overshot = 0; resampler->overshot = 0;
dumb_resample(resampler, NULL, 2, MONO_DEST_VOLUME_ZEROS, 1.0f); /* Doesn't matter which SUFFIX3. */ dumb_resample(resampler, NULL, 2, MONO_DEST_VOLUME_ZEROS,
1.0f); /* Doesn't matter which SUFFIX3. */
COPYSRC(resampler->X, 0, resampler->X, 1); COPYSRC(resampler->X, 0, resampler->X, 1);
} }
@ -59,15 +57,24 @@ static int process_pickup(DUMB_RESAMPLER *resampler)
SRCTYPE *src = resampler->src; SRCTYPE *src = resampler->src;
if (resampler->dir < 0) { if (resampler->dir < 0) {
if (resampler->overshot >= 3 && resampler->pos+3 >= resampler->start) COPYSRC(resampler->X, 0, src, resampler->pos+3); if (resampler->overshot >= 3 &&
if (resampler->overshot >= 2 && resampler->pos+2 >= resampler->start) COPYSRC(resampler->X, 1, src, resampler->pos+2); resampler->pos + 3 >= resampler->start)
if (resampler->overshot >= 1 && resampler->pos+1 >= resampler->start) COPYSRC(resampler->X, 2, src, resampler->pos+1); COPYSRC(resampler->X, 0, src, resampler->pos + 3);
resampler->overshot = resampler->start - resampler->pos - 1; if (resampler->overshot >= 2 &&
resampler->pos + 2 >= resampler->start)
COPYSRC(resampler->X, 1, src, resampler->pos + 2);
if (resampler->overshot >= 1 &&
resampler->pos + 1 >= resampler->start)
COPYSRC(resampler->X, 2, src, resampler->pos + 1);
resampler->overshot = (int)(resampler->start - resampler->pos - 1);
} else { } else {
if (resampler->overshot >= 3 && resampler->pos-3 < resampler->end) COPYSRC(resampler->X, 0, src, resampler->pos-3); if (resampler->overshot >= 3 && resampler->pos - 3 < resampler->end)
if (resampler->overshot >= 2 && resampler->pos-2 < resampler->end) COPYSRC(resampler->X, 1, src, resampler->pos-2); COPYSRC(resampler->X, 0, src, resampler->pos - 3);
if (resampler->overshot >= 1 && resampler->pos-1 < resampler->end) COPYSRC(resampler->X, 2, src, resampler->pos-1); if (resampler->overshot >= 2 && resampler->pos - 2 < resampler->end)
resampler->overshot = resampler->pos - resampler->end; COPYSRC(resampler->X, 1, src, resampler->pos - 2);
if (resampler->overshot >= 1 && resampler->pos - 1 < resampler->end)
COPYSRC(resampler->X, 2, src, resampler->pos - 1);
resampler->overshot = (int)(resampler->pos - resampler->end);
} }
if (resampler->overshot < 0) { if (resampler->overshot < 0) {
@ -80,13 +87,12 @@ static int process_pickup(DUMB_RESAMPLER *resampler)
return 1; return 1;
} }
(*resampler->pickup)(resampler, resampler->pickup_data); (*resampler->pickup)(resampler, resampler->pickup_data);
if (resampler->dir == 0) return 1; if (resampler->dir == 0)
return 1;
ASSERT(resampler->dir == -1 || resampler->dir == 1); ASSERT(resampler->dir == -1 || resampler->dir == 1);
} }
} }
/* Create mono destination resampler. */ /* Create mono destination resampler. */
/* SUFFIX3 was set above. */ /* SUFFIX3 was set above. */
#define VOLUME_PARAMETERS MONO_DEST_VOLUME_PARAMETERS #define VOLUME_PARAMETERS MONO_DEST_VOLUME_PARAMETERS
@ -101,48 +107,58 @@ static int process_pickup(DUMB_RESAMPLER *resampler)
/* Create stereo destination resampler. */ /* Create stereo destination resampler. */
#define SUFFIX3 _2 #define SUFFIX3 _2
#define VOLUME_PARAMETERS DUMB_VOLUME_RAMP_INFO * volume_left, DUMB_VOLUME_RAMP_INFO * volume_right #define VOLUME_PARAMETERS \
#define VOLUME_VARIABLES lvol, lvolr, lvold, lvolt, lvolm, rvol, rvolr, rvold, rvolt, rvolm DUMB_VOLUME_RAMP_INFO *volume_left, DUMB_VOLUME_RAMP_INFO *volume_right
#define SET_VOLUME_VARIABLES { \ #define VOLUME_VARIABLES \
if ( volume_left ) { \ lvol, lvolr, lvold, lvolt, lvolm, rvol, rvolr, rvold, rvolt, rvolm
#define SET_VOLUME_VARIABLES \
{ \
if (volume_left) { \
lvolr = volume_left->volume; \ lvolr = volume_left->volume; \
lvold = volume_left->delta; \ lvold = volume_left->delta; \
lvolt = volume_left->target; \ lvolt = volume_left->target; \
lvolm = volume_left->mix; \ lvolm = volume_left->mix; \
lvol = lvolr * lvolm; \ lvol = lvolr * lvolm; \
if ( lvolr == lvolt ) volume_left = NULL; \ if (lvolr == lvolt) \
volume_left = NULL; \
} else { \ } else { \
lvol = 0; \ lvol = 0; \
lvold = 0; \ lvold = 0; \
lvolt = 0; \ lvolt = 0; \
lvolm = 0; \ lvolm = 0; \
} \ } \
if ( volume_right ) { \ if (volume_right) { \
rvolr = volume_right->volume; \ rvolr = volume_right->volume; \
rvold = volume_right->delta; \ rvold = volume_right->delta; \
rvolt = volume_right->target; \ rvolt = volume_right->target; \
rvolm = volume_right->mix; \ rvolm = volume_right->mix; \
rvol = rvolr * rvolm; \ rvol = rvolr * rvolm; \
if ( rvolr == rvolt ) volume_right = NULL; \ if (rvolr == rvolt) \
volume_right = NULL; \
} else { \ } else { \
rvol = 0; \ rvol = 0; \
rvold = 0; \ rvold = 0; \
rvolt = 0; \ rvolt = 0; \
rvolm = 0; \ rvolm = 0; \
} \ } \
} }
#define RETURN_VOLUME_VARIABLES { \ #define RETURN_VOLUME_VARIABLES \
if ( volume_left ) volume_left->volume = lvolr; \ { \
if ( volume_right ) volume_right->volume = rvolr; \ if (volume_left) \
} volume_left->volume = lvolr; \
if (volume_right) \
volume_right->volume = rvolr; \
}
#define VOLUMES_ARE_ZERO (lvol == 0 && lvolt == 0 && rvol == 0 && rvolt == 0) #define VOLUMES_ARE_ZERO (lvol == 0 && lvolt == 0 && rvol == 0 && rvolt == 0)
#define PEEK_FIR STEREO_DEST_PEEK_FIR #define PEEK_FIR STEREO_DEST_PEEK_FIR
#define MIX_FIR STEREO_DEST_MIX_FIR #define MIX_FIR STEREO_DEST_MIX_FIR
#define MIX_ZEROS(op) { *dst++ op 0; *dst++ op 0; } #define MIX_ZEROS(op) \
{ \
*dst++ op 0; \
*dst++ op 0; \
}
#include "resamp3.inc" #include "resamp3.inc"
#undef MONO_DEST_VOLUMES_ARE_ZERO #undef MONO_DEST_VOLUMES_ARE_ZERO
#undef SET_MONO_DEST_VOLUME_VARIABLES #undef SET_MONO_DEST_VOLUME_VARIABLES
#undef RETURN_MONO_DEST_VOLUME_VARIABLES #undef RETURN_MONO_DEST_VOLUME_VARIABLES

View file

@ -42,10 +42,8 @@
* FIXME: these comments are somewhat out of date now. * FIXME: these comments are somewhat out of date now.
*/ */
long dumb_resample(DUMB_RESAMPLER *resampler, sample_t *dst, long dst_size,
VOLUME_PARAMETERS, float delta) {
long dumb_resample(DUMB_RESAMPLER *resampler, sample_t *dst, long dst_size, VOLUME_PARAMETERS, float delta)
{
int dt, inv_dt; int dt, inv_dt;
float VOLUME_VARIABLES; float VOLUME_VARIABLES;
long done; long done;
@ -53,16 +51,19 @@ long dumb_resample(DUMB_RESAMPLER *resampler, sample_t *dst, long dst_size, VOLU
LONG_LONG todo64; LONG_LONG todo64;
int quality; int quality;
if (!resampler || resampler->dir == 0) return 0; if (!resampler || resampler->dir == 0)
return 0;
ASSERT(resampler->dir == -1 || resampler->dir == 1); ASSERT(resampler->dir == -1 || resampler->dir == 1);
done = 0; done = 0;
dt = (int)(delta * 65536.0 + 0.5); dt = (int)(delta * 65536.0 + 0.5);
if (dt == 0 || dt == (int)-0x80000000) return 0; if (dt == 0 || dt == (int)-0x80000000)
return 0;
inv_dt = (int)(1.0 / delta * 65536.0 + 0.5); inv_dt = (int)(1.0 / delta * 65536.0 + 0.5);
SET_VOLUME_VARIABLES; SET_VOLUME_VARIABLES;
if (VOLUMES_ARE_ZERO) dst = NULL; if (VOLUMES_ARE_ZERO)
dst = NULL;
_dumb_init_cubic(); _dumb_init_cubic();
@ -78,16 +79,20 @@ long dumb_resample(DUMB_RESAMPLER *resampler, sample_t *dst, long dst_size, VOLU
dt = -dt; dt = -dt;
if (resampler->dir < 0) if (resampler->dir < 0)
todo64 = ((((LONG_LONG)(resampler->pos - resampler->start) << 16) + resampler->subpos - dt) / -dt); todo64 = ((((LONG_LONG)(resampler->pos - resampler->start) << 16) +
resampler->subpos - dt) /
-dt);
else else
todo64 = ((((LONG_LONG)(resampler->end - resampler->pos) << 16) - resampler->subpos - 1 + dt) / dt); todo64 = ((((LONG_LONG)(resampler->end - resampler->pos) << 16) -
resampler->subpos - 1 + dt) /
dt);
if (todo64 < 0) if (todo64 < 0)
todo = 0; todo = 0;
else if (todo64 > dst_size - done) else if (todo64 > dst_size - done)
todo = dst_size - done; todo = dst_size - done;
else else
todo = (long) todo64; todo = (long)todo64;
done += todo; done += todo;
@ -106,25 +111,30 @@ long dumb_resample(DUMB_RESAMPLER *resampler, sample_t *dst, long dst_size, VOLU
} else { } else {
/* FIR resampling, backwards */ /* FIR resampling, backwards */
SRCTYPE *x; SRCTYPE *x;
if ( resampler->fir_resampler_ratio != delta ) { if (resampler->fir_resampler_ratio != delta) {
resampler_set_rate( resampler->fir_resampler[0], delta ); resampler_set_rate(resampler->fir_resampler[0], delta);
resampler_set_rate( resampler->fir_resampler[1], delta ); resampler_set_rate(resampler->fir_resampler[1], delta);
resampler->fir_resampler_ratio = delta; resampler->fir_resampler_ratio = delta;
} }
x = &src[pos*SRC_CHANNELS]; x = &src[pos * SRC_CHANNELS];
while ( todo ) { while (todo) {
while ( ( resampler_get_free_count( resampler->fir_resampler[0] ) || while ((resampler_get_free_count(
(!resampler_get_sample_count( resampler->fir_resampler[0] ) resampler->fir_resampler[0]) ||
(!resampler_get_sample_count(
resampler->fir_resampler[0])
#if SRC_CHANNELS == 2 #if SRC_CHANNELS == 2
&& !resampler_get_sample_count( resampler->fir_resampler[1] ) && !resampler_get_sample_count(
resampler->fir_resampler[1])
#endif #endif
) ) && pos >= resampler->start ) )) &&
{ pos >= resampler->start) {
POKE_FIR(0); POKE_FIR(0);
pos--; pos--;
x -= SRC_CHANNELS; x -= SRC_CHANNELS;
} }
if ( !resampler_get_sample_count( resampler->fir_resampler[0] ) ) break; if (!resampler_get_sample_count(
resampler->fir_resampler[0]))
break;
MIX_FIR; MIX_FIR;
ADVANCE_FIR; ADVANCE_FIR;
--todo; --todo;
@ -134,17 +144,17 @@ long dumb_resample(DUMB_RESAMPLER *resampler, sample_t *dst, long dst_size, VOLU
diff = diff - pos; diff = diff - pos;
overshot = resampler->start - pos - 1; overshot = resampler->start - pos - 1;
if (diff >= 3) { if (diff >= 3) {
COPYSRC2(resampler->X, 0, overshot < 3, src, pos+3); COPYSRC2(resampler->X, 0, overshot < 3, src, pos + 3);
COPYSRC2(resampler->X, 1, overshot < 2, src, pos+2); COPYSRC2(resampler->X, 1, overshot < 2, src, pos + 2);
COPYSRC2(resampler->X, 2, overshot < 1, src, pos+1); COPYSRC2(resampler->X, 2, overshot < 1, src, pos + 1);
} else if (diff >= 2) { } else if (diff >= 2) {
COPYSRC(resampler->X, 0, resampler->X, 2); COPYSRC(resampler->X, 0, resampler->X, 2);
COPYSRC2(resampler->X, 1, overshot < 2, src, pos+2); COPYSRC2(resampler->X, 1, overshot < 2, src, pos + 2);
COPYSRC2(resampler->X, 2, overshot < 1, src, pos+1); COPYSRC2(resampler->X, 2, overshot < 1, src, pos + 1);
} else if (diff >= 1) { } else if (diff >= 1) {
COPYSRC(resampler->X, 0, resampler->X, 1); COPYSRC(resampler->X, 0, resampler->X, 1);
COPYSRC(resampler->X, 1, resampler->X, 2); COPYSRC(resampler->X, 1, resampler->X, 2);
COPYSRC2(resampler->X, 2, overshot < 1, src, pos+1); COPYSRC2(resampler->X, 2, overshot < 1, src, pos + 1);
} }
} else { } else {
if (!dst) { if (!dst) {
@ -155,25 +165,30 @@ long dumb_resample(DUMB_RESAMPLER *resampler, sample_t *dst, long dst_size, VOLU
} else { } else {
/* FIR resampling, forwards */ /* FIR resampling, forwards */
SRCTYPE *x; SRCTYPE *x;
if ( resampler->fir_resampler_ratio != delta ) { if (resampler->fir_resampler_ratio != delta) {
resampler_set_rate( resampler->fir_resampler[0], delta ); resampler_set_rate(resampler->fir_resampler[0], delta);
resampler_set_rate( resampler->fir_resampler[1], delta ); resampler_set_rate(resampler->fir_resampler[1], delta);
resampler->fir_resampler_ratio = delta; resampler->fir_resampler_ratio = delta;
} }
x = &src[pos*SRC_CHANNELS]; x = &src[pos * SRC_CHANNELS];
while ( todo ) { while (todo) {
while ( ( resampler_get_free_count( resampler->fir_resampler[0] ) || while ((resampler_get_free_count(
(!resampler_get_sample_count( resampler->fir_resampler[0] ) resampler->fir_resampler[0]) ||
(!resampler_get_sample_count(
resampler->fir_resampler[0])
#if SRC_CHANNELS == 2 #if SRC_CHANNELS == 2
&& !resampler_get_sample_count( resampler->fir_resampler[1] ) && !resampler_get_sample_count(
resampler->fir_resampler[1])
#endif #endif
) ) && pos < resampler->end ) )) &&
{ pos < resampler->end) {
POKE_FIR(0); POKE_FIR(0);
pos++; pos++;
x += SRC_CHANNELS; x += SRC_CHANNELS;
} }
if ( !resampler_get_sample_count( resampler->fir_resampler[0] ) ) break; if (!resampler_get_sample_count(
resampler->fir_resampler[0]))
break;
MIX_FIR; MIX_FIR;
ADVANCE_FIR; ADVANCE_FIR;
--todo; --todo;
@ -183,17 +198,17 @@ long dumb_resample(DUMB_RESAMPLER *resampler, sample_t *dst, long dst_size, VOLU
diff = pos - diff; diff = pos - diff;
overshot = pos - resampler->end; overshot = pos - resampler->end;
if (diff >= 3) { if (diff >= 3) {
COPYSRC2(resampler->X, 0, overshot < 3, src, pos-3); COPYSRC2(resampler->X, 0, overshot < 3, src, pos - 3);
COPYSRC2(resampler->X, 1, overshot < 2, src, pos-2); COPYSRC2(resampler->X, 1, overshot < 2, src, pos - 2);
COPYSRC2(resampler->X, 2, overshot < 1, src, pos-1); COPYSRC2(resampler->X, 2, overshot < 1, src, pos - 1);
} else if (diff >= 2) { } else if (diff >= 2) {
COPYSRC(resampler->X, 0, resampler->X, 2); COPYSRC(resampler->X, 0, resampler->X, 2);
COPYSRC2(resampler->X, 1, overshot < 2, src, pos-2); COPYSRC2(resampler->X, 1, overshot < 2, src, pos - 2);
COPYSRC2(resampler->X, 2, overshot < 1, src, pos-1); COPYSRC2(resampler->X, 2, overshot < 1, src, pos - 1);
} else if (diff >= 1) { } else if (diff >= 1) {
COPYSRC(resampler->X, 0, resampler->X, 1); COPYSRC(resampler->X, 0, resampler->X, 1);
COPYSRC(resampler->X, 1, resampler->X, 2); COPYSRC(resampler->X, 1, resampler->X, 2);
COPYSRC2(resampler->X, 2, overshot < 1, src, pos-1); COPYSRC2(resampler->X, 2, overshot < 1, src, pos - 1);
} }
} }
resampler->pos = pos; resampler->pos = pos;
@ -205,10 +220,8 @@ long dumb_resample(DUMB_RESAMPLER *resampler, sample_t *dst, long dst_size, VOLU
return done; return done;
} }
void dumb_resample_get_current_sample(DUMB_RESAMPLER *resampler,
VOLUME_PARAMETERS, sample_t *dst) {
void dumb_resample_get_current_sample(DUMB_RESAMPLER *resampler, VOLUME_PARAMETERS, sample_t *dst)
{
float VOLUME_VARIABLES; float VOLUME_VARIABLES;
SRCTYPE *src; SRCTYPE *src;
long pos; long pos;
@ -216,14 +229,23 @@ void dumb_resample_get_current_sample(DUMB_RESAMPLER *resampler, VOLUME_PARAMETE
int quality; int quality;
SRCTYPE *x; SRCTYPE *x;
if (!resampler || resampler->dir == 0) { MIX_ZEROS(=); return; } if (!resampler || resampler->dir == 0) {
MIX_ZEROS(=);
return;
}
ASSERT(resampler->dir == -1 || resampler->dir == 1); ASSERT(resampler->dir == -1 || resampler->dir == 1);
if (process_pickup(resampler)) { MIX_ZEROS(=); return; } if (process_pickup(resampler)) {
MIX_ZEROS(=);
return;
}
SET_VOLUME_VARIABLES; SET_VOLUME_VARIABLES;
if (VOLUMES_ARE_ZERO) { MIX_ZEROS(=); return; } if (VOLUMES_ARE_ZERO) {
MIX_ZEROS(=);
return;
}
_dumb_init_cubic(); _dumb_init_cubic();
@ -245,8 +267,6 @@ void dumb_resample_get_current_sample(DUMB_RESAMPLER *resampler, VOLUME_PARAMETE
} }
} }
#undef MIX_ZEROS #undef MIX_ZEROS
#undef MIX_FIR #undef MIX_FIR
#undef PEEK_FIR #undef PEEK_FIR

View file

@ -43,11 +43,8 @@
*/ */
#include <math.h> #include <math.h>
#include "dumb.h"
#include "internal/resampler.h" #include "internal/resampler.h"
#include "internal/dumb.h"
/* Compile with -DHEAVYDEBUG if you want to make sure the pick-up function is /* Compile with -DHEAVYDEBUG if you want to make sure the pick-up function is
* called when it should be. There will be a considerable performance hit, * called when it should be. There will be a considerable performance hit,
@ -59,15 +56,12 @@
#define HEAVYASSERT(cond) #define HEAVYASSERT(cond)
#endif #endif
/* Make MSVC shut the hell up about if ( upd ) UPDATE_VOLUME() conditions being
* constant */
/* Make MSVC shut the hell up about if ( upd ) UPDATE_VOLUME() conditions being constant */
#ifdef _MSC_VER #ifdef _MSC_VER
#pragma warning(disable:4127 4701) #pragma warning(disable : 4127 4701)
#endif #endif
/* A global variable for controlling resampling quality wherever a local /* A global variable for controlling resampling quality wherever a local
* specification doesn't override it. The following values are valid: * specification doesn't override it. The following values are valid:
* *
@ -83,28 +77,24 @@
*/ */
int dumb_resampling_quality = DUMB_RQ_CUBIC; int dumb_resampling_quality = DUMB_RQ_CUBIC;
//#define MULSC(a, b) ((int)((LONG_LONG)(a) * (b) >> 16)) //#define MULSC(a, b) ((int)((LONG_LONG)(a) * (b) >> 16))
//#define MULSC(a, b) ((a) * ((b) >> 2) >> 14) //#define MULSC(a, b) ((a) * ((b) >> 2) >> 14)
#define MULSCV(a, b) ((int)((LONG_LONG)(a) * (b) >> 32)) #define MULSCV(a, b) ((int)((LONG_LONG)(a) * (b) >> 32))
#define MULSC(a, b) ((int)((LONG_LONG)((a) << 4) * ((b) << 12) >> 32)) #define MULSC(a, b) ((int)((LONG_LONG)((a) << 4) * ((b) << 12) >> 32))
#define MULSC16(a, b) ((int)((LONG_LONG)((a) << 12) * ((b) << 12) >> 32)) #define MULSC16(a, b) ((int)((LONG_LONG)((a) << 12) * ((b) << 12) >> 32))
/* Executes the content 'iterator' times. /* Executes the content 'iterator' times.
* Clobbers the 'iterator' variable. * Clobbers the 'iterator' variable.
* The loop is unrolled by four. * The loop is unrolled by four.
*/ */
#if 0 #if 0
#define LOOP4(iterator, CONTENT) \ #define LOOP4(iterator, CONTENT) \
{ \ { \
if ((iterator) & 2) { \ if ((iterator)&2) { \
CONTENT; \ CONTENT; \
CONTENT; \ CONTENT; \
} \ } \
if ((iterator) & 1) { \ if ((iterator)&1) { \
CONTENT; \ CONTENT; \
} \ } \
(iterator) >>= 2; \ (iterator) >>= 2; \
@ -115,36 +105,32 @@ int dumb_resampling_quality = DUMB_RQ_CUBIC;
CONTENT; \ CONTENT; \
(iterator)--; \ (iterator)--; \
} \ } \
} }
#else #else
#define LOOP4(iterator, CONTENT) \ #define LOOP4(iterator, CONTENT) \
{ \
while ( (iterator)-- ) \
{ \ { \
while ((iterator)--) { \
CONTENT; \ CONTENT; \
} \ } \
} }
#endif #endif
#define PASTERAW(a, b) a ## b /* This does not expand macros in b ... */ #define PASTERAW(a, b) a##b /* This does not expand macros in b ... */
#define PASTE(a, b) PASTERAW(a, b) /* ... but b is expanded during this substitution. */ #define PASTE(a, b) \
PASTERAW(a, b) /* ... but b is expanded during this substitution. */
#define X PASTE(x.x, SRCBITS) #define X PASTE(x.x, SRCBITS)
void _dumb_init_cubic(void) {
void _dumb_init_cubic(void)
{
static int done = 0; static int done = 0;
if (done) return; if (done)
return;
resampler_init(); resampler_init();
done = 1; done = 1;
} }
/* Create resamplers for 24-in-32-bit source samples. */ /* Create resamplers for 24-in-32-bit source samples. */
/* #define SUFFIX /* #define SUFFIX
@ -154,7 +140,8 @@ void _dumb_init_cubic(void)
*/ */
#define process_pickup PASTE(process_pickup, SUFFIX2) #define process_pickup PASTE(process_pickup, SUFFIX2)
#define dumb_resample PASTE(PASTE(dumb_resample, SUFFIX2), SUFFIX3) #define dumb_resample PASTE(PASTE(dumb_resample, SUFFIX2), SUFFIX3)
#define dumb_resample_get_current_sample PASTE(PASTE(dumb_resample_get_current_sample, SUFFIX2), SUFFIX3) #define dumb_resample_get_current_sample \
PASTE(PASTE(dumb_resample_get_current_sample, SUFFIX2), SUFFIX3)
#define SRCTYPE sample_t #define SRCTYPE sample_t
#define SRCBITS 24 #define SRCBITS 24
@ -166,13 +153,15 @@ void _dumb_init_cubic(void)
#undef dumb_resample #undef dumb_resample
#undef process_pickup #undef process_pickup
/* Now define the proper ones that use SUFFIX. */ /* Now define the proper ones that use SUFFIX. */
#define dumb_reset_resampler PASTE(dumb_reset_resampler, SUFFIX) #define dumb_reset_resampler PASTE(dumb_reset_resampler, SUFFIX)
#define dumb_start_resampler PASTE(dumb_start_resampler, SUFFIX) #define dumb_start_resampler PASTE(dumb_start_resampler, SUFFIX)
#define process_pickup PASTE(PASTE(process_pickup, SUFFIX), SUFFIX2) #define process_pickup PASTE(PASTE(process_pickup, SUFFIX), SUFFIX2)
#define dumb_resample PASTE(PASTE(PASTE(dumb_resample, SUFFIX), SUFFIX2), SUFFIX3) #define dumb_resample \
#define dumb_resample_get_current_sample PASTE(PASTE(PASTE(dumb_resample_get_current_sample, SUFFIX), SUFFIX2), SUFFIX3) PASTE(PASTE(PASTE(dumb_resample, SUFFIX), SUFFIX2), SUFFIX3)
#define dumb_resample_get_current_sample \
PASTE(PASTE(PASTE(dumb_resample_get_current_sample, SUFFIX), SUFFIX2), \
SUFFIX3)
#define dumb_end_resampler PASTE(dumb_end_resampler, SUFFIX) #define dumb_end_resampler PASTE(dumb_end_resampler, SUFFIX)
/* Create resamplers for 16-bit source samples. */ /* Create resamplers for 16-bit source samples. */
@ -189,7 +178,6 @@ void _dumb_init_cubic(void)
#define FIR(x) (x * (1.0f / 256.0f)) #define FIR(x) (x * (1.0f / 256.0f))
#include "resample.inc" #include "resample.inc"
#undef dumb_reset_resampler #undef dumb_reset_resampler
#undef dumb_start_resampler #undef dumb_start_resampler
#undef process_pickup #undef process_pickup
@ -197,34 +185,37 @@ void _dumb_init_cubic(void)
#undef dumb_resample_get_current_sample #undef dumb_resample_get_current_sample
#undef dumb_end_resampler #undef dumb_end_resampler
void dumb_reset_resampler_n(int n, DUMB_RESAMPLER *resampler, void *src,
int src_channels, long pos, long start, long end,
void dumb_reset_resampler_n(int n, DUMB_RESAMPLER *resampler, void *src, int src_channels, long pos, long start, long end, int quality) int quality) {
{
if (n == 8) if (n == 8)
dumb_reset_resampler_8(resampler, src, src_channels, pos, start, end, quality); dumb_reset_resampler_8(resampler, src, src_channels, pos, start, end,
quality);
else if (n == 16) else if (n == 16)
dumb_reset_resampler_16(resampler, src, src_channels, pos, start, end, quality); dumb_reset_resampler_16(resampler, src, src_channels, pos, start, end,
quality);
else else
dumb_reset_resampler(resampler, src, src_channels, pos, start, end, quality); dumb_reset_resampler(resampler, src, src_channels, pos, start, end,
quality);
} }
DUMB_RESAMPLER *dumb_start_resampler_n(int n, void *src, int src_channels,
long pos, long start, long end,
DUMB_RESAMPLER *dumb_start_resampler_n(int n, void *src, int src_channels, long pos, long start, long end, int quality) int quality) {
{
if (n == 8) if (n == 8)
return dumb_start_resampler_8(src, src_channels, pos, start, end, quality); return dumb_start_resampler_8(src, src_channels, pos, start, end,
quality);
else if (n == 16) else if (n == 16)
return dumb_start_resampler_16(src, src_channels, pos, start, end, quality); return dumb_start_resampler_16(src, src_channels, pos, start, end,
quality);
else else
return dumb_start_resampler(src, src_channels, pos, start, end, quality); return dumb_start_resampler(src, src_channels, pos, start, end,
quality);
} }
long dumb_resample_n_1_1(int n, DUMB_RESAMPLER *resampler, sample_t *dst,
long dst_size, DUMB_VOLUME_RAMP_INFO *volume,
long dumb_resample_n_1_1(int n, DUMB_RESAMPLER *resampler, sample_t *dst, long dst_size, DUMB_VOLUME_RAMP_INFO * volume, float delta) float delta) {
{
if (n == 8) if (n == 8)
return dumb_resample_8_1_1(resampler, dst, dst_size, volume, delta); return dumb_resample_8_1_1(resampler, dst, dst_size, volume, delta);
else if (n == 16) else if (n == 16)
@ -233,46 +224,51 @@ long dumb_resample_n_1_1(int n, DUMB_RESAMPLER *resampler, sample_t *dst, long d
return dumb_resample_1_1(resampler, dst, dst_size, volume, delta); return dumb_resample_1_1(resampler, dst, dst_size, volume, delta);
} }
long dumb_resample_n_1_2(int n, DUMB_RESAMPLER *resampler, sample_t *dst,
long dst_size, DUMB_VOLUME_RAMP_INFO *volume_left,
long dumb_resample_n_1_2(int n, DUMB_RESAMPLER *resampler, sample_t *dst, long dst_size, DUMB_VOLUME_RAMP_INFO * volume_left, DUMB_VOLUME_RAMP_INFO * volume_right, float delta) DUMB_VOLUME_RAMP_INFO *volume_right, float delta) {
{
if (n == 8) if (n == 8)
return dumb_resample_8_1_2(resampler, dst, dst_size, volume_left, volume_right, delta); return dumb_resample_8_1_2(resampler, dst, dst_size, volume_left,
volume_right, delta);
else if (n == 16) else if (n == 16)
return dumb_resample_16_1_2(resampler, dst, dst_size, volume_left, volume_right, delta); return dumb_resample_16_1_2(resampler, dst, dst_size, volume_left,
volume_right, delta);
else else
return dumb_resample_1_2(resampler, dst, dst_size, volume_left, volume_right, delta); return dumb_resample_1_2(resampler, dst, dst_size, volume_left,
volume_right, delta);
} }
long dumb_resample_n_2_1(int n, DUMB_RESAMPLER *resampler, sample_t *dst,
long dst_size, DUMB_VOLUME_RAMP_INFO *volume_left,
long dumb_resample_n_2_1(int n, DUMB_RESAMPLER *resampler, sample_t *dst, long dst_size, DUMB_VOLUME_RAMP_INFO * volume_left, DUMB_VOLUME_RAMP_INFO * volume_right, float delta) DUMB_VOLUME_RAMP_INFO *volume_right, float delta) {
{
if (n == 8) if (n == 8)
return dumb_resample_8_2_1(resampler, dst, dst_size, volume_left, volume_right, delta); return dumb_resample_8_2_1(resampler, dst, dst_size, volume_left,
volume_right, delta);
else if (n == 16) else if (n == 16)
return dumb_resample_16_2_1(resampler, dst, dst_size, volume_left, volume_right, delta); return dumb_resample_16_2_1(resampler, dst, dst_size, volume_left,
volume_right, delta);
else else
return dumb_resample_2_1(resampler, dst, dst_size, volume_left, volume_right, delta); return dumb_resample_2_1(resampler, dst, dst_size, volume_left,
volume_right, delta);
} }
long dumb_resample_n_2_2(int n, DUMB_RESAMPLER *resampler, sample_t *dst,
long dst_size, DUMB_VOLUME_RAMP_INFO *volume_left,
long dumb_resample_n_2_2(int n, DUMB_RESAMPLER *resampler, sample_t *dst, long dst_size, DUMB_VOLUME_RAMP_INFO * volume_left, DUMB_VOLUME_RAMP_INFO * volume_right, float delta) DUMB_VOLUME_RAMP_INFO *volume_right, float delta) {
{
if (n == 8) if (n == 8)
return dumb_resample_8_2_2(resampler, dst, dst_size, volume_left, volume_right, delta); return dumb_resample_8_2_2(resampler, dst, dst_size, volume_left,
volume_right, delta);
else if (n == 16) else if (n == 16)
return dumb_resample_16_2_2(resampler, dst, dst_size, volume_left, volume_right, delta); return dumb_resample_16_2_2(resampler, dst, dst_size, volume_left,
volume_right, delta);
else else
return dumb_resample_2_2(resampler, dst, dst_size, volume_left, volume_right, delta); return dumb_resample_2_2(resampler, dst, dst_size, volume_left,
volume_right, delta);
} }
void dumb_resample_get_current_sample_n_1_1(int n, DUMB_RESAMPLER *resampler,
DUMB_VOLUME_RAMP_INFO *volume,
void dumb_resample_get_current_sample_n_1_1(int n, DUMB_RESAMPLER *resampler, DUMB_VOLUME_RAMP_INFO * volume, sample_t *dst) sample_t *dst) {
{
if (n == 8) if (n == 8)
dumb_resample_get_current_sample_8_1_1(resampler, volume, dst); dumb_resample_get_current_sample_8_1_1(resampler, volume, dst);
else if (n == 16) else if (n == 16)
@ -281,46 +277,52 @@ void dumb_resample_get_current_sample_n_1_1(int n, DUMB_RESAMPLER *resampler, DU
dumb_resample_get_current_sample_1_1(resampler, volume, dst); dumb_resample_get_current_sample_1_1(resampler, volume, dst);
} }
void dumb_resample_get_current_sample_n_1_2(int n, DUMB_RESAMPLER *resampler,
DUMB_VOLUME_RAMP_INFO *volume_left,
void dumb_resample_get_current_sample_n_1_2(int n, DUMB_RESAMPLER *resampler, DUMB_VOLUME_RAMP_INFO * volume_left, DUMB_VOLUME_RAMP_INFO * volume_right, sample_t *dst) DUMB_VOLUME_RAMP_INFO *volume_right,
{ sample_t *dst) {
if (n == 8) if (n == 8)
dumb_resample_get_current_sample_8_1_2(resampler, volume_left, volume_right, dst); dumb_resample_get_current_sample_8_1_2(resampler, volume_left,
volume_right, dst);
else if (n == 16) else if (n == 16)
dumb_resample_get_current_sample_16_1_2(resampler, volume_left, volume_right, dst); dumb_resample_get_current_sample_16_1_2(resampler, volume_left,
volume_right, dst);
else else
dumb_resample_get_current_sample_1_2(resampler, volume_left, volume_right, dst); dumb_resample_get_current_sample_1_2(resampler, volume_left,
volume_right, dst);
} }
void dumb_resample_get_current_sample_n_2_1(int n, DUMB_RESAMPLER *resampler,
DUMB_VOLUME_RAMP_INFO *volume_left,
void dumb_resample_get_current_sample_n_2_1(int n, DUMB_RESAMPLER *resampler, DUMB_VOLUME_RAMP_INFO * volume_left, DUMB_VOLUME_RAMP_INFO * volume_right, sample_t *dst) DUMB_VOLUME_RAMP_INFO *volume_right,
{ sample_t *dst) {
if (n == 8) if (n == 8)
dumb_resample_get_current_sample_8_2_1(resampler, volume_left, volume_right, dst); dumb_resample_get_current_sample_8_2_1(resampler, volume_left,
volume_right, dst);
else if (n == 16) else if (n == 16)
dumb_resample_get_current_sample_16_2_1(resampler, volume_left, volume_right, dst); dumb_resample_get_current_sample_16_2_1(resampler, volume_left,
volume_right, dst);
else else
dumb_resample_get_current_sample_2_1(resampler, volume_left, volume_right, dst); dumb_resample_get_current_sample_2_1(resampler, volume_left,
volume_right, dst);
} }
void dumb_resample_get_current_sample_n_2_2(int n, DUMB_RESAMPLER *resampler,
DUMB_VOLUME_RAMP_INFO *volume_left,
void dumb_resample_get_current_sample_n_2_2(int n, DUMB_RESAMPLER *resampler, DUMB_VOLUME_RAMP_INFO * volume_left, DUMB_VOLUME_RAMP_INFO * volume_right, sample_t *dst) DUMB_VOLUME_RAMP_INFO *volume_right,
{ sample_t *dst) {
if (n == 8) if (n == 8)
dumb_resample_get_current_sample_8_2_2(resampler, volume_left, volume_right, dst); dumb_resample_get_current_sample_8_2_2(resampler, volume_left,
volume_right, dst);
else if (n == 16) else if (n == 16)
dumb_resample_get_current_sample_16_2_2(resampler, volume_left, volume_right, dst); dumb_resample_get_current_sample_16_2_2(resampler, volume_left,
volume_right, dst);
else else
dumb_resample_get_current_sample_2_2(resampler, volume_left, volume_right, dst); dumb_resample_get_current_sample_2_2(resampler, volume_left,
volume_right, dst);
} }
void dumb_end_resampler_n(int n, DUMB_RESAMPLER *resampler) {
void dumb_end_resampler_n(int n, DUMB_RESAMPLER *resampler)
{
if (n == 8) if (n == 8)
dumb_end_resampler_8(resampler); dumb_end_resampler_8(resampler);
else if (n == 16) else if (n == 16)

View file

@ -42,10 +42,9 @@
* FIXME: these comments are somewhat out of date now. * FIXME: these comments are somewhat out of date now.
*/ */
void dumb_reset_resampler(DUMB_RESAMPLER *resampler, SRCTYPE *src,
int src_channels, long pos, long start, long end,
void dumb_reset_resampler(DUMB_RESAMPLER *resampler, SRCTYPE *src, int src_channels, long pos, long start, long end, int quality) int quality) {
{
int i; int i;
resampler->src = src; resampler->src = src;
resampler->pos = pos; resampler->pos = pos;
@ -55,19 +54,15 @@ void dumb_reset_resampler(DUMB_RESAMPLER *resampler, SRCTYPE *src, int src_chann
resampler->dir = 1; resampler->dir = 1;
resampler->pickup = NULL; resampler->pickup = NULL;
resampler->pickup_data = NULL; resampler->pickup_data = NULL;
if (quality < 0) if (quality < 0) {
{
resampler->quality = 0; resampler->quality = 0;
} } else if (quality > DUMB_RQ_N_LEVELS - 1) {
else if (quality > DUMB_RQ_N_LEVELS - 1)
{
resampler->quality = DUMB_RQ_N_LEVELS - 1; resampler->quality = DUMB_RQ_N_LEVELS - 1;
} } else {
else
{
resampler->quality = quality; resampler->quality = quality;
} }
for (i = 0; i < src_channels*3; i++) resampler->X[i] = 0; for (i = 0; i < src_channels * 3; i++)
resampler->X[i] = 0;
resampler->overshot = -1; resampler->overshot = -1;
resampler->fir_resampler_ratio = 0; resampler->fir_resampler_ratio = 0;
resampler_clear(resampler->fir_resampler[0]); resampler_clear(resampler->fir_resampler[0]);
@ -76,26 +71,24 @@ void dumb_reset_resampler(DUMB_RESAMPLER *resampler, SRCTYPE *src, int src_chann
resampler_set_quality(resampler->fir_resampler[1], resampler->quality); resampler_set_quality(resampler->fir_resampler[1], resampler->quality);
} }
DUMB_RESAMPLER *dumb_start_resampler(SRCTYPE *src, int src_channels, long pos,
long start, long end, int quality) {
DUMB_RESAMPLER *dumb_start_resampler(SRCTYPE *src, int src_channels, long pos, long start, long end, int quality)
{
DUMB_RESAMPLER *resampler = malloc(sizeof(*resampler)); DUMB_RESAMPLER *resampler = malloc(sizeof(*resampler));
if (!resampler) return NULL; if (!resampler)
dumb_reset_resampler(resampler, src, src_channels, pos, start, end, quality); return NULL;
dumb_reset_resampler(resampler, src, src_channels, pos, start, end,
quality);
return resampler; return resampler;
} }
#define UPDATE_VOLUME(pvol, vol) \
{ \
#define UPDATE_VOLUME( pvol, vol ) { \
if (pvol) { \ if (pvol) { \
vol##r += vol##d; \ vol##r += vol##d; \
if ((vol##d < 0 && vol##r <= vol##t) || \ if ((vol##d < 0 && vol##r <= vol##t) || \
(vol##d > 0 && vol##r >= vol##t)) { \ (vol##d > 0 && vol##r >= vol##t)) { \
pvol->volume = pvol->target; \ pvol->volume = pvol->target; \
if ( pvol->declick_stage == 0 || \ if (pvol->declick_stage == 0 || pvol->declick_stage >= 3) \
pvol->declick_stage >= 3) \
pvol->declick_stage++; \ pvol->declick_stage++; \
pvol = NULL; \ pvol = NULL; \
vol = vol##t * vol##m; \ vol = vol##t * vol##m; \
@ -103,153 +96,192 @@ DUMB_RESAMPLER *dumb_start_resampler(SRCTYPE *src, int src_channels, long pos, l
vol = vol##r * vol##m; \ vol = vol##r * vol##m; \
} \ } \
} \ } \
} }
/* Create mono source resampler. */ /* Create mono source resampler. */
#define SUFFIX2 _1 #define SUFFIX2 _1
#define SRC_CHANNELS 1 #define SRC_CHANNELS 1
#define DIVIDE_BY_SRC_CHANNELS(x) (x) #define DIVIDE_BY_SRC_CHANNELS(x) (x)
#define COPYSRC(dstarray, dstindex, srcarray, srcindex) (dstarray)[dstindex] = (srcarray)[srcindex] #define COPYSRC(dstarray, dstindex, srcarray, srcindex) \
#define COPYSRC2(dstarray, dstindex, condition, srcarray, srcindex) (dstarray)[dstindex] = condition ? (srcarray)[srcindex] : 0 (dstarray)[dstindex] = (srcarray)[srcindex]
#define MONO_DEST_VOLUME_PARAMETERS DUMB_VOLUME_RAMP_INFO * volume #define COPYSRC2(dstarray, dstindex, condition, srcarray, srcindex) \
(dstarray)[dstindex] = condition ? (srcarray)[srcindex] : 0
#define MONO_DEST_VOLUME_PARAMETERS DUMB_VOLUME_RAMP_INFO *volume
#define MONO_DEST_VOLUME_VARIABLES vol, volr, vold, volt, volm #define MONO_DEST_VOLUME_VARIABLES vol, volr, vold, volt, volm
#define MONO_DEST_VOLUME_ZEROS 0 #define MONO_DEST_VOLUME_ZEROS 0
#define SET_MONO_DEST_VOLUME_VARIABLES { \ #define SET_MONO_DEST_VOLUME_VARIABLES \
if ( volume ) { \ { \
if (volume) { \
volr = volume->volume; \ volr = volume->volume; \
vold = volume->delta; \ vold = volume->delta; \
volt = volume->target; \ volt = volume->target; \
volm = volume->mix; \ volm = volume->mix; \
vol = volr * volm; \ vol = volr * volm; \
if ( volr == volt ) volume = NULL; \ if (volr == volt) \
volume = NULL; \
} else { \ } else { \
vol = 0; \ vol = 0; \
volr = 0; \
vold = 0; \ vold = 0; \
volt = 0; \ volt = 0; \
volm = 0; \ volm = 0; \
} \ } \
} }
#define RETURN_MONO_DEST_VOLUME_VARIABLES if ( volume ) volume->volume = volr #define RETURN_MONO_DEST_VOLUME_VARIABLES \
if (volume) \
volume->volume = volr
#define MONO_DEST_VOLUMES_ARE_ZERO (vol == 0 && volt == 0) #define MONO_DEST_VOLUMES_ARE_ZERO (vol == 0 && volt == 0)
#define POKE_FIR(offset) { \ #define POKE_FIR(offset) \
resampler_write_sample_float( resampler->fir_resampler[0], FIR(x[offset]) ); \ { \
} resampler_write_sample_float(resampler->fir_resampler[0], \
#define MONO_DEST_PEEK_FIR *dst = resampler_get_sample_float( resampler->fir_resampler[0] ) * vol * 16777216.0f FIR(x[offset])); \
#define MONO_DEST_MIX_FIR { \ }
*dst++ += resampler_get_sample_float( resampler->fir_resampler[0] ) * vol * 16777216.0f; \ #define MONO_DEST_PEEK_FIR \
UPDATE_VOLUME( volume, vol ); \ *dst = resampler_get_sample_float(resampler->fir_resampler[0]) * vol * \
} 16777216.0f
#define ADVANCE_FIR resampler_remove_sample( resampler->fir_resampler[0], 1 ) #define MONO_DEST_MIX_FIR \
#define STEREO_DEST_PEEK_FIR { \ { \
float sample = resampler_get_sample_float( resampler->fir_resampler[0] ); \ *dst++ += resampler_get_sample_float(resampler->fir_resampler[0]) * \
vol * 16777216.0f; \
UPDATE_VOLUME(volume, vol); \
}
#define ADVANCE_FIR resampler_remove_sample(resampler->fir_resampler[0], 1)
#define STEREO_DEST_PEEK_FIR \
{ \
float sample = \
resampler_get_sample_float(resampler->fir_resampler[0]); \
*dst++ = sample * lvol * 16777216.0f; \ *dst++ = sample * lvol * 16777216.0f; \
*dst++ = sample * rvol * 16777216.0f; \ *dst++ = sample * rvol * 16777216.0f; \
} }
#define STEREO_DEST_MIX_FIR { \ #define STEREO_DEST_MIX_FIR \
float sample = resampler_get_sample_float( resampler->fir_resampler[0] ); \ { \
float sample = \
resampler_get_sample_float(resampler->fir_resampler[0]); \
*dst++ += sample * lvol * 16777216.0f; \ *dst++ += sample * lvol * 16777216.0f; \
*dst++ += sample * rvol * 16777216.0f; \ *dst++ += sample * rvol * 16777216.0f; \
UPDATE_VOLUME( volume_left, lvol ); \ UPDATE_VOLUME(volume_left, lvol); \
UPDATE_VOLUME( volume_right, rvol ); \ UPDATE_VOLUME(volume_right, rvol); \
} }
#include "resamp2.inc" #include "resamp2.inc"
/* Create stereo source resampler. */ /* Create stereo source resampler. */
#define SUFFIX2 _2 #define SUFFIX2 _2
#define SRC_CHANNELS 2 #define SRC_CHANNELS 2
#define DIVIDE_BY_SRC_CHANNELS(x) ((x) >> 1) #define DIVIDE_BY_SRC_CHANNELS(x) ((x) >> 1)
#define COPYSRC(dstarray, dstindex, srcarray, srcindex) { \ #define COPYSRC(dstarray, dstindex, srcarray, srcindex) \
{ \
(dstarray)[(dstindex)*2] = (srcarray)[(srcindex)*2]; \ (dstarray)[(dstindex)*2] = (srcarray)[(srcindex)*2]; \
(dstarray)[(dstindex)*2+1] = (srcarray)[(srcindex)*2+1]; \ (dstarray)[(dstindex)*2 + 1] = (srcarray)[(srcindex)*2 + 1]; \
} }
#define COPYSRC2(dstarray, dstindex, condition, srcarray, srcindex) { \ #define COPYSRC2(dstarray, dstindex, condition, srcarray, srcindex) \
{ \
if (condition) { \ if (condition) { \
(dstarray)[(dstindex)*2] = (srcarray)[(srcindex)*2]; \ (dstarray)[(dstindex)*2] = (srcarray)[(srcindex)*2]; \
(dstarray)[(dstindex)*2+1] = (srcarray)[(srcindex)*2+1]; \ (dstarray)[(dstindex)*2 + 1] = (srcarray)[(srcindex)*2 + 1]; \
} else { \ } else { \
(dstarray)[(dstindex)*2] = 0; \ (dstarray)[(dstindex)*2] = 0; \
(dstarray)[(dstindex)*2+1] = 0; \ (dstarray)[(dstindex)*2 + 1] = 0; \
} \ } \
} }
#define MONO_DEST_VOLUME_PARAMETERS DUMB_VOLUME_RAMP_INFO * volume_left, DUMB_VOLUME_RAMP_INFO * volume_right #define MONO_DEST_VOLUME_PARAMETERS \
#define MONO_DEST_VOLUME_VARIABLES lvol, lvolr, lvold, lvolt, lvolm, rvol, rvolr, rvold, rvolt, rvolm DUMB_VOLUME_RAMP_INFO *volume_left, DUMB_VOLUME_RAMP_INFO *volume_right
#define MONO_DEST_VOLUME_VARIABLES \
lvol, lvolr, lvold, lvolt, lvolm, rvol, rvolr, rvold, rvolt, rvolm
#define MONO_DEST_VOLUME_ZEROS 0, 0 #define MONO_DEST_VOLUME_ZEROS 0, 0
#define SET_MONO_DEST_VOLUME_VARIABLES { \ #define SET_MONO_DEST_VOLUME_VARIABLES \
if ( volume_left ) { \ { \
if (volume_left) { \
lvolr = volume_left->volume; \ lvolr = volume_left->volume; \
lvold = volume_left->delta; \ lvold = volume_left->delta; \
lvolt = volume_left->target; \ lvolt = volume_left->target; \
lvolm = volume_left->mix; \ lvolm = volume_left->mix; \
lvol = lvolr * lvolm; \ lvol = lvolr * lvolm; \
if ( lvolr == lvolt ) volume_left = NULL; \ if (lvolr == lvolt) \
volume_left = NULL; \
} else { \ } else { \
lvol = 0; \ lvol = 0; \
lvolr = 0; \
lvold = 0; \ lvold = 0; \
lvolt = 0; \ lvolt = 0; \
lvolm = 0; \ lvolm = 0; \
} \ } \
if ( volume_right ) { \ if (volume_right) { \
rvolr = volume_right->volume; \ rvolr = volume_right->volume; \
rvold = volume_right->delta; \ rvold = volume_right->delta; \
rvolt = volume_right->target; \ rvolt = volume_right->target; \
rvolm = volume_right->mix; \ rvolm = volume_right->mix; \
rvol = rvolr * rvolm; \ rvol = rvolr * rvolm; \
if ( rvolr == rvolt ) volume_right = NULL; \ if (rvolr == rvolt) \
volume_right = NULL; \
} else { \ } else { \
rvol = 0; \ rvol = 0; \
rvolr = 0; \
rvold = 0; \ rvold = 0; \
rvolt = 0; \ rvolt = 0; \
rvolm = 0; \ rvolm = 0; \
} \ } \
} }
#define RETURN_MONO_DEST_VOLUME_VARIABLES { \ #define RETURN_MONO_DEST_VOLUME_VARIABLES \
if ( volume_left ) volume_left->volume = lvolr; \ { \
if ( volume_right ) volume_right->volume = rvolr; \ if (volume_left) \
} volume_left->volume = lvolr; \
#define MONO_DEST_VOLUMES_ARE_ZERO (lvol == 0 && lvolt == 0 && rvol == 0 && rvolt == 0) if (volume_right) \
#define POKE_FIR(offset) { \ volume_right->volume = rvolr; \
resampler_write_sample_float( resampler->fir_resampler[0], FIR(x[(offset)*2+0]) ); \ }
resampler_write_sample_float( resampler->fir_resampler[1], FIR(x[(offset)*2+1]) ); \ #define MONO_DEST_VOLUMES_ARE_ZERO \
} (lvol == 0 && lvolt == 0 && rvol == 0 && rvolt == 0)
#define MONO_DEST_PEEK_FIR { \ #define POKE_FIR(offset) \
*dst = (resampler_get_sample_float( resampler->fir_resampler[0] ) * lvol + \ { \
resampler_get_sample_float( resampler->fir_resampler[1] ) * rvol) * 16777216.0f; \ resampler_write_sample_float(resampler->fir_resampler[0], \
} FIR(x[(offset)*2 + 0])); \
#define MONO_DEST_MIX_FIR { \ resampler_write_sample_float(resampler->fir_resampler[1], \
*dst++ += (resampler_get_sample_float( resampler->fir_resampler[0] ) * lvol + \ FIR(x[(offset)*2 + 1])); \
resampler_get_sample_float( resampler->fir_resampler[1] ) * rvol) * 16777216.0f; \ }
UPDATE_VOLUME( volume_left, lvol ); \ #define MONO_DEST_PEEK_FIR \
UPDATE_VOLUME( volume_right, rvol ); \ { \
} *dst = \
#define ADVANCE_FIR { \ (resampler_get_sample_float(resampler->fir_resampler[0]) * lvol + \
resampler_remove_sample( resampler->fir_resampler[0], 1 ); \ resampler_get_sample_float(resampler->fir_resampler[1]) * rvol) * \
resampler_remove_sample( resampler->fir_resampler[1], 1 ); \ 16777216.0f; \
} }
#define STEREO_DEST_PEEK_FIR { \ #define MONO_DEST_MIX_FIR \
*dst++ = resampler_get_sample_float( resampler->fir_resampler[0] ) * lvol * 16777216.0f; \ { \
*dst++ = resampler_get_sample_float( resampler->fir_resampler[1] ) * rvol * 16777216.0f; \ *dst++ += \
} (resampler_get_sample_float(resampler->fir_resampler[0]) * lvol + \
#define STEREO_DEST_MIX_FIR { \ resampler_get_sample_float(resampler->fir_resampler[1]) * rvol) * \
*dst++ += resampler_get_sample_float( resampler->fir_resampler[0] ) * lvol * 16777216.0f; \ 16777216.0f; \
*dst++ += resampler_get_sample_float( resampler->fir_resampler[1] ) * rvol * 16777216.0f; \ UPDATE_VOLUME(volume_left, lvol); \
UPDATE_VOLUME( volume_left, lvol ); \ UPDATE_VOLUME(volume_right, rvol); \
UPDATE_VOLUME( volume_right, rvol ); \ }
} #define ADVANCE_FIR \
{ \
resampler_remove_sample(resampler->fir_resampler[0], 1); \
resampler_remove_sample(resampler->fir_resampler[1], 1); \
}
#define STEREO_DEST_PEEK_FIR \
{ \
*dst++ = resampler_get_sample_float(resampler->fir_resampler[0]) * \
lvol * 16777216.0f; \
*dst++ = resampler_get_sample_float(resampler->fir_resampler[1]) * \
rvol * 16777216.0f; \
}
#define STEREO_DEST_MIX_FIR \
{ \
*dst++ += resampler_get_sample_float(resampler->fir_resampler[0]) * \
lvol * 16777216.0f; \
*dst++ += resampler_get_sample_float(resampler->fir_resampler[1]) * \
rvol * 16777216.0f; \
UPDATE_VOLUME(volume_left, lvol); \
UPDATE_VOLUME(volume_right, rvol); \
}
#include "resamp2.inc" #include "resamp2.inc"
void dumb_end_resampler(DUMB_RESAMPLER *resampler) {
void dumb_end_resampler(DUMB_RESAMPLER *resampler)
{
if (resampler) if (resampler)
free(resampler); free(resampler);
} }
#undef FIR #undef FIR
#undef SRCBITS #undef SRCBITS
#undef SRCTYPE #undef SRCTYPE

File diff suppressed because it is too large Load diff

View file

@ -3,83 +3,86 @@
#include <stdlib.h> #include <stdlib.h>
struct riff * riff_parse( DUMBFILE * f, long offset, long size, unsigned proper ) struct riff *riff_parse(DUMBFILE *f, long offset, long size, unsigned proper) {
{
unsigned stream_size; unsigned stream_size;
struct riff * stream; struct riff *stream;
if ( size < 8 ) return 0; if (size < 8)
return 0;
if ( dumbfile_seek(f, offset, DFS_SEEK_SET) ) return 0; if (dumbfile_seek(f, offset, DFS_SEEK_SET))
if ( dumbfile_mgetl(f) != DUMB_ID('R','I','F','F') ) return 0; return 0;
if (dumbfile_mgetl(f) != DUMB_ID('R', 'I', 'F', 'F'))
return 0;
stream_size = (int) dumbfile_igetl(f); stream_size = (int)dumbfile_igetl(f);
if ( stream_size + 8 > size ) return 0; if (stream_size + 8 > size)
if ( stream_size < 4 ) return 0; return 0;
if (stream_size < 4)
return 0;
stream = (struct riff *) malloc( sizeof( struct riff ) ); stream = (struct riff *)malloc(sizeof(struct riff));
if ( ! stream ) return 0; if (!stream)
return 0;
stream->type = (int) dumbfile_mgetl(f); stream->type = (int)dumbfile_mgetl(f);
stream->chunk_count = 0; stream->chunk_count = 0;
stream->chunks = 0; stream->chunks = 0;
stream_size -= 4; stream_size -= 4;
while ( stream_size && !dumbfile_error(f) ) while (stream_size && !dumbfile_error(f)) {
{ struct riff_chunk *chunk;
struct riff_chunk * chunk; if (stream_size < 8)
if ( stream_size < 8 ) break; break;
stream->chunks = ( struct riff_chunk * ) realloc( stream->chunks, ( stream->chunk_count + 1 ) * sizeof( struct riff_chunk ) ); stream->chunks = (struct riff_chunk *)realloc(
if ( ! stream->chunks ) break; stream->chunks,
(stream->chunk_count + 1) * sizeof(struct riff_chunk));
if (!stream->chunks)
break;
chunk = stream->chunks + stream->chunk_count; chunk = stream->chunks + stream->chunk_count;
chunk->type = (int) dumbfile_mgetl(f); chunk->type = (int)dumbfile_mgetl(f);
chunk->size = (int) dumbfile_igetl(f); chunk->size = (int)dumbfile_igetl(f);
chunk->offset = dumbfile_pos(f); chunk->offset = dumbfile_pos(f);
stream_size -= 8; stream_size -= 8;
if ( stream_size < chunk->size ) break; if (stream_size < chunk->size)
if ( chunk->type == DUMB_ID('R','I','F','F') ) break;
{ if (chunk->type == DUMB_ID('R', 'I', 'F', 'F')) {
chunk->nested = riff_parse( f, chunk->offset - 8, chunk->size + 8, proper ); chunk->nested =
if ( ! chunk->nested ) break; riff_parse(f, chunk->offset - 8, chunk->size + 8, proper);
} if (!chunk->nested)
else break;
{ } else {
chunk->nested = 0; chunk->nested = 0;
} }
dumbfile_seek(f, chunk->offset + chunk->size, DFS_SEEK_SET); dumbfile_seek(f, chunk->offset + chunk->size, DFS_SEEK_SET);
stream_size -= chunk->size; stream_size -= chunk->size;
if ( proper && ( chunk->size & 1 ) ) if (proper && (chunk->size & 1)) {
{
dumbfile_skip(f, 1); dumbfile_skip(f, 1);
-- stream_size; --stream_size;
} }
++stream->chunk_count; ++stream->chunk_count;
} }
if ( stream_size ) if (stream_size) {
{ riff_free(stream);
riff_free( stream );
stream = 0; stream = 0;
} }
return stream; return stream;
} }
void riff_free( struct riff * stream ) void riff_free(struct riff *stream) {
{ if (stream) {
if ( stream ) if (stream->chunks) {
{
if ( stream->chunks )
{
unsigned i; unsigned i;
for ( i = 0; i < stream->chunk_count; ++i ) for (i = 0; i < stream->chunk_count; ++i) {
{ struct riff_chunk *chunk = stream->chunks + i;
struct riff_chunk * chunk = stream->chunks + i; if (chunk->nested)
if ( chunk->nested ) riff_free( chunk->nested ); riff_free(chunk->nested);
} }
free( stream->chunks ); free(stream->chunks);
} }
free( stream ); free(stream);
} }
} }

View file

@ -20,43 +20,22 @@
#include <stdlib.h> #include <stdlib.h>
#include "dumb.h" #include "dumb.h"
sample_t **allocate_sample_buffer(int n_channels, long length) {
/* DEPRECATED */
sample_t **create_sample_buffer(int n_channels, long length)
{
int i;
sample_t **samples = malloc(n_channels * sizeof(*samples));
if (!samples) return NULL;
samples[0] = malloc(n_channels * length * sizeof(*samples[0]));
if (!samples[0]) {
free(samples);
return NULL;
}
for (i = 1; i < n_channels; i++) samples[i] = samples[i-1] + length;
return samples;
}
sample_t **allocate_sample_buffer(int n_channels, long length)
{
int i; int i;
sample_t **samples = malloc(((n_channels + 1) >> 1) * sizeof(*samples)); sample_t **samples = malloc(((n_channels + 1) >> 1) * sizeof(*samples));
if (!samples) return NULL; if (!samples)
return NULL;
samples[0] = malloc(n_channels * length * sizeof(*samples[0])); samples[0] = malloc(n_channels * length * sizeof(*samples[0]));
if (!samples[0]) { if (!samples[0]) {
free(samples); free(samples);
return NULL; return NULL;
} }
for (i = 1; i < (n_channels + 1) >> 1; i++) samples[i] = samples[i-1] + length*2; for (i = 1; i<(n_channels + 1)>> 1; i++)
samples[i] = samples[i - 1] + length * 2;
return samples; return samples;
} }
void destroy_sample_buffer(sample_t **samples) {
void destroy_sample_buffer(sample_t **samples)
{
if (samples) { if (samples) {
free(samples[0]); free(samples[0]);
free(samples); free(samples);

View file

@ -20,10 +20,6 @@
#include <string.h> #include <string.h>
#include "dumb.h" #include "dumb.h"
void dumb_silence(sample_t *samples, long length) {
void dumb_silence(sample_t *samples, long length)
{
memset(samples, 0, length * sizeof(*samples)); memset(samples, 0, length * sizeof(*samples));
} }

View file

@ -21,129 +21,91 @@
#include "dumb.h" #include "dumb.h"
typedef struct dumb_stdfile {
FILE *file;
typedef struct dumb_stdfile dumb_off_t size;
{
FILE * file;
long size;
} dumb_stdfile; } dumb_stdfile;
static void *dumb_stdfile_open(const char *filename) {
dumb_stdfile *file = (dumb_stdfile *)malloc(sizeof(dumb_stdfile));
static void *dumb_stdfile_open(const char *filename) if (!file)
{ return 0;
dumb_stdfile * file = ( dumb_stdfile * ) malloc( sizeof(dumb_stdfile) );
if ( !file ) return 0;
file->file = fopen(filename, "rb"); file->file = fopen(filename, "rb");
if ( !file->file ) if (!file->file) {
{ free(file);
free( file );
return 0; return 0;
} }
fseek(file->file, 0, SEEK_END); fseek(file->file, 0, SEEK_END);
file->size = ftell(file->file); file->size = ftell(file->file);
if (file->size < 0) {
fclose(file->file);
free(file);
return 0;
}
fseek(file->file, 0, SEEK_SET); fseek(file->file, 0, SEEK_SET);
return file; return file;
} }
static int dumb_stdfile_skip(void *f, dumb_off_t n) {
dumb_stdfile *file = (dumb_stdfile *)f;
static int dumb_stdfile_skip(void *f, long n)
{
dumb_stdfile * file = ( dumb_stdfile * ) f;
return fseek(file->file, n, SEEK_CUR); return fseek(file->file, n, SEEK_CUR);
} }
static int dumb_stdfile_getc(void *f) {
dumb_stdfile *file = (dumb_stdfile *)f;
static int dumb_stdfile_getc(void *f)
{
dumb_stdfile * file = ( dumb_stdfile * ) f;
return fgetc(file->file); return fgetc(file->file);
} }
static dumb_ssize_t dumb_stdfile_getnc(char *ptr, size_t n, void *f) {
dumb_stdfile *file = (dumb_stdfile *)f;
static long dumb_stdfile_getnc(char *ptr, long n, void *f)
{
dumb_stdfile * file = ( dumb_stdfile * ) f;
return fread(ptr, 1, n, file->file); return fread(ptr, 1, n, file->file);
} }
static void dumb_stdfile_close(void *f) {
dumb_stdfile *file = (dumb_stdfile *)f;
static void dumb_stdfile_close(void *f)
{
dumb_stdfile * file = ( dumb_stdfile * ) f;
fclose(file->file); fclose(file->file);
free(f); free(f);
} }
static void dumb_stdfile_noclose(void *f) { free(f); }
static int dumb_stdfile_seek(void *f, dumb_off_t n) {
static void dumb_stdfile_noclose(void *f) dumb_stdfile *file = (dumb_stdfile *)f;
{
free(f);
}
static int dumb_stdfile_seek(void *f, long n)
{
dumb_stdfile * file = ( dumb_stdfile * ) f;
return fseek(file->file, n, SEEK_SET); return fseek(file->file, n, SEEK_SET);
} }
static dumb_off_t dumb_stdfile_get_size(void *f) {
dumb_stdfile *file = (dumb_stdfile *)f;
static long dumb_stdfile_get_size(void *f)
{
dumb_stdfile * file = ( dumb_stdfile * ) f;
return file->size; return file->size;
} }
static const DUMBFILE_SYSTEM stdfile_dfs = { static const DUMBFILE_SYSTEM stdfile_dfs = {
&dumb_stdfile_open, &dumb_stdfile_open, &dumb_stdfile_skip, &dumb_stdfile_getc,
&dumb_stdfile_skip, &dumb_stdfile_getnc, &dumb_stdfile_close, &dumb_stdfile_seek,
&dumb_stdfile_getc, &dumb_stdfile_get_size};
&dumb_stdfile_getnc,
&dumb_stdfile_close,
&dumb_stdfile_seek,
&dumb_stdfile_get_size
};
void dumb_register_stdfiles(void) { register_dumbfile_system(&stdfile_dfs); }
static const DUMBFILE_SYSTEM stdfile_dfs_leave_open = {NULL,
void dumb_register_stdfiles(void)
{
register_dumbfile_system(&stdfile_dfs);
}
static const DUMBFILE_SYSTEM stdfile_dfs_leave_open = {
NULL,
&dumb_stdfile_skip, &dumb_stdfile_skip,
&dumb_stdfile_getc, &dumb_stdfile_getc,
&dumb_stdfile_getnc, &dumb_stdfile_getnc,
&dumb_stdfile_noclose, &dumb_stdfile_noclose,
&dumb_stdfile_seek, &dumb_stdfile_seek,
&dumb_stdfile_get_size &dumb_stdfile_get_size};
};
DUMBFILE *dumbfile_open_stdfile(FILE *p) {
dumb_stdfile *file = (dumb_stdfile *)malloc(sizeof(dumb_stdfile));
DUMBFILE *dumbfile_open_stdfile(FILE *p)
{
dumb_stdfile * file = ( dumb_stdfile * ) malloc( sizeof(dumb_stdfile) );
DUMBFILE *d; DUMBFILE *d;
if ( !file ) return 0; if (!file)
return 0;
file->file = p; file->file = p;
fseek(p, 0, SEEK_END); fseek(p, 0, SEEK_END);
file->size = ftell(p); file->size = ftell(p);
if (file->size < 0) {
free(file);
return 0;
}
fseek(p, 0, SEEK_SET); fseek(p, 0, SEEK_SET);
d = dumbfile_open_ex(file, &stdfile_dfs_leave_open); d = dumbfile_open_ex(file, &stdfile_dfs_leave_open);

View file

@ -2,67 +2,69 @@
#include <string.h> #include <string.h>
/* /*
Structures which contain the play times of each pattern and row combination in the song, Structures which contain the play times of each pattern and row combination
not guaranteed to be valid for the whole song until the loop status is no longer zero. in the song, not guaranteed to be valid for the whole song until the loop
The initial count and restart count will both be zero on song start, then both will be status is no longer zero. The initial count and restart count will both be
incremented until the song loops. Restart count will be reset to zero on loop for all zero on song start, then both will be incremented until the song loops.
rows which have a time equal to or greater than the loop start point, so time keeping Restart count will be reset to zero on loop for all rows which have a time
functions will know which timestamp the song is currently located at. equal to or greater than the loop start point, so time keeping functions will
know which timestamp the song is currently located at.
Timestamp lists are guaranteed to be allocated in blocks of 16 timestamps at a time. Timestamp lists are guaranteed to be allocated in blocks of 16 timestamps at
*/ a time.
*/
/* /*
We don't need full timekeeping because the player loop only wants the first play time We don't need full timekeeping because the player loop only wants the first
of the loop start order/row. We also don't really want full timekeeping because it play time of the loop start order/row. We also don't really want full
involves a lot of memory allocations, which is also slow. timekeeping because it involves a lot of memory allocations, which is also
*/ slow.
*/
#undef FULL_TIMEKEEPING #undef FULL_TIMEKEEPING
typedef struct DUMB_IT_ROW_TIME typedef struct DUMB_IT_ROW_TIME {
{
unsigned int count, restart_count; unsigned int count, restart_count;
#ifndef FULL_TIMEKEEPING #ifndef FULL_TIMEKEEPING
LONG_LONG first_time; LONG_LONG first_time;
#else #else
LONG_LONG * times; LONG_LONG *times;
#endif #endif
} DUMB_IT_ROW_TIME; } DUMB_IT_ROW_TIME;
void * timekeeping_array_create(size_t size) void *timekeeping_array_create(size_t size) {
{ size_t *_size =
size_t * _size = (size_t *) calloc( 1, sizeof(size_t) + sizeof(DUMB_IT_ROW_TIME) * size ); (size_t *)calloc(1, sizeof(size_t) + sizeof(DUMB_IT_ROW_TIME) * size);
if ( _size ) { if (_size) {
*_size = size; *_size = size;
} }
return _size; return _size;
} }
void timekeeping_array_destroy(void * array) void timekeeping_array_destroy(void *array) {
{
#ifdef FULL_TIMEKEEPING #ifdef FULL_TIMEKEEPING
size_t i; size_t i;
size_t * size = (size_t *) array; size_t *size = (size_t *)array;
DUMB_IT_ROW_TIME * s = (DUMB_IT_ROW_TIME *)(size + 1); DUMB_IT_ROW_TIME *s = (DUMB_IT_ROW_TIME *)(size + 1);
for (i = 0; i < *size; i++) { for (i = 0; i < *size; i++) {
if (s[i].times) free(s[i].times); if (s[i].times)
free(s[i].times);
} }
#endif #endif
free(array); free(array);
} }
void * timekeeping_array_dup(void * array) void *timekeeping_array_dup(void *array) {
{
size_t i; size_t i;
size_t * size = (size_t *) array; size_t *size = (size_t *)array;
DUMB_IT_ROW_TIME * s = (DUMB_IT_ROW_TIME *)(size + 1); DUMB_IT_ROW_TIME *s = (DUMB_IT_ROW_TIME *)(size + 1);
size_t * new_size = (size_t *) calloc( 1, sizeof(size_t) + sizeof(DUMB_IT_ROW_TIME) * *size ); size_t *new_size =
if ( new_size ) { (size_t *)calloc(1, sizeof(size_t) + sizeof(DUMB_IT_ROW_TIME) * *size);
DUMB_IT_ROW_TIME * new_s = (DUMB_IT_ROW_TIME *)(new_size + 1); if (new_size) {
DUMB_IT_ROW_TIME *new_s = (DUMB_IT_ROW_TIME *)(new_size + 1);
*new_size = *size; *new_size = *size;
@ -73,14 +75,16 @@ void * timekeeping_array_dup(void * array)
#ifndef FULL_TIMEKEEPING #ifndef FULL_TIMEKEEPING
new_s[i].first_time = s[i].first_time; new_s[i].first_time = s[i].first_time;
#else #else
if ( s[i].times ) { if (s[i].times) {
size_t time_count = ( s[i].count + 15 ) & ~15; size_t time_count = (s[i].count + 15) & ~15;
new_s[i].times = (LONG_LONG *) malloc( sizeof(LONG_LONG) * time_count ); new_s[i].times =
if ( new_s[i].times == (void *)0 ) { (LONG_LONG *)malloc(sizeof(LONG_LONG) * time_count);
timekeeping_array_destroy( new_size ); if (new_s[i].times == (void *)0) {
return (void *) 0; timekeeping_array_destroy(new_size);
return (void *)0;
} }
memcpy( new_s[i].times, s[i].times, sizeof(LONG_LONG) * s[i].count ); memcpy(new_s[i].times, s[i].times,
sizeof(LONG_LONG) * s[i].count);
} }
#endif #endif
} }
@ -89,16 +93,16 @@ void * timekeeping_array_dup(void * array)
return new_size; return new_size;
} }
void timekeeping_array_reset(void * array, size_t loop_start) void timekeeping_array_reset(void *array, size_t loop_start) {
{
size_t i; size_t i;
size_t * size = (size_t *) array; size_t *size = (size_t *)array;
DUMB_IT_ROW_TIME * s = (DUMB_IT_ROW_TIME *)(size + 1); DUMB_IT_ROW_TIME *s = (DUMB_IT_ROW_TIME *)(size + 1);
DUMB_IT_ROW_TIME * s_loop_start = s + loop_start; DUMB_IT_ROW_TIME *s_loop_start = s + loop_start;
LONG_LONG loop_start_time; LONG_LONG loop_start_time;
if ( loop_start >= *size || s_loop_start->count < 1 ) return; if (loop_start >= *size || s_loop_start->count < 1)
return;
#ifndef FULL_TIMEKEEPING #ifndef FULL_TIMEKEEPING
loop_start_time = s_loop_start->first_time; loop_start_time = s_loop_start->first_time;
@ -106,66 +110,67 @@ void timekeeping_array_reset(void * array, size_t loop_start)
loop_start_time = s_loop_start->times[0]; loop_start_time = s_loop_start->times[0];
#endif #endif
for ( i = 0; i < *size; i++ ) { for (i = 0; i < *size; i++) {
#ifndef FULL_TIMEKEEPING #ifndef FULL_TIMEKEEPING
if ( s[i].count && s[i].first_time >= loop_start_time ) { if (s[i].count && s[i].first_time >= loop_start_time) {
#else #else
if ( s[i].count && s[i].times[0] >= loop_start_time ) { if (s[i].count && s[i].times[0] >= loop_start_time) {
#endif #endif
s[i].restart_count = 0; s[i].restart_count = 0;
} }
} }
} }
void timekeeping_array_push(void * array, size_t index, LONG_LONG time) void timekeeping_array_push(void *array, size_t index, LONG_LONG time) {
{
#ifdef FULL_TIMEKEEPING #ifdef FULL_TIMEKEEPING
size_t i; size_t i;
size_t time_count; size_t time_count;
#endif #endif
size_t * size = (size_t *) array; size_t *size = (size_t *)array;
DUMB_IT_ROW_TIME * s = (DUMB_IT_ROW_TIME *)(size + 1); DUMB_IT_ROW_TIME *s = (DUMB_IT_ROW_TIME *)(size + 1);
if (index >= *size) return; if (index >= *size)
return;
#ifndef FULL_TIMEKEEPING #ifndef FULL_TIMEKEEPING
if ( !s[index].count++ ) if (!s[index].count++)
s[index].first_time = time; s[index].first_time = time;
#else #else
time_count = ( s[index].count + 16 ) & ~15; time_count = (s[index].count + 16) & ~15;
s[index].times = (LONG_LONG *) realloc( s[index].times, sizeof(LONG_LONG) * time_count ); s[index].times =
(LONG_LONG *)realloc(s[index].times, sizeof(LONG_LONG) * time_count);
s[index].times[s[index].count++] = time; s[index].times[s[index].count++] = time;
#endif #endif
} }
void timekeeping_array_bump(void * array, size_t index) void timekeeping_array_bump(void *array, size_t index) {
{ size_t *size = (size_t *)array;
size_t * size = (size_t *) array; DUMB_IT_ROW_TIME *s = (DUMB_IT_ROW_TIME *)(size + 1);
DUMB_IT_ROW_TIME * s = (DUMB_IT_ROW_TIME *)(size + 1);
if (index >= *size) return; if (index >= *size)
return;
s[index].restart_count++; s[index].restart_count++;
} }
unsigned int timekeeping_array_get_count(void * array, size_t index) unsigned int timekeeping_array_get_count(void *array, size_t index) {
{ size_t *size = (size_t *)array;
size_t * size = (size_t *) array; DUMB_IT_ROW_TIME *s = (DUMB_IT_ROW_TIME *)(size + 1);
DUMB_IT_ROW_TIME * s = (DUMB_IT_ROW_TIME *)(size + 1);
if (index >= *size) return 0; if (index >= *size)
return 0;
return s[index].count; return s[index].count;
} }
LONG_LONG timekeeping_array_get_item(void * array, size_t index) LONG_LONG timekeeping_array_get_item(void *array, size_t index) {
{ size_t *size = (size_t *)array;
size_t * size = (size_t *) array; DUMB_IT_ROW_TIME *s = (DUMB_IT_ROW_TIME *)(size + 1);
DUMB_IT_ROW_TIME * s = (DUMB_IT_ROW_TIME *)(size + 1);
if (index >= *size || s[index].restart_count >= s[index].count) return 0; if (index >= *size || s[index].restart_count >= s[index].count)
return 0;
#ifndef FULL_TIMEKEEPING #ifndef FULL_TIMEKEEPING
return s[index].first_time; return s[index].first_time;

View file

@ -20,14 +20,11 @@
#include "dumb.h" #include "dumb.h"
#include "internal/it.h" #include "internal/it.h"
/* dumb_load_it_quick(): loads an IT file into a DUH struct, returning a /* dumb_load_it_quick(): loads an IT file into a DUH struct, returning a
* pointer to the DUH struct. When you have finished with it, you must pass * pointer to the DUH struct. When you have finished with it, you must pass
* the pointer to unload_duh() so that the memory can be freed. * the pointer to unload_duh() so that the memory can be freed.
*/ */
DUH *dumb_load_it_quick(const char *filename) DUH *dumb_load_it_quick(const char *filename) {
{
DUH *duh; DUH *duh;
DUMBFILE *f = dumbfile_open(filename); DUMBFILE *f = dumbfile_open(filename);
@ -40,4 +37,3 @@ DUH *dumb_load_it_quick(const char *filename)
return duh; return duh;
} }

View file

@ -19,10 +19,7 @@
#include "dumb.h" #include "dumb.h"
DUH *dumb_load_it(const char *filename) {
DUH *dumb_load_it(const char *filename)
{
DUH *duh = dumb_load_it_quick(filename); DUH *duh = dumb_load_it_quick(filename);
dumb_it_do_initial_runthrough(duh); dumb_it_do_initial_runthrough(duh);
return duh; return duh;

View file

@ -20,219 +20,142 @@
#include "dumb.h" #include "dumb.h"
#include "internal/it.h" #include "internal/it.h"
int dumb_it_default_panning_separation = 25; int dumb_it_default_panning_separation = 25;
DUMB_IT_SIGDATA *duh_get_it_sigdata(DUH *duh) {
DUMB_IT_SIGDATA *duh_get_it_sigdata(DUH *duh)
{
return duh_get_raw_sigdata(duh, -1, SIGTYPE_IT); return duh_get_raw_sigdata(duh, -1, SIGTYPE_IT);
} }
const unsigned char *dumb_it_sd_get_song_message(DUMB_IT_SIGDATA *sd) {
const unsigned char *dumb_it_sd_get_song_message(DUMB_IT_SIGDATA *sd)
{
return sd ? sd->song_message : NULL; return sd ? sd->song_message : NULL;
} }
int dumb_it_sd_get_n_orders(DUMB_IT_SIGDATA *sd) {
int dumb_it_sd_get_n_orders(DUMB_IT_SIGDATA *sd)
{
return sd ? sd->n_orders : 0; return sd ? sd->n_orders : 0;
} }
int dumb_it_sd_get_n_samples(DUMB_IT_SIGDATA *sd) {
int dumb_it_sd_get_n_samples(DUMB_IT_SIGDATA *sd)
{
return sd ? sd->n_samples : 0; return sd ? sd->n_samples : 0;
} }
int dumb_it_sd_get_n_instruments(DUMB_IT_SIGDATA *sd) {
int dumb_it_sd_get_n_instruments(DUMB_IT_SIGDATA *sd)
{
return sd ? sd->n_instruments : 0; return sd ? sd->n_instruments : 0;
} }
const unsigned char *dumb_it_sd_get_sample_name(DUMB_IT_SIGDATA *sd, int i) {
const unsigned char *dumb_it_sd_get_sample_name(DUMB_IT_SIGDATA *sd, int i)
{
ASSERT(sd && sd->sample && i >= 0 && i < sd->n_samples); ASSERT(sd && sd->sample && i >= 0 && i < sd->n_samples);
return sd->sample[i].name; return sd->sample[i].name;
} }
const unsigned char *dumb_it_sd_get_sample_filename(DUMB_IT_SIGDATA *sd,
int i) {
const unsigned char *dumb_it_sd_get_sample_filename(DUMB_IT_SIGDATA *sd, int i)
{
ASSERT(sd && sd->sample && i >= 0 && i < sd->n_samples); ASSERT(sd && sd->sample && i >= 0 && i < sd->n_samples);
return sd->sample[i].filename; return sd->sample[i].filename;
} }
const unsigned char *dumb_it_sd_get_instrument_name(DUMB_IT_SIGDATA *sd,
int i) {
const unsigned char *dumb_it_sd_get_instrument_name(DUMB_IT_SIGDATA *sd, int i)
{
ASSERT(sd && sd->instrument && i >= 0 && i < sd->n_instruments); ASSERT(sd && sd->instrument && i >= 0 && i < sd->n_instruments);
return sd->instrument[i].name; return sd->instrument[i].name;
} }
const unsigned char *dumb_it_sd_get_instrument_filename(DUMB_IT_SIGDATA *sd,
int i) {
const unsigned char *dumb_it_sd_get_instrument_filename(DUMB_IT_SIGDATA *sd, int i)
{
ASSERT(sd && sd->instrument && i >= 0 && i < sd->n_instruments); ASSERT(sd && sd->instrument && i >= 0 && i < sd->n_instruments);
return sd->instrument[i].filename; return sd->instrument[i].filename;
} }
int dumb_it_sd_get_initial_global_volume(DUMB_IT_SIGDATA *sd) {
int dumb_it_sd_get_initial_global_volume(DUMB_IT_SIGDATA *sd)
{
return sd ? sd->global_volume : 0; return sd ? sd->global_volume : 0;
} }
void dumb_it_sd_set_initial_global_volume(DUMB_IT_SIGDATA *sd, int gv) {
if (sd)
void dumb_it_sd_set_initial_global_volume(DUMB_IT_SIGDATA *sd, int gv) sd->global_volume = gv;
{
if (sd) sd->global_volume = gv;
} }
int dumb_it_sd_get_mixing_volume(DUMB_IT_SIGDATA *sd) {
int dumb_it_sd_get_mixing_volume(DUMB_IT_SIGDATA *sd)
{
return sd ? sd->mixing_volume : 0; return sd ? sd->mixing_volume : 0;
} }
void dumb_it_sd_set_mixing_volume(DUMB_IT_SIGDATA *sd, int mv) {
if (sd)
void dumb_it_sd_set_mixing_volume(DUMB_IT_SIGDATA *sd, int mv) sd->mixing_volume = mv;
{
if (sd) sd->mixing_volume = mv;
} }
int dumb_it_sd_get_initial_speed(DUMB_IT_SIGDATA *sd) {
int dumb_it_sd_get_initial_speed(DUMB_IT_SIGDATA *sd)
{
return sd ? sd->speed : 0; return sd ? sd->speed : 0;
} }
void dumb_it_sd_set_initial_speed(DUMB_IT_SIGDATA *sd, int speed) {
if (sd)
void dumb_it_sd_set_initial_speed(DUMB_IT_SIGDATA *sd, int speed) sd->speed = speed;
{
if (sd) sd->speed = speed;
} }
int dumb_it_sd_get_initial_tempo(DUMB_IT_SIGDATA *sd) {
int dumb_it_sd_get_initial_tempo(DUMB_IT_SIGDATA *sd)
{
return sd ? sd->tempo : 0; return sd ? sd->tempo : 0;
} }
void dumb_it_sd_set_initial_tempo(DUMB_IT_SIGDATA *sd, int tempo) {
if (sd)
void dumb_it_sd_set_initial_tempo(DUMB_IT_SIGDATA *sd, int tempo) sd->tempo = tempo;
{
if (sd) sd->tempo = tempo;
} }
int dumb_it_sd_get_initial_channel_volume(DUMB_IT_SIGDATA *sd, int channel) {
int dumb_it_sd_get_initial_channel_volume(DUMB_IT_SIGDATA *sd, int channel)
{
ASSERT(channel >= 0 && channel < DUMB_IT_N_CHANNELS); ASSERT(channel >= 0 && channel < DUMB_IT_N_CHANNELS);
return sd ? sd->channel_volume[channel] : 0; return sd ? sd->channel_volume[channel] : 0;
} }
void dumb_it_sd_set_initial_channel_volume(DUMB_IT_SIGDATA *sd, int channel, int volume) void dumb_it_sd_set_initial_channel_volume(DUMB_IT_SIGDATA *sd, int channel,
{ int volume) {
ASSERT(channel >= 0 && channel < DUMB_IT_N_CHANNELS); ASSERT(channel >= 0 && channel < DUMB_IT_N_CHANNELS);
if (sd) sd->channel_volume[channel] = volume; if (sd)
sd->channel_volume[channel] = volume;
} }
int dumb_it_sr_get_current_order(DUMB_IT_SIGRENDERER *sr) {
int dumb_it_sr_get_current_order(DUMB_IT_SIGRENDERER *sr)
{
return sr ? sr->order : -1; return sr ? sr->order : -1;
} }
int dumb_it_sr_get_current_row(DUMB_IT_SIGRENDERER *sr) {
int dumb_it_sr_get_current_row(DUMB_IT_SIGRENDERER *sr)
{
return sr ? sr->row : -1; return sr ? sr->row : -1;
} }
int dumb_it_sr_get_global_volume(DUMB_IT_SIGRENDERER *sr) {
int dumb_it_sr_get_global_volume(DUMB_IT_SIGRENDERER *sr)
{
return sr ? sr->globalvolume : 0; return sr ? sr->globalvolume : 0;
} }
void dumb_it_sr_set_global_volume(DUMB_IT_SIGRENDERER *sr, int gv) {
if (sr)
void dumb_it_sr_set_global_volume(DUMB_IT_SIGRENDERER *sr, int gv) sr->globalvolume = gv;
{
if (sr) sr->globalvolume = gv;
} }
int dumb_it_sr_get_tempo(DUMB_IT_SIGRENDERER *sr) { return sr ? sr->tempo : 0; }
void dumb_it_sr_set_tempo(DUMB_IT_SIGRENDERER *sr, int tempo) {
int dumb_it_sr_get_tempo(DUMB_IT_SIGRENDERER *sr) if (sr)
{ sr->tempo = tempo;
return sr ? sr->tempo : 0;
} }
int dumb_it_sr_get_speed(DUMB_IT_SIGRENDERER *sr) { return sr ? sr->speed : 0; }
void dumb_it_sr_set_speed(DUMB_IT_SIGRENDERER *sr, int speed) {
void dumb_it_sr_set_tempo(DUMB_IT_SIGRENDERER *sr, int tempo) if (sr)
{ sr->speed = speed;
if (sr) sr->tempo = tempo;
} }
int dumb_it_sr_get_channel_volume(DUMB_IT_SIGRENDERER *sr, int channel) {
int dumb_it_sr_get_speed(DUMB_IT_SIGRENDERER *sr)
{
return sr ? sr->speed : 0;
}
void dumb_it_sr_set_speed(DUMB_IT_SIGRENDERER *sr, int speed)
{
if (sr) sr->speed = speed;
}
int dumb_it_sr_get_channel_volume(DUMB_IT_SIGRENDERER *sr, int channel)
{
return sr ? sr->channel[channel].channelvolume : 0; return sr ? sr->channel[channel].channelvolume : 0;
} }
void dumb_it_sr_set_channel_volume(DUMB_IT_SIGRENDERER *sr, int channel,
int volume) {
void dumb_it_sr_set_channel_volume(DUMB_IT_SIGRENDERER *sr, int channel, int volume) if (sr)
{ sr->channel[channel].channelvolume = volume;
if (sr) sr->channel[channel].channelvolume = volume;
} }
void dumb_it_sr_set_channel_muted(DUMB_IT_SIGRENDERER *sr, int channel,
int muted) {
void dumb_it_sr_set_channel_muted(DUMB_IT_SIGRENDERER *sr, int channel, int muted)
{
if (sr) { if (sr) {
if (muted) if (muted)
sr->channel[channel].flags |= IT_CHANNEL_MUTED; sr->channel[channel].flags |= IT_CHANNEL_MUTED;
@ -241,9 +164,6 @@ void dumb_it_sr_set_channel_muted(DUMB_IT_SIGRENDERER *sr, int channel, int mute
} }
} }
int dumb_it_sr_get_channel_muted(DUMB_IT_SIGRENDERER *sr, int channel) {
int dumb_it_sr_get_channel_muted(DUMB_IT_SIGRENDERER *sr, int channel)
{
return sr ? (sr->channel[channel].flags & IT_CHANNEL_MUTED) != 0 : 0; return sr ? (sr->channel[channel].flags & IT_CHANNEL_MUTED) != 0 : 0;
} }

View file

@ -17,23 +17,18 @@
* \__/ * \__/
*/ */
#include <stdlib.h> #include <stdlib.h>
#include "dumb.h" #include "dumb.h"
#include "internal/it.h" #include "internal/it.h"
/* This function ensures that any pattern mentioned in the order table but /* This function ensures that any pattern mentioned in the order table but
* not present in the pattern table is treated as an empty 64 rows pattern. * not present in the pattern table is treated as an empty 64 rows pattern.
* This is done by adding such a dummy pattern at the end of the pattern * This is done by adding such a dummy pattern at the end of the pattern
* table, and redirect invalid orders to it. * table, and redirect invalid orders to it.
* Patterns 254 and 255 are left untouched, unless the signal is an XM. * Patterns 254 and 255 are left untouched, unless the signal is an XM.
*/ */
int _dumb_it_fix_invalid_orders(DUMB_IT_SIGDATA *sigdata) int _dumb_it_fix_invalid_orders(DUMB_IT_SIGDATA *sigdata) {
{
int i; int i;
int found_some = 0; int found_some = 0;
@ -41,14 +36,17 @@ int _dumb_it_fix_invalid_orders(DUMB_IT_SIGDATA *sigdata)
int last_invalid = (sigdata->flags & IT_WAS_AN_XM) ? 255 : 253; int last_invalid = (sigdata->flags & IT_WAS_AN_XM) ? 255 : 253;
for (i = 0; i < sigdata->n_orders; i++) { for (i = 0; i < sigdata->n_orders; i++) {
if (sigdata->order[i] >= first_invalid && sigdata->order[i] <= last_invalid) { if (sigdata->order[i] >= first_invalid &&
sigdata->order[i] <= last_invalid) {
sigdata->order[i] = sigdata->n_patterns; sigdata->order[i] = sigdata->n_patterns;
found_some = 1; found_some = 1;
} }
} }
if (found_some) { if (found_some) {
IT_PATTERN *new_pattern = realloc(sigdata->pattern, sizeof(*sigdata->pattern) * (sigdata->n_patterns + 1)); IT_PATTERN *new_pattern =
realloc(sigdata->pattern,
sizeof(*sigdata->pattern) * (sigdata->n_patterns + 1));
if (!new_pattern) if (!new_pattern)
return -1; return -1;

File diff suppressed because it is too large Load diff

View file

@ -19,10 +19,7 @@
#include "dumb.h" #include "dumb.h"
DUH *dumb_read_it(DUMBFILE *f) {
DUH *dumb_read_it(DUMBFILE *f)
{
DUH *duh = dumb_read_it_quick(f); DUH *duh = dumb_read_it_quick(f);
dumb_it_do_initial_runthrough(duh); dumb_it_do_initial_runthrough(duh);
return duh; return duh;

File diff suppressed because it is too large Load diff

View file

@ -22,10 +22,7 @@
#include "dumb.h" #include "dumb.h"
#include "internal/it.h" #include "internal/it.h"
void _dumb_it_unload_sigdata(sigdata_t *vsigdata) {
void _dumb_it_unload_sigdata(sigdata_t *vsigdata)
{
if (vsigdata) { if (vsigdata) {
DUMB_IT_SIGDATA *sigdata = vsigdata; DUMB_IT_SIGDATA *sigdata = vsigdata;
int n; int n;

View file

@ -20,14 +20,11 @@
#include "dumb.h" #include "dumb.h"
#include "internal/it.h" #include "internal/it.h"
/* dumb_load_669_quick(): loads a 669 file into a DUH struct, returning a /* dumb_load_669_quick(): loads a 669 file into a DUH struct, returning a
* pointer to the DUH struct. When you have finished with it, you must * pointer to the DUH struct. When you have finished with it, you must
* pass the pointer to unload_duh() so that the memory can be freed. * pass the pointer to unload_duh() so that the memory can be freed.
*/ */
DUH *dumb_load_669_quick(const char *filename) DUH *dumb_load_669_quick(const char *filename) {
{
DUH *duh; DUH *duh;
DUMBFILE *f = dumbfile_open(filename); DUMBFILE *f = dumbfile_open(filename);

View file

@ -20,14 +20,11 @@
#include "dumb.h" #include "dumb.h"
#include "internal/it.h" #include "internal/it.h"
/* dumb_load_669(): loads a 669 file into a DUH struct, returning a pointer /* dumb_load_669(): loads a 669 file into a DUH struct, returning a pointer
* to the DUH struct. When you have finished with it, you must pass the * to the DUH struct. When you have finished with it, you must pass the
* pointer to unload_duh() so that the memory can be freed. * pointer to unload_duh() so that the memory can be freed.
*/ */
DUH *dumb_load_669(const char *filename) DUH *dumb_load_669(const char *filename) {
{
DUH *duh = dumb_load_669_quick(filename); DUH *duh = dumb_load_669_quick(filename);
dumb_it_do_initial_runthrough(duh); dumb_it_do_initial_runthrough(duh);
return duh; return duh;

View file

@ -20,14 +20,11 @@
#include "dumb.h" #include "dumb.h"
#include "internal/it.h" #include "internal/it.h"
/* dumb_load_amf_quick(): loads a AMF file into a DUH struct, returning a /* dumb_load_amf_quick(): loads a AMF file into a DUH struct, returning a
* pointer to the DUH struct. When you have finished with it, you must * pointer to the DUH struct. When you have finished with it, you must
* pass the pointer to unload_duh() so that the memory can be freed. * pass the pointer to unload_duh() so that the memory can be freed.
*/ */
DUH *dumb_load_amf_quick(const char *filename) DUH *dumb_load_amf_quick(const char *filename) {
{
DUH *duh; DUH *duh;
DUMBFILE *f = dumbfile_open(filename); DUMBFILE *f = dumbfile_open(filename);

View file

@ -20,14 +20,11 @@
#include "dumb.h" #include "dumb.h"
#include "internal/it.h" #include "internal/it.h"
/* dumb_load_amf(): loads a AMF file into a DUH struct, returning a pointer /* dumb_load_amf(): loads a AMF file into a DUH struct, returning a pointer
* to the DUH struct. When you have finished with it, you must pass the * to the DUH struct. When you have finished with it, you must pass the
* pointer to unload_duh() so that the memory can be freed. * pointer to unload_duh() so that the memory can be freed.
*/ */
DUH *dumb_load_amf(const char *filename) DUH *dumb_load_amf(const char *filename) {
{
DUH *duh = dumb_load_amf_quick(filename); DUH *duh = dumb_load_amf_quick(filename);
dumb_it_do_initial_runthrough(duh); dumb_it_do_initial_runthrough(duh);
return duh; return duh;

View file

@ -20,10 +20,7 @@
#include "dumb.h" #include "dumb.h"
#include "internal/it.h" #include "internal/it.h"
DUH *dumb_load_any_quick(const char *filename, int restrict_, int subsong) {
DUH *dumb_load_any_quick(const char *filename, int restrict_, int subsong)
{
DUH *duh; DUH *duh;
DUMBFILE *f = dumbfile_open(filename); DUMBFILE *f = dumbfile_open(filename);

View file

@ -19,10 +19,7 @@
#include "dumb.h" #include "dumb.h"
DUH *dumb_load_any(const char *filename, int restrict_, int subsong) {
DUH *dumb_load_any(const char *filename, int restrict_, int subsong)
{
DUH *duh = dumb_load_any_quick(filename, restrict_, subsong); DUH *duh = dumb_load_any_quick(filename, restrict_, subsong);
dumb_it_do_initial_runthrough(duh); dumb_it_do_initial_runthrough(duh);
return duh; return duh;

View file

@ -20,14 +20,11 @@
#include "dumb.h" #include "dumb.h"
#include "internal/it.h" #include "internal/it.h"
/* dumb_load_asy_quick(): loads a AMF file into a DUH struct, returning a /* dumb_load_asy_quick(): loads a AMF file into a DUH struct, returning a
* pointer to the DUH struct. When you have finished with it, you must * pointer to the DUH struct. When you have finished with it, you must
* pass the pointer to unload_duh() so that the memory can be freed. * pass the pointer to unload_duh() so that the memory can be freed.
*/ */
DUH *dumb_load_asy_quick(const char *filename) DUH *dumb_load_asy_quick(const char *filename) {
{
DUH *duh; DUH *duh;
DUMBFILE *f = dumbfile_open(filename); DUMBFILE *f = dumbfile_open(filename);

View file

@ -20,14 +20,11 @@
#include "dumb.h" #include "dumb.h"
#include "internal/it.h" #include "internal/it.h"
/* dumb_load_asy(): loads a AMF file into a DUH struct, returning a pointer /* dumb_load_asy(): loads a AMF file into a DUH struct, returning a pointer
* to the DUH struct. When you have finished with it, you must pass the * to the DUH struct. When you have finished with it, you must pass the
* pointer to unload_duh() so that the memory can be freed. * pointer to unload_duh() so that the memory can be freed.
*/ */
DUH *dumb_load_asy(const char *filename) DUH *dumb_load_asy(const char *filename) {
{
DUH *duh = dumb_load_asy_quick(filename); DUH *duh = dumb_load_asy_quick(filename);
dumb_it_do_initial_runthrough(duh); dumb_it_do_initial_runthrough(duh);
return duh; return duh;

View file

@ -20,14 +20,11 @@
#include "dumb.h" #include "dumb.h"
#include "internal/it.h" #include "internal/it.h"
/* dumb_load_mod_quick(): loads a MOD file into a DUH struct, returning a /* dumb_load_mod_quick(): loads a MOD file into a DUH struct, returning a
* pointer to the DUH struct. When you have finished with it, you must * pointer to the DUH struct. When you have finished with it, you must
* pass the pointer to unload_duh() so that the memory can be freed. * pass the pointer to unload_duh() so that the memory can be freed.
*/ */
DUH *dumb_load_mod_quick(const char *filename, int restrict_) DUH *dumb_load_mod_quick(const char *filename, int restrict_) {
{
DUH *duh; DUH *duh;
DUMBFILE *f = dumbfile_open(filename); DUMBFILE *f = dumbfile_open(filename);

View file

@ -19,10 +19,7 @@
#include "dumb.h" #include "dumb.h"
DUH *dumb_load_mod(const char *filename, int restrict_) {
DUH *dumb_load_mod(const char *filename, int restrict_)
{
DUH *duh = dumb_load_mod_quick(filename, restrict_); DUH *duh = dumb_load_mod_quick(filename, restrict_);
dumb_it_do_initial_runthrough(duh); dumb_it_do_initial_runthrough(duh);
return duh; return duh;

View file

@ -20,14 +20,11 @@
#include "dumb.h" #include "dumb.h"
#include "internal/it.h" #include "internal/it.h"
/* dumb_load_mtm_quick(): loads a MTM file into a DUH struct, returning a /* dumb_load_mtm_quick(): loads a MTM file into a DUH struct, returning a
* pointer to the DUH struct. When you have finished with it, you must * pointer to the DUH struct. When you have finished with it, you must
* pass the pointer to unload_duh() so that the memory can be freed. * pass the pointer to unload_duh() so that the memory can be freed.
*/ */
DUH *dumb_load_mtm_quick(const char *filename) DUH *dumb_load_mtm_quick(const char *filename) {
{
DUH *duh; DUH *duh;
DUMBFILE *f = dumbfile_open(filename); DUMBFILE *f = dumbfile_open(filename);

View file

@ -20,14 +20,11 @@
#include "dumb.h" #include "dumb.h"
#include "internal/it.h" #include "internal/it.h"
/* dumb_load_mtm(): loads a MTM file into a DUH struct, returning a pointer /* dumb_load_mtm(): loads a MTM file into a DUH struct, returning a pointer
* to the DUH struct. When you have finished with it, you must pass the * to the DUH struct. When you have finished with it, you must pass the
* pointer to unload_duh() so that the memory can be freed. * pointer to unload_duh() so that the memory can be freed.
*/ */
DUH *dumb_load_mtm(const char *filename) DUH *dumb_load_mtm(const char *filename) {
{
DUH *duh = dumb_load_mtm_quick(filename); DUH *duh = dumb_load_mtm_quick(filename);
dumb_it_do_initial_runthrough(duh); dumb_it_do_initial_runthrough(duh);
return duh; return duh;

View file

@ -20,14 +20,11 @@
#include "dumb.h" #include "dumb.h"
#include "internal/it.h" #include "internal/it.h"
/* dumb_load_okt_quick(): loads an OKT file into a DUH struct, returning a /* dumb_load_okt_quick(): loads an OKT file into a DUH struct, returning a
* pointer to the DUH struct. When you have finished with it, you must * pointer to the DUH struct. When you have finished with it, you must
* pass the pointer to unload_duh() so that the memory can be freed. * pass the pointer to unload_duh() so that the memory can be freed.
*/ */
DUH *dumb_load_okt_quick(const char *filename) DUH *dumb_load_okt_quick(const char *filename) {
{
DUH *duh; DUH *duh;
DUMBFILE *f = dumbfile_open(filename); DUMBFILE *f = dumbfile_open(filename);

View file

@ -19,10 +19,7 @@
#include "dumb.h" #include "dumb.h"
DUH *dumb_load_okt(const char *filename) {
DUH *dumb_load_okt(const char *filename)
{
DUH *duh = dumb_load_okt_quick(filename); DUH *duh = dumb_load_okt_quick(filename);
dumb_it_do_initial_runthrough(duh); dumb_it_do_initial_runthrough(duh);
return duh; return duh;

View file

@ -20,15 +20,12 @@
#include "dumb.h" #include "dumb.h"
#include "internal/it.h" #include "internal/it.h"
/* dumb_load_old_psm_quick(): loads an old PSM file into a DUH struct, /* dumb_load_old_psm_quick(): loads an old PSM file into a DUH struct,
* returning a pointer to the DUH struct. When you have finished with it, * returning a pointer to the DUH struct. When you have finished with it,
* you must pass the pointer to unload_duh() so that the memory can be * you must pass the pointer to unload_duh() so that the memory can be
* freed. * freed.
*/ */
DUH *dumb_load_old_psm_quick(const char *filename) DUH *dumb_load_old_psm_quick(const char *filename) {
{
DUH *duh; DUH *duh;
DUMBFILE *f = dumbfile_open(filename); DUMBFILE *f = dumbfile_open(filename);

View file

@ -20,14 +20,11 @@
#include "dumb.h" #include "dumb.h"
#include "internal/it.h" #include "internal/it.h"
/* dumb_load_old_psm(): loads an old PSM file into a DUH struct, returning /* dumb_load_old_psm(): loads an old PSM file into a DUH struct, returning
* a pointer to the DUH struct. When you have finished with it, you must * a pointer to the DUH struct. When you have finished with it, you must
* pass the pointer to unload_duh() so that the memory can be freed. * pass the pointer to unload_duh() so that the memory can be freed.
*/ */
DUH *dumb_load_old_psm(const char *filename) DUH *dumb_load_old_psm(const char *filename) {
{
DUH *duh = dumb_load_old_psm_quick(filename); DUH *duh = dumb_load_old_psm_quick(filename);
dumb_it_do_initial_runthrough(duh); dumb_it_do_initial_runthrough(duh);
return duh; return duh;

View file

@ -20,14 +20,11 @@
#include "dumb.h" #include "dumb.h"
#include "internal/it.h" #include "internal/it.h"
/* dumb_load_psm_quick(): loads a PSM file into a DUH struct, returning a /* dumb_load_psm_quick(): loads a PSM file into a DUH struct, returning a
* pointer to the DUH struct. When you have finished with it, you must * pointer to the DUH struct. When you have finished with it, you must
* pass the pointer to unload_duh() so that the memory can be freed. * pass the pointer to unload_duh() so that the memory can be freed.
*/ */
DUH *dumb_load_psm_quick(const char *filename, int subsong) DUH *dumb_load_psm_quick(const char *filename, int subsong) {
{
DUH *duh; DUH *duh;
DUMBFILE *f = dumbfile_open(filename); DUMBFILE *f = dumbfile_open(filename);

View file

@ -20,14 +20,11 @@
#include "dumb.h" #include "dumb.h"
#include "internal/it.h" #include "internal/it.h"
/* dumb_load_psm(): loads a PSM file into a DUH struct, returning a pointer /* dumb_load_psm(): loads a PSM file into a DUH struct, returning a pointer
* to the DUH struct. When you have finished with it, you must pass the * to the DUH struct. When you have finished with it, you must pass the
* pointer to unload_duh() so that the memory can be freed. * pointer to unload_duh() so that the memory can be freed.
*/ */
DUH *dumb_load_psm(const char *filename, int subsong) DUH *dumb_load_psm(const char *filename, int subsong) {
{
DUH *duh = dumb_load_psm_quick(filename, subsong); DUH *duh = dumb_load_psm_quick(filename, subsong);
dumb_it_do_initial_runthrough(duh); dumb_it_do_initial_runthrough(duh);
return duh; return duh;

View file

@ -20,14 +20,11 @@
#include "dumb.h" #include "dumb.h"
#include "internal/it.h" #include "internal/it.h"
/* dumb_load_ptm_quick(): loads a PTM file into a DUH struct, returning a /* dumb_load_ptm_quick(): loads a PTM file into a DUH struct, returning a
* pointer to the DUH struct. When you have finished with it, you must * pointer to the DUH struct. When you have finished with it, you must
* pass the pointer to unload_duh() so that the memory can be freed. * pass the pointer to unload_duh() so that the memory can be freed.
*/ */
DUH *dumb_load_ptm_quick(const char *filename) DUH *dumb_load_ptm_quick(const char *filename) {
{
DUH *duh; DUH *duh;
DUMBFILE *f = dumbfile_open(filename); DUMBFILE *f = dumbfile_open(filename);

View file

@ -20,14 +20,11 @@
#include "dumb.h" #include "dumb.h"
#include "internal/it.h" #include "internal/it.h"
/* dumb_load_ptm(): loads a PTM file into a DUH struct, returning a pointer /* dumb_load_ptm(): loads a PTM file into a DUH struct, returning a pointer
* to the DUH struct. When you have finished with it, you must pass the * to the DUH struct. When you have finished with it, you must pass the
* pointer to unload_duh() so that the memory can be freed. * pointer to unload_duh() so that the memory can be freed.
*/ */
DUH *dumb_load_ptm(const char *filename) DUH *dumb_load_ptm(const char *filename) {
{
DUH *duh = dumb_load_ptm_quick(filename); DUH *duh = dumb_load_ptm_quick(filename);
dumb_it_do_initial_runthrough(duh); dumb_it_do_initial_runthrough(duh);
return duh; return duh;

View file

@ -20,23 +20,20 @@
#include "dumb.h" #include "dumb.h"
#include "internal/it.h" #include "internal/it.h"
/* dumb_load_riff_quick(): loads a RIFF file into a DUH struct, returning /* dumb_load_riff_quick(): loads a RIFF file into a DUH struct, returning
* a pointer to the DUH struct. When you have finished with it, you must * a pointer to the DUH struct. When you have finished with it, you must
* pass the pointer to unload_duh() so that the memory can be freed. * pass the pointer to unload_duh() so that the memory can be freed.
*/ */
DUH * dumb_load_riff_quick( const char *filename ) DUH *dumb_load_riff_quick(const char *filename) {
{ DUH *duh;
DUH * duh; DUMBFILE *f = dumbfile_open(filename);
DUMBFILE * f = dumbfile_open( filename );
if ( ! f ) if (!f)
return NULL; return NULL;
duh = dumb_read_riff_quick( f ); duh = dumb_read_riff_quick(f);
dumbfile_close( f ); dumbfile_close(f);
return duh; return duh;
} }

View file

@ -19,10 +19,7 @@
#include "dumb.h" #include "dumb.h"
DUH *dumb_load_riff(const char *filename) {
DUH *dumb_load_riff(const char *filename)
{
DUH *duh = dumb_load_riff_quick(filename); DUH *duh = dumb_load_riff_quick(filename);
dumb_it_do_initial_runthrough(duh); dumb_it_do_initial_runthrough(duh);
return duh; return duh;

View file

@ -20,14 +20,11 @@
#include "dumb.h" #include "dumb.h"
#include "internal/it.h" #include "internal/it.h"
/* dumb_load_s3m_quick(): loads an S3M file into a DUH struct, returning /* dumb_load_s3m_quick(): loads an S3M file into a DUH struct, returning
* a pointer to the DUH struct. When you have finished with it, you must * a pointer to the DUH struct. When you have finished with it, you must
* pass the pointer to unload_duh() so that the memory can be freed. * pass the pointer to unload_duh() so that the memory can be freed.
*/ */
DUH *dumb_load_s3m_quick(const char *filename) DUH *dumb_load_s3m_quick(const char *filename) {
{
DUH *duh; DUH *duh;
DUMBFILE *f = dumbfile_open(filename); DUMBFILE *f = dumbfile_open(filename);

View file

@ -19,10 +19,7 @@
#include "dumb.h" #include "dumb.h"
DUH *dumb_load_s3m(const char *filename) {
DUH *dumb_load_s3m(const char *filename)
{
DUH *duh = dumb_load_s3m_quick(filename); DUH *duh = dumb_load_s3m_quick(filename);
dumb_it_do_initial_runthrough(duh); dumb_it_do_initial_runthrough(duh);
return duh; return duh;

View file

@ -20,14 +20,11 @@
#include "dumb.h" #include "dumb.h"
#include "internal/it.h" #include "internal/it.h"
/* dumb_load_stm_quick(): loads an STM file into a DUH struct, returning a /* dumb_load_stm_quick(): loads an STM file into a DUH struct, returning a
* pointer to the DUH struct. When you have finished with it, you must * pointer to the DUH struct. When you have finished with it, you must
* pass the pointer to unload_duh() so that the memory can be freed. * pass the pointer to unload_duh() so that the memory can be freed.
*/ */
DUH *dumb_load_stm_quick(const char *filename) DUH *dumb_load_stm_quick(const char *filename) {
{
DUH *duh; DUH *duh;
DUMBFILE *f = dumbfile_open(filename); DUMBFILE *f = dumbfile_open(filename);

View file

@ -19,10 +19,7 @@
#include "dumb.h" #include "dumb.h"
DUH *dumb_load_stm(const char *filename) {
DUH *dumb_load_stm(const char *filename)
{
DUH *duh = dumb_load_stm_quick(filename); DUH *duh = dumb_load_stm_quick(filename);
dumb_it_do_initial_runthrough(duh); dumb_it_do_initial_runthrough(duh);
return duh; return duh;

View file

@ -20,14 +20,11 @@
#include "dumb.h" #include "dumb.h"
#include "internal/it.h" #include "internal/it.h"
/* dumb_load_xm_quick(): loads an XM file into a DUH struct, returning a /* dumb_load_xm_quick(): loads an XM file into a DUH struct, returning a
* pointer to the DUH struct. When you have finished with it, you must * pointer to the DUH struct. When you have finished with it, you must
* pass the pointer to unload_duh() so that the memory can be freed. * pass the pointer to unload_duh() so that the memory can be freed.
*/ */
DUH *dumb_load_xm_quick(const char *filename) DUH *dumb_load_xm_quick(const char *filename) {
{
DUH *duh; DUH *duh;
DUMBFILE *f = dumbfile_open(filename); DUMBFILE *f = dumbfile_open(filename);

View file

@ -19,10 +19,7 @@
#include "dumb.h" #include "dumb.h"
DUH *dumb_load_xm(const char *filename) {
DUH *dumb_load_xm(const char *filename)
{
DUH *duh = dumb_load_xm_quick(filename); DUH *duh = dumb_load_xm_quick(filename);
dumb_it_do_initial_runthrough(duh); dumb_it_do_initial_runthrough(duh);
return duh; return duh;

View file

@ -17,16 +17,13 @@
* \__/ * \__/
*/ */
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include "dumb.h" #include "dumb.h"
#include "internal/it.h" #include "internal/it.h"
void _dumb_it_ptm_convert_effect(int effect, int value, IT_ENTRY *entry) void _dumb_it_ptm_convert_effect(int effect, int value, IT_ENTRY *entry) {
{
if (effect >= PTM_N_EFFECTS) if (effect >= PTM_N_EFFECTS)
return; return;
@ -40,41 +37,93 @@ void _dumb_it_ptm_convert_effect(int effect, int value, IT_ENTRY *entry)
entry->mask |= IT_ENTRY_EFFECT; entry->mask |= IT_ENTRY_EFFECT;
switch (effect) { switch (effect) {
case PTM_APPREGIO: effect = IT_ARPEGGIO; break; case PTM_APPREGIO:
case PTM_PORTAMENTO_UP: effect = IT_PORTAMENTO_UP; break; effect = IT_ARPEGGIO;
case PTM_PORTAMENTO_DOWN: effect = IT_PORTAMENTO_DOWN; break; break;
case PTM_TONE_PORTAMENTO: effect = IT_TONE_PORTAMENTO; break; case PTM_PORTAMENTO_UP:
case PTM_VIBRATO: effect = IT_VIBRATO; break; effect = IT_PORTAMENTO_UP;
case PTM_VOLSLIDE_TONEPORTA: effect = IT_VOLSLIDE_TONEPORTA; break; break;
case PTM_VOLSLIDE_VIBRATO: effect = IT_VOLSLIDE_VIBRATO; break; case PTM_PORTAMENTO_DOWN:
case PTM_TREMOLO: effect = IT_TREMOLO; break; effect = IT_PORTAMENTO_DOWN;
case PTM_SAMPLE_OFFSET: effect = IT_SET_SAMPLE_OFFSET; break; break;
case PTM_VOLUME_SLIDE: effect = IT_VOLUME_SLIDE; break; case PTM_TONE_PORTAMENTO:
case PTM_POSITION_JUMP: effect = IT_JUMP_TO_ORDER; break; effect = IT_TONE_PORTAMENTO;
case PTM_SET_CHANNEL_VOLUME: effect = IT_SET_CHANNEL_VOLUME; break; break;
case PTM_PATTERN_BREAK: effect = IT_BREAK_TO_ROW; break; case PTM_VIBRATO:
case PTM_SET_GLOBAL_VOLUME: effect = IT_SET_GLOBAL_VOLUME; break; effect = IT_VIBRATO;
case PTM_RETRIGGER: effect = IT_RETRIGGER_NOTE; break; break;
case PTM_FINE_VIBRATO: effect = IT_FINE_VIBRATO; break; case PTM_VOLSLIDE_TONEPORTA:
effect = IT_VOLSLIDE_TONEPORTA;
break;
case PTM_VOLSLIDE_VIBRATO:
effect = IT_VOLSLIDE_VIBRATO;
break;
case PTM_TREMOLO:
effect = IT_TREMOLO;
break;
case PTM_SAMPLE_OFFSET:
effect = IT_SET_SAMPLE_OFFSET;
break;
case PTM_VOLUME_SLIDE:
effect = IT_VOLUME_SLIDE;
break;
case PTM_POSITION_JUMP:
effect = IT_JUMP_TO_ORDER;
break;
case PTM_SET_CHANNEL_VOLUME:
effect = IT_SET_CHANNEL_VOLUME;
break;
case PTM_PATTERN_BREAK:
effect = IT_BREAK_TO_ROW;
break;
case PTM_SET_GLOBAL_VOLUME:
effect = IT_SET_GLOBAL_VOLUME;
break;
case PTM_RETRIGGER:
effect = IT_RETRIGGER_NOTE;
break;
case PTM_FINE_VIBRATO:
effect = IT_FINE_VIBRATO;
break;
/* TODO properly */ /* TODO properly */
case PTM_NOTE_SLIDE_UP: effect = IT_PTM_NOTE_SLIDE_UP; break; case PTM_NOTE_SLIDE_UP:
case PTM_NOTE_SLIDE_DOWN: effect = IT_PTM_NOTE_SLIDE_DOWN; break; effect = IT_PTM_NOTE_SLIDE_UP;
case PTM_NOTE_SLIDE_UP_RETRIG: effect = IT_PTM_NOTE_SLIDE_UP_RETRIG; break; break;
case PTM_NOTE_SLIDE_DOWN_RETRIG: effect = IT_PTM_NOTE_SLIDE_DOWN_RETRIG; break; case PTM_NOTE_SLIDE_DOWN:
effect = IT_PTM_NOTE_SLIDE_DOWN;
break;
case PTM_NOTE_SLIDE_UP_RETRIG:
effect = IT_PTM_NOTE_SLIDE_UP_RETRIG;
break;
case PTM_NOTE_SLIDE_DOWN_RETRIG:
effect = IT_PTM_NOTE_SLIDE_DOWN_RETRIG;
break;
case PTM_SET_TEMPO_BPM: case PTM_SET_TEMPO_BPM:
effect = (value < 0x20) ? (IT_SET_SPEED) : (IT_SET_SONG_TEMPO); effect = (value < 0x20) ? (IT_SET_SPEED) : (IT_SET_SONG_TEMPO);
break; break;
case PTM_EBASE+PTM_E_SET_FINETUNE: effect = SBASE+IT_S_FINETUNE; break; /** TODO */ case PTM_EBASE + PTM_E_SET_FINETUNE:
case PTM_EBASE+PTM_E_SET_LOOP: effect = SBASE+IT_S_PATTERN_LOOP; break; effect = SBASE + IT_S_FINETUNE;
case PTM_EBASE+PTM_E_NOTE_CUT: effect = SBASE+IT_S_DELAYED_NOTE_CUT; break; break; /** TODO */
case PTM_EBASE+PTM_E_NOTE_DELAY: effect = SBASE+IT_S_NOTE_DELAY; break; case PTM_EBASE + PTM_E_SET_LOOP:
case PTM_EBASE+PTM_E_PATTERN_DELAY: effect = SBASE+IT_S_PATTERN_DELAY; break; effect = SBASE + IT_S_PATTERN_LOOP;
case PTM_EBASE+PTM_E_SET_PANNING: effect = SBASE+IT_S_SET_PAN; break; break;
case PTM_EBASE + PTM_E_NOTE_CUT:
effect = SBASE + IT_S_DELAYED_NOTE_CUT;
break;
case PTM_EBASE + PTM_E_NOTE_DELAY:
effect = SBASE + IT_S_NOTE_DELAY;
break;
case PTM_EBASE + PTM_E_PATTERN_DELAY:
effect = SBASE + IT_S_PATTERN_DELAY;
break;
case PTM_EBASE + PTM_E_SET_PANNING:
effect = SBASE + IT_S_SET_PAN;
break;
case PTM_EBASE+PTM_E_FINE_VOLSLIDE_UP: case PTM_EBASE + PTM_E_FINE_VOLSLIDE_UP:
effect = IT_VOLUME_SLIDE; effect = IT_VOLUME_SLIDE;
value = EFFECT_VALUE(value, 0xF); value = EFFECT_VALUE(value, 0xF);
break; break;
@ -100,12 +149,12 @@ void _dumb_it_ptm_convert_effect(int effect, int value, IT_ENTRY *entry)
break; break;
case PTM_EBASE + PTM_E_SET_VIBRATO_CONTROL: case PTM_EBASE + PTM_E_SET_VIBRATO_CONTROL:
effect = SBASE+IT_S_SET_VIBRATO_WAVEFORM; effect = SBASE + IT_S_SET_VIBRATO_WAVEFORM;
value &= ~4; /** TODO: value&4 -> don't retrig wave */ value &= ~4; /** TODO: value&4 -> don't retrig wave */
break; break;
case PTM_EBASE + PTM_E_SET_TREMOLO_CONTROL: case PTM_EBASE + PTM_E_SET_TREMOLO_CONTROL:
effect = SBASE+IT_S_SET_TREMOLO_WAVEFORM; effect = SBASE + IT_S_SET_TREMOLO_WAVEFORM;
value &= ~4; /** TODO: value&4 -> don't retrig wave */ value &= ~4; /** TODO: value&4 -> don't retrig wave */
break; break;
@ -115,8 +164,8 @@ void _dumb_it_ptm_convert_effect(int effect, int value, IT_ENTRY *entry)
} }
/* Inverse linearisation... */ /* Inverse linearisation... */
if (effect >= SBASE && effect < SBASE+16) { if (effect >= SBASE && effect < SBASE + 16) {
value = EFFECT_VALUE(effect-SBASE, value); value = EFFECT_VALUE(effect - SBASE, value);
effect = IT_S; effect = IT_S;
} }

View file

@ -24,10 +24,9 @@
#include "dumb.h" #include "dumb.h"
#include "internal/it.h" #include "internal/it.h"
static int it_669_read_pattern(IT_PATTERN *pattern, DUMBFILE *f, int tempo,
int breakpoint, unsigned char *buffer,
static int it_669_read_pattern(IT_PATTERN *pattern, DUMBFILE *f, int tempo, int breakpoint, unsigned char *buffer, int * used_channels) int *used_channels) {
{
int pos; int pos;
int channel; int channel;
int row; int row;
@ -39,13 +38,15 @@ static int it_669_read_pattern(IT_PATTERN *pattern, DUMBFILE *f, int tempo, int
return -1; return -1;
/* compute number of entries */ /* compute number of entries */
pattern->n_entries = 64 + 1; /* Account for the row end markers, speed command */ pattern->n_entries =
if (breakpoint < 63) pattern->n_entries++; /* and break to row 0 */ 64 + 1; /* Account for the row end markers, speed command */
if (breakpoint < 63)
pattern->n_entries++; /* and break to row 0 */
pos = 0; pos = 0;
for (row = 0; row < 64; row++) { for (row = 0; row < 64; row++) {
for (channel = 0; channel < 8; channel++) { for (channel = 0; channel < 8; channel++) {
if (buffer[pos+0] != 0xFF || buffer[pos+2] != 0xFF) if (buffer[pos + 0] != 0xFF || buffer[pos + 2] != 0xFF)
pattern->n_entries++; pattern->n_entries++;
pos += 3; pos += 3;
} }
@ -55,7 +56,8 @@ static int it_669_read_pattern(IT_PATTERN *pattern, DUMBFILE *f, int tempo, int
if (!pattern->entry) if (!pattern->entry)
return -1; return -1;
if (breakpoint == 63) breakpoint++; if (breakpoint == 63)
breakpoint++;
entry = pattern->entry; entry = pattern->entry;
@ -77,24 +79,28 @@ static int it_669_read_pattern(IT_PATTERN *pattern, DUMBFILE *f, int tempo, int
} }
for (channel = 0; channel < 8; channel++) { for (channel = 0; channel < 8; channel++) {
if (buffer[pos+0] != 0xFF || buffer[pos+2] != 0xFF) { if (buffer[pos + 0] != 0xFF || buffer[pos + 2] != 0xFF) {
entry->channel = channel; entry->channel = channel;
entry->mask = 0; entry->mask = 0;
if (buffer[pos+0] < 0xFE) { if (buffer[pos + 0] < 0xFE) {
entry->mask |= IT_ENTRY_NOTE | IT_ENTRY_INSTRUMENT; entry->mask |= IT_ENTRY_NOTE | IT_ENTRY_INSTRUMENT;
entry->note = (buffer[pos+0] >> 2) + 36; entry->note = (buffer[pos + 0] >> 2) + 36;
entry->instrument = (((buffer[pos+0] << 4) | (buffer[pos+1] >> 4)) & 0x3F) + 1; entry->instrument =
(((buffer[pos + 0] << 4) | (buffer[pos + 1] >> 4)) &
0x3F) +
1;
} }
if (buffer[pos+0] <= 0xFE) { if (buffer[pos + 0] <= 0xFE) {
entry->mask |= IT_ENTRY_VOLPAN; entry->mask |= IT_ENTRY_VOLPAN;
entry->volpan = ((buffer[pos+1] & 15) << 6) / 15; entry->volpan = ((buffer[pos + 1] & 15) << 6) / 15;
if (*used_channels < channel + 1) *used_channels = channel + 1; if (*used_channels < channel + 1)
*used_channels = channel + 1;
} }
if (buffer[pos+2] != 0xFF) { if (buffer[pos + 2] != 0xFF) {
entry->mask |= IT_ENTRY_EFFECT; entry->mask |= IT_ENTRY_EFFECT;
entry->effectvalue = buffer[pos+2] & 15; entry->effectvalue = buffer[pos + 2] & 15;
switch (buffer[pos+2] >> 4) { switch (buffer[pos + 2] >> 4) {
case 0: case 0:
entry->effect = IT_PORTAMENTO_UP; entry->effect = IT_PORTAMENTO_UP;
break; break;
@ -138,7 +144,8 @@ static int it_669_read_pattern(IT_PATTERN *pattern, DUMBFILE *f, int tempo, int
entry->mask &= ~IT_ENTRY_EFFECT; entry->mask &= ~IT_ENTRY_EFFECT;
break; break;
} }
if (*used_channels < channel + 1) *used_channels = channel + 1; if (*used_channels < channel + 1)
*used_channels = channel + 1;
} }
entry++; entry++;
@ -152,10 +159,7 @@ static int it_669_read_pattern(IT_PATTERN *pattern, DUMBFILE *f, int tempo, int
return 0; return 0;
} }
static int it_669_read_sample_header(IT_SAMPLE *sample, DUMBFILE *f) {
static int it_669_read_sample_header(IT_SAMPLE *sample, DUMBFILE *f)
{
dumbfile_getnc((char *)sample->name, 13, f); dumbfile_getnc((char *)sample->name, 13, f);
sample->name[13] = 0; sample->name[13] = 0;
@ -201,10 +205,7 @@ static int it_669_read_sample_header(IT_SAMPLE *sample, DUMBFILE *f)
return 0; return 0;
} }
static int it_669_read_sample_data(IT_SAMPLE *sample, DUMBFILE *f) {
static int it_669_read_sample_data(IT_SAMPLE *sample, DUMBFILE *f)
{
long i; long i;
long truncated_size; long truncated_size;
@ -221,19 +222,19 @@ static int it_669_read_sample_data(IT_SAMPLE *sample, DUMBFILE *f)
if (!sample->data) if (!sample->data)
return -1; return -1;
if (sample->length) if (sample->length) {
{
i = dumbfile_getnc(sample->data, sample->length, f); i = dumbfile_getnc(sample->data, sample->length, f);
if (i < sample->length) { if (i < sample->length) {
//return -1; // return -1;
// ficking truncated files // ficking truncated files
if (i <= 0) { if (i <= 0) {
sample->flags = 0; sample->flags = 0;
return 0; return 0;
} }
sample->length = i; sample->length = i;
if (sample->loop_end > i) sample->loop_end = i; if (sample->loop_end > i)
sample->loop_end = i;
} else { } else {
/* skip truncated data */ /* skip truncated data */
dumbfile_skip(f, truncated_size); dumbfile_skip(f, truncated_size);
@ -249,9 +250,7 @@ static int it_669_read_sample_data(IT_SAMPLE *sample, DUMBFILE *f)
return 0; return 0;
} }
static DUMB_IT_SIGDATA *it_669_load_sigdata(DUMBFILE *f, int *ext) {
static DUMB_IT_SIGDATA *it_669_load_sigdata(DUMBFILE *f, int * ext)
{
DUMB_IT_SIGDATA *sigdata; DUMB_IT_SIGDATA *sigdata;
int n_channels; int n_channels;
int i; int i;
@ -259,7 +258,8 @@ static DUMB_IT_SIGDATA *it_669_load_sigdata(DUMBFILE *f, int * ext)
unsigned char breaklist[128]; unsigned char breaklist[128];
i = dumbfile_igetw(f); i = dumbfile_igetw(f);
if (i != 0x6669 && i != 0x4E4A) return NULL; if (i != 0x6669 && i != 0x4E4A)
return NULL;
*ext = (i == 0x4E4A); *ext = (i == 0x4E4A);
@ -320,7 +320,8 @@ static DUMB_IT_SIGDATA *it_669_load_sigdata(DUMBFILE *f, int * ext)
} }
for (i = 0; i < 128; i++) { for (i = 0; i < 128; i++) {
if (sigdata->order[i] == 255) break; if (sigdata->order[i] == 255)
break;
if (sigdata->order[i] >= sigdata->n_patterns) { if (sigdata->order[i] >= sigdata->n_patterns) {
_dumb_it_unload_sigdata(sigdata); _dumb_it_unload_sigdata(sigdata);
return NULL; return NULL;
@ -361,7 +362,8 @@ static DUMB_IT_SIGDATA *it_669_load_sigdata(DUMBFILE *f, int * ext)
/* May as well try to save a tiny bit of memory. */ /* May as well try to save a tiny bit of memory. */
if (sigdata->n_orders < 128) { if (sigdata->n_orders < 128) {
unsigned char *order = realloc(sigdata->order, sigdata->n_orders); unsigned char *order = realloc(sigdata->order, sigdata->n_orders);
if (order) sigdata->order = order; if (order)
sigdata->order = order;
} }
sigdata->pattern = malloc(sigdata->n_patterns * sizeof(*sigdata->pattern)); sigdata->pattern = malloc(sigdata->n_patterns * sizeof(*sigdata->pattern));
@ -376,13 +378,15 @@ static DUMB_IT_SIGDATA *it_669_load_sigdata(DUMBFILE *f, int * ext)
/* Read in the patterns */ /* Read in the patterns */
{ {
unsigned char *buffer = malloc(64 * 3 * 8); /* 64 rows * 3 bytes * 8 channels */ unsigned char *buffer =
malloc(64 * 3 * 8); /* 64 rows * 3 bytes * 8 channels */
if (!buffer) { if (!buffer) {
_dumb_it_unload_sigdata(sigdata); _dumb_it_unload_sigdata(sigdata);
return NULL; return NULL;
} }
for (i = 0; i < sigdata->n_patterns; i++) { for (i = 0; i < sigdata->n_patterns; i++) {
if (it_669_read_pattern(&sigdata->pattern[i], f, tempolist[i], breaklist[i], buffer, &n_channels) != 0) { if (it_669_read_pattern(&sigdata->pattern[i], f, tempolist[i],
breaklist[i], buffer, &n_channels) != 0) {
free(buffer); free(buffer);
_dumb_it_unload_sigdata(sigdata); _dumb_it_unload_sigdata(sigdata);
return NULL; return NULL;
@ -402,7 +406,8 @@ static DUMB_IT_SIGDATA *it_669_load_sigdata(DUMBFILE *f, int * ext)
} }
/* Now let's initialise the remaining variables, and we're done! */ /* Now let's initialise the remaining variables, and we're done! */
sigdata->flags = IT_OLD_EFFECTS | IT_LINEAR_SLIDES | IT_STEREO | IT_WAS_A_669; sigdata->flags =
IT_OLD_EFFECTS | IT_LINEAR_SLIDES | IT_STEREO | IT_WAS_A_669;
sigdata->global_volume = 128; sigdata->global_volume = 128;
sigdata->mixing_volume = 48; sigdata->mixing_volume = 48;
@ -414,8 +419,8 @@ static DUMB_IT_SIGDATA *it_669_load_sigdata(DUMBFILE *f, int * ext)
for (i = 0; i < DUMB_IT_N_CHANNELS; i += 2) { for (i = 0; i < DUMB_IT_N_CHANNELS; i += 2) {
int sep = 32 * dumb_it_default_panning_separation / 100; int sep = 32 * dumb_it_default_panning_separation / 100;
sigdata->channel_pan[i+0] = 32 + sep; sigdata->channel_pan[i + 0] = 32 + sep;
sigdata->channel_pan[i+1] = 32 - sep; sigdata->channel_pan[i + 1] = 32 - sep;
} }
_dumb_it_fix_invalid_orders(sigdata); _dumb_it_fix_invalid_orders(sigdata);
@ -423,10 +428,7 @@ static DUMB_IT_SIGDATA *it_669_load_sigdata(DUMBFILE *f, int * ext)
return sigdata; return sigdata;
} }
DUH *dumb_read_669_quick(DUMBFILE *f) {
DUH *dumb_read_669_quick(DUMBFILE *f)
{
sigdata_t *sigdata; sigdata_t *sigdata;
int ext; int ext;
@ -443,6 +445,7 @@ DUH *dumb_read_669_quick(DUMBFILE *f)
tag[0][1] = (const char *)(((DUMB_IT_SIGDATA *)sigdata)->name); tag[0][1] = (const char *)(((DUMB_IT_SIGDATA *)sigdata)->name);
tag[1][0] = "FORMAT"; tag[1][0] = "FORMAT";
tag[1][1] = ext ? "669 Extended" : "669"; tag[1][1] = ext ? "669 Extended" : "669";
return make_duh(-1, 2, (const char *const (*)[2])tag, 1, &descptr, &sigdata); return make_duh(-1, 2, (const char *const(*)[2])tag, 1, &descptr,
&sigdata);
} }
} }

View file

@ -19,10 +19,7 @@
#include "dumb.h" #include "dumb.h"
DUH *dumb_read_669(DUMBFILE *f) {
DUH *dumb_read_669(DUMBFILE *f)
{
DUH *duh = dumb_read_669_quick(f); DUH *duh = dumb_read_669_quick(f);
dumb_it_do_initial_runthrough(duh); dumb_it_do_initial_runthrough(duh);
return duh; return duh;

File diff suppressed because it is too large Load diff

View file

@ -24,135 +24,160 @@
#include "dumb.h" #include "dumb.h"
#include "internal/it.h" #include "internal/it.h"
static void it_amf_process_track(IT_ENTRY *entry_table, unsigned char *track,
int rows, int channels) {
static void it_amf_process_track( IT_ENTRY *entry_table, unsigned char *track, int rows, int channels )
{
int last_instrument = 0; int last_instrument = 0;
int tracksize = track[ 0 ] + ( track[ 1 ] << 8 ) + ( track[ 2 ] << 16 ); int tracksize = track[0] + (track[1] << 8) + (track[2] << 16);
track += 3; track += 3;
while ( tracksize-- ) { while (tracksize--) {
unsigned int row = track[ 0 ]; unsigned int row = track[0];
unsigned int command = track[ 1 ]; unsigned int command = track[1];
unsigned int argument = track[ 2 ]; unsigned int argument = track[2];
IT_ENTRY * entry = entry_table + row * channels; IT_ENTRY *entry = entry_table + row * channels;
if ( row >= ( unsigned int ) rows ) break; if (row >= (unsigned int)rows)
if ( command < 0x7F ) { break;
entry->mask |= IT_ENTRY_NOTE | IT_ENTRY_INSTRUMENT | IT_ENTRY_VOLPAN; if (command < 0x7F) {
entry->mask |=
IT_ENTRY_NOTE | IT_ENTRY_INSTRUMENT | IT_ENTRY_VOLPAN;
entry->note = command; entry->note = command;
if ( ! entry->instrument ) entry->instrument = last_instrument; if (!entry->instrument)
entry->instrument = last_instrument;
entry->volpan = argument; entry->volpan = argument;
} else if (command == 0x7F) {
signed char row_delta = (signed char)argument;
int row_source = (int)row + (int)row_delta;
if (row_source >= 0 && row_source < (int)rows) {
*entry = entry_table[row_source * channels];
} }
else if ( command == 0x7F ) { } else if (command == 0x80) {
signed char row_delta = ( signed char ) argument;
int row_source = ( int ) row + ( int ) row_delta;
if ( row_source >= 0 && row_source < ( int ) rows ) {
*entry = entry_table[ row_source * channels ];
}
}
else if ( command == 0x80 ) {
entry->mask |= IT_ENTRY_INSTRUMENT; entry->mask |= IT_ENTRY_INSTRUMENT;
last_instrument = argument + 1; last_instrument = argument + 1;
entry->instrument = last_instrument; entry->instrument = last_instrument;
} } else if (command == 0x83) {
else if ( command == 0x83 ) {
entry->mask |= IT_ENTRY_VOLPAN; entry->mask |= IT_ENTRY_VOLPAN;
entry->volpan = argument; entry->volpan = argument;
} } else {
else {
unsigned int effect = command & 0x7F; unsigned int effect = command & 0x7F;
unsigned int effectvalue = argument; unsigned int effectvalue = argument;
switch (effect) { switch (effect) {
case 0x01: effect = IT_SET_SPEED; break; case 0x01:
effect = IT_SET_SPEED;
break;
case 0x02: effect = IT_VOLUME_SLIDE; case 0x02:
case 0x0A: if ( effect == 0x0A ) effect = IT_VOLSLIDE_TONEPORTA; effect = IT_VOLUME_SLIDE;
case 0x0B: if ( effect == 0x0B ) effect = IT_VOLSLIDE_VIBRATO; case 0x0A:
if ( effectvalue & 0x80 ) effectvalue = ( -( signed char ) effectvalue ) & 0x0F; if (effect == 0x0A)
else effectvalue = ( effectvalue & 0x0F ) << 4; effect = IT_VOLSLIDE_TONEPORTA;
case 0x0B:
if (effect == 0x0B)
effect = IT_VOLSLIDE_VIBRATO;
if (effectvalue & 0x80)
effectvalue = (-(signed char)effectvalue) & 0x0F;
else
effectvalue = (effectvalue & 0x0F) << 4;
break; break;
case 0x04: case 0x04:
if ( effectvalue & 0x80 ) { if (effectvalue & 0x80) {
effect = IT_PORTAMENTO_UP; effect = IT_PORTAMENTO_UP;
effectvalue = ( -( signed char ) effectvalue ) & 0x7F; effectvalue = (-(signed char)effectvalue) & 0x7F;
} } else {
else {
effect = IT_PORTAMENTO_DOWN; effect = IT_PORTAMENTO_DOWN;
} }
break; break;
case 0x06: effect = IT_TONE_PORTAMENTO; break; case 0x06:
effect = IT_TONE_PORTAMENTO;
break;
case 0x07: effect = IT_TREMOR; break; case 0x07:
effect = IT_TREMOR;
break;
case 0x08: effect = IT_ARPEGGIO; break; case 0x08:
effect = IT_ARPEGGIO;
break;
case 0x09: effect = IT_VIBRATO; break; case 0x09:
effect = IT_VIBRATO;
break;
case 0x0C: effect = IT_BREAK_TO_ROW; break; case 0x0C:
effect = IT_BREAK_TO_ROW;
break;
case 0x0D: effect = IT_JUMP_TO_ORDER; break; case 0x0D:
effect = IT_JUMP_TO_ORDER;
break;
case 0x0F: effect = IT_RETRIGGER_NOTE; break; case 0x0F:
effect = IT_RETRIGGER_NOTE;
break;
case 0x10: effect = IT_SET_SAMPLE_OFFSET; break; case 0x10:
effect = IT_SET_SAMPLE_OFFSET;
break;
case 0x11: case 0x11:
if ( effectvalue ) { if (effectvalue) {
effect = IT_VOLUME_SLIDE; effect = IT_VOLUME_SLIDE;
if ( effectvalue & 0x80 ) if (effectvalue & 0x80)
effectvalue = 0xF0 | ( ( -( signed char ) effectvalue ) & 0x0F ); effectvalue =
else 0xF0 | ((-(signed char)effectvalue) & 0x0F);
effectvalue = 0x0F | ( ( effectvalue & 0x0F ) << 4 );
}
else else
effectvalue = 0x0F | ((effectvalue & 0x0F) << 4);
} else
effect = 0; effect = 0;
break; break;
case 0x12: case 0x12:
case 0x16: case 0x16:
if ( effectvalue ) { if (effectvalue) {
int mask = ( effect == 0x16 ) ? 0xE0 : 0xF0; int mask = (effect == 0x16) ? 0xE0 : 0xF0;
effect = ( effectvalue & 0x80 ) ? IT_PORTAMENTO_UP : IT_PORTAMENTO_DOWN; effect = (effectvalue & 0x80) ? IT_PORTAMENTO_UP
if ( effectvalue & 0x80 ) : IT_PORTAMENTO_DOWN;
effectvalue = mask | ( ( -( signed char ) effectvalue ) & 0x0F ); if (effectvalue & 0x80)
else effectvalue =
effectvalue = mask | ( effectvalue & 0x0F ); mask | ((-(signed char)effectvalue) & 0x0F);
}
else else
effectvalue = mask | (effectvalue & 0x0F);
} else
effect = 0; effect = 0;
break; break;
case 0x13: case 0x13:
effect = IT_S; effect = IT_S;
effectvalue = EFFECT_VALUE( IT_S_NOTE_DELAY, effectvalue & 0x0F ); effectvalue = EFFECT_VALUE(IT_S_NOTE_DELAY, effectvalue & 0x0F);
break; break;
case 0x14: case 0x14:
effect = IT_S; effect = IT_S;
effectvalue = EFFECT_VALUE( IT_S_DELAYED_NOTE_CUT, effectvalue & 0x0F ); effectvalue =
EFFECT_VALUE(IT_S_DELAYED_NOTE_CUT, effectvalue & 0x0F);
break; break;
case 0x15: effect = IT_SET_SONG_TEMPO; break; case 0x15:
effect = IT_SET_SONG_TEMPO;
break;
case 0x17: case 0x17:
effectvalue = ( effectvalue + 64 ) & 0x7F; effectvalue = (effectvalue + 64) & 0x7F;
if ( entry->mask & IT_ENTRY_EFFECT ) { if (entry->mask & IT_ENTRY_EFFECT) {
if ( !( entry->mask & IT_ENTRY_VOLPAN ) ) { if (!(entry->mask & IT_ENTRY_VOLPAN)) {
entry->mask |= IT_ENTRY_VOLPAN; entry->mask |= IT_ENTRY_VOLPAN;
entry->volpan = ( effectvalue / 2 ) + 128; entry->volpan = (effectvalue / 2) + 128;
} }
effect = 0; effect = 0;
} } else {
else {
effect = IT_SET_PANNING; effect = IT_SET_PANNING;
} }
break; break;
default: effect = effectvalue = 0; default:
effect = effectvalue = 0;
} }
if ( effect ) { if (effect) {
entry->mask |= IT_ENTRY_EFFECT; entry->mask |= IT_ENTRY_EFFECT;
entry->effect = effect; entry->effect = effect;
entry->effectvalue = effectvalue; entry->effectvalue = effectvalue;
@ -162,70 +187,71 @@ static void it_amf_process_track( IT_ENTRY *entry_table, unsigned char *track, i
} }
} }
static int it_amf_process_pattern( IT_PATTERN *pattern, IT_ENTRY *entry_table, int rows, int channels ) static int it_amf_process_pattern(IT_PATTERN *pattern, IT_ENTRY *entry_table,
{ int rows, int channels) {
int i, j; int i, j;
int n_entries = rows; int n_entries = rows;
IT_ENTRY * entry; IT_ENTRY *entry;
pattern->n_rows = rows; pattern->n_rows = rows;
for ( i = 0, j = channels * rows; i < j; i++ ) { for (i = 0, j = channels * rows; i < j; i++) {
if ( entry_table[ i ].mask ) { if (entry_table[i].mask) {
n_entries++; n_entries++;
} }
} }
pattern->n_entries = n_entries; pattern->n_entries = n_entries;
pattern->entry = entry = malloc( n_entries * sizeof( IT_ENTRY ) ); pattern->entry = entry = malloc(n_entries * sizeof(IT_ENTRY));
if ( !entry ) { if (!entry) {
return -1; return -1;
} }
for ( i = 0; i < rows; i++ ) { for (i = 0; i < rows; i++) {
for ( j = 0; j < channels; j++ ) { for (j = 0; j < channels; j++) {
if ( entry_table[ i * channels + j ].mask ) { if (entry_table[i * channels + j].mask) {
*entry = entry_table[ i * channels + j ]; *entry = entry_table[i * channels + j];
entry->channel = j; entry->channel = j;
entry++; entry++;
} }
} }
IT_SET_END_ROW( entry ); IT_SET_END_ROW(entry);
entry++; entry++;
} }
return 0; return 0;
} }
static int it_amf_read_sample_header( IT_SAMPLE *sample, DUMBFILE *f, int * offset, int ver ) static int it_amf_read_sample_header(IT_SAMPLE *sample, DUMBFILE *f,
{ int *offset, int ver) {
int exists; int exists;
exists = dumbfile_getc( f ); exists = dumbfile_getc(f);
dumbfile_getnc( (char *) sample->name, 32, f ); dumbfile_getnc((char *)sample->name, 32, f);
sample->name[32] = 0; sample->name[32] = 0;
dumbfile_getnc( (char *) sample->filename, 13, f ); dumbfile_getnc((char *)sample->filename, 13, f);
sample->filename[13] = 0; sample->filename[13] = 0;
*offset = (int)dumbfile_igetl( f ); *offset = (int)dumbfile_igetl(f);
sample->length = dumbfile_igetl( f ); sample->length = dumbfile_igetl(f);
sample->C5_speed = dumbfile_igetw( f ); sample->C5_speed = dumbfile_igetw(f);
sample->default_volume = dumbfile_getc( f ); sample->default_volume = dumbfile_getc(f);
sample->global_volume = 64; sample->global_volume = 64;
if ( sample->default_volume > 64 ) sample->default_volume = 64; if (sample->default_volume > 64)
sample->default_volume = 64;
if ( ver >= 11 ) { if (ver >= 11) {
sample->loop_start = dumbfile_igetl( f ); sample->loop_start = dumbfile_igetl(f);
sample->loop_end = dumbfile_igetl( f ); sample->loop_end = dumbfile_igetl(f);
} else { } else {
sample->loop_start = dumbfile_igetw( f ); sample->loop_start = dumbfile_igetw(f);
sample->loop_end = sample->length; sample->loop_end = sample->length;
} }
if ( sample->length <= 0 ) { if (sample->length <= 0) {
sample->flags = 0; sample->flags = 0;
return 0; return 0;
} }
@ -235,7 +261,8 @@ static int it_amf_read_sample_header( IT_SAMPLE *sample, DUMBFILE *f, int * offs
sample->default_pan = 0; sample->default_pan = 0;
sample->finetune = 0; sample->finetune = 0;
if ( sample->loop_end > sample->loop_start + 2 && sample->loop_end <= sample->length ) if (sample->loop_end > sample->loop_start + 2 &&
sample->loop_end <= sample->length)
sample->flags |= IT_SAMPLE_LOOP; sample->flags |= IT_SAMPLE_LOOP;
sample->vibrato_speed = 0; sample->vibrato_speed = 0;
@ -247,36 +274,32 @@ static int it_amf_read_sample_header( IT_SAMPLE *sample, DUMBFILE *f, int * offs
return dumbfile_error(f); return dumbfile_error(f);
} }
static int it_amf_read_sample_data(IT_SAMPLE *sample, DUMBFILE *f) {
static int it_amf_read_sample_data( IT_SAMPLE *sample, DUMBFILE *f )
{
int i, read_length = 0; int i, read_length = 0;
sample->data = malloc( sample->length ); sample->data = malloc(sample->length);
if ( !sample->data ) if (!sample->data)
return -1; return -1;
if ( sample->length ) if (sample->length)
read_length = (int)dumbfile_getnc( sample->data, sample->length, f ); read_length = (int)dumbfile_getnc(sample->data, sample->length, f);
if ( read_length < 0 ) if (read_length < 0)
read_length = 0; read_length = 0;
for ( i = 0; i < read_length; i++ ) { for (i = 0; i < read_length; i++) {
( ( signed char * ) sample->data )[ i ] ^= 0x80; ((signed char *)sample->data)[i] ^= 0x80;
} }
for ( i = read_length; i < sample->length; i++ ) { for (i = read_length; i < sample->length; i++) {
( ( signed char * ) sample->data )[ i ] = 0; ((signed char *)sample->data)[i] = 0;
} }
return 0; /* Sometimes the last sample is truncated :( */ return 0; /* Sometimes the last sample is truncated :( */
} }
static DUMB_IT_SIGDATA *it_amf_load_sigdata(DUMBFILE *f, int * version) static DUMB_IT_SIGDATA *it_amf_load_sigdata(DUMBFILE *f, int *version) {
{
DUMB_IT_SIGDATA *sigdata; DUMB_IT_SIGDATA *sigdata;
int i, j, ver, ntracks, realntracks, nchannels; int i, j, ver, ntracks, realntracks, nchannels;
@ -291,15 +314,14 @@ static DUMB_IT_SIGDATA *it_amf_load_sigdata(DUMBFILE *f, int * version)
static const char sig[] = "AMF"; static const char sig[] = "AMF";
char signature [3]; char signature[3];
if ( dumbfile_getnc( signature, 3, f ) != 3 || if (dumbfile_getnc(signature, 3, f) != 3 || memcmp(signature, sig, 3)) {
memcmp( signature, sig, 3 ) ) {
return NULL; return NULL;
} }
*version = ver = dumbfile_getc( f ); *version = ver = dumbfile_getc(f);
if ( ver < 10 || ver > 14) { if (ver < 10 || ver > 14) {
return NULL; return NULL;
} }
@ -308,88 +330,92 @@ static DUMB_IT_SIGDATA *it_amf_load_sigdata(DUMBFILE *f, int * version)
return NULL; return NULL;
} }
dumbfile_getnc( (char *) sigdata->name, 32, f ); dumbfile_getnc((char *)sigdata->name, 32, f);
sigdata->name[ 32 ] = 0; sigdata->name[32] = 0;
sigdata->n_samples = dumbfile_getc( f ); sigdata->n_samples = dumbfile_getc(f);
sigdata->n_orders = dumbfile_getc( f ); sigdata->n_orders = dumbfile_getc(f);
ntracks = dumbfile_igetw( f ); ntracks = dumbfile_igetw(f);
nchannels = dumbfile_getc( f ); nchannels = dumbfile_getc(f);
if ( dumbfile_error( f ) || if (dumbfile_error(f) || sigdata->n_samples < 1 ||
sigdata->n_samples < 1 || sigdata->n_samples > 255 || sigdata->n_samples > 255 || sigdata->n_orders < 1 ||
sigdata->n_orders < 1 || sigdata->n_orders > 255 || sigdata->n_orders > 255 || !ntracks || nchannels < 1 ||
! ntracks || nchannels > 32) {
nchannels < 1 || nchannels > 32 ) { free(sigdata);
free( sigdata );
return NULL; return NULL;
} }
sigdata->n_pchannels = nchannels; sigdata->n_pchannels = nchannels;
memset( sigdata->channel_volume, 64, DUMB_IT_N_CHANNELS ); memset(sigdata->channel_volume, 64, DUMB_IT_N_CHANNELS);
if ( ver >= 11 ) { if (ver >= 11) {
int nchannels = ( ver >= 13 ) ? 32 : 16; int nchannels = (ver >= 13) ? 32 : 16;
for ( i = 0; i < nchannels; i++ ) { for (i = 0; i < nchannels; i++) {
signed char panpos = dumbfile_getc( f ); signed char panpos = dumbfile_getc(f);
int pan = ( panpos + 64 ) / 2; int pan = (panpos + 64) / 2;
if ( pan < 0 ) pan = 0; if (pan < 0)
else if ( pan > 64 ) pan = IT_SURROUND; pan = 0;
sigdata->channel_pan[ i ] = pan; else if (pan > 64)
pan = IT_SURROUND;
sigdata->channel_pan[i] = pan;
} }
} } else {
else {
int sep = 32 * dumb_it_default_panning_separation / 100; int sep = 32 * dumb_it_default_panning_separation / 100;
for ( i = 0; i < 16; i++ ) { for (i = 0; i < 16; i++) {
sigdata->channel_pan[ i ] = ( dumbfile_getc( f ) & 1 ) ? 32 - sep : 32 + sep; sigdata->channel_pan[i] =
(dumbfile_getc(f) & 1) ? 32 - sep : 32 + sep;
} }
} }
sigdata->tempo = 125; sigdata->tempo = 125;
sigdata->speed = 6; sigdata->speed = 6;
if ( ver >= 13 ) { if (ver >= 13) {
i = dumbfile_getc( f ); i = dumbfile_getc(f);
if ( i >= 32 ) sigdata->tempo = i; if (i >= 32)
i = dumbfile_getc( f ); sigdata->tempo = i;
if ( i <= 32 ) sigdata->speed = i; i = dumbfile_getc(f);
if (i <= 32)
sigdata->speed = i;
} }
sigdata->order = malloc( sigdata->n_orders ); sigdata->order = malloc(sigdata->n_orders);
if ( !sigdata->order ) { if (!sigdata->order) {
free( sigdata ); free(sigdata);
return NULL; return NULL;
} }
orderstotracks = malloc( sigdata->n_orders * nchannels * sizeof( unsigned short ) ); orderstotracks =
if ( !orderstotracks ) { malloc(sigdata->n_orders * nchannels * sizeof(unsigned short));
free( sigdata->order ); if (!orderstotracks) {
free( sigdata ); free(sigdata->order);
free(sigdata);
return NULL; return NULL;
} }
for ( i = 0; i < sigdata->n_orders; i++ ) { for (i = 0; i < sigdata->n_orders; i++) {
sigdata->order[ i ] = i; sigdata->order[i] = i;
tracksize[ i ] = 64; tracksize[i] = 64;
if ( ver >= 14 ) { if (ver >= 14) {
tracksize[ i ] = dumbfile_igetw( f ); tracksize[i] = dumbfile_igetw(f);
} }
for ( j = 0; j < nchannels; j++ ) { for (j = 0; j < nchannels; j++) {
orderstotracks[ i * nchannels + j ] = dumbfile_igetw( f ); orderstotracks[i * nchannels + j] = dumbfile_igetw(f);
} }
} }
if ( dumbfile_error( f ) ) { if (dumbfile_error(f)) {
free( orderstotracks ); free(orderstotracks);
free( sigdata->order ); free(sigdata->order);
free( sigdata ); free(sigdata);
return NULL; return NULL;
} }
sigdata->sample = malloc( sigdata->n_samples * sizeof( *sigdata->sample ) ); sigdata->sample = malloc(sigdata->n_samples * sizeof(*sigdata->sample));
if ( !sigdata->sample ) { if (!sigdata->sample) {
free( orderstotracks ); free(orderstotracks);
free( sigdata->order ); free(sigdata->order);
free( sigdata ); free(sigdata);
return NULL; return NULL;
} }
@ -403,66 +429,70 @@ static DUMB_IT_SIGDATA *it_amf_load_sigdata(DUMBFILE *f, int * version)
sigdata->n_instruments = 0; sigdata->n_instruments = 0;
for ( i = 0; i < sigdata->n_samples; ++i ) for (i = 0; i < sigdata->n_samples; ++i)
sigdata->sample[i].data = NULL; sigdata->sample[i].data = NULL;
for ( i = 0; i < sigdata->n_samples; ++i ) { for (i = 0; i < sigdata->n_samples; ++i) {
int offset; int offset;
if ( it_amf_read_sample_header( &sigdata->sample[i], f, &offset, ver ) ) { if (it_amf_read_sample_header(&sigdata->sample[i], f, &offset, ver)) {
goto error_ott; goto error_ott;
} }
sampleseekpos[ i ] = offset; sampleseekpos[i] = offset;
if ( offset > maxsampleseekpos ) maxsampleseekpos = offset; if (offset > maxsampleseekpos)
maxsampleseekpos = offset;
} }
sigdata->n_patterns = sigdata->n_orders; sigdata->n_patterns = sigdata->n_orders;
sigdata->pattern = malloc( sigdata->n_patterns * sizeof( *sigdata->pattern ) ); sigdata->pattern = malloc(sigdata->n_patterns * sizeof(*sigdata->pattern));
if ( !sigdata->pattern ) { if (!sigdata->pattern) {
goto error_ott; goto error_ott;
} }
for (i = 0; i < sigdata->n_patterns; ++i) for (i = 0; i < sigdata->n_patterns; ++i)
sigdata->pattern[i].entry = NULL; sigdata->pattern[i].entry = NULL;
trackmap = malloc( ntracks * sizeof( unsigned short ) ); trackmap = malloc(ntracks * sizeof(unsigned short));
if ( !trackmap ) { if (!trackmap) {
goto error_ott; goto error_ott;
} }
if ( dumbfile_getnc( ( char * ) trackmap, ntracks * sizeof( unsigned short ), f ) != (long)(ntracks * sizeof( unsigned short )) ) { if (dumbfile_getnc((char *)trackmap, ntracks * sizeof(unsigned short), f) !=
(long)(ntracks * sizeof(unsigned short))) {
goto error_tm; goto error_tm;
} }
realntracks = 0; realntracks = 0;
for ( i = 0; i < ntracks; i++ ) { for (i = 0; i < ntracks; i++) {
if ( trackmap[ i ] > realntracks ) realntracks = trackmap[ i ]; if (trackmap[i] > realntracks)
realntracks = trackmap[i];
} }
track = calloc( realntracks, sizeof( unsigned char * ) ); track = calloc(realntracks, sizeof(unsigned char *));
if ( !track ) { if (!track) {
goto error_tm; goto error_tm;
} }
for ( i = 0; i < realntracks; i++ ) { for (i = 0; i < realntracks; i++) {
int tracksize = dumbfile_igetw( f ); int tracksize = dumbfile_igetw(f);
tracksize += dumbfile_getc( f ) << 16; tracksize += dumbfile_getc(f) << 16;
track[ i ] = malloc( tracksize * 3 + 3 ); track[i] = malloc(tracksize * 3 + 3);
if ( !track[ i ] ) { if (!track[i]) {
goto error_all; goto error_all;
} }
track[ i ][ 0 ] = tracksize & 255; track[i][0] = tracksize & 255;
track[ i ][ 1 ] = ( tracksize >> 8 ) & 255; track[i][1] = (tracksize >> 8) & 255;
track[ i ][ 2 ] = ( tracksize >> 16 ) & 255; track[i][2] = (tracksize >> 16) & 255;
if ( dumbfile_getnc( (char *) track[ i ] + 3, tracksize * 3, f ) != tracksize * 3 ) { if (dumbfile_getnc((char *)track[i] + 3, tracksize * 3, f) !=
tracksize * 3) {
goto error_all; goto error_all;
} }
} }
for ( i = 1; i <= maxsampleseekpos; i++ ) { for (i = 1; i <= maxsampleseekpos; i++) {
for ( j = 0; j < sigdata->n_samples; j++ ) { for (j = 0; j < sigdata->n_samples; j++) {
if ( sampleseekpos[ j ] == i ) { if (sampleseekpos[j] == i) {
if ( it_amf_read_sample_data( &sigdata->sample[ j ], f ) ) { if (it_amf_read_sample_data(&sigdata->sample[j], f)) {
goto error_all; goto error_all;
} }
break; break;
@ -471,32 +501,36 @@ static DUMB_IT_SIGDATA *it_amf_load_sigdata(DUMBFILE *f, int * version)
} }
/* Process tracks into patterns */ /* Process tracks into patterns */
for ( i = 0; i < sigdata->n_patterns; i++ ) { for (i = 0; i < sigdata->n_patterns; i++) {
IT_ENTRY * entry_table = calloc( tracksize[ i ] * nchannels, sizeof( IT_ENTRY ) ); IT_ENTRY *entry_table =
if ( !entry_table ) { calloc(tracksize[i] * nchannels, sizeof(IT_ENTRY));
if (!entry_table) {
goto error_all; goto error_all;
} }
for ( j = 0; j < nchannels; j++ ) { for (j = 0; j < nchannels; j++) {
int ntrack = orderstotracks[ i * nchannels + j ]; int ntrack = orderstotracks[i * nchannels + j];
if ( ntrack && ntrack <= ntracks ) { if (ntrack && ntrack <= ntracks) {
int realtrack = trackmap[ ntrack - 1 ]; int realtrack = trackmap[ntrack - 1];
if ( realtrack ) { if (realtrack) {
realtrack--; realtrack--;
if ( realtrack < realntracks && track[ realtrack ] ) { if (realtrack < realntracks && track[realtrack]) {
it_amf_process_track( entry_table + j, track[ realtrack ], tracksize[ i ], nchannels ); it_amf_process_track(entry_table + j, track[realtrack],
tracksize[i], nchannels);
} }
} }
} }
} }
if ( it_amf_process_pattern( &sigdata->pattern[ i ], entry_table, tracksize[ i ], nchannels ) ) { if (it_amf_process_pattern(&sigdata->pattern[i], entry_table,
free( entry_table ); tracksize[i], nchannels)) {
free(entry_table);
goto error_all; goto error_all;
} }
free( entry_table ); free(entry_table);
} }
/* Now let's initialise the remaining variables, and we're done! */ /* Now let's initialise the remaining variables, and we're done! */
sigdata->flags = IT_OLD_EFFECTS | IT_COMPATIBLE_GXX | IT_STEREO | IT_WAS_AN_S3M; sigdata->flags =
IT_OLD_EFFECTS | IT_COMPATIBLE_GXX | IT_STEREO | IT_WAS_AN_S3M;
sigdata->global_volume = 128; sigdata->global_volume = 128;
sigdata->mixing_volume = 48; sigdata->mixing_volume = 48;
@ -504,36 +538,33 @@ static DUMB_IT_SIGDATA *it_amf_load_sigdata(DUMBFILE *f, int * version)
_dumb_it_fix_invalid_orders(sigdata); _dumb_it_fix_invalid_orders(sigdata);
for ( i = 0; i < realntracks; i++ ) { for (i = 0; i < realntracks; i++) {
if ( track[ i ] ) { if (track[i]) {
free( track[ i ] ); free(track[i]);
} }
} }
free( track ); free(track);
free( trackmap ); free(trackmap);
free( orderstotracks ); free(orderstotracks);
return sigdata; return sigdata;
error_all: error_all:
for ( i = 0; i < realntracks; i++ ) { for (i = 0; i < realntracks; i++) {
if ( track[ i ] ) { if (track[i]) {
free( track[ i ] ); free(track[i]);
} }
} }
free( track ); free(track);
error_tm: error_tm:
free( trackmap ); free(trackmap);
error_ott: error_ott:
free( orderstotracks ); free(orderstotracks);
_dumb_it_unload_sigdata( sigdata ); _dumb_it_unload_sigdata(sigdata);
return NULL; return NULL;
} }
DUH *dumb_read_amf_quick(DUMBFILE *f) {
DUH *dumb_read_amf_quick(DUMBFILE *f)
{
sigdata_t *sigdata; sigdata_t *sigdata;
DUH_SIGTYPE_DESC *descptr = &_dumb_sigtype_it; DUH_SIGTYPE_DESC *descptr = &_dumb_sigtype_it;
@ -551,12 +582,13 @@ DUH *dumb_read_amf_quick(DUMBFILE *f)
tag[0][0] = "TITLE"; tag[0][0] = "TITLE";
tag[0][1] = (const char *)(((DUMB_IT_SIGDATA *)sigdata)->name); tag[0][1] = (const char *)(((DUMB_IT_SIGDATA *)sigdata)->name);
tag[1][0] = "FORMAT"; tag[1][0] = "FORMAT";
memcpy( ver_string, "DSMI AMF v", 10 ); memcpy(ver_string, "DSMI AMF v", 10);
ver_string[10] = '0' + version / 10; ver_string[10] = '0' + version / 10;
ver_string[11] = '.'; ver_string[11] = '.';
ver_string[12] = '0' + version % 10; ver_string[12] = '0' + version % 10;
ver_string[13] = 0; ver_string[13] = 0;
tag[1][1] = ver_string; tag[1][1] = ver_string;
return make_duh(-1, 2, (const char *const (*)[2])tag, 1, &descptr, &sigdata); return make_duh(-1, 2, (const char *const(*)[2])tag, 1, &descptr,
&sigdata);
} }
} }

View file

@ -19,10 +19,7 @@
#include "dumb.h" #include "dumb.h"
DUH *dumb_read_amf(DUMBFILE *f) {
DUH *dumb_read_amf(DUMBFILE *f)
{
DUH *duh = dumb_read_amf_quick(f); DUH *duh = dumb_read_amf_quick(f);
dumb_it_do_initial_runthrough(duh); dumb_it_do_initial_runthrough(duh);
return duh; return duh;

View file

@ -23,109 +23,80 @@
#include "dumb.h" #include "dumb.h"
#ifdef _MSC_VER #ifdef _MSC_VER
#define strnicmp _strnicmp #define strnicmp _strnicmp
#else #else
#if defined(unix) || defined(__unix__) || defined(__unix) #if defined(unix) || defined(__unix__) || defined(__unix)
#include <strings.h> #include <strings.h>
#endif #endif
#define strnicmp strncasecmp #define strnicmp strncasecmp
#endif #endif
enum { maximum_signature_size = 0x30 }; enum { maximum_signature_size = 0x30 };
DUH *dumb_read_any_quick(DUMBFILE *f, int restrict_, int subsong) DUH *dumb_read_any_quick(DUMBFILE *f, int restrict_, int subsong) {
{ unsigned char signature[maximum_signature_size];
unsigned char signature[ maximum_signature_size ];
unsigned long signature_size; unsigned long signature_size;
DUH * duh = NULL; DUH *duh = NULL;
/* signature_size = dumbfile_get_size(f); */ /* signature_size = dumbfile_get_size(f); */
signature_size = dumbfile_getnc( (char *)signature, maximum_signature_size, f ); signature_size =
dumbfile_seek( f, 0, DFS_SEEK_SET ); dumbfile_getnc((char *)signature, maximum_signature_size, f);
dumbfile_seek(f, 0, DFS_SEEK_SET);
if (signature_size >= 4 && if (signature_size >= 4 && signature[0] == 'I' && signature[1] == 'M' &&
signature[0] == 'I' && signature[1] == 'M' && signature[2] == 'P' && signature[3] == 'M') {
signature[2] == 'P' && signature[3] == 'M') duh = dumb_read_it_quick(f);
{ } else if (signature_size >= 17 &&
duh = dumb_read_it_quick( f ); !memcmp(signature, "Extended Module: ", 17)) {
} duh = dumb_read_xm_quick(f);
else if (signature_size >= 17 && !memcmp(signature, "Extended Module: ", 17)) } else if (signature_size >= 0x30 && signature[0x2C] == 'S' &&
{ signature[0x2D] == 'C' && signature[0x2E] == 'R' &&
duh = dumb_read_xm_quick( f ); signature[0x2F] == 'M') {
} duh = dumb_read_s3m_quick(f);
else if (signature_size >= 0x30 && } else if (signature_size >= 30 &&
signature[0x2C] == 'S' && signature[0x2D] == 'C' &&
signature[0x2E] == 'R' && signature[0x2F] == 'M')
{
duh = dumb_read_s3m_quick( f );
}
else if (signature_size >= 30 &&
/*signature[28] == 0x1A &&*/ signature[29] == 2 && /*signature[28] == 0x1A &&*/ signature[29] == 2 &&
( ! strnicmp( ( const char * ) signature + 20, "!Scream!", 8 ) || (!strnicmp((const char *)signature + 20, "!Scream!", 8) ||
! strnicmp( ( const char * ) signature + 20, "BMOD2STM", 8 ) || !strnicmp((const char *)signature + 20, "BMOD2STM", 8) ||
! strnicmp( ( const char * ) signature + 20, "WUZAMOD!", 8 ) ) ) !strnicmp((const char *)signature + 20, "WUZAMOD!", 8))) {
{ duh = dumb_read_stm_quick(f);
duh = dumb_read_stm_quick( f ); } else if (signature_size >= 2 &&
}
else if (signature_size >= 2 &&
((signature[0] == 0x69 && signature[1] == 0x66) || ((signature[0] == 0x69 && signature[1] == 0x66) ||
(signature[0] == 0x4A && signature[1] == 0x4E))) (signature[0] == 0x4A && signature[1] == 0x4E))) {
{ duh = dumb_read_669_quick(f);
duh = dumb_read_669_quick( f ); } else if (signature_size >= 0x30 && signature[0x2C] == 'P' &&
} signature[0x2D] == 'T' && signature[0x2E] == 'M' &&
else if (signature_size >= 0x30 && signature[0x2F] == 'F') {
signature[0x2C] == 'P' && signature[0x2D] == 'T' && duh = dumb_read_ptm_quick(f);
signature[0x2E] == 'M' && signature[0x2F] == 'F') } else if (signature_size >= 4 && signature[0] == 'P' &&
{ signature[1] == 'S' && signature[2] == 'M' &&
duh = dumb_read_ptm_quick( f ); signature[3] == ' ') {
} duh = dumb_read_psm_quick(f, subsong);
else if (signature_size >= 4 && } else if (signature_size >= 4 && signature[0] == 'P' &&
signature[0] == 'P' && signature[1] == 'S' && signature[1] == 'S' && signature[2] == 'M' &&
signature[2] == 'M' && signature[3] == ' ') signature[3] == 254) {
{ duh = dumb_read_old_psm_quick(f);
duh = dumb_read_psm_quick( f, subsong ); } else if (signature_size >= 3 && signature[0] == 'M' &&
} signature[1] == 'T' && signature[2] == 'M') {
else if (signature_size >= 4 && duh = dumb_read_mtm_quick(f);
signature[0] == 'P' && signature[1] == 'S' && } else if (signature_size >= 4 && signature[0] == 'R' &&
signature[2] == 'M' && signature[3] == 254) signature[1] == 'I' && signature[2] == 'F' &&
{ signature[3] == 'F') {
duh = dumb_read_old_psm_quick( f ); duh = dumb_read_riff_quick(f);
} } else if (signature_size >= 24 &&
else if (signature_size >= 3 && !memcmp(signature, "ASYLUM Music Format", 19) &&
signature[0] == 'M' && signature[1] == 'T' && !memcmp(signature + 19, " V1.0", 5)) {
signature[2] == 'M') duh = dumb_read_asy_quick(f);
{ } else if (signature_size >= 3 && signature[0] == 'A' &&
duh = dumb_read_mtm_quick( f ); signature[1] == 'M' && signature[2] == 'F') {
} duh = dumb_read_amf_quick(f);
else if ( signature_size >= 4 && } else if (signature_size >= 8 && !memcmp(signature, "OKTASONG", 8)) {
signature[0] == 'R' && signature[1] == 'I' && duh = dumb_read_okt_quick(f);
signature[2] == 'F' && signature[3] == 'F')
{
duh = dumb_read_riff_quick( f );
}
else if ( signature_size >= 24 &&
!memcmp( signature, "ASYLUM Music Format", 19 ) &&
!memcmp( signature + 19, " V1.0", 5 ) )
{
duh = dumb_read_asy_quick( f );
}
else if ( signature_size >= 3 &&
signature[0] == 'A' && signature[1] == 'M' &&
signature[2] == 'F')
{
duh = dumb_read_amf_quick( f );
}
else if ( signature_size >= 8 &&
!memcmp( signature, "OKTASONG", 8 ) )
{
duh = dumb_read_okt_quick( f );
} }
if ( !duh ) if (!duh) {
{ dumbfile_seek(f, 0, DFS_SEEK_SET);
dumbfile_seek( f, 0, DFS_SEEK_SET ); duh = dumb_read_mod_quick(f, restrict_);
duh = dumb_read_mod_quick( f, restrict_ );
} }
return duh; return duh;

View file

@ -19,10 +19,7 @@
#include "dumb.h" #include "dumb.h"
DUH *dumb_read_any(DUMBFILE *f, int restrict_, int subsong) {
DUH *dumb_read_any(DUMBFILE *f, int restrict_, int subsong)
{
DUH *duh = dumb_read_any_quick(f, restrict_, subsong); DUH *duh = dumb_read_any_quick(f, restrict_, subsong);
dumb_it_do_initial_runthrough(duh); dumb_it_do_initial_runthrough(duh);
return duh; return duh;

View file

@ -24,10 +24,8 @@
#include "dumb.h" #include "dumb.h"
#include "internal/it.h" #include "internal/it.h"
static int it_asy_read_pattern(IT_PATTERN *pattern, DUMBFILE *f,
unsigned char *buffer) {
static int it_asy_read_pattern( IT_PATTERN *pattern, DUMBFILE *f, unsigned char *buffer )
{
int pos; int pos;
int channel; int channel;
int row; int row;
@ -35,56 +33,60 @@ static int it_asy_read_pattern( IT_PATTERN *pattern, DUMBFILE *f, unsigned char
pattern->n_rows = 64; pattern->n_rows = 64;
if ( dumbfile_getnc( (char *) buffer, 64 * 8 * 4, f ) != 64 * 8 * 4 ) if (dumbfile_getnc((char *)buffer, 64 * 8 * 4, f) != 64 * 8 * 4)
return -1; return -1;
/* compute number of entries */ /* compute number of entries */
pattern->n_entries = 64; /* Account for the row end markers */ pattern->n_entries = 64; /* Account for the row end markers */
pos = 0; pos = 0;
for ( row = 0; row < 64; ++row ) { for (row = 0; row < 64; ++row) {
for ( channel = 0; channel < 8; ++channel ) { for (channel = 0; channel < 8; ++channel) {
if ( buffer[ pos + 0 ] | buffer[ pos + 1 ] | buffer[ pos + 2 ] | buffer[ pos + 3 ] ) if (buffer[pos + 0] | buffer[pos + 1] | buffer[pos + 2] |
buffer[pos + 3])
++pattern->n_entries; ++pattern->n_entries;
pos += 4; pos += 4;
} }
} }
pattern->entry = malloc( pattern->n_entries * sizeof( *pattern->entry ) ); pattern->entry = malloc(pattern->n_entries * sizeof(*pattern->entry));
if ( !pattern->entry ) if (!pattern->entry)
return -1; return -1;
entry = pattern->entry; entry = pattern->entry;
pos = 0; pos = 0;
for ( row = 0; row < 64; ++row ) { for (row = 0; row < 64; ++row) {
for ( channel = 0; channel < 8; ++channel ) { for (channel = 0; channel < 8; ++channel) {
if ( buffer[ pos + 0 ] | buffer[ pos + 1 ] | buffer[ pos + 2 ] | buffer[ pos + 3 ] ) { if (buffer[pos + 0] | buffer[pos + 1] | buffer[pos + 2] |
buffer[pos + 3]) {
entry->channel = channel; entry->channel = channel;
entry->mask = 0; entry->mask = 0;
if ( buffer[ pos + 0 ] && buffer[ pos + 0 ] < 96 ) { if (buffer[pos + 0] && buffer[pos + 0] < 96) {
entry->note = buffer[ pos + 0 ]; entry->note = buffer[pos + 0];
entry->mask |= IT_ENTRY_NOTE; entry->mask |= IT_ENTRY_NOTE;
} }
if ( buffer[ pos + 1 ] && buffer[ pos + 1 ] <= 64 ) { if (buffer[pos + 1] && buffer[pos + 1] <= 64) {
entry->instrument = buffer[ pos + 1 ]; entry->instrument = buffer[pos + 1];
entry->mask |= IT_ENTRY_INSTRUMENT; entry->mask |= IT_ENTRY_INSTRUMENT;
} }
_dumb_it_xm_convert_effect( buffer[ pos + 2 ], buffer[ pos + 3 ], entry, 1 ); _dumb_it_xm_convert_effect(buffer[pos + 2], buffer[pos + 3],
entry, 1);
// fixup // fixup
switch ( entry->effect ) { switch (entry->effect) {
case IT_SET_PANNING: case IT_SET_PANNING:
entry->effectvalue <<= 1; entry->effectvalue <<= 1;
break; break;
} }
if ( entry->mask ) ++entry; if (entry->mask)
++entry;
} }
pos += 4; pos += 4;
} }
IT_SET_END_ROW( entry ); IT_SET_END_ROW(entry);
++entry; ++entry;
} }
@ -93,37 +95,36 @@ static int it_asy_read_pattern( IT_PATTERN *pattern, DUMBFILE *f, unsigned char
return 0; return 0;
} }
static int it_asy_read_sample_header(IT_SAMPLE *sample, DUMBFILE *f) {
static int it_asy_read_sample_header( IT_SAMPLE *sample, DUMBFILE *f )
{
int finetune, key_offset; int finetune, key_offset;
/** /**
21 22 Chars Sample 1 name. If the name is not a full 21 22 Chars Sample 1 name. If the name is not a full
22 chars in length, it will be null 22 chars in length, it will be null
terminated. terminated.
If If
the sample name begins with a '#' character (ASCII $23 (35)) then this is the sample name begins with a '#' character (ASCII $23 (35)) then this is
assumed not to be an instrument name, and is probably a message. assumed not to be an instrument name, and is probably a message.
*/ */
dumbfile_getnc( (char *) sample->name, 22, f ); dumbfile_getnc((char *)sample->name, 22, f);
sample->name[22] = 0; sample->name[22] = 0;
sample->filename[0] = 0; sample->filename[0] = 0;
/** Each finetune step changes the note 1/8th of a semitone. */ /** Each finetune step changes the note 1/8th of a semitone. */
finetune = ( signed char ) ( dumbfile_getc( f ) << 4 ) >> 4; /* signed nibble */ finetune = (signed char)(dumbfile_getc(f) << 4) >> 4; /* signed nibble */
sample->default_volume = dumbfile_getc( f ); // Should we be setting global_volume to this instead? sample->default_volume =
dumbfile_getc(f); // Should we be setting global_volume to this instead?
sample->global_volume = 64; sample->global_volume = 64;
if ( sample->default_volume > 64 ) sample->default_volume = 64; if (sample->default_volume > 64)
key_offset = ( signed char ) dumbfile_getc( f ); /* base key offset */ sample->default_volume = 64;
sample->length = dumbfile_igetl( f ); key_offset = (signed char)dumbfile_getc(f); /* base key offset */
sample->loop_start = dumbfile_igetl( f ); sample->length = dumbfile_igetl(f);
sample->loop_end = sample->loop_start + dumbfile_igetl( f ); sample->loop_start = dumbfile_igetl(f);
sample->loop_end = sample->loop_start + dumbfile_igetl(f);
if ( sample->length <= 0 ) { if (sample->length <= 0) {
sample->flags = 0; sample->flags = 0;
return 0; return 0;
} }
@ -131,11 +132,16 @@ assumed not to be an instrument name, and is probably a message.
sample->flags = IT_SAMPLE_EXISTS; sample->flags = IT_SAMPLE_EXISTS;
sample->default_pan = 0; sample->default_pan = 0;
sample->C5_speed = (int)( AMIGA_CLOCK / 214.0 * pow( DUMB_SEMITONE_BASE, key_offset ) );//( long )( 16726.0 * pow( DUMB_PITCH_BASE, finetune * 32 ) ); sample->C5_speed =
(int)(AMIGA_CLOCK / 214.0 *
pow(DUMB_SEMITONE_BASE, key_offset)); //( long )( 16726.0 * pow(
// DUMB_PITCH_BASE, finetune
//* 32 ) );
sample->finetune = finetune * 32; sample->finetune = finetune * 32;
// the above line might be wrong // the above line might be wrong
if ( ( sample->loop_end - sample->loop_start > 2 ) && ( sample->loop_end <= sample->length ) ) if ((sample->loop_end - sample->loop_start > 2) &&
(sample->loop_end <= sample->length))
sample->flags |= IT_SAMPLE_LOOP; sample->flags |= IT_SAMPLE_LOOP;
sample->vibrato_speed = 0; sample->vibrato_speed = 0;
@ -147,48 +153,43 @@ assumed not to be an instrument name, and is probably a message.
return dumbfile_error(f); return dumbfile_error(f);
} }
static int it_asy_read_sample_data(IT_SAMPLE *sample, DUMBFILE *f) {
static int it_asy_read_sample_data( IT_SAMPLE *sample, DUMBFILE *f )
{
long truncated_size; long truncated_size;
/* let's get rid of the sample data coming after the end of the loop */ /* let's get rid of the sample data coming after the end of the loop */
if ( ( sample->flags & IT_SAMPLE_LOOP ) && sample->loop_end < sample->length ) { if ((sample->flags & IT_SAMPLE_LOOP) && sample->loop_end < sample->length) {
truncated_size = sample->length - sample->loop_end; truncated_size = sample->length - sample->loop_end;
sample->length = sample->loop_end; sample->length = sample->loop_end;
} else { } else {
truncated_size = 0; truncated_size = 0;
} }
sample->data = malloc( sample->length ); sample->data = malloc(sample->length);
if ( !sample->data ) if (!sample->data)
return -1; return -1;
if ( sample->length ) if (sample->length)
dumbfile_getnc( sample->data, sample->length, f ); dumbfile_getnc(sample->data, sample->length, f);
dumbfile_skip( f, truncated_size ); dumbfile_skip(f, truncated_size);
return dumbfile_error( f ); return dumbfile_error(f);
} }
static DUMB_IT_SIGDATA *it_asy_load_sigdata(DUMBFILE *f) {
static DUMB_IT_SIGDATA *it_asy_load_sigdata(DUMBFILE *f)
{
DUMB_IT_SIGDATA *sigdata; DUMB_IT_SIGDATA *sigdata;
int i; int i;
static const char sig_part[] = "ASYLUM Music Format"; static const char sig_part[] = "ASYLUM Music Format";
static const char sig_rest[] = " V1.0"; /* whee, string space optimization with format type below */ static const char sig_rest[] =
" V1.0"; /* whee, string space optimization with format type below */
char signature [32]; char signature[32];
if ( dumbfile_getnc( signature, 32, f ) != 32 || if (dumbfile_getnc(signature, 32, f) != 32 ||
memcmp( signature, sig_part, 19 ) || memcmp(signature, sig_part, 19) ||
memcmp( signature + 19, sig_rest, 5 ) ) { memcmp(signature + 19, sig_rest, 5)) {
return NULL; return NULL;
} }
@ -197,39 +198,40 @@ static DUMB_IT_SIGDATA *it_asy_load_sigdata(DUMBFILE *f)
return NULL; return NULL;
} }
sigdata->speed = dumbfile_getc( f ); /* XXX seems to fit the files I have */ sigdata->speed = dumbfile_getc(f); /* XXX seems to fit the files I have */
sigdata->tempo = dumbfile_getc( f ); /* ditto */ sigdata->tempo = dumbfile_getc(f); /* ditto */
sigdata->n_samples = dumbfile_getc( f ); /* ditto */ sigdata->n_samples = dumbfile_getc(f); /* ditto */
sigdata->n_patterns = dumbfile_getc( f ); sigdata->n_patterns = dumbfile_getc(f);
sigdata->n_orders = dumbfile_getc( f ); sigdata->n_orders = dumbfile_getc(f);
sigdata->restart_position = dumbfile_getc( f ); sigdata->restart_position = dumbfile_getc(f);
if ( dumbfile_error( f ) || !sigdata->n_samples || sigdata->n_samples > 64 || !sigdata->n_patterns || if (dumbfile_error(f) || !sigdata->n_samples || sigdata->n_samples > 64 ||
!sigdata->n_orders ) { !sigdata->n_patterns || !sigdata->n_orders) {
free( sigdata ); free(sigdata);
return NULL; return NULL;
} }
if ( sigdata->restart_position > sigdata->n_orders ) /* XXX */ if (sigdata->restart_position > sigdata->n_orders) /* XXX */
sigdata->restart_position = 0; sigdata->restart_position = 0;
sigdata->order = malloc( sigdata->n_orders ); sigdata->order = malloc(sigdata->n_orders);
if ( !sigdata->order ) { if (!sigdata->order) {
free( sigdata ); free(sigdata);
return NULL; return NULL;
} }
if ( dumbfile_getnc( (char *) sigdata->order, sigdata->n_orders, f ) != sigdata->n_orders || if (dumbfile_getnc((char *)sigdata->order, sigdata->n_orders, f) !=
dumbfile_skip( f, 256 - sigdata->n_orders ) ) { sigdata->n_orders ||
free( sigdata->order ); dumbfile_skip(f, 256 - sigdata->n_orders)) {
free( sigdata ); free(sigdata->order);
free(sigdata);
return NULL; return NULL;
} }
sigdata->sample = malloc( sigdata->n_samples * sizeof( *sigdata->sample ) ); sigdata->sample = malloc(sigdata->n_samples * sizeof(*sigdata->sample));
if ( !sigdata->sample ) { if (!sigdata->sample) {
free( sigdata->order ); free(sigdata->order);
free( sigdata ); free(sigdata);
return NULL; return NULL;
} }
@ -241,24 +243,24 @@ static DUMB_IT_SIGDATA *it_asy_load_sigdata(DUMBFILE *f)
sigdata->n_instruments = 0; sigdata->n_instruments = 0;
for ( i = 0; i < sigdata->n_samples; ++i ) for (i = 0; i < sigdata->n_samples; ++i)
sigdata->sample[i].data = NULL; sigdata->sample[i].data = NULL;
for ( i = 0; i < sigdata->n_samples; ++i ) { for (i = 0; i < sigdata->n_samples; ++i) {
if ( it_asy_read_sample_header( &sigdata->sample[i], f ) ) { if (it_asy_read_sample_header(&sigdata->sample[i], f)) {
_dumb_it_unload_sigdata( sigdata ); _dumb_it_unload_sigdata(sigdata);
return NULL; return NULL;
} }
} }
if ( dumbfile_skip( f, 37 * ( 64 - sigdata->n_samples ) ) ) { if (dumbfile_skip(f, 37 * (64 - sigdata->n_samples))) {
_dumb_it_unload_sigdata( sigdata ); _dumb_it_unload_sigdata(sigdata);
return NULL; return NULL;
} }
sigdata->pattern = malloc( sigdata->n_patterns * sizeof( *sigdata->pattern ) ); sigdata->pattern = malloc(sigdata->n_patterns * sizeof(*sigdata->pattern));
if ( !sigdata->pattern ) { if (!sigdata->pattern) {
_dumb_it_unload_sigdata( sigdata ); _dumb_it_unload_sigdata(sigdata);
return NULL; return NULL;
} }
for (i = 0; i < sigdata->n_patterns; ++i) for (i = 0; i < sigdata->n_patterns; ++i)
@ -266,31 +268,33 @@ static DUMB_IT_SIGDATA *it_asy_load_sigdata(DUMBFILE *f)
/* Read in the patterns */ /* Read in the patterns */
{ {
unsigned char *buffer = malloc( 64 * 8 * 4 ); /* 64 rows * 8 channels * 4 bytes */ unsigned char *buffer =
if ( !buffer ) { malloc(64 * 8 * 4); /* 64 rows * 8 channels * 4 bytes */
_dumb_it_unload_sigdata( sigdata ); if (!buffer) {
_dumb_it_unload_sigdata(sigdata);
return NULL; return NULL;
} }
for ( i = 0; i < sigdata->n_patterns; ++i ) { for (i = 0; i < sigdata->n_patterns; ++i) {
if ( it_asy_read_pattern( &sigdata->pattern[i], f, buffer ) != 0 ) { if (it_asy_read_pattern(&sigdata->pattern[i], f, buffer) != 0) {
free( buffer ); free(buffer);
_dumb_it_unload_sigdata( sigdata ); _dumb_it_unload_sigdata(sigdata);
return NULL; return NULL;
} }
} }
free( buffer ); free(buffer);
} }
/* And finally, the sample data */ /* And finally, the sample data */
for ( i = 0; i < sigdata->n_samples; ++i ) { for (i = 0; i < sigdata->n_samples; ++i) {
if ( it_asy_read_sample_data( &sigdata->sample[i], f ) ) { if (it_asy_read_sample_data(&sigdata->sample[i], f)) {
_dumb_it_unload_sigdata( sigdata ); _dumb_it_unload_sigdata(sigdata);
return NULL; return NULL;
} }
} }
/* Now let's initialise the remaining variables, and we're done! */ /* Now let's initialise the remaining variables, and we're done! */
sigdata->flags = IT_WAS_AN_XM | IT_WAS_A_MOD | IT_OLD_EFFECTS | IT_COMPATIBLE_GXX | IT_STEREO; sigdata->flags = IT_WAS_AN_XM | IT_WAS_A_MOD | IT_OLD_EFFECTS |
IT_COMPATIBLE_GXX | IT_STEREO;
sigdata->global_volume = 128; sigdata->global_volume = 128;
sigdata->mixing_volume = 48; sigdata->mixing_volume = 48;
@ -304,10 +308,10 @@ static DUMB_IT_SIGDATA *it_asy_load_sigdata(DUMBFILE *f)
for (i = 0; i < DUMB_IT_N_CHANNELS; i += 4) { for (i = 0; i < DUMB_IT_N_CHANNELS; i += 4) {
int sep = 32 * dumb_it_default_panning_separation / 100; int sep = 32 * dumb_it_default_panning_separation / 100;
sigdata->channel_pan[i+0] = 32 - sep; sigdata->channel_pan[i + 0] = 32 - sep;
sigdata->channel_pan[i+1] = 32 + sep; sigdata->channel_pan[i + 1] = 32 + sep;
sigdata->channel_pan[i+2] = 32 + sep; sigdata->channel_pan[i + 2] = 32 + sep;
sigdata->channel_pan[i+3] = 32 - sep; sigdata->channel_pan[i + 3] = 32 - sep;
} }
_dumb_it_fix_invalid_orders(sigdata); _dumb_it_fix_invalid_orders(sigdata);
@ -315,10 +319,7 @@ static DUMB_IT_SIGDATA *it_asy_load_sigdata(DUMBFILE *f)
return sigdata; return sigdata;
} }
DUH *dumb_read_asy_quick(DUMBFILE *f) {
DUH *dumb_read_asy_quick(DUMBFILE *f)
{
sigdata_t *sigdata; sigdata_t *sigdata;
DUH_SIGTYPE_DESC *descptr = &_dumb_sigtype_it; DUH_SIGTYPE_DESC *descptr = &_dumb_sigtype_it;
@ -334,6 +335,7 @@ DUH *dumb_read_asy_quick(DUMBFILE *f)
tag[0][1] = (const char *)(((DUMB_IT_SIGDATA *)sigdata)->name); tag[0][1] = (const char *)(((DUMB_IT_SIGDATA *)sigdata)->name);
tag[1][0] = "FORMAT"; tag[1][0] = "FORMAT";
tag[1][1] = "ASYLUM Music Format"; tag[1][1] = "ASYLUM Music Format";
return make_duh(-1, 2, (const char *const (*)[2])tag, 1, &descptr, &sigdata); return make_duh(-1, 2, (const char *const(*)[2])tag, 1, &descptr,
&sigdata);
} }
} }

View file

@ -24,28 +24,28 @@
#include "internal/it.h" #include "internal/it.h"
#include "internal/riff.h" #include "internal/riff.h"
static int it_riff_dsmf_process_sample( IT_SAMPLE * sample, DUMBFILE * f, int len ) static int it_riff_dsmf_process_sample(IT_SAMPLE *sample, DUMBFILE *f,
{ int len) {
int flags; int flags;
dumbfile_getnc( (char *) sample->filename, 13, f ); dumbfile_getnc((char *)sample->filename, 13, f);
sample->filename[ 14 ] = 0; sample->filename[14] = 0;
flags = dumbfile_igetw( f ); flags = dumbfile_igetw(f);
sample->default_volume = dumbfile_getc( f ); sample->default_volume = dumbfile_getc(f);
sample->length = dumbfile_igetl( f ); sample->length = dumbfile_igetl(f);
sample->loop_start = dumbfile_igetl( f ); sample->loop_start = dumbfile_igetl(f);
sample->loop_end = dumbfile_igetl( f ); sample->loop_end = dumbfile_igetl(f);
dumbfile_skip( f, 32 - 28 ); dumbfile_skip(f, 32 - 28);
sample->C5_speed = dumbfile_igetw( f ) * 2; sample->C5_speed = dumbfile_igetw(f) * 2;
dumbfile_skip( f, 36 - 34 ); dumbfile_skip(f, 36 - 34);
dumbfile_getnc( (char *) sample->name, 28, f ); dumbfile_getnc((char *)sample->name, 28, f);
sample->name[ 28 ] = 0; sample->name[28] = 0;
/*if ( data[ 0x38 ] || data[ 0x39 ] || data[ 0x3A ] || data[ 0x3B ] ) /*if ( data[ 0x38 ] || data[ 0x39 ] || data[ 0x3A ] || data[ 0x3B ] )
return -1;*/ return -1;*/
if ( ! sample->length ) { if (!sample->length) {
sample->flags &= ~IT_SAMPLE_EXISTS; sample->flags &= ~IT_SAMPLE_EXISTS;
return 0; return 0;
} }
@ -53,7 +53,7 @@ static int it_riff_dsmf_process_sample( IT_SAMPLE * sample, DUMBFILE * f, int le
/*if ( flags & ~( 2 | 1 ) ) /*if ( flags & ~( 2 | 1 ) )
return -1;*/ return -1;*/
if ( sample->length + 64 > len ) if (sample->length + 64 > len)
return -1; return -1;
sample->flags = IT_SAMPLE_EXISTS; sample->flags = IT_SAMPLE_EXISTS;
@ -67,42 +67,42 @@ static int it_riff_dsmf_process_sample( IT_SAMPLE * sample, DUMBFILE * f, int le
sample->finetune = 0; sample->finetune = 0;
sample->max_resampling_quality = -1; sample->max_resampling_quality = -1;
if ( flags & 1 ) if (flags & 1) {
{
if (((unsigned int)sample->loop_end <= (unsigned int)sample->length) && if (((unsigned int)sample->loop_end <= (unsigned int)sample->length) &&
((unsigned int)sample->loop_start < (unsigned int)sample->loop_end)) ((unsigned int)sample->loop_start <
{ (unsigned int)sample->loop_end)) {
sample->length = sample->loop_end; sample->length = sample->loop_end;
sample->flags |= IT_SAMPLE_LOOP; sample->flags |= IT_SAMPLE_LOOP;
if ( flags & 0x10 ) sample->flags |= IT_SAMPLE_PINGPONG_LOOP; if (flags & 0x10)
sample->flags |= IT_SAMPLE_PINGPONG_LOOP;
} }
} }
sample->data = malloc( sample->length ); sample->data = malloc(sample->length);
if ( ! sample->data ) if (!sample->data)
return -1; return -1;
dumbfile_getnc( sample->data, sample->length, f ); dumbfile_getnc(sample->data, sample->length, f);
if ( ! ( flags & 2 ) ) if (!(flags & 2)) {
{ for (flags = 0; flags < sample->length; ++flags)
for ( flags = 0; flags < sample->length; ++flags ) ((signed char *)sample->data)[flags] ^= 0x80;
( ( signed char * ) sample->data ) [ flags ] ^= 0x80;
} }
return 0; return 0;
} }
static int it_riff_dsmf_process_pattern( IT_PATTERN * pattern, DUMBFILE * f, int len ) static int it_riff_dsmf_process_pattern(IT_PATTERN *pattern, DUMBFILE *f,
{ int len) {
int length, row; int length, row;
unsigned flags; unsigned flags;
long start, end; long start, end;
int p, q, r; int p, q, r;
IT_ENTRY * entry; IT_ENTRY *entry;
length = dumbfile_igetw( f ); length = dumbfile_igetw(f);
if ( length > len ) return -1; if (length > len)
return -1;
len = length - 2; len = length - 2;
@ -111,46 +111,51 @@ static int it_riff_dsmf_process_pattern( IT_PATTERN * pattern, DUMBFILE * f, int
row = 0; row = 0;
start = dumbfile_pos( f ); start = dumbfile_pos(f);
end = start + len; end = start + len;
while ( (row < 64) && !dumbfile_error( f ) && (dumbfile_pos( f ) < end) ) { while ((row < 64) && !dumbfile_error(f) && (dumbfile_pos(f) < end)) {
p = dumbfile_getc( f ); p = dumbfile_getc(f);
if ( ! p ) { if (!p) {
++ row; ++row;
continue; continue;
} }
flags = p & 0xF0; flags = p & 0xF0;
if (flags) { if (flags) {
++ pattern->n_entries; ++pattern->n_entries;
if (flags & 0x80) dumbfile_skip( f, 1 ); if (flags & 0x80)
if (flags & 0x40) dumbfile_skip( f, 1 ); dumbfile_skip(f, 1);
if (flags & 0x20) dumbfile_skip( f, 1 ); if (flags & 0x40)
if (flags & 0x10) dumbfile_skip( f, 2 ); dumbfile_skip(f, 1);
if (flags & 0x20)
dumbfile_skip(f, 1);
if (flags & 0x10)
dumbfile_skip(f, 2);
} }
} }
if ( pattern->n_entries == 64 ) return 0; if (pattern->n_entries == 64)
return 0;
pattern->entry = malloc( pattern->n_entries * sizeof( * pattern->entry ) ); pattern->entry = malloc(pattern->n_entries * sizeof(*pattern->entry));
if ( ! pattern->entry ) return -1; if (!pattern->entry)
return -1;
entry = pattern->entry; entry = pattern->entry;
row = 0; row = 0;
if ( dumbfile_seek( f, start, DFS_SEEK_SET ) ) return -1; if (dumbfile_seek(f, start, DFS_SEEK_SET))
return -1;
while ( ( row < 64 ) && !dumbfile_error( f ) && ( dumbfile_pos( f ) < end ) ) while ((row < 64) && !dumbfile_error(f) && (dumbfile_pos(f) < end)) {
{ p = dumbfile_getc(f);
p = dumbfile_getc( f ); if (!p) {
if ( ! p ) IT_SET_END_ROW(entry);
{ ++entry;
IT_SET_END_ROW( entry ); ++row;
++ entry;
++ row;
continue; continue;
} }
@ -158,70 +163,67 @@ static int it_riff_dsmf_process_pattern( IT_PATTERN * pattern, DUMBFILE * f, int
entry->channel = flags & 0x0F; entry->channel = flags & 0x0F;
entry->mask = 0; entry->mask = 0;
if ( flags & 0xF0 ) if (flags & 0xF0) {
{ if (flags & 0x80) {
if ( flags & 0x80 ) q = dumbfile_getc(f);
{ if (q) {
q = dumbfile_getc( f );
if ( q )
{
entry->mask |= IT_ENTRY_NOTE; entry->mask |= IT_ENTRY_NOTE;
entry->note = q - 1; entry->note = q - 1;
} }
} }
if ( flags & 0x40 ) if (flags & 0x40) {
{ q = dumbfile_getc(f);
q = dumbfile_getc( f ); if (q) {
if ( q )
{
entry->mask |= IT_ENTRY_INSTRUMENT; entry->mask |= IT_ENTRY_INSTRUMENT;
entry->instrument = q; entry->instrument = q;
} }
} }
if ( flags & 0x20 ) if (flags & 0x20) {
{
entry->mask |= IT_ENTRY_VOLPAN; entry->mask |= IT_ENTRY_VOLPAN;
entry->volpan = dumbfile_getc( f ); entry->volpan = dumbfile_getc(f);
} }
if ( flags & 0x10 ) if (flags & 0x10) {
{ q = dumbfile_getc(f);
q = dumbfile_getc( f ); r = dumbfile_getc(f);
r = dumbfile_getc( f ); _dumb_it_xm_convert_effect(q, r, entry, 0);
_dumb_it_xm_convert_effect( q, r, entry, 0 );
} }
if (entry->mask) entry++; if (entry->mask)
entry++;
} }
} }
while ( row < 64 ) while (row < 64) {
{ IT_SET_END_ROW(entry);
IT_SET_END_ROW( entry ); ++entry;
++ entry; ++row;
++ row;
} }
pattern->n_entries = entry - pattern->entry; pattern->n_entries = (int)((long)entry - (long)pattern->entry);
if ( ! pattern->n_entries ) return -1; if (!pattern->n_entries)
return -1;
return 0; return 0;
} }
static DUMB_IT_SIGDATA *it_riff_dsmf_load_sigdata( DUMBFILE * f, struct riff * stream ) static DUMB_IT_SIGDATA *it_riff_dsmf_load_sigdata(DUMBFILE *f,
{ struct riff *stream) {
DUMB_IT_SIGDATA *sigdata; DUMB_IT_SIGDATA *sigdata;
int n, o, found; int n, o, found;
if ( ! stream ) goto error; if (!stream)
goto error;
if ( stream->type != DUMB_ID( 'D', 'S', 'M', 'F' ) ) goto error; if (stream->type != DUMB_ID('D', 'S', 'M', 'F'))
goto error;
sigdata = malloc(sizeof(*sigdata)); sigdata = malloc(sizeof(*sigdata));
if ( ! sigdata ) goto error; if (!sigdata)
goto error;
sigdata->n_patterns = 0; sigdata->n_patterns = 0;
sigdata->n_samples = 0; sigdata->n_samples = 0;
@ -229,30 +231,31 @@ static DUMB_IT_SIGDATA *it_riff_dsmf_load_sigdata( DUMBFILE * f, struct riff * s
found = 0; found = 0;
for ( n = 0; (unsigned)n < stream->chunk_count; ++n ) for (n = 0; (unsigned)n < stream->chunk_count; ++n) {
{ struct riff_chunk *c = stream->chunks + n;
struct riff_chunk * c = stream->chunks + n; switch (c->type) {
switch( c->type ) case DUMB_ID('S', 'O', 'N', 'G'):
{
case DUMB_ID( 'S' ,'O' ,'N' ,'G' ):
/* initialization data */ /* initialization data */
if ( ( found ) || ( c->size < 192 ) ) goto error_sd; if ((found) || (c->size < 192))
goto error_sd;
found = 1; found = 1;
break; break;
case DUMB_ID( 'P', 'A', 'T', 'T' ): case DUMB_ID('P', 'A', 'T', 'T'):
++ sigdata->n_patterns; ++sigdata->n_patterns;
break; break;
case DUMB_ID( 'I', 'N', 'S', 'T' ): case DUMB_ID('I', 'N', 'S', 'T'):
++ sigdata->n_samples; ++sigdata->n_samples;
break; break;
} }
} }
if ( !found || !sigdata->n_samples || !sigdata->n_patterns ) goto error_sd; if (!found || !sigdata->n_samples || !sigdata->n_patterns)
goto error_sd;
if ( sigdata->n_samples > 255 || sigdata->n_patterns > 255 ) goto error_sd; if (sigdata->n_samples > 255 || sigdata->n_patterns > 255)
goto error_sd;
sigdata->song_message = NULL; sigdata->song_message = NULL;
sigdata->order = NULL; sigdata->order = NULL;
@ -273,101 +276,104 @@ static DUMB_IT_SIGDATA *it_riff_dsmf_load_sigdata( DUMBFILE * f, struct riff * s
for (n = 0; n < DUMB_IT_N_CHANNELS; n += 4) { for (n = 0; n < DUMB_IT_N_CHANNELS; n += 4) {
int sep = 32 * dumb_it_default_panning_separation / 100; int sep = 32 * dumb_it_default_panning_separation / 100;
sigdata->channel_pan[n ] = 32 - sep; sigdata->channel_pan[n] = 32 - sep;
sigdata->channel_pan[n+1] = 32 + sep; sigdata->channel_pan[n + 1] = 32 + sep;
sigdata->channel_pan[n+2] = 32 + sep; sigdata->channel_pan[n + 2] = 32 + sep;
sigdata->channel_pan[n+3] = 32 - sep; sigdata->channel_pan[n + 3] = 32 - sep;
} }
for ( n = 0; (unsigned)n < stream->chunk_count; ++n ) for (n = 0; (unsigned)n < stream->chunk_count; ++n) {
{ struct riff_chunk *c = stream->chunks + n;
struct riff_chunk * c = stream->chunks + n; switch (c->type) {
switch ( c->type ) case DUMB_ID('S', 'O', 'N', 'G'):
{ if (dumbfile_seek(f, c->offset, DFS_SEEK_SET))
case DUMB_ID( 'S', 'O', 'N', 'G' ): goto error_usd;
if ( dumbfile_seek( f, c->offset, DFS_SEEK_SET ) ) goto error_usd; dumbfile_getnc((char *)sigdata->name, 28, f);
dumbfile_getnc( (char *) sigdata->name, 28, f ); sigdata->name[28] = 0;
sigdata->name[ 28 ] = 0;
sigdata->flags = IT_STEREO | IT_OLD_EFFECTS | IT_COMPATIBLE_GXX; sigdata->flags = IT_STEREO | IT_OLD_EFFECTS | IT_COMPATIBLE_GXX;
dumbfile_skip( f, 36 - 28 ); dumbfile_skip(f, 36 - 28);
sigdata->n_orders = dumbfile_igetw( f ); sigdata->n_orders = dumbfile_igetw(f);
//sigdata->n_samples = ptr[ 38 ] | ( ptr[ 39 ] << 8 ); // whatever // sigdata->n_samples = ptr[ 38 ] | ( ptr[ 39 ] << 8 ); // whatever
//sigdata->n_patterns = ptr[ 40 ] | ( ptr[ 41 ] << 8 ); // sigdata->n_patterns = ptr[ 40 ] | ( ptr[ 41 ] << 8 );
dumbfile_skip( f, 42 - 38 ); dumbfile_skip(f, 42 - 38);
sigdata->n_pchannels = dumbfile_igetw( f ); sigdata->n_pchannels = dumbfile_igetw(f);
sigdata->global_volume = dumbfile_getc( f ); sigdata->global_volume = dumbfile_getc(f);
sigdata->mixing_volume = dumbfile_getc( f ); sigdata->mixing_volume = dumbfile_getc(f);
sigdata->speed = dumbfile_getc( f ); sigdata->speed = dumbfile_getc(f);
sigdata->tempo = dumbfile_getc( f ); sigdata->tempo = dumbfile_getc(f);
for ( o = 0; o < 16; ++o ) for (o = 0; o < 16; ++o) {
{ sigdata->channel_pan[o] = dumbfile_getc(f) / 2;
sigdata->channel_pan[ o ] = dumbfile_getc( f ) / 2;
} }
sigdata->order = malloc( 128 ); sigdata->order = malloc(128);
if ( ! sigdata->order ) goto error_usd; if (!sigdata->order)
dumbfile_getnc( (char *) sigdata->order, 128, f ); goto error_usd;
dumbfile_getnc((char *)sigdata->order, 128, f);
break; break;
} }
} }
sigdata->pattern = malloc( sigdata->n_patterns * sizeof( *sigdata->pattern ) ); sigdata->pattern = malloc(sigdata->n_patterns * sizeof(*sigdata->pattern));
if ( ! sigdata->pattern ) goto error_usd; if (!sigdata->pattern)
for ( n = 0; n < sigdata->n_patterns; ++n ) goto error_usd;
sigdata->pattern[ n ].entry = NULL; for (n = 0; n < sigdata->n_patterns; ++n)
sigdata->pattern[n].entry = NULL;
sigdata->sample = malloc( sigdata->n_samples * sizeof( *sigdata->sample ) ); sigdata->sample = malloc(sigdata->n_samples * sizeof(*sigdata->sample));
if ( ! sigdata->sample ) goto error_usd; if (!sigdata->sample)
for ( n = 0; n < sigdata->n_samples; ++n ) goto error_usd;
{ for (n = 0; n < sigdata->n_samples; ++n) {
IT_SAMPLE * sample = sigdata->sample + n; IT_SAMPLE *sample = sigdata->sample + n;
sample->data = NULL; sample->data = NULL;
} }
sigdata->n_samples = 0; sigdata->n_samples = 0;
sigdata->n_patterns = 0; sigdata->n_patterns = 0;
for ( n = 0; (unsigned)n < stream->chunk_count; ++n ) for (n = 0; (unsigned)n < stream->chunk_count; ++n) {
{ struct riff_chunk *c = stream->chunks + n;
struct riff_chunk * c = stream->chunks + n; switch (c->type) {
switch ( c->type ) case DUMB_ID('P', 'A', 'T', 'T'):
{ if (dumbfile_seek(f, c->offset, DFS_SEEK_SET))
case DUMB_ID( 'P', 'A', 'T', 'T' ): goto error_usd;
if ( dumbfile_seek( f, c->offset, DFS_SEEK_SET ) ) goto error_usd; if (it_riff_dsmf_process_pattern(
if ( it_riff_dsmf_process_pattern( sigdata->pattern + sigdata->n_patterns, f, c->size ) ) goto error_usd; sigdata->pattern + sigdata->n_patterns, f, c->size))
++ sigdata->n_patterns; goto error_usd;
++sigdata->n_patterns;
break; break;
case DUMB_ID( 'I', 'N', 'S', 'T' ): case DUMB_ID('I', 'N', 'S', 'T'):
if ( dumbfile_seek( f, c->offset, DFS_SEEK_SET ) ) goto error_usd; if (dumbfile_seek(f, c->offset, DFS_SEEK_SET))
if ( it_riff_dsmf_process_sample( sigdata->sample + sigdata->n_samples, f, c->size ) ) goto error_usd; goto error_usd;
++ sigdata->n_samples; if (it_riff_dsmf_process_sample(
sigdata->sample + sigdata->n_samples, f, c->size))
goto error_usd;
++sigdata->n_samples;
break; break;
} }
} }
_dumb_it_fix_invalid_orders( sigdata ); _dumb_it_fix_invalid_orders(sigdata);
return sigdata; return sigdata;
error_usd: error_usd:
_dumb_it_unload_sigdata( sigdata ); _dumb_it_unload_sigdata(sigdata);
goto error; goto error;
error_sd: error_sd:
free( sigdata ); free(sigdata);
error: error:
return NULL; return NULL;
} }
DUH *dumb_read_riff_dsmf( DUMBFILE * f, struct riff * stream ) DUH *dumb_read_riff_dsmf(DUMBFILE *f, struct riff *stream) {
{
sigdata_t *sigdata; sigdata_t *sigdata;
DUH_SIGTYPE_DESC *descptr = &_dumb_sigtype_it; DUH_SIGTYPE_DESC *descptr = &_dumb_sigtype_it;
sigdata = it_riff_dsmf_load_sigdata( f, stream ); sigdata = it_riff_dsmf_load_sigdata(f, stream);
if (!sigdata) if (!sigdata)
return NULL; return NULL;
@ -378,6 +384,7 @@ DUH *dumb_read_riff_dsmf( DUMBFILE * f, struct riff * stream )
tag[0][1] = (const char *)(((DUMB_IT_SIGDATA *)sigdata)->name); tag[0][1] = (const char *)(((DUMB_IT_SIGDATA *)sigdata)->name);
tag[1][0] = "FORMAT"; tag[1][0] = "FORMAT";
tag[1][1] = "RIFF DSMF"; tag[1][1] = "RIFF DSMF";
return make_duh( -1, 2, ( const char * const (*) [ 2 ] ) tag, 1, & descptr, & sigdata ); return make_duh(-1, 2, (const char *const(*)[2])tag, 1, &descptr,
&sigdata);
} }
} }

View file

@ -25,10 +25,8 @@
#include "internal/dumb.h" #include "internal/dumb.h"
#include "internal/it.h" #include "internal/it.h"
static int it_mod_read_pattern(IT_PATTERN *pattern, DUMBFILE *f, int n_channels,
unsigned char *buffer) {
static int it_mod_read_pattern(IT_PATTERN *pattern, DUMBFILE *f, int n_channels, unsigned char *buffer)
{
int pos; int pos;
int channel; int channel;
int row; int row;
@ -38,11 +36,11 @@ static int it_mod_read_pattern(IT_PATTERN *pattern, DUMBFILE *f, int n_channels,
if (n_channels == 0) { if (n_channels == 0) {
/* Read the first four channels, leaving gaps for the rest. */ /* Read the first four channels, leaving gaps for the rest. */
for (pos = 0; pos < 64*8*4; pos += 8*4) for (pos = 0; pos < 64 * 8 * 4; pos += 8 * 4)
dumbfile_getnc((char *)buffer + pos, 4*4, f); dumbfile_getnc((char *)buffer + pos, 4 * 4, f);
/* Read the other channels into the gaps we left. */ /* Read the other channels into the gaps we left. */
for (pos = 4*4; pos < 64*8*4; pos += 8*4) for (pos = 4 * 4; pos < 64 * 8 * 4; pos += 8 * 4)
dumbfile_getnc((char *)buffer + pos, 4*4, f); dumbfile_getnc((char *)buffer + pos, 4 * 4, f);
n_channels = 8; n_channels = 8;
} else } else
@ -56,7 +54,8 @@ static int it_mod_read_pattern(IT_PATTERN *pattern, DUMBFILE *f, int n_channels,
pos = 0; pos = 0;
for (row = 0; row < 64; row++) { for (row = 0; row < 64; row++) {
for (channel = 0; channel < n_channels; channel++) { for (channel = 0; channel < n_channels; channel++) {
if (buffer[pos+0] | buffer[pos+1] | buffer[pos+2] | buffer[pos+3]) if (buffer[pos + 0] | buffer[pos + 1] | buffer[pos + 2] |
buffer[pos + 3])
pattern->n_entries++; pattern->n_entries++;
pos += 4; pos += 4;
} }
@ -70,9 +69,12 @@ static int it_mod_read_pattern(IT_PATTERN *pattern, DUMBFILE *f, int n_channels,
pos = 0; pos = 0;
for (row = 0; row < 64; row++) { for (row = 0; row < 64; row++) {
for (channel = 0; channel < n_channels; channel++) { for (channel = 0; channel < n_channels; channel++) {
if (buffer[pos+0] | buffer[pos+1] | buffer[pos+2] | buffer[pos+3]) { if (buffer[pos + 0] | buffer[pos + 1] | buffer[pos + 2] |
unsigned char sample = (buffer[pos+0] & 0xF0) | (buffer[pos+2] >> 4); buffer[pos + 3]) {
int period = ((int)(buffer[pos+0] & 0x0F) << 8) | buffer[pos+1]; unsigned char sample =
(buffer[pos + 0] & 0xF0) | (buffer[pos + 2] >> 4);
int period =
((int)(buffer[pos + 0] & 0x0F) << 8) | buffer[pos + 1];
entry->channel = channel; entry->channel = channel;
entry->mask = 0; entry->mask = 0;
@ -91,11 +93,12 @@ static int it_mod_read_pattern(IT_PATTERN *pattern, DUMBFILE *f, int n_channels,
* pow(DUMB_SEMITONE_BASE, note - 60) = 214 / period * pow(DUMB_SEMITONE_BASE, note - 60) = 214 / period
* note - 60 = log(214/period) / log(DUMB_SEMITONE_BASE) * note - 60 = log(214/period) / log(DUMB_SEMITONE_BASE)
*/ */
note = (int)floor(log(214.0/period) / log(DUMB_SEMITONE_BASE) + 60.5); note = (int)floor(
log(214.0 / period) / log(DUMB_SEMITONE_BASE) + 60.5);
entry->note = MID(0, note, 119); entry->note = MID(0, note, 119);
// or should we preserve the period? // or should we preserve the period?
//entry->note = buffer[pos+0] & 0x0F; /* High nibble */ // entry->note = buffer[pos+0] & 0x0F; /* High nibble */
//entry->volpan = buffer[pos+1]; /* Low byte */ // entry->volpan = buffer[pos+1]; /* Low byte */
// and what about finetune? // and what about finetune?
} }
@ -104,7 +107,8 @@ static int it_mod_read_pattern(IT_PATTERN *pattern, DUMBFILE *f, int n_channels,
entry->instrument = sample; entry->instrument = sample;
} }
_dumb_it_xm_convert_effect(buffer[pos+2] & 0x0F, buffer[pos+3], entry, 1); _dumb_it_xm_convert_effect(buffer[pos + 2] & 0x0F,
buffer[pos + 3], entry, 1);
entry++; entry++;
} }
@ -117,49 +121,51 @@ static int it_mod_read_pattern(IT_PATTERN *pattern, DUMBFILE *f, int n_channels,
return 0; return 0;
} }
static int it_mod_read_sample_header(IT_SAMPLE *sample, DUMBFILE *f,
unsigned long fft, int stk) {
static int it_mod_read_sample_header(IT_SAMPLE *sample, DUMBFILE *f, unsigned long fft, int stk)
{
int finetune, loop_start, loop_length; int finetune, loop_start, loop_length;
/** /**
21 22 Chars Sample 1 name. If the name is not a full 21 22 Chars Sample 1 name. If the name is not a full
22 chars in length, it will be null 22 chars in length, it will be null
terminated. terminated.
If If
the sample name begins with a '#' character (ASCII $23 (35)) then this is the sample name begins with a '#' character (ASCII $23 (35)) then this is
assumed not to be an instrument name, and is probably a message. assumed not to be an instrument name, and is probably a message.
*/ */
dumbfile_getnc((char *)sample->name, 22, f); dumbfile_getnc((char *)sample->name, 22, f);
sample->name[22] = 0; sample->name[22] = 0;
sample->filename[0] = 0; sample->filename[0] = 0;
sample->length = dumbfile_mgetw(f) << 1; sample->length = dumbfile_mgetw(f) << 1;
if (fft == DUMB_ID('F','E','S','T')) if (fft == DUMB_ID('F', 'E', 'S', 'T'))
finetune = (signed char)((-dumbfile_getc(f) & 0x1F) << 3) >> 3; finetune = (signed char)((-dumbfile_getc(f) & 0x1F) << 3) >> 3;
else else
finetune = (signed char)(dumbfile_getc(f) << 4) >> 4; /* signed nibble */ finetune =
/** Each finetune step changes the note 1/8th of a semitone. */ (signed char)(dumbfile_getc(f) << 4) >> 4; /* signed nibble */
/** Each finetune step changes the note 1/8th of a semitone. */
sample->global_volume = 64; sample->global_volume = 64;
sample->default_volume = dumbfile_getc(f); // Should we be setting global_volume to this instead? sample->default_volume =
dumbfile_getc(f); // Should we be setting global_volume to this instead?
loop_start = dumbfile_mgetw(f); loop_start = dumbfile_mgetw(f);
if ( !stk ) loop_start <<= 1; if (!stk)
loop_start <<= 1;
loop_length = dumbfile_mgetw(f) << 1; loop_length = dumbfile_mgetw(f) << 1;
if ( loop_length > 2 && loop_start + loop_length > sample->length && loop_start / 2 + loop_length <= sample->length ) if (loop_length > 2 && loop_start + loop_length > sample->length &&
loop_start / 2 + loop_length <= sample->length)
loop_start /= 2; loop_start /= 2;
sample->loop_start = loop_start; sample->loop_start = loop_start;
sample->loop_end = loop_start + loop_length; sample->loop_end = loop_start + loop_length;
/** /**
Once this sample has been played completely from beginning Once this sample has been played completely from beginning
to end, if the repeat length (next field) is greater than two bytes it to end, if the repeat length (next field) is greater than two bytes it
will loop back to this position in the sample and continue playing. Once will loop back to this position in the sample and continue playing. Once
it has played for the repeat length, it continues to loop back to the it has played for the repeat length, it continues to loop back to the
repeat start offset. This means the sample continues playing until it is repeat start offset. This means the sample continues playing until it is
told to stop. told to stop.
*/ */
if (sample->length <= 0) { if (sample->length <= 0) {
sample->flags = 0; sample->flags = 0;
@ -169,8 +175,11 @@ told to stop.
sample->flags = IT_SAMPLE_EXISTS; sample->flags = IT_SAMPLE_EXISTS;
sample->default_pan = 0; sample->default_pan = 0;
sample->C5_speed = (int)( AMIGA_CLOCK / 214.0 ); //(long)(16726.0*pow(DUMB_PITCH_BASE, finetune*32)); sample->C5_speed =
sample->finetune = finetune * ((fft == DUMB_ID('F','E','S','T')) ? 16 : 32); (int)(AMIGA_CLOCK /
214.0); //(long)(16726.0*pow(DUMB_PITCH_BASE, finetune*32));
sample->finetune =
finetune * ((fft == DUMB_ID('F', 'E', 'S', 'T')) ? 16 : 32);
// the above line might be wrong // the above line might be wrong
if (sample->loop_end > sample->length) if (sample->loop_end > sample->length)
@ -188,10 +197,8 @@ told to stop.
return dumbfile_error(f); return dumbfile_error(f);
} }
static int it_mod_read_sample_data(IT_SAMPLE *sample, DUMBFILE *f,
unsigned long fft) {
static int it_mod_read_sample_data(IT_SAMPLE *sample, DUMBFILE *f, unsigned long fft)
{
long i; long i;
long truncated_size; long truncated_size;
@ -215,53 +222,46 @@ static int it_mod_read_sample_data(IT_SAMPLE *sample, DUMBFILE *f, unsigned long
((signed char *)sample->left)[i] = dumbfile_getc(f); ((signed char *)sample->left)[i] = dumbfile_getc(f);
*/ */
/* F U Olivier Lapicque */ /* F U Olivier Lapicque */
if (sample->length >= 5) if (sample->length >= 5) {
{
i = dumbfile_getnc(sample->data, 5, f); i = dumbfile_getnc(sample->data, 5, f);
if (i == 5) if (i == 5) {
{ if (!memcmp(sample->data, "ADPCM", 5)) {
if (!memcmp(sample->data, "ADPCM", 5))
{
if (_dumb_it_read_sample_data_adpcm4(sample, f) < 0) if (_dumb_it_read_sample_data_adpcm4(sample, f) < 0)
return -1; return -1;
return 0; return 0;
} } else {
else i += dumbfile_getnc(((char *)sample->data) + 5,
{ sample->length - 5, f);
i += dumbfile_getnc(((char *)sample->data) + 5, sample->length - 5, f);
} }
} }
} } else {
else
{
i = dumbfile_getnc(sample->data, sample->length, f); i = dumbfile_getnc(sample->data, sample->length, f);
} }
if (i < sample->length) if (i < sample->length) {
{ if (i <= 0) {
if (i <= 0)
{
sample->flags = 0; sample->flags = 0;
return 0; return 0;
} }
sample->length = i; sample->length = i;
if (sample->loop_end > i) sample->loop_end = i; if (sample->loop_end > i)
sample->loop_end = i;
// holy crap! // holy crap!
if (sample->loop_start > i) sample->flags &= ~IT_SAMPLE_LOOP; if (sample->loop_start > i)
} sample->flags &= ~IT_SAMPLE_LOOP;
else } else {
{
/* skip truncated data */ /* skip truncated data */
int feh = dumbfile_error(f); int feh = dumbfile_error(f);
if (truncated_size) dumbfile_skip(f, truncated_size); if (truncated_size)
dumbfile_skip(f, truncated_size);
// Should we be truncating it? // Should we be truncating it?
if (feh) if (feh)
return -1; return -1;
} }
if (fft == DUMB_ID('M',0,0,0) || fft == DUMB_ID('8',0,0,0)) { if (fft == DUMB_ID('M', 0, 0, 0) || fft == DUMB_ID('8', 0, 0, 0)) {
int delta = 0; int delta = 0;
for (i = 0; i < sample->length; i++) { for (i = 0; i < sample->length; i++) {
delta += ((signed char *)sample->data)[i]; delta += ((signed char *)sample->data)[i];
@ -273,25 +273,22 @@ static int it_mod_read_sample_data(IT_SAMPLE *sample, DUMBFILE *f, unsigned long
return 0; return 0;
} }
#define MOD_FFT_OFFSET (20 + 31 * (22 + 2 + 1 + 1 + 2 + 2) + 1 + 1 + 128)
static DUMB_IT_SIGDATA *it_mod_load_sigdata(DUMBFILE *f, int restrict_) {
#define MOD_FFT_OFFSET (20 + 31*(22+2+1+1+2+2) + 1 + 1 + 128)
static DUMB_IT_SIGDATA *it_mod_load_sigdata(DUMBFILE *f, int restrict_)
{
DUMB_IT_SIGDATA *sigdata; DUMB_IT_SIGDATA *sigdata;
int n_channels; int n_channels;
int i; int i;
unsigned long fft; unsigned long fft;
if ( dumbfile_seek(f, MOD_FFT_OFFSET, DFS_SEEK_SET) ) if (dumbfile_seek(f, MOD_FFT_OFFSET, DFS_SEEK_SET))
return NULL; return NULL;
fft = dumbfile_mgetl(f); fft = dumbfile_mgetl(f);
if (dumbfile_error(f)) if (dumbfile_error(f))
return NULL; return NULL;
if ( dumbfile_seek(f, 0, DFS_SEEK_SET) ) if (dumbfile_seek(f, 0, DFS_SEEK_SET))
return NULL; return NULL;
sigdata = malloc(sizeof(*sigdata)); sigdata = malloc(sizeof(*sigdata));
@ -313,18 +310,18 @@ static DUMB_IT_SIGDATA *it_mod_load_sigdata(DUMBFILE *f, int restrict_)
sigdata->n_samples = 31; sigdata->n_samples = 31;
switch (fft) { switch (fft) {
case DUMB_ID('M','.','K','.'): case DUMB_ID('M', '.', 'K', '.'):
case DUMB_ID('M','!','K','!'): case DUMB_ID('M', '!', 'K', '!'):
case DUMB_ID('M','&','K','!'): case DUMB_ID('M', '&', 'K', '!'):
case DUMB_ID('N','.','T','.'): case DUMB_ID('N', '.', 'T', '.'):
case DUMB_ID('N','S','M','S'): case DUMB_ID('N', 'S', 'M', 'S'):
case DUMB_ID('F','L','T','4'): case DUMB_ID('F', 'L', 'T', '4'):
case DUMB_ID('M',0,0,0): case DUMB_ID('M', 0, 0, 0):
case DUMB_ID('8',0,0,0): case DUMB_ID('8', 0, 0, 0):
case DUMB_ID('F','E','S','T'): case DUMB_ID('F', 'E', 'S', 'T'):
n_channels = 4; n_channels = 4;
break; break;
case DUMB_ID('F','L','T','8'): case DUMB_ID('F', 'L', 'T', '8'):
n_channels = 0; n_channels = 0;
/* 0 indicates a special case; two four-channel patterns must be /* 0 indicates a special case; two four-channel patterns must be
* combined into one eight-channel pattern. Pattern indexes must * combined into one eight-channel pattern. Pattern indexes must
@ -333,20 +330,20 @@ static DUMB_IT_SIGDATA *it_mod_load_sigdata(DUMBFILE *f, int restrict_)
/*for (i = 0; i < 128; i++) /*for (i = 0; i < 128; i++)
sigdata->order[i] >>= 1;*/ sigdata->order[i] >>= 1;*/
break; break;
case DUMB_ID('C','D','8','1'): case DUMB_ID('C', 'D', '8', '1'):
case DUMB_ID('O','C','T','A'): case DUMB_ID('O', 'C', 'T', 'A'):
case DUMB_ID('O','K','T','A'): case DUMB_ID('O', 'K', 'T', 'A'):
n_channels = 8; n_channels = 8;
break; break;
case DUMB_ID('1','6','C','N'): case DUMB_ID('1', '6', 'C', 'N'):
n_channels = 16; n_channels = 16;
break; break;
case DUMB_ID('3','2','C','N'): case DUMB_ID('3', '2', 'C', 'N'):
n_channels = 32; n_channels = 32;
break; break;
default: default:
/* If we get an illegal tag, assume 4 channels 15 samples. */ /* If we get an illegal tag, assume 4 channels 15 samples. */
if ((fft & 0x0000FFFFL) == DUMB_ID(0,0,'C','H')) { if ((fft & 0x0000FFFFL) == DUMB_ID(0, 0, 'C', 'H')) {
if (fft >= '1' << 24 && fft < '4' << 24) { if (fft >= '1' << 24 && fft < '4' << 24) {
n_channels = ((fft & 0x00FF0000L) >> 16) - '0'; n_channels = ((fft & 0x00FF0000L) >> 16) - '0';
if ((unsigned int)n_channels >= 10) { if ((unsigned int)n_channels >= 10) {
@ -355,8 +352,10 @@ static DUMB_IT_SIGDATA *it_mod_load_sigdata(DUMBFILE *f, int restrict_)
sigdata->n_samples = 15; sigdata->n_samples = 15;
} else { } else {
n_channels += (((fft & 0xFF000000L) >> 24) - '0') * 10; n_channels += (((fft & 0xFF000000L) >> 24) - '0') * 10;
/* MODs should really only go up to 32 channels, but we're lenient. */ /* MODs should really only go up to 32 channels, but we're
if ((unsigned int)(n_channels - 1) >= DUMB_IT_N_CHANNELS - 1) { * lenient. */
if ((unsigned int)(n_channels - 1) >=
DUMB_IT_N_CHANNELS - 1) {
/* No channels or too many? Can't be right... */ /* No channels or too many? Can't be right... */
n_channels = 4; n_channels = 4;
sigdata->n_samples = 15; sigdata->n_samples = 15;
@ -366,14 +365,14 @@ static DUMB_IT_SIGDATA *it_mod_load_sigdata(DUMBFILE *f, int restrict_)
n_channels = 4; n_channels = 4;
sigdata->n_samples = 15; sigdata->n_samples = 15;
} }
} else if ((fft & 0x00FFFFFFL) == DUMB_ID(0,'C','H','N')) { } else if ((fft & 0x00FFFFFFL) == DUMB_ID(0, 'C', 'H', 'N')) {
n_channels = (fft >> 24) - '0'; n_channels = (int)((fft >> 24) - '0');
if ((unsigned int)(n_channels - 1) >= 9) { if ((unsigned int)(n_channels - 1) >= 9) {
/* Character was '0' or it wasn't a digit */ /* Character was '0' or it wasn't a digit */
n_channels = 4; n_channels = 4;
sigdata->n_samples = 15; sigdata->n_samples = 15;
} }
} else if ((fft & 0xFFFFFF00L) == DUMB_ID('T','D','Z',0)) { } else if ((fft & 0xFFFFFF00L) == DUMB_ID('T', 'D', 'Z', 0)) {
n_channels = (fft & 0x000000FFL) - '0'; n_channels = (fft & 0x000000FFL) - '0';
if ((unsigned int)(n_channels - 1) >= 9) { if ((unsigned int)(n_channels - 1) >= 9) {
/* We've been very lenient, given that it should have /* We've been very lenient, given that it should have
@ -391,13 +390,13 @@ static DUMB_IT_SIGDATA *it_mod_load_sigdata(DUMBFILE *f, int restrict_)
} }
// moo // moo
if ( ( restrict_ & 1 ) && sigdata->n_samples == 15 ) if ((restrict_ & 1) && sigdata->n_samples == 15) {
{
free(sigdata); free(sigdata);
return NULL; return NULL;
} }
sigdata->n_pchannels = n_channels ? n_channels : 8; /* special case for 0, see above */ sigdata->n_pchannels =
n_channels ? n_channels : 8; /* special case for 0, see above */
sigdata->sample = malloc(sigdata->n_samples * sizeof(*sigdata->sample)); sigdata->sample = malloc(sigdata->n_samples * sizeof(*sigdata->sample));
if (!sigdata->sample) { if (!sigdata->sample) {
@ -418,7 +417,8 @@ static DUMB_IT_SIGDATA *it_mod_load_sigdata(DUMBFILE *f, int restrict_)
sigdata->sample[i].data = NULL; sigdata->sample[i].data = NULL;
for (i = 0; i < sigdata->n_samples; i++) { for (i = 0; i < sigdata->n_samples; i++) {
if (it_mod_read_sample_header(&sigdata->sample[i], f, fft, sigdata->n_samples == 15)) { if (it_mod_read_sample_header(&sigdata->sample[i], f, fft,
sigdata->n_samples == 15)) {
_dumb_it_unload_sigdata(sigdata); _dumb_it_unload_sigdata(sigdata);
return NULL; return NULL;
} }
@ -428,13 +428,12 @@ static DUMB_IT_SIGDATA *it_mod_load_sigdata(DUMBFILE *f, int restrict_)
sigdata->restart_position = dumbfile_getc(f); sigdata->restart_position = dumbfile_getc(f);
// what if this is >= 127? what about with Fast Tracker II? // what if this is >= 127? what about with Fast Tracker II?
/* if (sigdata->n_orders <= 0 || sigdata->n_orders > 128) { // is this right? /* if (sigdata->n_orders <= 0 || sigdata->n_orders > 128) { // is this
_dumb_it_unload_sigdata(sigdata); right? _dumb_it_unload_sigdata(sigdata); return NULL;
return NULL;
}*/ }*/
//if (sigdata->restart_position >= sigdata->n_orders) // if (sigdata->restart_position >= sigdata->n_orders)
//sigdata->restart_position = 0; // sigdata->restart_position = 0;
sigdata->order = malloc(128); /* We may need to scan the extra ones! */ sigdata->order = malloc(128); /* We may need to scan the extra ones! */
if (!sigdata->order) { if (!sigdata->order) {
@ -448,10 +447,11 @@ static DUMB_IT_SIGDATA *it_mod_load_sigdata(DUMBFILE *f, int restrict_)
if (sigdata->n_orders <= 0 || sigdata->n_orders > 128) { // is this right? if (sigdata->n_orders <= 0 || sigdata->n_orders > 128) { // is this right?
sigdata->n_orders = 128; sigdata->n_orders = 128;
//while (sigdata->n_orders > 1 && !sigdata->order[sigdata->n_orders - 1]) sigdata->n_orders--; // while (sigdata->n_orders > 1 && !sigdata->order[sigdata->n_orders -
// 1]) sigdata->n_orders--;
} }
if ( ! n_channels ) if (!n_channels)
for (i = 0; i < 128; i++) for (i = 0; i < 128; i++)
sigdata->order[i] >>= 1; sigdata->order[i] >>= 1;
@ -466,15 +466,13 @@ static DUMB_IT_SIGDATA *it_mod_load_sigdata(DUMBFILE *f, int restrict_)
sigdata->n_patterns = -1; sigdata->n_patterns = -1;
if ( ( restrict_ & 2 ) ) if ((restrict_ & 2)) {
{
unsigned char buffer[5]; unsigned char buffer[5];
long sample_number; long sample_number;
long total_sample_size; long total_sample_size;
long offset = dumbfile_pos(f); long offset = dumbfile_pos(f);
long remain = dumbfile_get_size(f) - offset; long remain = dumbfile_get_size(f) - offset;
if ( dumbfile_error( f ) || if (dumbfile_error(f) || dumbfile_seek(f, 0, SEEK_END)) {
dumbfile_seek( f, 0, SEEK_END ) ) {
_dumb_it_unload_sigdata(sigdata); _dumb_it_unload_sigdata(sigdata);
return NULL; return NULL;
} }
@ -482,20 +480,32 @@ static DUMB_IT_SIGDATA *it_mod_load_sigdata(DUMBFILE *f, int restrict_)
total_sample_size = 0; total_sample_size = 0;
while (dumbfile_pos(f) > offset && sample_number >= 0) { while (dumbfile_pos(f) > offset && sample_number >= 0) {
if (sigdata->sample[sample_number].flags & IT_SAMPLE_EXISTS) { if (sigdata->sample[sample_number].flags & IT_SAMPLE_EXISTS) {
if ( dumbfile_seek(f, -((sigdata->sample[sample_number].length + 1) / 2 + 5 + 16), DFS_SEEK_CUR) || if (dumbfile_seek(
dumbfile_getnc((char *)buffer, 5, f) < 5 ) { f,
-((sigdata->sample[sample_number].length + 1) / 2 + 5 +
16),
DFS_SEEK_CUR) ||
dumbfile_getnc((char *)buffer, 5, f) < 5) {
_dumb_it_unload_sigdata(sigdata); _dumb_it_unload_sigdata(sigdata);
return NULL; return NULL;
} }
if ( !memcmp( buffer, "ADPCM", 5 ) ) { /* BAH */ if (!memcmp(buffer, "ADPCM", 5)) { /* BAH */
total_sample_size += (sigdata->sample[sample_number].length + 1) / 2 + 5 + 16; total_sample_size +=
if ( dumbfile_seek(f, -5, DFS_SEEK_CUR) ) { (sigdata->sample[sample_number].length + 1) / 2 + 5 +
16;
if (dumbfile_seek(f, -5, DFS_SEEK_CUR)) {
_dumb_it_unload_sigdata(sigdata); _dumb_it_unload_sigdata(sigdata);
return NULL; return NULL;
} }
} else { } else {
total_sample_size += sigdata->sample[sample_number].length; total_sample_size += sigdata->sample[sample_number].length;
if ( dumbfile_seek(f, -(sigdata->sample[sample_number].length - ((sigdata->sample[sample_number].length + 1) / 2 + 5 + 16) + 5), DFS_SEEK_CUR) ) { if (dumbfile_seek(
f,
-(sigdata->sample[sample_number].length -
((sigdata->sample[sample_number].length + 1) / 2 +
5 + 16) +
5),
DFS_SEEK_CUR)) {
_dumb_it_unload_sigdata(sigdata); _dumb_it_unload_sigdata(sigdata);
return NULL; return NULL;
} }
@ -505,8 +515,9 @@ static DUMB_IT_SIGDATA *it_mod_load_sigdata(DUMBFILE *f, int restrict_)
} }
if (remain > total_sample_size) { if (remain > total_sample_size) {
sigdata->n_patterns = ( remain - total_sample_size + 4 ) / ( 256 * sigdata->n_pchannels ); sigdata->n_patterns = (int)((remain - total_sample_size + 4) /
if (fft == DUMB_ID('M',0,0,0) || fft == DUMB_ID('8',0,0,0)) { (256 * sigdata->n_pchannels));
if (fft == DUMB_ID('M', 0, 0, 0) || fft == DUMB_ID('8', 0, 0, 0)) {
remain -= sigdata->n_patterns * 256 * sigdata->n_pchannels; remain -= sigdata->n_patterns * 256 * sigdata->n_pchannels;
if (dumbfile_skip(f, remain - total_sample_size)) { if (dumbfile_skip(f, remain - total_sample_size)) {
_dumb_it_unload_sigdata(sigdata); _dumb_it_unload_sigdata(sigdata);
@ -514,18 +525,15 @@ static DUMB_IT_SIGDATA *it_mod_load_sigdata(DUMBFILE *f, int restrict_)
} }
} }
} }
} } else {
else for (i = 0; i < 128; i++) {
{
for (i = 0; i < 128; i++)
{
if (sigdata->order[i] > sigdata->n_patterns) if (sigdata->order[i] > sigdata->n_patterns)
sigdata->n_patterns = sigdata->order[i]; sigdata->n_patterns = sigdata->order[i];
} }
sigdata->n_patterns++; sigdata->n_patterns++;
} }
if ( sigdata->n_patterns <= 0 ) { if (sigdata->n_patterns <= 0) {
_dumb_it_unload_sigdata(sigdata); _dumb_it_unload_sigdata(sigdata);
return NULL; return NULL;
} }
@ -533,7 +541,8 @@ static DUMB_IT_SIGDATA *it_mod_load_sigdata(DUMBFILE *f, int restrict_)
/* May as well try to save a tiny bit of memory. */ /* May as well try to save a tiny bit of memory. */
if (sigdata->n_orders < 128) { if (sigdata->n_orders < 128) {
unsigned char *order = realloc(sigdata->order, sigdata->n_orders); unsigned char *order = realloc(sigdata->order, sigdata->n_orders);
if (order) sigdata->order = order; if (order)
sigdata->order = order;
} }
sigdata->pattern = malloc(sigdata->n_patterns * sizeof(*sigdata->pattern)); sigdata->pattern = malloc(sigdata->n_patterns * sizeof(*sigdata->pattern));
@ -546,13 +555,15 @@ static DUMB_IT_SIGDATA *it_mod_load_sigdata(DUMBFILE *f, int restrict_)
/* Read in the patterns */ /* Read in the patterns */
{ {
unsigned char *buffer = malloc(256 * sigdata->n_pchannels); /* 64 rows * 4 bytes */ unsigned char *buffer =
malloc(256 * sigdata->n_pchannels); /* 64 rows * 4 bytes */
if (!buffer) { if (!buffer) {
_dumb_it_unload_sigdata(sigdata); _dumb_it_unload_sigdata(sigdata);
return NULL; return NULL;
} }
for (i = 0; i < sigdata->n_patterns; i++) { for (i = 0; i < sigdata->n_patterns; i++) {
if (it_mod_read_pattern(&sigdata->pattern[i], f, n_channels, buffer) != 0) { if (it_mod_read_pattern(&sigdata->pattern[i], f, n_channels,
buffer) != 0) {
free(buffer); free(buffer);
_dumb_it_unload_sigdata(sigdata); _dumb_it_unload_sigdata(sigdata);
return NULL; return NULL;
@ -588,7 +599,8 @@ static DUMB_IT_SIGDATA *it_mod_load_sigdata(DUMBFILE *f, int restrict_)
}*/ }*/
/* Now let's initialise the remaining variables, and we're done! */ /* Now let's initialise the remaining variables, and we're done! */
sigdata->flags = IT_WAS_AN_XM | IT_WAS_A_MOD | IT_OLD_EFFECTS | IT_COMPATIBLE_GXX | IT_STEREO; sigdata->flags = IT_WAS_AN_XM | IT_WAS_A_MOD | IT_OLD_EFFECTS |
IT_COMPATIBLE_GXX | IT_STEREO;
sigdata->global_volume = 128; sigdata->global_volume = 128;
sigdata->mixing_volume = 48; sigdata->mixing_volume = 48;
@ -603,10 +615,10 @@ static DUMB_IT_SIGDATA *it_mod_load_sigdata(DUMBFILE *f, int restrict_)
for (i = 0; i < DUMB_IT_N_CHANNELS; i += 4) { for (i = 0; i < DUMB_IT_N_CHANNELS; i += 4) {
int sep = 32 * dumb_it_default_panning_separation / 100; int sep = 32 * dumb_it_default_panning_separation / 100;
sigdata->channel_pan[i+0] = 32 - sep; sigdata->channel_pan[i + 0] = 32 - sep;
sigdata->channel_pan[i+1] = 32 + sep; sigdata->channel_pan[i + 1] = 32 + sep;
sigdata->channel_pan[i+2] = 32 + sep; sigdata->channel_pan[i + 2] = 32 + sep;
sigdata->channel_pan[i+3] = 32 - sep; sigdata->channel_pan[i + 3] = 32 - sep;
} }
_dumb_it_fix_invalid_orders(sigdata); _dumb_it_fix_invalid_orders(sigdata);
@ -614,10 +626,7 @@ static DUMB_IT_SIGDATA *it_mod_load_sigdata(DUMBFILE *f, int restrict_)
return sigdata; return sigdata;
} }
DUH *dumb_read_mod_quick(DUMBFILE *f, int restrict_) {
DUH *dumb_read_mod_quick(DUMBFILE *f, int restrict_)
{
sigdata_t *sigdata; sigdata_t *sigdata;
DUH_SIGTYPE_DESC *descptr = &_dumb_sigtype_it; DUH_SIGTYPE_DESC *descptr = &_dumb_sigtype_it;
@ -633,6 +642,7 @@ DUH *dumb_read_mod_quick(DUMBFILE *f, int restrict_)
tag[0][1] = (const char *)(((DUMB_IT_SIGDATA *)sigdata)->name); tag[0][1] = (const char *)(((DUMB_IT_SIGDATA *)sigdata)->name);
tag[1][0] = "FORMAT"; tag[1][0] = "FORMAT";
tag[1][1] = "MOD"; tag[1][1] = "MOD";
return make_duh(-1, 2, (const char *const (*)[2])tag, 1, &descptr, &sigdata); return make_duh(-1, 2, (const char *const(*)[2])tag, 1, &descptr,
&sigdata);
} }
} }

View file

@ -19,10 +19,7 @@
#include "dumb.h" #include "dumb.h"
DUH *dumb_read_mod(DUMBFILE *f, int restrict_) {
DUH *dumb_read_mod(DUMBFILE *f, int restrict_)
{
DUH *duh = dumb_read_mod_quick(f, restrict_); DUH *duh = dumb_read_mod_quick(f, restrict_);
dumb_it_do_initial_runthrough(duh); dumb_it_do_initial_runthrough(duh);
return duh; return duh;

View file

@ -24,21 +24,23 @@
#include "dumb.h" #include "dumb.h"
#include "internal/it.h" #include "internal/it.h"
size_t strlen_max(const char * ptr, size_t max) size_t strlen_max(const char *ptr, size_t max) {
{ const char *end, *start;
const char * end, * start; if (ptr == 0)
if (ptr==0) return 0; return 0;
start = ptr; start = ptr;
end = ptr + max; end = ptr + max;
while(ptr < end && *ptr) ptr++; while (ptr < end && *ptr)
ptr++;
return ptr - start; return ptr - start;
} }
static int it_mtm_assemble_pattern(IT_PATTERN *pattern, const unsigned char * track, const unsigned short * sequence, int n_rows) static int it_mtm_assemble_pattern(IT_PATTERN *pattern,
{ const unsigned char *track,
const unsigned short *sequence, int n_rows) {
int n, o, note, sample; int n, o, note, sample;
const unsigned char * t; const unsigned char *t;
IT_ENTRY * entry; IT_ENTRY *entry;
pattern->n_rows = n_rows; pattern->n_rows = n_rows;
pattern->n_entries = n_rows; pattern->n_entries = n_rows;
@ -47,14 +49,16 @@ static int it_mtm_assemble_pattern(IT_PATTERN *pattern, const unsigned char * tr
if (sequence[n]) { if (sequence[n]) {
t = &track[192 * (sequence[n] - 1)]; t = &track[192 * (sequence[n] - 1)];
for (o = 0; o < n_rows; o++) { for (o = 0; o < n_rows; o++) {
if (t[0] || t[1] || t[2]) pattern->n_entries++; if (t[0] || t[1] || t[2])
pattern->n_entries++;
t += 3; t += 3;
} }
} }
} }
entry = malloc(pattern->n_entries * sizeof(*entry)); entry = malloc(pattern->n_entries * sizeof(*entry));
if (!entry) return -1; if (!entry)
return -1;
pattern->entry = entry; pattern->entry = entry;
for (n = 0; n < n_rows; n++) { for (n = 0; n < n_rows; n++) {
@ -79,7 +83,8 @@ static int it_mtm_assemble_pattern(IT_PATTERN *pattern, const unsigned char * tr
_dumb_it_xm_convert_effect(t[1] & 0xF, t[2], entry, 1); _dumb_it_xm_convert_effect(t[1] & 0xF, t[2], entry, 1);
if (entry->mask) entry++; if (entry->mask)
entry++;
} }
} }
} }
@ -92,8 +97,8 @@ static int it_mtm_assemble_pattern(IT_PATTERN *pattern, const unsigned char * tr
return 0; return 0;
} }
static int it_mtm_read_sample_header(IT_SAMPLE *sample, DUMBFILE *f, int * skip_bytes) static int it_mtm_read_sample_header(IT_SAMPLE *sample, DUMBFILE *f,
{ int *skip_bytes) {
int finetune, flags; int finetune, flags;
dumbfile_getnc((char *)sample->name, 22, f); dumbfile_getnc((char *)sample->name, 22, f);
@ -127,7 +132,9 @@ static int it_mtm_read_sample_header(IT_SAMPLE *sample, DUMBFILE *f, int * skip_
} }
sample->default_pan = 0; sample->default_pan = 0;
sample->C5_speed = (int)( AMIGA_CLOCK / 214.0 );//(long)(16726.0*pow(DUMB_PITCH_BASE, finetune*32)); sample->C5_speed =
(int)(AMIGA_CLOCK /
214.0); //(long)(16726.0*pow(DUMB_PITCH_BASE, finetune*32));
sample->finetune = finetune * 32; sample->finetune = finetune * 32;
// the above line might be wrong // the above line might be wrong
@ -146,8 +153,8 @@ static int it_mtm_read_sample_header(IT_SAMPLE *sample, DUMBFILE *f, int * skip_
return dumbfile_error(f); return dumbfile_error(f);
} }
static int it_mtm_read_sample_data(IT_SAMPLE *sample, DUMBFILE *f, int skip_bytes) static int it_mtm_read_sample_data(IT_SAMPLE *sample, DUMBFILE *f,
{ int skip_bytes) {
long i; long i;
long truncated_size; long truncated_size;
long bytes_per_sample; long bytes_per_sample;
@ -181,28 +188,28 @@ static int it_mtm_read_sample_data(IT_SAMPLE *sample, DUMBFILE *f, int skip_byte
return 0; return 0;
} }
static DUMB_IT_SIGDATA *it_mtm_load_sigdata(DUMBFILE *f, int * version) static DUMB_IT_SIGDATA *it_mtm_load_sigdata(DUMBFILE *f, int *version) {
{
DUMB_IT_SIGDATA *sigdata; DUMB_IT_SIGDATA *sigdata;
int n, o, n_tracks, l_comment, n_rows, n_channels; int n, o, n_tracks, l_comment, n_rows, n_channels;
unsigned char * track; unsigned char *track;
unsigned short * sequence; unsigned short *sequence;
char * comment; char *comment;
int * skip_bytes; int *skip_bytes;
if (dumbfile_getc(f) != 'M' || if (dumbfile_getc(f) != 'M' || dumbfile_getc(f) != 'T' ||
dumbfile_getc(f) != 'T' || dumbfile_getc(f) != 'M')
dumbfile_getc(f) != 'M') goto error; goto error;
*version = dumbfile_getc(f); *version = dumbfile_getc(f);
sigdata = malloc(sizeof(*sigdata)); sigdata = malloc(sizeof(*sigdata));
if (!sigdata) goto error; if (!sigdata)
goto error;
dumbfile_getnc((char *)sigdata->name, 20, f); dumbfile_getnc((char *)sigdata->name, 20, f);
sigdata->name[20] = 0; sigdata->name[20] = 0;
@ -212,20 +219,19 @@ static DUMB_IT_SIGDATA *it_mtm_load_sigdata(DUMBFILE *f, int * version)
sigdata->n_orders = dumbfile_getc(f) + 1; sigdata->n_orders = dumbfile_getc(f) + 1;
l_comment = dumbfile_igetw(f); l_comment = dumbfile_igetw(f);
sigdata->n_samples = dumbfile_getc(f); sigdata->n_samples = dumbfile_getc(f);
//if (dumbfile_getc(f)) goto error_sd; // if (dumbfile_getc(f)) goto error_sd;
dumbfile_getc(f); dumbfile_getc(f);
n_rows = dumbfile_getc(f); n_rows = dumbfile_getc(f);
n_channels = dumbfile_getc(f); n_channels = dumbfile_getc(f);
if (dumbfile_error(f) || if (dumbfile_error(f) || (n_tracks <= 0) || (sigdata->n_samples <= 0) ||
(n_tracks <= 0) || (n_rows <= 0 || n_rows > 64) || (n_channels <= 0 || n_channels > 32))
(sigdata->n_samples <= 0) || goto error_sd;
(n_rows <= 0 || n_rows > 64) ||
(n_channels <= 0 || n_channels > 32)) goto error_sd;
memset(sigdata->channel_volume, 64, DUMB_IT_N_CHANNELS); memset(sigdata->channel_volume, 64, DUMB_IT_N_CHANNELS);
if (dumbfile_getnc((char *)sigdata->channel_pan, 32, f) < 32) goto error_sd; if (dumbfile_getnc((char *)sigdata->channel_pan, 32, f) < 32)
goto error_sd;
for (n = 0; n < 32; n++) { for (n = 0; n < 32; n++) {
if (sigdata->channel_pan[n] <= 15) { if (sigdata->channel_pan[n] <= 15) {
@ -239,16 +245,18 @@ static DUMB_IT_SIGDATA *it_mtm_load_sigdata(DUMBFILE *f, int * version)
for (n = 32; n < DUMB_IT_N_CHANNELS; n += 4) { for (n = 32; n < DUMB_IT_N_CHANNELS; n += 4) {
int sep = 32 * dumb_it_default_panning_separation / 100; int sep = 32 * dumb_it_default_panning_separation / 100;
sigdata->channel_pan[n ] = 32 - sep; sigdata->channel_pan[n] = 32 - sep;
sigdata->channel_pan[n+1] = 32 + sep; sigdata->channel_pan[n + 1] = 32 + sep;
sigdata->channel_pan[n+2] = 32 + sep; sigdata->channel_pan[n + 2] = 32 + sep;
sigdata->channel_pan[n+3] = 32 - sep; sigdata->channel_pan[n + 3] = 32 - sep;
} }
sigdata->sample = malloc(sigdata->n_samples * sizeof(*sigdata->sample)); sigdata->sample = malloc(sigdata->n_samples * sizeof(*sigdata->sample));
if (!sigdata->sample) goto error_sd; if (!sigdata->sample)
goto error_sd;
sigdata->flags = IT_WAS_AN_XM | IT_WAS_A_MOD | IT_STEREO | IT_OLD_EFFECTS | IT_COMPATIBLE_GXX; sigdata->flags = IT_WAS_AN_XM | IT_WAS_A_MOD | IT_STEREO | IT_OLD_EFFECTS |
IT_COMPATIBLE_GXX;
sigdata->global_volume = 128; sigdata->global_volume = 128;
sigdata->mixing_volume = 48; sigdata->mixing_volume = 48;
@ -272,38 +280,47 @@ static DUMB_IT_SIGDATA *it_mtm_load_sigdata(DUMBFILE *f, int * version)
sigdata->sample[n].data = NULL; sigdata->sample[n].data = NULL;
skip_bytes = calloc(sizeof(int), sigdata->n_samples); skip_bytes = calloc(sizeof(int), sigdata->n_samples);
if (!skip_bytes) goto error_usd; if (!skip_bytes)
goto error_usd;
for (n = 0; n < sigdata->n_samples; n++) { for (n = 0; n < sigdata->n_samples; n++) {
if (it_mtm_read_sample_header(&sigdata->sample[n], f, skip_bytes + n)) goto error_sb; if (it_mtm_read_sample_header(&sigdata->sample[n], f, skip_bytes + n))
goto error_sb;
} }
sigdata->order = malloc(sigdata->n_orders); sigdata->order = malloc(sigdata->n_orders);
if (!sigdata->order) goto error_sb; if (!sigdata->order)
goto error_sb;
if (dumbfile_getnc((char *)sigdata->order, sigdata->n_orders, f) < sigdata->n_orders) goto error_sb; if (dumbfile_getnc((char *)sigdata->order, sigdata->n_orders, f) <
sigdata->n_orders)
goto error_sb;
if (sigdata->n_orders < 128) if (sigdata->n_orders < 128)
if (dumbfile_skip(f, 128 - sigdata->n_orders)) goto error_sb; if (dumbfile_skip(f, 128 - sigdata->n_orders))
goto error_sb;
track = malloc(192 * n_tracks); track = malloc(192 * n_tracks);
if (!track) goto error_sb; if (!track)
goto error_sb;
if (dumbfile_getnc((char *)track, 192 * n_tracks, f) < 192 * n_tracks) goto error_ft; if (dumbfile_getnc((char *)track, 192 * n_tracks, f) < 192 * n_tracks)
goto error_ft;
sigdata->pattern = malloc(sigdata->n_patterns * sizeof(*sigdata->pattern)); sigdata->pattern = malloc(sigdata->n_patterns * sizeof(*sigdata->pattern));
if (!sigdata->pattern) goto error_ft; if (!sigdata->pattern)
goto error_ft;
for (n = 0; n < sigdata->n_patterns; n++) for (n = 0; n < sigdata->n_patterns; n++)
sigdata->pattern[n].entry = NULL; sigdata->pattern[n].entry = NULL;
sequence = malloc(sigdata->n_patterns * 32 * sizeof(*sequence)); sequence = malloc(sigdata->n_patterns * 32 * sizeof(*sequence));
if (!sequence) goto error_ft; if (!sequence)
goto error_ft;
for (n = 0; n < sigdata->n_patterns; n++) { for (n = 0; n < sigdata->n_patterns; n++) {
for (o = 0; o < 32; o++) { for (o = 0; o < 32; o++) {
sequence[(n * 32) + o] = dumbfile_igetw(f); sequence[(n * 32) + o] = dumbfile_igetw(f);
if (sequence[(n * 32) + o] > n_tracks) if (sequence[(n * 32) + o] > n_tracks) {
{ // goto error_fs;
//goto error_fs;
// illegal track number, silence instead of rejecting the file // illegal track number, silence instead of rejecting the file
sequence[(n * 32) + o] = 0; sequence[(n * 32) + o] = 0;
} }
@ -311,13 +328,17 @@ static DUMB_IT_SIGDATA *it_mtm_load_sigdata(DUMBFILE *f, int * version)
} }
for (n = 0; n < sigdata->n_patterns; n++) { for (n = 0; n < sigdata->n_patterns; n++) {
if (it_mtm_assemble_pattern(&sigdata->pattern[n], track, &sequence[n * 32], n_rows)) goto error_fs; if (it_mtm_assemble_pattern(&sigdata->pattern[n], track,
&sequence[n * 32], n_rows))
goto error_fs;
} }
if (l_comment) { if (l_comment) {
comment = malloc(l_comment); comment = malloc(l_comment);
if (!comment) goto error_fs; if (!comment)
if (dumbfile_getnc(comment, l_comment, f) < l_comment) goto error_fc; goto error_fs;
if (dumbfile_getnc(comment, l_comment, f) < l_comment)
goto error_fc;
/* Time for annoying "logic", yes. We want each line which has text, /* Time for annoying "logic", yes. We want each line which has text,
* and each blank line in between all the valid lines. * and each blank line in between all the valid lines.
@ -325,7 +346,8 @@ static DUMB_IT_SIGDATA *it_mtm_load_sigdata(DUMBFILE *f, int * version)
/* Find last actual line. */ /* Find last actual line. */
for (o = -1, n = 0; n < l_comment; n += 40) { for (o = -1, n = 0; n < l_comment; n += 40) {
if (comment[n]) o = n; if (comment[n])
o = n;
} }
if (o >= 0) { if (o >= 0) {
@ -340,11 +362,12 @@ static DUMB_IT_SIGDATA *it_mtm_load_sigdata(DUMBFILE *f, int * version)
l -= 1; l -= 1;
sigdata->song_message = malloc(l); sigdata->song_message = malloc(l);
if (!sigdata->song_message) goto error_fc; if (!sigdata->song_message)
goto error_fc;
for (m = 0, n = 0; n <= o; n += 40) { for (m = 0, n = 0; n <= o; n += 40) {
int maxlen = l_comment - n; int maxlen = l_comment - n;
int p = (int) strlen_max(&comment[n], maxlen > 40 ? 40 : maxlen); int p = (int)strlen_max(&comment[n], maxlen > 40 ? 40 : maxlen);
if (p) { if (p) {
memcpy(sigdata->song_message + m, &comment[n], p); memcpy(sigdata->song_message + m, &comment[n], p);
m += p; m += p;
@ -362,7 +385,8 @@ static DUMB_IT_SIGDATA *it_mtm_load_sigdata(DUMBFILE *f, int * version)
} }
for (n = 0; n < sigdata->n_samples; n++) { for (n = 0; n < sigdata->n_samples; n++) {
if (it_mtm_read_sample_data(&sigdata->sample[n], f, skip_bytes[n])) goto error_fs; if (it_mtm_read_sample_data(&sigdata->sample[n], f, skip_bytes[n]))
goto error_fs;
} }
_dumb_it_fix_invalid_orders(sigdata); _dumb_it_fix_invalid_orders(sigdata);
@ -391,14 +415,14 @@ error:
return NULL; return NULL;
} }
static char hexdigit(int in) static char hexdigit(int in) {
{ if (in < 10)
if (in < 10) return in + '0'; return in + '0';
else return in + 'A' - 10; else
return in + 'A' - 10;
} }
DUH *dumb_read_mtm_quick(DUMBFILE *f) DUH *dumb_read_mtm_quick(DUMBFILE *f) {
{
sigdata_t *sigdata; sigdata_t *sigdata;
int ver; int ver;
@ -424,7 +448,8 @@ DUH *dumb_read_mtm_quick(DUMBFILE *f)
version[6] = '.'; version[6] = '.';
version[7] = hexdigit(ver & 15); version[7] = hexdigit(ver & 15);
version[8] = 0; version[8] = 0;
tag[1][1] = (const char *) &version; tag[1][1] = (const char *)&version;
return make_duh(-1, 2, (const char *const (*)[2])tag, 1, &descptr, &sigdata); return make_duh(-1, 2, (const char *const(*)[2])tag, 1, &descptr,
&sigdata);
} }
} }

View file

@ -24,22 +24,23 @@
#include "dumb.h" #include "dumb.h"
#include "internal/it.h" #include "internal/it.h"
static int it_okt_read_pattern(IT_PATTERN *pattern, const unsigned char *data,
int length, int n_channels) {
static int it_okt_read_pattern(IT_PATTERN *pattern, const unsigned char *data, int length, int n_channels)
{
int pos; int pos;
int channel; int channel;
int row; int row;
int n_rows; int n_rows;
IT_ENTRY *entry; IT_ENTRY *entry;
if (length < 2) return -1; if (length < 2)
return -1;
n_rows = (data[0] << 8) | data[1]; n_rows = (data[0] << 8) | data[1];
if (!n_rows) n_rows = 64; if (!n_rows)
n_rows = 64;
if (length < 2 + (n_rows * n_channels * 4)) return -1; if (length < 2 + (n_rows * n_channels * 4))
return -1;
pattern->n_rows = n_rows; pattern->n_rows = n_rows;
@ -48,13 +49,14 @@ static int it_okt_read_pattern(IT_PATTERN *pattern, const unsigned char *data, i
pos = 2; pos = 2;
for (row = 0; row < pattern->n_rows; row++) { for (row = 0; row < pattern->n_rows; row++) {
for (channel = 0; channel < n_channels; channel++) { for (channel = 0; channel < n_channels; channel++) {
if (data[pos+0] | data[pos+2]) if (data[pos + 0] | data[pos + 2])
pattern->n_entries++; pattern->n_entries++;
pos += 4; pos += 4;
} }
} }
pattern->entry = (IT_ENTRY *) malloc(pattern->n_entries * sizeof(*pattern->entry)); pattern->entry =
(IT_ENTRY *)malloc(pattern->n_entries * sizeof(*pattern->entry));
if (!pattern->entry) if (!pattern->entry)
return -1; return -1;
@ -62,51 +64,101 @@ static int it_okt_read_pattern(IT_PATTERN *pattern, const unsigned char *data, i
pos = 2; pos = 2;
for (row = 0; row < n_rows; row++) { for (row = 0; row < n_rows; row++) {
for (channel = 0; channel < n_channels; channel++) { for (channel = 0; channel < n_channels; channel++) {
if (data[pos+0] | data[pos+2]) { if (data[pos + 0] | data[pos + 2]) {
entry->channel = channel; entry->channel = channel;
entry->mask = 0; entry->mask = 0;
if (data[pos+0] > 0 && data[pos+0] <= 36) { if (data[pos + 0] > 0 && data[pos + 0] <= 36) {
entry->mask |= IT_ENTRY_NOTE | IT_ENTRY_INSTRUMENT; entry->mask |= IT_ENTRY_NOTE | IT_ENTRY_INSTRUMENT;
entry->note = data[pos+0] + 35; entry->note = data[pos + 0] + 35;
entry->instrument = data[pos+1] + 1; entry->instrument = data[pos + 1] + 1;
} }
entry->effect = 0; entry->effect = 0;
entry->effectvalue = data[pos+3]; entry->effectvalue = data[pos + 3];
switch (data[pos+2]) { switch (data[pos + 2]) {
case 2: if (data[pos+3]) entry->effect = IT_PORTAMENTO_DOWN; break; // XXX code calls this rs_portu, but it's adding to the period, which decreases the pitch case 2:
case 13: if (data[pos+3]) entry->effect = IT_OKT_NOTE_SLIDE_DOWN; break; if (data[pos + 3])
case 21: if (data[pos+3]) entry->effect = IT_OKT_NOTE_SLIDE_DOWN_ROW; break; entry->effect = IT_PORTAMENTO_DOWN;
break; // XXX code calls this rs_portu, but it's adding to
// the period, which decreases the pitch
case 13:
if (data[pos + 3])
entry->effect = IT_OKT_NOTE_SLIDE_DOWN;
break;
case 21:
if (data[pos + 3])
entry->effect = IT_OKT_NOTE_SLIDE_DOWN_ROW;
break;
case 1: if (data[pos+3]) entry->effect = IT_PORTAMENTO_UP; break; // XXX same deal here, increasing the pitch case 1:
case 17: if (data[pos+3]) entry->effect = IT_OKT_NOTE_SLIDE_UP; break; if (data[pos + 3])
case 30: if (data[pos+3]) entry->effect = IT_OKT_NOTE_SLIDE_UP_ROW; break; entry->effect = IT_PORTAMENTO_UP;
break; // XXX same deal here, increasing the pitch
case 17:
if (data[pos + 3])
entry->effect = IT_OKT_NOTE_SLIDE_UP;
break;
case 30:
if (data[pos + 3])
entry->effect = IT_OKT_NOTE_SLIDE_UP_ROW;
break;
case 10: if (data[pos+3]) entry->effect = IT_OKT_ARPEGGIO_3; break; case 10:
case 11: if (data[pos+3]) entry->effect = IT_OKT_ARPEGGIO_4; break; if (data[pos + 3])
case 12: if (data[pos+3]) entry->effect = IT_OKT_ARPEGGIO_5; break; entry->effect = IT_OKT_ARPEGGIO_3;
break;
case 11:
if (data[pos + 3])
entry->effect = IT_OKT_ARPEGGIO_4;
break;
case 12:
if (data[pos + 3])
entry->effect = IT_OKT_ARPEGGIO_5;
break;
case 15: entry->effect = IT_S; entry->effectvalue = EFFECT_VALUE(IT_S_SET_FILTER, data[pos+3] & 0x0F); break; case 15:
entry->effect = IT_S;
entry->effectvalue =
EFFECT_VALUE(IT_S_SET_FILTER, data[pos + 3] & 0x0F);
break;
case 25: entry->effect = IT_JUMP_TO_ORDER; break; case 25:
entry->effect = IT_JUMP_TO_ORDER;
break;
case 27: entry->note = IT_NOTE_OFF; entry->mask |= IT_ENTRY_NOTE; break; case 27:
entry->note = IT_NOTE_OFF;
entry->mask |= IT_ENTRY_NOTE;
break;
case 28: entry->effect = IT_SET_SPEED; break; case 28:
entry->effect = IT_SET_SPEED;
break;
case 31: case 31:
if ( data[pos+3] <= 0x40 ) entry->effect = IT_SET_CHANNEL_VOLUME; if (data[pos + 3] <= 0x40)
else if ( data[pos+3] <= 0x50 ) { entry->effect = IT_OKT_VOLUME_SLIDE_DOWN; entry->effectvalue = data[pos+3] - 0x40; } entry->effect = IT_SET_CHANNEL_VOLUME;
else if ( data[pos+3] <= 0x60 ) { entry->effect = IT_OKT_VOLUME_SLIDE_UP; entry->effectvalue = data[pos+3] - 0x50; } else if (data[pos + 3] <= 0x50) {
else if ( data[pos+3] <= 0x70 ) { entry->effect = IT_OKT_VOLUME_SLIDE_DOWN; entry->effectvalue = data[pos+3] - 0x50; } entry->effect = IT_OKT_VOLUME_SLIDE_DOWN;
else if ( data[pos+3] <= 0x80 ) { entry->effect = IT_OKT_VOLUME_SLIDE_UP; entry->effectvalue = data[pos+3] - 0x60; } entry->effectvalue = data[pos + 3] - 0x40;
} else if (data[pos + 3] <= 0x60) {
entry->effect = IT_OKT_VOLUME_SLIDE_UP;
entry->effectvalue = data[pos + 3] - 0x50;
} else if (data[pos + 3] <= 0x70) {
entry->effect = IT_OKT_VOLUME_SLIDE_DOWN;
entry->effectvalue = data[pos + 3] - 0x50;
} else if (data[pos + 3] <= 0x80) {
entry->effect = IT_OKT_VOLUME_SLIDE_UP;
entry->effectvalue = data[pos + 3] - 0x60;
}
break; break;
} }
if ( entry->effect ) entry->mask |= IT_ENTRY_EFFECT; if (entry->effect)
entry->mask |= IT_ENTRY_EFFECT;
entry++; entry++;
} }
@ -119,10 +171,8 @@ static int it_okt_read_pattern(IT_PATTERN *pattern, const unsigned char *data, i
return 0; return 0;
} }
static void it_okt_read_sample_header(IT_SAMPLE *sample,
const unsigned char *data) {
static void it_okt_read_sample_header(IT_SAMPLE *sample, const unsigned char * data)
{
int loop_start, loop_length; int loop_start, loop_length;
memcpy(sample->name, data, 20); memcpy(sample->name, data, 20);
@ -130,7 +180,8 @@ static void it_okt_read_sample_header(IT_SAMPLE *sample, const unsigned char * d
sample->filename[0] = 0; sample->filename[0] = 0;
sample->length = (data[20] << 24) | (data[21] << 16) | (data[22] << 8) | data[23]; sample->length =
(data[20] << 24) | (data[21] << 16) | (data[22] << 8) | data[23];
sample->global_volume = 64; sample->global_volume = 64;
sample->default_volume = data[29]; sample->default_volume = data[29];
loop_start = ((data[24] << 8) | data[25]) << 1; loop_start = ((data[24] << 8) | data[25]) << 1;
@ -146,7 +197,9 @@ static void it_okt_read_sample_header(IT_SAMPLE *sample, const unsigned char * d
sample->flags = IT_SAMPLE_EXISTS; sample->flags = IT_SAMPLE_EXISTS;
sample->default_pan = 0; sample->default_pan = 0;
sample->C5_speed = (int)( AMIGA_CLOCK / 214.0 ); //(long)(16726.0*pow(DUMB_PITCH_BASE, finetune*32)); sample->C5_speed =
(int)(AMIGA_CLOCK /
214.0); //(long)(16726.0*pow(DUMB_PITCH_BASE, finetune*32));
sample->finetune = 0; sample->finetune = 0;
if (sample->sus_loop_end > sample->length) if (sample->sus_loop_end > sample->length)
@ -162,14 +215,13 @@ static void it_okt_read_sample_header(IT_SAMPLE *sample, const unsigned char * d
sample->max_resampling_quality = -1; sample->max_resampling_quality = -1;
} }
static int it_okt_read_sample_data(IT_SAMPLE *sample, const char *data,
int length) {
static int it_okt_read_sample_data(IT_SAMPLE *sample, const char * data, int length)
{
if (length && sample->length) { if (length && sample->length) {
if (length < sample->length) { if (length < sample->length) {
sample->length = length; sample->length = length;
if (length < sample->sus_loop_end) sample->sus_loop_end = length; if (length < sample->sus_loop_end)
sample->sus_loop_end = length;
} }
sample->data = malloc(length); sample->data = malloc(length);
@ -183,71 +235,65 @@ static int it_okt_read_sample_data(IT_SAMPLE *sample, const char * data, int len
return 0; return 0;
} }
typedef struct IFF_CHUNK IFF_CHUNK; typedef struct IFF_CHUNK IFF_CHUNK;
typedef struct IFF_CHUNKED IFF_CHUNKED; typedef struct IFF_CHUNKED IFF_CHUNKED;
struct IFF_CHUNK struct IFF_CHUNK {
{
unsigned type; unsigned type;
unsigned char * data; unsigned char *data;
unsigned size; unsigned size;
}; };
struct IFF_CHUNKED struct IFF_CHUNKED {
{
unsigned chunk_count; unsigned chunk_count;
IFF_CHUNK * chunks; IFF_CHUNK *chunks;
}; };
static IFF_CHUNKED *dumbfile_read_okt(DUMBFILE *f) {
IFF_CHUNKED *mod = (IFF_CHUNKED *)malloc(sizeof(*mod));
static IFF_CHUNKED *dumbfile_read_okt(DUMBFILE *f) if (!mod)
{ return NULL;
IFF_CHUNKED *mod = (IFF_CHUNKED *) malloc(sizeof(*mod));
if (!mod) return NULL;
mod->chunk_count = 0; mod->chunk_count = 0;
mod->chunks = 0; mod->chunks = 0;
for (;;) for (;;) {
{
long bytes_read; long bytes_read;
IFF_CHUNK * chunk = ( IFF_CHUNK * ) realloc( mod->chunks, ( mod->chunk_count + 1 ) * sizeof( IFF_CHUNK ) ); IFF_CHUNK *chunk = (IFF_CHUNK *)realloc(
if ( !chunk ) mod->chunks, (mod->chunk_count + 1) * sizeof(IFF_CHUNK));
{ if (!chunk) {
if ( mod->chunks ) free( mod->chunks ); if (mod->chunks)
free( mod ); free(mod->chunks);
free(mod);
return NULL; return NULL;
} }
mod->chunks = chunk; mod->chunks = chunk;
chunk += mod->chunk_count; chunk += mod->chunk_count;
bytes_read = dumbfile_mgetl( f ); bytes_read = dumbfile_mgetl(f);
if ( bytes_read < 0 ) break; if (bytes_read < 0)
break;
chunk->type = bytes_read; chunk->type = (unsigned int)bytes_read;
chunk->size = dumbfile_mgetl( f ); chunk->size = (unsigned int)dumbfile_mgetl(f);
if ( dumbfile_error( f ) ) break; if (dumbfile_error(f))
break;
chunk->data = (unsigned char *) malloc( chunk->size ); chunk->data = (unsigned char *)malloc(chunk->size);
if ( !chunk->data ) if (!chunk->data) {
{ free(mod->chunks);
free( mod->chunks ); free(mod);
free( mod );
return NULL; return NULL;
} }
bytes_read = dumbfile_getnc( ( char * ) chunk->data, chunk->size, f ); bytes_read = dumbfile_getnc((char *)chunk->data, chunk->size, f);
if ( bytes_read < chunk->size ) if (bytes_read < chunk->size) {
{ if (bytes_read <= 0) {
if ( bytes_read <= 0 ) { free(chunk->data);
free( chunk->data );
break; break;
} else { } else {
chunk->size = bytes_read; chunk->size = (unsigned int)bytes_read;
mod->chunk_count++; mod->chunk_count++;
break; break;
} }
@ -256,8 +302,9 @@ static IFF_CHUNKED *dumbfile_read_okt(DUMBFILE *f)
mod->chunk_count++; mod->chunk_count++;
} }
if ( !mod->chunk_count ) { if (!mod->chunk_count) {
if ( mod->chunks ) free(mod->chunks); if (mod->chunks)
free(mod->chunks);
free(mod); free(mod);
mod = NULL; mod = NULL;
} }
@ -265,16 +312,13 @@ static IFF_CHUNKED *dumbfile_read_okt(DUMBFILE *f)
return mod; return mod;
} }
void free_okt(IFF_CHUNKED * mod) void free_okt(IFF_CHUNKED *mod) {
{
unsigned i; unsigned i;
if (mod) if (mod) {
{ if (mod->chunks) {
if (mod->chunks) for (i = 0; i < mod->chunk_count; i++) {
{ if (mod->chunks[i].data)
for (i = 0; i < mod->chunk_count; i++) free(mod->chunks[i].data);
{
if (mod->chunks[i].data) free(mod->chunks[i].data);
} }
free(mod->chunks); free(mod->chunks);
} }
@ -282,19 +326,17 @@ void free_okt(IFF_CHUNKED * mod)
} }
} }
const IFF_CHUNK * get_chunk_by_type(IFF_CHUNKED * mod, unsigned type, unsigned offset) const IFF_CHUNK *get_chunk_by_type(IFF_CHUNKED *mod, unsigned type,
{ unsigned offset) {
unsigned i; unsigned i;
if (mod) if (mod) {
{ if (mod->chunks) {
if (mod->chunks) for (i = 0; i < mod->chunk_count; i++) {
{ if (mod->chunks[i].type == type) {
for (i = 0; i < mod->chunk_count; i++) if (!offset)
{ return &mod->chunks[i];
if (mod->chunks[i].type == type) else
{ offset--;
if (!offset) return &mod->chunks[i];
else offset--;
} }
} }
} }
@ -302,25 +344,20 @@ const IFF_CHUNK * get_chunk_by_type(IFF_CHUNKED * mod, unsigned type, unsigned o
return NULL; return NULL;
} }
unsigned get_chunk_count(IFF_CHUNKED *mod, unsigned type) unsigned get_chunk_count(IFF_CHUNKED *mod, unsigned type) {
{
unsigned i, count = 0; unsigned i, count = 0;
if (mod) if (mod) {
{ if (mod->chunks) {
if (mod->chunks) for (i = 0; i < mod->chunk_count; i++) {
{ if (mod->chunks[i].type == type)
for (i = 0; i < mod->chunk_count; i++) count++;
{
if (mod->chunks[i].type == type) count++;
} }
} }
} }
return count; return count;
} }
static DUMB_IT_SIGDATA *it_okt_load_sigdata(DUMBFILE *f) {
static DUMB_IT_SIGDATA *it_okt_load_sigdata(DUMBFILE *f)
{
DUMB_IT_SIGDATA *sigdata; DUMB_IT_SIGDATA *sigdata;
int n_channels; int n_channels;
int i, j, k, l; int i, j, k, l;
@ -338,7 +375,7 @@ static DUMB_IT_SIGDATA *it_okt_load_sigdata(DUMBFILE *f)
if (!mod) if (!mod)
return NULL; return NULL;
sigdata = (DUMB_IT_SIGDATA *) malloc(sizeof(*sigdata)); sigdata = (DUMB_IT_SIGDATA *)malloc(sizeof(*sigdata));
if (!sigdata) { if (!sigdata) {
free_okt(mod); free_okt(mod);
return NULL; return NULL;
@ -346,7 +383,7 @@ static DUMB_IT_SIGDATA *it_okt_load_sigdata(DUMBFILE *f)
sigdata->name[0] = 0; sigdata->name[0] = 0;
chunk = get_chunk_by_type(mod, DUMB_ID('S','P','E','E'), 0); chunk = get_chunk_by_type(mod, DUMB_ID('S', 'P', 'E', 'E'), 0);
if (!chunk || chunk->size < 2) { if (!chunk || chunk->size < 2) {
free(sigdata); free(sigdata);
free_okt(mod); free_okt(mod);
@ -355,7 +392,7 @@ static DUMB_IT_SIGDATA *it_okt_load_sigdata(DUMBFILE *f)
sigdata->speed = (chunk->data[0] << 8) | chunk->data[1]; sigdata->speed = (chunk->data[0] << 8) | chunk->data[1];
chunk = get_chunk_by_type(mod, DUMB_ID('S','A','M','P'), 0); chunk = get_chunk_by_type(mod, DUMB_ID('S', 'A', 'M', 'P'), 0);
if (!chunk || chunk->size < 32) { if (!chunk || chunk->size < 32) {
free(sigdata); free(sigdata);
free_okt(mod); free_okt(mod);
@ -364,7 +401,7 @@ static DUMB_IT_SIGDATA *it_okt_load_sigdata(DUMBFILE *f)
sigdata->n_samples = chunk->size / 32; sigdata->n_samples = chunk->size / 32;
chunk = get_chunk_by_type(mod, DUMB_ID('C','M','O','D'), 0); chunk = get_chunk_by_type(mod, DUMB_ID('C', 'M', 'O', 'D'), 0);
if (!chunk || chunk->size < 8) { if (!chunk || chunk->size < 8) {
free(sigdata); free(sigdata);
free_okt(mod); free_okt(mod);
@ -375,8 +412,10 @@ static DUMB_IT_SIGDATA *it_okt_load_sigdata(DUMBFILE *f)
for (i = 0; i < 4; i++) { for (i = 0; i < 4; i++) {
j = (chunk->data[i * 2] << 8) | chunk->data[i * 2 + 1]; j = (chunk->data[i * 2] << 8) | chunk->data[i * 2 + 1];
if (!j) n_channels++; if (!j)
else if (j == 1) n_channels += 2; n_channels++;
else if (j == 1)
n_channels += 2;
} }
if (!n_channels) { if (!n_channels) {
@ -387,7 +426,8 @@ static DUMB_IT_SIGDATA *it_okt_load_sigdata(DUMBFILE *f)
sigdata->n_pchannels = n_channels; sigdata->n_pchannels = n_channels;
sigdata->sample = (IT_SAMPLE *) malloc(sigdata->n_samples * sizeof(*sigdata->sample)); sigdata->sample =
(IT_SAMPLE *)malloc(sigdata->n_samples * sizeof(*sigdata->sample));
if (!sigdata->sample) { if (!sigdata->sample) {
free(sigdata); free(sigdata);
free_okt(mod); free_okt(mod);
@ -406,7 +446,7 @@ static DUMB_IT_SIGDATA *it_okt_load_sigdata(DUMBFILE *f)
for (i = 0; i < sigdata->n_samples; i++) for (i = 0; i < sigdata->n_samples; i++)
sigdata->sample[i].data = NULL; sigdata->sample[i].data = NULL;
chunk = get_chunk_by_type(mod, DUMB_ID('S','A','M','P'), 0); chunk = get_chunk_by_type(mod, DUMB_ID('S', 'A', 'M', 'P'), 0);
for (i = 0; i < sigdata->n_samples; i++) { for (i = 0; i < sigdata->n_samples; i++) {
it_okt_read_sample_header(&sigdata->sample[i], chunk->data + 32 * i); it_okt_read_sample_header(&sigdata->sample[i], chunk->data + 32 * i);
@ -414,7 +454,7 @@ static DUMB_IT_SIGDATA *it_okt_load_sigdata(DUMBFILE *f)
sigdata->restart_position = 0; sigdata->restart_position = 0;
chunk = get_chunk_by_type(mod, DUMB_ID('P','L','E','N'), 0); chunk = get_chunk_by_type(mod, DUMB_ID('P', 'L', 'E', 'N'), 0);
if (!chunk || chunk->size < 2) { if (!chunk || chunk->size < 2) {
_dumb_it_unload_sigdata(sigdata); _dumb_it_unload_sigdata(sigdata);
free_okt(mod); free_okt(mod);
@ -430,14 +470,14 @@ static DUMB_IT_SIGDATA *it_okt_load_sigdata(DUMBFILE *f)
return NULL; return NULL;
} }
chunk = get_chunk_by_type(mod, DUMB_ID('P','A','T','T'), 0); chunk = get_chunk_by_type(mod, DUMB_ID('P', 'A', 'T', 'T'), 0);
if (!chunk || chunk->size < (unsigned)sigdata->n_orders) { if (!chunk || chunk->size < (unsigned)sigdata->n_orders) {
_dumb_it_unload_sigdata(sigdata); _dumb_it_unload_sigdata(sigdata);
free_okt(mod); free_okt(mod);
return NULL; return NULL;
} }
sigdata->order = (unsigned char *) malloc(sigdata->n_orders); sigdata->order = (unsigned char *)malloc(sigdata->n_orders);
if (!sigdata->order) { if (!sigdata->order) {
_dumb_it_unload_sigdata(sigdata); _dumb_it_unload_sigdata(sigdata);
free_okt(mod); free_okt(mod);
@ -447,7 +487,7 @@ static DUMB_IT_SIGDATA *it_okt_load_sigdata(DUMBFILE *f)
memcpy(sigdata->order, chunk->data, sigdata->n_orders); memcpy(sigdata->order, chunk->data, sigdata->n_orders);
/* Work out how many patterns there are. */ /* Work out how many patterns there are. */
chunk = get_chunk_by_type(mod, DUMB_ID('S','L','E','N'), 0); chunk = get_chunk_by_type(mod, DUMB_ID('S', 'L', 'E', 'N'), 0);
if (!chunk || chunk->size < 2) { if (!chunk || chunk->size < 2) {
_dumb_it_unload_sigdata(sigdata); _dumb_it_unload_sigdata(sigdata);
free_okt(mod); free_okt(mod);
@ -456,8 +496,9 @@ static DUMB_IT_SIGDATA *it_okt_load_sigdata(DUMBFILE *f)
sigdata->n_patterns = (chunk->data[0] << 8) | chunk->data[1]; sigdata->n_patterns = (chunk->data[0] << 8) | chunk->data[1];
j = get_chunk_count(mod, DUMB_ID('P','B','O','D')); j = get_chunk_count(mod, DUMB_ID('P', 'B', 'O', 'D'));
if (sigdata->n_patterns > j) sigdata->n_patterns = j; if (sigdata->n_patterns > j)
sigdata->n_patterns = j;
if (!sigdata->n_patterns) { if (!sigdata->n_patterns) {
_dumb_it_unload_sigdata(sigdata); _dumb_it_unload_sigdata(sigdata);
@ -465,7 +506,8 @@ static DUMB_IT_SIGDATA *it_okt_load_sigdata(DUMBFILE *f)
return NULL; return NULL;
} }
sigdata->pattern = (IT_PATTERN *) malloc(sigdata->n_patterns * sizeof(*sigdata->pattern)); sigdata->pattern =
(IT_PATTERN *)malloc(sigdata->n_patterns * sizeof(*sigdata->pattern));
if (!sigdata->pattern) { if (!sigdata->pattern) {
_dumb_it_unload_sigdata(sigdata); _dumb_it_unload_sigdata(sigdata);
free_okt(mod); free_okt(mod);
@ -476,8 +518,9 @@ static DUMB_IT_SIGDATA *it_okt_load_sigdata(DUMBFILE *f)
/* Read in the patterns */ /* Read in the patterns */
for (i = 0; i < sigdata->n_patterns; i++) { for (i = 0; i < sigdata->n_patterns; i++) {
chunk = get_chunk_by_type(mod, DUMB_ID('P','B','O','D'), i); chunk = get_chunk_by_type(mod, DUMB_ID('P', 'B', 'O', 'D'), i);
if (it_okt_read_pattern(&sigdata->pattern[i], chunk->data, chunk->size, n_channels) != 0) { if (it_okt_read_pattern(&sigdata->pattern[i], chunk->data, chunk->size,
n_channels) != 0) {
_dumb_it_unload_sigdata(sigdata); _dumb_it_unload_sigdata(sigdata);
free_okt(mod); free_okt(mod);
return NULL; return NULL;
@ -485,11 +528,13 @@ static DUMB_IT_SIGDATA *it_okt_load_sigdata(DUMBFILE *f)
} }
/* And finally, the sample data */ /* And finally, the sample data */
k = get_chunk_count(mod, DUMB_ID('S','B','O','D')); k = get_chunk_count(mod, DUMB_ID('S', 'B', 'O', 'D'));
for (i = 0, j = 0; i < sigdata->n_samples && j < k; i++) { for (i = 0, j = 0; i < sigdata->n_samples && j < k; i++) {
if (sigdata->sample[i].flags & IT_SAMPLE_EXISTS) { if (sigdata->sample[i].flags & IT_SAMPLE_EXISTS) {
chunk = get_chunk_by_type(mod, DUMB_ID('S','B','O','D'), j); chunk = get_chunk_by_type(mod, DUMB_ID('S', 'B', 'O', 'D'), j);
if (it_okt_read_sample_data(&sigdata->sample[i], (const char *)chunk->data, chunk->size)) { if (it_okt_read_sample_data(&sigdata->sample[i],
(const char *)chunk->data,
chunk->size)) {
_dumb_it_unload_sigdata(sigdata); _dumb_it_unload_sigdata(sigdata);
free_okt(mod); free_okt(mod);
return NULL; return NULL;
@ -501,15 +546,14 @@ static DUMB_IT_SIGDATA *it_okt_load_sigdata(DUMBFILE *f)
sigdata->sample[i].flags = 0; sigdata->sample[i].flags = 0;
} }
chunk = get_chunk_by_type(mod, DUMB_ID('C','M','O','D'), 0); chunk = get_chunk_by_type(mod, DUMB_ID('C', 'M', 'O', 'D'), 0);
for (i = 0, j = 0; i < n_channels && j < 4; j++) { for (i = 0, j = 0; i < n_channels && j < 4; j++) {
k = (chunk->data[j * 2] << 8) | chunk->data[j * 2 + 1]; k = (chunk->data[j * 2] << 8) | chunk->data[j * 2 + 1];
l = (j == 1 || j == 2) ? 48 : 16; l = (j == 1 || j == 2) ? 48 : 16;
if (k == 0) { if (k == 0) {
sigdata->channel_pan[i++] = l; sigdata->channel_pan[i++] = l;
} } else if (k == 1) {
else if (k == 1) {
sigdata->channel_pan[i++] = l; sigdata->channel_pan[i++] = l;
sigdata->channel_pan[i++] = l; sigdata->channel_pan[i++] = l;
} }
@ -518,7 +562,8 @@ static DUMB_IT_SIGDATA *it_okt_load_sigdata(DUMBFILE *f)
free_okt(mod); free_okt(mod);
/* Now let's initialise the remaining variables, and we're done! */ /* Now let's initialise the remaining variables, and we're done! */
sigdata->flags = IT_WAS_AN_OKT | IT_WAS_AN_XM | IT_WAS_A_MOD | IT_OLD_EFFECTS | IT_COMPATIBLE_GXX | IT_STEREO; sigdata->flags = IT_WAS_AN_OKT | IT_WAS_AN_XM | IT_WAS_A_MOD |
IT_OLD_EFFECTS | IT_COMPATIBLE_GXX | IT_STEREO;
sigdata->global_volume = 128; sigdata->global_volume = 128;
sigdata->mixing_volume = 48; sigdata->mixing_volume = 48;
@ -529,17 +574,15 @@ static DUMB_IT_SIGDATA *it_okt_load_sigdata(DUMBFILE *f)
sigdata->pan_separation = 128; sigdata->pan_separation = 128;
memset(sigdata->channel_volume, 64, DUMB_IT_N_CHANNELS); memset(sigdata->channel_volume, 64, DUMB_IT_N_CHANNELS);
memset(sigdata->channel_pan + n_channels, 32, DUMB_IT_N_CHANNELS - n_channels); memset(sigdata->channel_pan + n_channels, 32,
DUMB_IT_N_CHANNELS - n_channels);
_dumb_it_fix_invalid_orders(sigdata); _dumb_it_fix_invalid_orders(sigdata);
return sigdata; return sigdata;
} }
DUH *dumb_read_okt_quick(DUMBFILE *f) {
DUH *dumb_read_okt_quick(DUMBFILE *f)
{
sigdata_t *sigdata; sigdata_t *sigdata;
DUH_SIGTYPE_DESC *descptr = &_dumb_sigtype_it; DUH_SIGTYPE_DESC *descptr = &_dumb_sigtype_it;
@ -553,6 +596,7 @@ DUH *dumb_read_okt_quick(DUMBFILE *f)
const char *tag[1][2]; const char *tag[1][2];
tag[0][0] = "FORMAT"; tag[0][0] = "FORMAT";
tag[0][1] = "Oktalyzer"; tag[0][1] = "Oktalyzer";
return make_duh(-1, 1, (const char *const (*)[2])tag, 1, &descptr, &sigdata); return make_duh(-1, 1, (const char *const(*)[2])tag, 1, &descptr,
&sigdata);
} }
} }

View file

@ -19,10 +19,7 @@
#include "dumb.h" #include "dumb.h"
DUH *dumb_read_okt(DUMBFILE *f) {
DUH *dumb_read_okt(DUMBFILE *f)
{
DUH *duh = dumb_read_okt_quick(f); DUH *duh = dumb_read_okt_quick(f);
dumb_it_do_initial_runthrough(duh); dumb_it_do_initial_runthrough(duh);
return duh; return duh;

View file

@ -24,39 +24,42 @@
#include "dumb.h" #include "dumb.h"
#include "internal/it.h" #include "internal/it.h"
static int psm_sample_compare(const void *e1, const void *e2) static int psm_sample_compare(const void *e1, const void *e2) {
{ const unsigned char *pa = e1;
const unsigned char * pa = e1; const unsigned char *pb = e2;
const unsigned char * pb = e2;
int a = pa[37] | (pa[38] << 8) | (pa[39] << 16) | (pa[40] << 24); int a = pa[37] | (pa[38] << 8) | (pa[39] << 16) | (pa[40] << 24);
int b = pb[37] | (pb[38] << 8) | (pb[39] << 16) | (pb[40] << 24); int b = pb[37] | (pb[38] << 8) | (pb[39] << 16) | (pb[40] << 24);
return a - b; return a - b;
} }
static int it_old_psm_read_samples(IT_SAMPLE ** sample, DUMBFILE * f, int * num) static int it_old_psm_read_samples(IT_SAMPLE **sample, DUMBFILE *f, int *num) {
{
int n, o, count = *num, true_num, snum, offset, flags, finetune, delta; int n, o, count = *num, true_num, snum, offset, flags, finetune, delta;
unsigned char * buffer; unsigned char *buffer;
const unsigned char * sdata; const unsigned char *sdata;
long sample_bytes; long sample_bytes;
buffer = malloc(count * 64); buffer = malloc(count * 64);
if (!buffer) goto error; if (!buffer)
goto error;
if (dumbfile_getnc((char *)buffer, count * 64, f) < count * 64) goto error_fb; if (dumbfile_getnc((char *)buffer, count * 64, f) < count * 64)
goto error_fb;
true_num = 0; true_num = 0;
for (n = 0; n < count; n++) { for (n = 0; n < count; n++) {
snum = buffer[(n * 64) + 45] | (buffer[(n * 64) + 46] << 8); snum = buffer[(n * 64) + 45] | (buffer[(n * 64) + 46] << 8);
if ((snum < 1) || (snum > 255)) goto error_fb; if ((snum < 1) || (snum > 255))
if (true_num < snum) true_num = snum; goto error_fb;
if (true_num < snum)
true_num = snum;
} }
if (true_num > count) { if (true_num > count) {
IT_SAMPLE * meh = realloc(*sample, true_num * sizeof(*meh)); IT_SAMPLE *meh = realloc(*sample, true_num * sizeof(*meh));
if (!meh) goto error_fb; if (!meh)
goto error_fb;
for (n = count; n < true_num; n++) { for (n = count; n < true_num; n++) {
meh[n].data = NULL; meh[n].data = NULL;
} }
@ -72,7 +75,7 @@ static int it_old_psm_read_samples(IT_SAMPLE ** sample, DUMBFILE * f, int * num)
for (n = 0; n < count; n++) { for (n = 0; n < count; n++) {
IT_SAMPLE smp; IT_SAMPLE smp;
IT_SAMPLE * s; IT_SAMPLE *s;
snum = buffer[(n * 64) + 45] | (buffer[(n * 64) + 46] << 8); snum = buffer[(n * 64) + 45] | (buffer[(n * 64) + 46] << 8);
s = &((*sample)[snum - 1]); s = &((*sample)[snum - 1]);
memcpy(smp.filename, buffer + (n * 64), 13); memcpy(smp.filename, buffer + (n * 64), 13);
@ -83,30 +86,38 @@ static int it_old_psm_read_samples(IT_SAMPLE ** sample, DUMBFILE * f, int * num)
(buffer[(n * 64) + 39] << 16) | (buffer[(n * 64) + 40] << 24); (buffer[(n * 64) + 39] << 16) | (buffer[(n * 64) + 40] << 24);
flags = buffer[(n * 64) + 47]; flags = buffer[(n * 64) + 47];
smp.length = buffer[(n * 64) + 48] | (buffer[(n * 64) + 49] << 8) | smp.length = buffer[(n * 64) + 48] | (buffer[(n * 64) + 49] << 8) |
(buffer[(n * 64) + 50] << 16) | (buffer[(n * 64) + 51] << 24); (buffer[(n * 64) + 50] << 16) |
(buffer[(n * 64) + 51] << 24);
smp.loop_start = buffer[(n * 64) + 52] | (buffer[(n * 64) + 53] << 8) | smp.loop_start = buffer[(n * 64) + 52] | (buffer[(n * 64) + 53] << 8) |
(buffer[(n * 64) + 54] << 16) | (buffer[(n * 64) + 55] << 24); (buffer[(n * 64) + 54] << 16) |
(buffer[(n * 64) + 55] << 24);
smp.loop_end = buffer[(n * 64) + 56] | (buffer[(n * 64) + 57] << 8) | smp.loop_end = buffer[(n * 64) + 56] | (buffer[(n * 64) + 57] << 8) |
(buffer[(n * 64) + 58] << 16) | (buffer[(n * 64) + 59] << 24); (buffer[(n * 64) + 58] << 16) |
(buffer[(n * 64) + 59] << 24);
if (smp.length <= 0) continue; if (smp.length <= 0)
continue;
finetune = buffer[(n * 64) + 60]; finetune = buffer[(n * 64) + 60];
smp.default_volume = buffer[(n * 64) + 61]; smp.default_volume = buffer[(n * 64) + 61];
smp.C5_speed = buffer[(n * 64) + 62] | (buffer[(n * 64) + 63] << 8); smp.C5_speed = buffer[(n * 64) + 62] | (buffer[(n * 64) + 63] << 8);
if (finetune & 15) { if (finetune & 15) {
finetune &= 15; finetune &= 15;
if (finetune >= 8) finetune -= 16; if (finetune >= 8)
//s->C5_speed = (long)((double)s->C5_speed * pow(DUMB_PITCH_BASE, finetune*32)); finetune -= 16;
// s->C5_speed = (long)((double)s->C5_speed * pow(DUMB_PITCH_BASE,
// finetune*32));
smp.finetune = finetune * 32; smp.finetune = finetune * 32;
} } else
else smp.finetune = 0; smp.finetune = 0;
smp.flags |= IT_SAMPLE_EXISTS; smp.flags |= IT_SAMPLE_EXISTS;
if (flags & 0x41) if (flags & 0x41)
continue; continue;
if (flags & 0x20) smp.flags |= IT_SAMPLE_PINGPONG_LOOP; if (flags & 0x20)
if (flags & 4) smp.flags |= IT_SAMPLE_16BIT; smp.flags |= IT_SAMPLE_PINGPONG_LOOP;
if (flags & 4)
smp.flags |= IT_SAMPLE_16BIT;
if (flags & 0x80) { if (flags & 0x80) {
smp.flags |= IT_SAMPLE_LOOP; smp.flags |= IT_SAMPLE_LOOP;
@ -128,16 +139,20 @@ static int it_old_psm_read_samples(IT_SAMPLE ** sample, DUMBFILE * f, int * num)
sample_bytes = smp.length * ((flags & 4) ? 2 : 1); sample_bytes = smp.length * ((flags & 4) ? 2 : 1);
smp.data = malloc(sample_bytes); smp.data = malloc(sample_bytes);
if (!smp.data) goto error_fb; if (!smp.data)
sdata = (const unsigned char *) smp.data; goto error_fb;
sdata = (const unsigned char *)smp.data;
if (dumbfile_seek(f, offset, DFS_SEEK_SET) || dumbfile_getnc(smp.data, sample_bytes, f) < sample_bytes) goto error_fd; if (dumbfile_seek(f, offset, DFS_SEEK_SET) ||
dumbfile_getnc(smp.data, sample_bytes, f) < sample_bytes)
goto error_fd;
if (flags & 0x10) { if (flags & 0x10) {
if (flags & 8) { if (flags & 8) {
if (flags & 4) { if (flags & 4) {
for (o = 0; o < smp.length; o++) for (o = 0; o < smp.length; o++)
((short *)smp.data)[o] = (sdata[o * 2] | (sdata[(o * 2) + 1] << 8)) ^ 0x8000; ((short *)smp.data)[o] =
(sdata[o * 2] | (sdata[(o * 2) + 1] << 8)) ^ 0x8000;
} else { } else {
for (o = 0; o < smp.length; o++) for (o = 0; o < smp.length; o++)
((signed char *)smp.data)[o] = sdata[o] ^ 0x80; ((signed char *)smp.data)[o] = sdata[o] ^ 0x80;
@ -145,7 +160,8 @@ static int it_old_psm_read_samples(IT_SAMPLE ** sample, DUMBFILE * f, int * num)
} else { } else {
if (flags & 4) { if (flags & 4) {
for (o = 0; o < smp.length; o++) for (o = 0; o < smp.length; o++)
((short *)smp.data)[o] = sdata[o * 2] | (sdata[(o * 2) + 1] << 8); ((short *)smp.data)[o] =
sdata[o * 2] | (sdata[(o * 2) + 1] << 8);
} else { } else {
memcpy(smp.data, sdata, smp.length); memcpy(smp.data, sdata, smp.length);
} }
@ -156,7 +172,8 @@ static int it_old_psm_read_samples(IT_SAMPLE ** sample, DUMBFILE * f, int * num)
/* unsigned delta? mehhh, does anything even use this? */ /* unsigned delta? mehhh, does anything even use this? */
if (flags & 4) { if (flags & 4) {
for (o = 0; o < smp.length; o++) { for (o = 0; o < smp.length; o++) {
delta += (short)(sdata[o * 2] | (sdata[(o * 2) + 1] << 8)); delta +=
(short)(sdata[o * 2] | (sdata[(o * 2) + 1] << 8));
((short *)smp.data)[o] = delta ^ 0x8000; ((short *)smp.data)[o] = delta ^ 0x8000;
} }
} else { } else {
@ -168,7 +185,8 @@ static int it_old_psm_read_samples(IT_SAMPLE ** sample, DUMBFILE * f, int * num)
} else { } else {
if (flags & 4) { if (flags & 4) {
for (o = 0; o < smp.length; o++) { for (o = 0; o < smp.length; o++) {
delta += (signed short)(sdata[o * 2] | (sdata[(o * 2) + 1] << 8)); delta += (signed short)(sdata[o * 2] |
(sdata[(o * 2) + 1] << 8));
((signed short *)smp.data)[o] = delta; ((signed short *)smp.data)[o] = delta;
} }
} else { } else {
@ -180,7 +198,8 @@ static int it_old_psm_read_samples(IT_SAMPLE ** sample, DUMBFILE * f, int * num)
} }
} }
if (s->data) free(s->data); if (s->data)
free(s->data);
*s = smp; *s = smp;
} }
@ -196,25 +215,28 @@ error:
return -1; return -1;
} }
static int it_old_psm_read_patterns(IT_PATTERN * pattern, DUMBFILE * f, int num, int size, int pchans) static int it_old_psm_read_patterns(IT_PATTERN *pattern, DUMBFILE *f, int num,
{ int size, int pchans) {
int n, offset, psize, rows, chans, row, flags, channel; int n, offset, psize, rows, chans, row, flags, channel;
unsigned char * buffer, * ptr, * end; unsigned char *buffer, *ptr, *end;
IT_ENTRY * entry; IT_ENTRY *entry;
buffer = malloc(size); buffer = malloc(size);
if (!buffer) goto error; if (!buffer)
goto error;
if (dumbfile_getnc((char *)buffer, size, f) < size) goto error_fb; if (dumbfile_getnc((char *)buffer, size, f) < size)
goto error_fb;
offset = 0; offset = 0;
for (n = 0; n < num; n++) { for (n = 0; n < num; n++) {
IT_PATTERN * p = &pattern[n]; IT_PATTERN *p = &pattern[n];
if (offset >= size) goto error_fb; if (offset >= size)
goto error_fb;
ptr = buffer + offset; ptr = buffer + offset;
psize = ptr[0] | (ptr[1] << 8); psize = ptr[0] | (ptr[1] << 8);
@ -229,7 +251,8 @@ static int it_old_psm_read_patterns(IT_PATTERN * pattern, DUMBFILE * f, int num,
psize = (psize + 15) & ~15; psize = (psize + 15) & ~15;
if (offset + psize > size) goto error_fb; if (offset + psize > size)
goto error_fb;
end = ptr + psize; end = ptr + psize;
ptr += 4; ptr += 4;
@ -246,17 +269,22 @@ static int it_old_psm_read_patterns(IT_PATTERN * pattern, DUMBFILE * f, int num,
} }
if (flags & 0xE0) { if (flags & 0xE0) {
p->n_entries++; p->n_entries++;
if (flags & 0x80) ptr += 2; if (flags & 0x80)
if (flags & 0x40) ptr++; ptr += 2;
if (flags & 0x40)
ptr++;
if (flags & 0x20) { if (flags & 0x20) {
if (*ptr == 40) ptr += 4; if (*ptr == 40)
else ptr += 2; ptr += 4;
else
ptr += 2;
} }
} }
} }
entry = malloc(p->n_entries * sizeof(*p->entry)); entry = malloc(p->n_entries * sizeof(*p->entry));
if (!entry) goto error_fb; if (!entry)
goto error_fb;
p->entry = entry; p->entry = entry;
@ -274,10 +302,9 @@ static int it_old_psm_read_patterns(IT_PATTERN * pattern, DUMBFILE * f, int num,
if (flags & 0xE0) { if (flags & 0xE0) {
entry->mask = 0; entry->mask = 0;
entry->channel = channel = flags & 0x1F; entry->channel = channel = flags & 0x1F;
if (channel >= chans) if (channel >= chans) {
{ // channel = 0;
//channel = 0; // goto error_fb;
//goto error_fb;
} }
if (flags & 0x80) { if (flags & 0x80) {
if ((*ptr < 60) && (channel < pchans)) { if ((*ptr < 60) && (channel < pchans)) {
@ -349,7 +376,8 @@ static int it_old_psm_read_patterns(IT_PATTERN * pattern, DUMBFILE * f, int num,
case 15: case 15:
entry->effect = IT_S; entry->effect = IT_S;
entry->effectvalue = EFFECT_VALUE(IT_S_SET_GLISSANDO_CONTROL, ptr[1] & 15); entry->effectvalue = EFFECT_VALUE(
IT_S_SET_GLISSANDO_CONTROL, ptr[1] & 15);
break; break;
case 16: case 16:
@ -369,7 +397,8 @@ static int it_old_psm_read_patterns(IT_PATTERN * pattern, DUMBFILE * f, int num,
case 21: case 21:
entry->effect = IT_S; entry->effect = IT_S;
entry->effectvalue = EFFECT_VALUE(IT_S_SET_VIBRATO_WAVEFORM, ptr[1] & 11); entry->effectvalue = EFFECT_VALUE(
IT_S_SET_VIBRATO_WAVEFORM, ptr[1] & 11);
break; break;
case 22: case 22:
@ -389,7 +418,8 @@ static int it_old_psm_read_patterns(IT_PATTERN * pattern, DUMBFILE * f, int num,
case 31: case 31:
entry->effect = IT_S; entry->effect = IT_S;
entry->effectvalue = EFFECT_VALUE(IT_S_SET_TREMOLO_WAVEFORM, ptr[1] & 11); entry->effectvalue = EFFECT_VALUE(
IT_S_SET_TREMOLO_WAVEFORM, ptr[1] & 11);
break; break;
case 40: case 40:
@ -405,12 +435,14 @@ static int it_old_psm_read_patterns(IT_PATTERN * pattern, DUMBFILE * f, int num,
case 42: case 42:
entry->effect = IT_S; entry->effect = IT_S;
entry->effectvalue = EFFECT_VALUE(IT_S_DELAYED_NOTE_CUT, ptr[1] & 0xF); entry->effectvalue =
EFFECT_VALUE(IT_S_DELAYED_NOTE_CUT, ptr[1] & 0xF);
break; break;
case 43: case 43:
entry->effect = IT_S; entry->effect = IT_S;
entry->effectvalue = EFFECT_VALUE(IT_S_NOTE_DELAY, ptr[1] & 0xF); entry->effectvalue =
EFFECT_VALUE(IT_S_NOTE_DELAY, ptr[1] & 0xF);
break; break;
case 50: case 50:
@ -425,12 +457,14 @@ static int it_old_psm_read_patterns(IT_PATTERN * pattern, DUMBFILE * f, int num,
case 52: case 52:
entry->effect = IT_S; entry->effect = IT_S;
entry->effectvalue = EFFECT_VALUE(IT_S_PATTERN_LOOP, ptr[1] & 0xF); entry->effectvalue =
EFFECT_VALUE(IT_S_PATTERN_LOOP, ptr[1] & 0xF);
break; break;
case 53: case 53:
entry->effect = IT_S; entry->effect = IT_S;
entry->effectvalue = EFFECT_VALUE(IT_S_PATTERN_DELAY, ptr[1] & 0xF); entry->effectvalue =
EFFECT_VALUE(IT_S_PATTERN_DELAY, ptr[1] & 0xF);
break; break;
case 60: case 60:
@ -450,13 +484,15 @@ static int it_old_psm_read_patterns(IT_PATTERN * pattern, DUMBFILE * f, int num,
case 71: case 71:
entry->effect = IT_S; entry->effect = IT_S;
entry->effectvalue = EFFECT_VALUE(IT_S_FINETUNE, ptr[1] & 0xF); entry->effectvalue =
EFFECT_VALUE(IT_S_FINETUNE, ptr[1] & 0xF);
break; break;
case 72: case 72:
/* "balance" ... panning? */ /* "balance" ... panning? */
entry->effect = IT_SET_PANNING; entry->effect = IT_SET_PANNING;
entry->effectvalue = ((ptr[1] - ((ptr[1] & 8) >> 3)) << 5) / 7; entry->effectvalue =
((ptr[1] - ((ptr[1] & 8) >> 3)) << 5) / 7;
break; break;
default: default:
@ -465,7 +501,8 @@ static int it_old_psm_read_patterns(IT_PATTERN * pattern, DUMBFILE * f, int num,
ptr += 2; ptr += 2;
} }
if (entry->mask) entry++; if (entry->mask)
entry++;
} }
} }
@ -489,21 +526,17 @@ error:
#define PSM_COMPONENT_SAMPLE_HEADERS 3 #define PSM_COMPONENT_SAMPLE_HEADERS 3
#define PSM_COMPONENT_COMMENTS 4 #define PSM_COMPONENT_COMMENTS 4
typedef struct PSM_COMPONENT typedef struct PSM_COMPONENT {
{
unsigned char type; unsigned char type;
long offset; long offset;
} } PSM_COMPONENT;
PSM_COMPONENT;
static int psm_component_compare(const void *e1, const void *e2) static int psm_component_compare(const void *e1, const void *e2) {
{
return (int)(((const PSM_COMPONENT *)e1)->offset - return (int)(((const PSM_COMPONENT *)e1)->offset -
((const PSM_COMPONENT *)e2)->offset); ((const PSM_COMPONENT *)e2)->offset);
} }
static DUMB_IT_SIGDATA *it_old_psm_load_sigdata(DUMBFILE *f) static DUMB_IT_SIGDATA *it_old_psm_load_sigdata(DUMBFILE *f) {
{
DUMB_IT_SIGDATA *sigdata; DUMB_IT_SIGDATA *sigdata;
PSM_COMPONENT *component; PSM_COMPONENT *component;
@ -511,13 +544,16 @@ static DUMB_IT_SIGDATA *it_old_psm_load_sigdata(DUMBFILE *f)
int n, flags, version, pver, n_orders, n_channels, total_pattern_size; int n, flags, version, pver, n_orders, n_channels, total_pattern_size;
if (dumbfile_mgetl(f) != DUMB_ID('P','S','M',254)) goto error; if (dumbfile_mgetl(f) != DUMB_ID('P', 'S', 'M', 254))
goto error;
sigdata = malloc(sizeof(*sigdata)); sigdata = malloc(sizeof(*sigdata));
if (!sigdata) goto error; if (!sigdata)
goto error;
if (dumbfile_getnc((char *)sigdata->name, 60, f) < 60 || if (dumbfile_getnc((char *)sigdata->name, 60, f) < 60 ||
sigdata->name[59] != 0x1A) goto error_sd; sigdata->name[59] != 0x1A)
goto error_sd;
sigdata->name[59] = 0; sigdata->name[59] = 0;
flags = dumbfile_getc(f); flags = dumbfile_getc(f);
@ -533,16 +569,10 @@ static DUMB_IT_SIGDATA *it_old_psm_load_sigdata(DUMBFILE *f)
sigdata->n_pchannels = dumbfile_igetw(f); sigdata->n_pchannels = dumbfile_igetw(f);
n_channels = dumbfile_igetw(f); n_channels = dumbfile_igetw(f);
if (dumbfile_error(f) || if (dumbfile_error(f) || (flags & 1) || (version != 1 && version != 0x10) ||
(flags & 1) || (pver) || (sigdata->n_orders <= 0) || (sigdata->n_orders > 255) ||
(version != 1 && version != 0x10) || (n_orders > 255) || (n_orders < sigdata->n_orders) ||
(pver) || (sigdata->n_patterns > 255) || (sigdata->n_samples > 255) ||
(sigdata->n_orders <= 0) ||
(sigdata->n_orders > 255) ||
(n_orders > 255) ||
(n_orders < sigdata->n_orders) ||
(sigdata->n_patterns > 255) ||
(sigdata->n_samples > 255) ||
(sigdata->n_pchannels > DUMB_IT_N_CHANNELS) || (sigdata->n_pchannels > DUMB_IT_N_CHANNELS) ||
(sigdata->n_pchannels > n_channels) || (sigdata->n_pchannels > n_channels) ||
(n_channels > DUMB_IT_N_CHANNELS)) (n_channels > DUMB_IT_N_CHANNELS))
@ -566,24 +596,29 @@ static DUMB_IT_SIGDATA *it_old_psm_load_sigdata(DUMBFILE *f)
sigdata->restart_position = 0; sigdata->restart_position = 0;
sigdata->order = malloc(sigdata->n_orders); sigdata->order = malloc(sigdata->n_orders);
if (!sigdata->order) goto error_usd; if (!sigdata->order)
goto error_usd;
if (sigdata->n_samples) { if (sigdata->n_samples) {
sigdata->sample = malloc(sigdata->n_samples * sizeof(*sigdata->sample)); sigdata->sample = malloc(sigdata->n_samples * sizeof(*sigdata->sample));
if (!sigdata->sample) goto error_usd; if (!sigdata->sample)
goto error_usd;
for (n = 0; n < sigdata->n_samples; n++) for (n = 0; n < sigdata->n_samples; n++)
sigdata->sample[n].data = NULL; sigdata->sample[n].data = NULL;
} }
if (sigdata->n_patterns) { if (sigdata->n_patterns) {
sigdata->pattern = malloc(sigdata->n_patterns * sizeof(*sigdata->pattern)); sigdata->pattern =
if (!sigdata->pattern) goto error_usd; malloc(sigdata->n_patterns * sizeof(*sigdata->pattern));
if (!sigdata->pattern)
goto error_usd;
for (n = 0; n < sigdata->n_patterns; n++) for (n = 0; n < sigdata->n_patterns; n++)
sigdata->pattern[n].entry = NULL; sigdata->pattern[n].entry = NULL;
} }
component = malloc(5 * sizeof(*component)); component = malloc(5 * sizeof(*component));
if (!component) goto error_usd; if (!component)
goto error_usd;
for (n = 0; n < 5; n++) { for (n = 0; n < 5; n++) {
component[n_components].offset = dumbfile_igetl(f); component[n_components].offset = dumbfile_igetl(f);
@ -593,61 +628,76 @@ static DUMB_IT_SIGDATA *it_old_psm_load_sigdata(DUMBFILE *f)
} }
} }
if (!n_components) goto error_fc; if (!n_components)
goto error_fc;
total_pattern_size = (int)dumbfile_igetl(f); total_pattern_size = (int)dumbfile_igetl(f);
if (!total_pattern_size) goto error_fc; if (!total_pattern_size)
goto error_fc;
qsort(component, n_components, sizeof(PSM_COMPONENT), &psm_component_compare); qsort(component, n_components, sizeof(PSM_COMPONENT),
&psm_component_compare);
memset(sigdata->channel_volume, 64, DUMB_IT_N_CHANNELS); memset(sigdata->channel_volume, 64, DUMB_IT_N_CHANNELS);
for (n = 0; n < DUMB_IT_N_CHANNELS; n += 4) { for (n = 0; n < DUMB_IT_N_CHANNELS; n += 4) {
int sep = 32 * dumb_it_default_panning_separation / 100; int sep = 32 * dumb_it_default_panning_separation / 100;
sigdata->channel_pan[n ] = 32 - sep; sigdata->channel_pan[n] = 32 - sep;
sigdata->channel_pan[n+1] = 32 + sep; sigdata->channel_pan[n + 1] = 32 + sep;
sigdata->channel_pan[n+2] = 32 + sep; sigdata->channel_pan[n + 2] = 32 + sep;
sigdata->channel_pan[n+3] = 32 - sep; sigdata->channel_pan[n + 3] = 32 - sep;
} }
for (n = 0; n < n_components; n++) for (n = 0; n < n_components; n++) {
{
int o; int o;
if ( dumbfile_seek(f, component[n].offset, DFS_SEEK_SET) ) goto error_fc; if (dumbfile_seek(f, component[n].offset, DFS_SEEK_SET))
goto error_fc;
switch (component[n].type) { switch (component[n].type) {
case PSM_COMPONENT_ORDERS: case PSM_COMPONENT_ORDERS:
if (dumbfile_getnc((char *)sigdata->order, sigdata->n_orders, f) < sigdata->n_orders) goto error_fc; if (dumbfile_getnc((char *)sigdata->order, sigdata->n_orders, f) <
sigdata->n_orders)
goto error_fc;
if (n_orders > sigdata->n_orders) if (n_orders > sigdata->n_orders)
if (dumbfile_skip(f, n_orders - sigdata->n_orders)) if (dumbfile_skip(f, n_orders - sigdata->n_orders))
goto error_fc; goto error_fc;
if (dumbfile_igetw(f)) goto error_fc; if (dumbfile_igetw(f))
goto error_fc;
break; break;
case PSM_COMPONENT_PANPOS: case PSM_COMPONENT_PANPOS:
if (dumbfile_getnc((char *)sigdata->channel_pan, sigdata->n_pchannels, f) < sigdata->n_pchannels) goto error_fc; if (dumbfile_getnc((char *)sigdata->channel_pan,
sigdata->n_pchannels, f) < sigdata->n_pchannels)
goto error_fc;
for (o = 0; o < sigdata->n_pchannels; o++) { for (o = 0; o < sigdata->n_pchannels; o++) {
sigdata->channel_pan[o] -= (sigdata->channel_pan[o] & 8) >> 3; sigdata->channel_pan[o] -= (sigdata->channel_pan[o] & 8) >> 3;
sigdata->channel_pan[o] = ((int)sigdata->channel_pan[o] << 5) / 7; sigdata->channel_pan[o] =
((int)sigdata->channel_pan[o] << 5) / 7;
} }
break; break;
case PSM_COMPONENT_PATTERNS: case PSM_COMPONENT_PATTERNS:
if (it_old_psm_read_patterns(sigdata->pattern, f, sigdata->n_patterns, total_pattern_size, sigdata->n_pchannels)) goto error_fc; if (it_old_psm_read_patterns(
sigdata->pattern, f, sigdata->n_patterns,
total_pattern_size, sigdata->n_pchannels))
goto error_fc;
break; break;
case PSM_COMPONENT_SAMPLE_HEADERS: case PSM_COMPONENT_SAMPLE_HEADERS:
if (it_old_psm_read_samples(&sigdata->sample, f, &sigdata->n_samples)) goto error_fc; if (it_old_psm_read_samples(&sigdata->sample, f,
&sigdata->n_samples))
goto error_fc;
break; break;
case PSM_COMPONENT_COMMENTS: case PSM_COMPONENT_COMMENTS:
if (dumbfile_mgetl(f) == DUMB_ID('T','E','X','T')) { if (dumbfile_mgetl(f) == DUMB_ID('T', 'E', 'X', 'T')) {
o = dumbfile_igetw(f); o = dumbfile_igetw(f);
if (o > 0) { if (o > 0) {
sigdata->song_message = malloc(o + 1); sigdata->song_message = malloc(o + 1);
if (dumbfile_getnc((char *)sigdata->song_message, o, f) < o) goto error_fc; if (dumbfile_getnc((char *)sigdata->song_message, o, f) < o)
goto error_fc;
sigdata->song_message[o] = 0; sigdata->song_message[o] = 0;
} }
} }
@ -672,8 +722,7 @@ error:
return NULL; return NULL;
} }
DUH *dumb_read_old_psm_quick(DUMBFILE *f) DUH *dumb_read_old_psm_quick(DUMBFILE *f) {
{
sigdata_t *sigdata; sigdata_t *sigdata;
DUH_SIGTYPE_DESC *descptr = &_dumb_sigtype_it; DUH_SIGTYPE_DESC *descptr = &_dumb_sigtype_it;
@ -689,6 +738,7 @@ DUH *dumb_read_old_psm_quick(DUMBFILE *f)
tag[0][1] = (const char *)(((DUMB_IT_SIGDATA *)sigdata)->name); tag[0][1] = (const char *)(((DUMB_IT_SIGDATA *)sigdata)->name);
tag[1][0] = "FORMAT"; tag[1][0] = "FORMAT";
tag[1][1] = "PSM (old)"; tag[1][1] = "PSM (old)";
return make_duh(-1, 2, (const char *const (*)[2])tag, 1, &descptr, &sigdata); return make_duh(-1, 2, (const char *const(*)[2])tag, 1, &descptr,
&sigdata);
} }
} }

File diff suppressed because it is too large Load diff

View file

@ -24,10 +24,8 @@
#include "dumb.h" #include "dumb.h"
#include "internal/it.h" #include "internal/it.h"
static int it_ptm_read_sample_header(IT_SAMPLE *sample, long *offset,
DUMBFILE *f) {
static int it_ptm_read_sample_header(IT_SAMPLE *sample, long *offset, DUMBFILE *f)
{
int flags; int flags;
flags = dumbfile_getc(f); flags = dumbfile_getc(f);
@ -48,7 +46,7 @@ static int it_ptm_read_sample_header(IT_SAMPLE *sample, long *offset, DUMBFILE *
sample->loop_end = dumbfile_igetl(f); sample->loop_end = dumbfile_igetl(f);
/* GUSBegin, GUSLStart, GUSLEnd, GUSLoop, reserverd */ /* GUSBegin, GUSLStart, GUSLEnd, GUSLoop, reserverd */
dumbfile_skip(f, 4+4+4+1+1); dumbfile_skip(f, 4 + 4 + 4 + 1 + 1);
dumbfile_getnc((char *)sample->name, 28, f); dumbfile_getnc((char *)sample->name, 28, f);
sample->name[28] = 0; sample->name[28] = 0;
@ -70,8 +68,10 @@ static int it_ptm_read_sample_header(IT_SAMPLE *sample, long *offset, DUMBFILE *
sample->global_volume = 64; sample->global_volume = 64;
sample->flags = IT_SAMPLE_EXISTS; sample->flags = IT_SAMPLE_EXISTS;
if (flags & 4) sample->flags |= IT_SAMPLE_LOOP; if (flags & 4)
if (flags & 8) sample->flags |= IT_SAMPLE_PINGPONG_LOOP; sample->flags |= IT_SAMPLE_LOOP;
if (flags & 8)
sample->flags |= IT_SAMPLE_PINGPONG_LOOP;
if (flags & 16) { if (flags & 16) {
sample->flags |= IT_SAMPLE_16BIT; sample->flags |= IT_SAMPLE_16BIT;
@ -81,7 +81,8 @@ static int it_ptm_read_sample_header(IT_SAMPLE *sample, long *offset, DUMBFILE *
sample->loop_end >>= 1; sample->loop_end >>= 1;
} }
if (sample->loop_end) sample->loop_end--; if (sample->loop_end)
sample->loop_end--;
sample->default_pan = 0; // 0 = don't use, or 160 = centre? sample->default_pan = 0; // 0 = don't use, or 160 = centre?
@ -90,14 +91,14 @@ static int it_ptm_read_sample_header(IT_SAMPLE *sample, long *offset, DUMBFILE *
else if (sample->flags & IT_SAMPLE_LOOP) { else if (sample->flags & IT_SAMPLE_LOOP) {
if ((unsigned int)sample->loop_end > (unsigned int)sample->length) if ((unsigned int)sample->loop_end > (unsigned int)sample->length)
sample->flags &= ~IT_SAMPLE_LOOP; sample->flags &= ~IT_SAMPLE_LOOP;
else if ((unsigned int)sample->loop_start >= (unsigned int)sample->loop_end) else if ((unsigned int)sample->loop_start >=
(unsigned int)sample->loop_end)
sample->flags &= ~IT_SAMPLE_LOOP; sample->flags &= ~IT_SAMPLE_LOOP;
else else
sample->length = sample->loop_end; sample->length = sample->loop_end;
} }
// Do we need to set all these?
//Do we need to set all these?
sample->vibrato_speed = 0; sample->vibrato_speed = 0;
sample->vibrato_depth = 0; sample->vibrato_depth = 0;
sample->vibrato_rate = 0; sample->vibrato_rate = 0;
@ -108,20 +109,19 @@ static int it_ptm_read_sample_header(IT_SAMPLE *sample, long *offset, DUMBFILE *
return dumbfile_error(f); return dumbfile_error(f);
} }
static int it_ptm_read_byte(DUMBFILE *f) {
static int it_ptm_read_byte(DUMBFILE *f)
{
int meh = dumbfile_getc(f); int meh = dumbfile_getc(f);
if (meh < 0) return 0; if (meh < 0)
return 0;
return meh; return meh;
} }
static int it_ptm_read_sample_data(IT_SAMPLE *sample, int last, DUMBFILE *f) static int it_ptm_read_sample_data(IT_SAMPLE *sample, int last, DUMBFILE *f) {
{
long n; long n;
int s; int s;
sample->data = malloc(sample->length * (sample->flags & IT_SAMPLE_16BIT ? 2 : 1)); sample->data =
malloc(sample->length * (sample->flags & IT_SAMPLE_16BIT ? 2 : 1));
if (!sample->data) if (!sample->data)
return -1; return -1;
@ -130,13 +130,13 @@ static int it_ptm_read_sample_data(IT_SAMPLE *sample, int last, DUMBFILE *f)
if (sample->flags & IT_SAMPLE_16BIT) { if (sample->flags & IT_SAMPLE_16BIT) {
unsigned char a, b; unsigned char a, b;
for (n = 0; n < sample->length; n++) { for (n = 0; n < sample->length; n++) {
a = s += (signed char) it_ptm_read_byte(f); a = s += (signed char)it_ptm_read_byte(f);
b = s += (signed char) it_ptm_read_byte(f); b = s += (signed char)it_ptm_read_byte(f);
((short *)sample->data)[n] = a | (b << 8); ((short *)sample->data)[n] = a | (b << 8);
} }
} else { } else {
for (n = 0; n < sample->length; n++) { for (n = 0; n < sample->length; n++) {
s += (signed char) it_ptm_read_byte(f); s += (signed char)it_ptm_read_byte(f);
((signed char *)sample->data)[n] = s; ((signed char *)sample->data)[n] = s;
} }
} }
@ -147,10 +147,8 @@ static int it_ptm_read_sample_data(IT_SAMPLE *sample, int last, DUMBFILE *f)
return 0; return 0;
} }
static int it_ptm_read_pattern(IT_PATTERN *pattern, DUMBFILE *f,
unsigned char *buffer, size_t length) {
static int it_ptm_read_pattern(IT_PATTERN *pattern, DUMBFILE *f, unsigned char *buffer, int length)
{
int buflen = 0; int buflen = 0;
int bufpos = 0; int bufpos = 0;
int effect, effectvalue; int effect, effectvalue;
@ -177,27 +175,33 @@ static int it_ptm_read_pattern(IT_PATTERN *pattern, DUMBFILE *f, unsigned char *
b >>= 5; b >>= 5;
pattern->n_entries++; pattern->n_entries++;
if (b) { if (b) {
if (buflen + used[b] >= 65536) return -1; if (buflen + used[b] >= 65536)
return -1;
dumbfile_getnc((char *)buffer + buflen, used[b], f); dumbfile_getnc((char *)buffer + buflen, used[b], f);
buflen += used[b]; buflen += used[b];
} else { } else {
/* End of row */ /* End of row */
if (++pattern->n_rows == 64) break; if (++pattern->n_rows == 64)
if (buflen >= 65536) return -1; break;
if (buflen >= 65536)
return -1;
} }
#else #else
if (b == 0) { if (b == 0) {
/* End of row */ /* End of row */
pattern->n_entries++; pattern->n_entries++;
if (++pattern->n_rows == 64) break; if (++pattern->n_rows == 64)
if (buflen >= 65536) return -1; break;
if (buflen >= 65536)
return -1;
} else { } else {
static const unsigned char used[8] = {0, 2, 2, 4, 1, 3, 3, 5}; static const unsigned char used[8] = {0, 2, 2, 4, 1, 3, 3, 5};
channel = b & 31; channel = b & 31;
b >>= 5; b >>= 5;
if (b) { if (b) {
pattern->n_entries++; pattern->n_entries++;
if (buflen + used[b] >= 65536) return -1; if (buflen + used[b] >= 65536)
return -1;
dumbfile_getnc(buffer + buflen, used[b], f); dumbfile_getnc(buffer + buflen, used[b], f);
buflen += used[b]; buflen += used[b];
} }
@ -216,11 +220,10 @@ static int it_ptm_read_pattern(IT_PATTERN *pattern, DUMBFILE *f, unsigned char *
/* Great. We ran out of data, but there should be data for more rows. /* Great. We ran out of data, but there should be data for more rows.
* Fill the rest with null data... * Fill the rest with null data...
*/ */
if (buflen >= length && pattern->n_rows < 64) if (buflen >= (dumb_ssize_t)length && pattern->n_rows < 64) {
{ while (pattern->n_rows < 64) {
while (pattern->n_rows < 64) if (buflen >= 65536)
{ return -1;
if (buflen >= 65536) return -1;
buffer[buflen++] = 0; buffer[buflen++] = 0;
pattern->n_entries++; pattern->n_entries++;
pattern->n_rows++; pattern->n_rows++;
@ -239,8 +242,7 @@ static int it_ptm_read_pattern(IT_PATTERN *pattern, DUMBFILE *f, unsigned char *
while (bufpos < buflen) { while (bufpos < buflen) {
unsigned char b = buffer[bufpos++]; unsigned char b = buffer[bufpos++];
if (b == 0) if (b == 0) {
{
/* End of row */ /* End of row */
IT_SET_END_ROW(entry); IT_SET_END_ROW(entry);
entry++; entry++;
@ -289,9 +291,8 @@ static int it_ptm_read_pattern(IT_PATTERN *pattern, DUMBFILE *f, unsigned char *
return 0; return 0;
} }
/** WARNING: this is duplicated in itread.c - also bad practice to use the same
* struct name unless they are unified in a header */
/** WARNING: this is duplicated in itread.c - also bad practice to use the same struct name unless they are unified in a header */
/* Currently we assume the sample data are stored after the sample headers in /* Currently we assume the sample data are stored after the sample headers in
* module files. This assumption may be unjustified; let me know if you have * module files. This assumption may be unjustified; let me know if you have
* trouble. * trouble.
@ -301,26 +302,18 @@ static int it_ptm_read_pattern(IT_PATTERN *pattern, DUMBFILE *f, unsigned char *
#define PTM_COMPONENT_PATTERN 2 #define PTM_COMPONENT_PATTERN 2
#define PTM_COMPONENT_SAMPLE 3 #define PTM_COMPONENT_SAMPLE 3
typedef struct PTM_COMPONENT typedef struct PTM_COMPONENT {
{
unsigned char type; unsigned char type;
unsigned char n; unsigned char n;
long offset; long offset;
} } PTM_COMPONENT;
PTM_COMPONENT;
static int ptm_component_compare(const void *e1, const void *e2) {
return (int)(((const PTM_COMPONENT *)e1)->offset -
static int ptm_component_compare(const void *e1, const void *e2) ((const PTM_COMPONENT *)e2)->offset);
{
return ((const PTM_COMPONENT *)e1)->offset -
((const PTM_COMPONENT *)e2)->offset;
} }
static DUMB_IT_SIGDATA *it_ptm_load_sigdata(DUMBFILE *f) {
static DUMB_IT_SIGDATA *it_ptm_load_sigdata(DUMBFILE *f)
{
DUMB_IT_SIGDATA *sigdata; DUMB_IT_SIGDATA *sigdata;
PTM_COMPONENT *component; PTM_COMPONENT *component;
@ -331,7 +324,8 @@ static DUMB_IT_SIGDATA *it_ptm_load_sigdata(DUMBFILE *f)
unsigned char *buffer; unsigned char *buffer;
sigdata = malloc(sizeof(*sigdata)); sigdata = malloc(sizeof(*sigdata));
if (!sigdata) return NULL; if (!sigdata)
return NULL;
/* Skip song name. */ /* Skip song name. */
dumbfile_getnc((char *)sigdata->name, 28, f); dumbfile_getnc((char *)sigdata->name, 28, f);
@ -357,7 +351,8 @@ static DUMB_IT_SIGDATA *it_ptm_load_sigdata(DUMBFILE *f)
sigdata->n_samples = dumbfile_igetw(f); sigdata->n_samples = dumbfile_igetw(f);
sigdata->n_patterns = dumbfile_igetw(f); sigdata->n_patterns = dumbfile_igetw(f);
if (dumbfile_error(f) || sigdata->n_orders <= 0 || sigdata->n_samples > 255 || sigdata->n_patterns > 128) { if (dumbfile_error(f) || sigdata->n_orders <= 0 ||
sigdata->n_samples > 255 || sigdata->n_patterns > 128) {
_dumb_it_unload_sigdata(sigdata); _dumb_it_unload_sigdata(sigdata);
return NULL; return NULL;
} }
@ -371,7 +366,7 @@ static DUMB_IT_SIGDATA *it_ptm_load_sigdata(DUMBFILE *f)
dumbfile_skip(f, 2); dumbfile_skip(f, 2);
if (dumbfile_mgetl(f) != DUMB_ID('P','T','M','F')) { if (dumbfile_mgetl(f) != DUMB_ID('P', 'T', 'M', 'F')) {
_dumb_it_unload_sigdata(sigdata); _dumb_it_unload_sigdata(sigdata);
return NULL; return NULL;
} }
@ -395,7 +390,8 @@ static DUMB_IT_SIGDATA *it_ptm_load_sigdata(DUMBFILE *f)
} }
if (sigdata->n_patterns) { if (sigdata->n_patterns) {
sigdata->pattern = malloc(sigdata->n_patterns * sizeof(*sigdata->pattern)); sigdata->pattern =
malloc(sigdata->n_patterns * sizeof(*sigdata->pattern));
if (!sigdata->pattern) { if (!sigdata->pattern) {
_dumb_it_unload_sigdata(sigdata); _dumb_it_unload_sigdata(sigdata);
return NULL; return NULL;
@ -405,7 +401,8 @@ static DUMB_IT_SIGDATA *it_ptm_load_sigdata(DUMBFILE *f)
} }
/** WARNING: which ones? */ /** WARNING: which ones? */
sigdata->flags = IT_STEREO | IT_OLD_EFFECTS | IT_COMPATIBLE_GXX | IT_WAS_A_PTM; sigdata->flags =
IT_STEREO | IT_OLD_EFFECTS | IT_COMPATIBLE_GXX | IT_WAS_A_PTM;
sigdata->global_volume = 128; sigdata->global_volume = 128;
sigdata->speed = 6; sigdata->speed = 6;
@ -421,7 +418,8 @@ static DUMB_IT_SIGDATA *it_ptm_load_sigdata(DUMBFILE *f)
sigdata->channel_volume[i] = 64; sigdata->channel_volume[i] = 64;
sigdata->channel_pan[i] = c; sigdata->channel_pan[i] = c;
} else { } else {
/** WARNING: this could be improved if we support channel muting... */ /** WARNING: this could be improved if we support channel
* muting... */
sigdata->channel_volume[i] = 0; sigdata->channel_volume[i] = 0;
sigdata->channel_pan[i] = 7; sigdata->channel_pan[i] = 7;
} }
@ -432,7 +430,7 @@ static DUMB_IT_SIGDATA *it_ptm_load_sigdata(DUMBFILE *f)
dumbfile_getnc((char *)sigdata->order, sigdata->n_orders, f); dumbfile_getnc((char *)sigdata->order, sigdata->n_orders, f);
sigdata->restart_position = 0; sigdata->restart_position = 0;
component = malloc(768*sizeof(*component)); component = malloc(768 * sizeof(*component));
if (!component) { if (!component) {
_dumb_it_unload_sigdata(sigdata); _dumb_it_unload_sigdata(sigdata);
return NULL; return NULL;
@ -458,25 +456,29 @@ static DUMB_IT_SIGDATA *it_ptm_load_sigdata(DUMBFILE *f)
} }
for (n = 0; n < sigdata->n_samples; n++) { for (n = 0; n < sigdata->n_samples; n++) {
if (it_ptm_read_sample_header(&sigdata->sample[n], &component[n_components].offset, f)) { if (it_ptm_read_sample_header(&sigdata->sample[n],
&component[n_components].offset, f)) {
free(component); free(component);
_dumb_it_unload_sigdata(sigdata); _dumb_it_unload_sigdata(sigdata);
return NULL; return NULL;
} }
if (!(sigdata->sample[n].flags & IT_SAMPLE_EXISTS)) continue; if (!(sigdata->sample[n].flags & IT_SAMPLE_EXISTS))
continue;
component[n_components].type = PTM_COMPONENT_SAMPLE; component[n_components].type = PTM_COMPONENT_SAMPLE;
component[n_components].n = n; component[n_components].n = n;
n_components++; n_components++;
} }
qsort(component, n_components, sizeof(PTM_COMPONENT), &ptm_component_compare); qsort(component, n_components, sizeof(PTM_COMPONENT),
&ptm_component_compare);
{ {
int i; int i;
for (i = 0; i < 32; i++) { for (i = 0; i < 32; i++) {
sigdata->channel_pan[i] -= (sigdata->channel_pan[i] & 8) >> 3; sigdata->channel_pan[i] -= (sigdata->channel_pan[i] & 8) >> 3;
sigdata->channel_pan[i] = ((int)sigdata->channel_pan[i] << 5) / 7; sigdata->channel_pan[i] = ((int)sigdata->channel_pan[i] << 5) / 7;
if (sigdata->channel_pan[i] > 64) sigdata->channel_pan[i] = 64; if (sigdata->channel_pan[i] > 64)
sigdata->channel_pan[i] = 64;
} }
} }
@ -506,7 +508,11 @@ static DUMB_IT_SIGDATA *it_ptm_load_sigdata(DUMBFILE *f)
switch (component[n].type) { switch (component[n].type) {
case PTM_COMPONENT_PATTERN: case PTM_COMPONENT_PATTERN:
if (it_ptm_read_pattern(&sigdata->pattern[component[n].n], f, buffer, (n + 1 < n_components) ? (component[n+1].offset - component[n].offset) : 0)) { if (it_ptm_read_pattern(
&sigdata->pattern[component[n].n], f, buffer,
(n + 1 < n_components)
? (component[n + 1].offset - component[n].offset)
: 0)) {
free(buffer); free(buffer);
free(component); free(component);
_dumb_it_unload_sigdata(sigdata); _dumb_it_unload_sigdata(sigdata);
@ -515,7 +521,8 @@ static DUMB_IT_SIGDATA *it_ptm_load_sigdata(DUMBFILE *f)
break; break;
case PTM_COMPONENT_SAMPLE: case PTM_COMPONENT_SAMPLE:
if (it_ptm_read_sample_data(&sigdata->sample[component[n].n], (n + 1 == n_components), f)) { if (it_ptm_read_sample_data(&sigdata->sample[component[n].n],
(n + 1 == n_components), f)) {
free(buffer); free(buffer);
free(component); free(component);
_dumb_it_unload_sigdata(sigdata); _dumb_it_unload_sigdata(sigdata);
@ -532,8 +539,7 @@ static DUMB_IT_SIGDATA *it_ptm_load_sigdata(DUMBFILE *f)
return sigdata; return sigdata;
} }
DUH *dumb_read_ptm_quick(DUMBFILE *f) DUH *dumb_read_ptm_quick(DUMBFILE *f) {
{
sigdata_t *sigdata; sigdata_t *sigdata;
DUH_SIGTYPE_DESC *descptr = &_dumb_sigtype_it; DUH_SIGTYPE_DESC *descptr = &_dumb_sigtype_it;
@ -549,6 +555,7 @@ DUH *dumb_read_ptm_quick(DUMBFILE *f)
tag[0][1] = (const char *)(((DUMB_IT_SIGDATA *)sigdata)->name); tag[0][1] = (const char *)(((DUMB_IT_SIGDATA *)sigdata)->name);
tag[1][0] = "FORMAT"; tag[1][0] = "FORMAT";
tag[1][1] = "PTM"; tag[1][1] = "PTM";
return make_duh(-1, 2, (const char *const (*)[2])tag, 1, &descptr, &sigdata); return make_duh(-1, 2, (const char *const(*)[2])tag, 1, &descptr,
&sigdata);
} }
} }

View file

@ -21,37 +21,38 @@
#include "internal/it.h" #include "internal/it.h"
#include "internal/riff.h" #include "internal/riff.h"
DUH *dumb_read_riff_amff(DUMBFILE *f, struct riff *stream);
DUH *dumb_read_riff_amff( DUMBFILE * f, struct riff * stream ); DUH *dumb_read_riff_am(DUMBFILE *f, struct riff *stream);
DUH *dumb_read_riff_am( DUMBFILE * f, struct riff * stream ); DUH *dumb_read_riff_dsmf(DUMBFILE *f, struct riff *stream);
DUH *dumb_read_riff_dsmf( DUMBFILE * f, struct riff * stream );
/* dumb_read_riff_quick(): reads a RIFF file into a DUH struct, returning a /* dumb_read_riff_quick(): reads a RIFF file into a DUH struct, returning a
* pointer to the DUH struct. When you have finished with it, you must pass * pointer to the DUH struct. When you have finished with it, you must pass
* the pointer to unload_duh() so that the memory can be freed. * the pointer to unload_duh() so that the memory can be freed.
*/ */
DUH *dumb_read_riff_quick( DUMBFILE * f ) DUH *dumb_read_riff_quick(DUMBFILE *f) {
{ DUH *duh;
DUH * duh; struct riff *stream;
struct riff * stream;
long size; long size;
size = dumbfile_get_size(f); size = dumbfile_get_size(f);
stream = riff_parse( f, 0, size, 1 ); stream = riff_parse(f, 0, size, 1);
if ( ! stream ) stream = riff_parse( f, 0, size, 0 ); if (!stream)
stream = riff_parse(f, 0, size, 0);
if ( ! stream ) return 0; if (!stream)
return 0;
if ( stream->type == DUMB_ID( 'A', 'M', ' ', ' ' ) ) if (stream->type == DUMB_ID('A', 'M', ' ', ' '))
duh = dumb_read_riff_am( f, stream ); duh = dumb_read_riff_am(f, stream);
else if ( stream->type == DUMB_ID( 'A', 'M', 'F', 'F' ) ) else if (stream->type == DUMB_ID('A', 'M', 'F', 'F'))
duh = dumb_read_riff_amff( f, stream ); duh = dumb_read_riff_amff(f, stream);
else if ( stream->type == DUMB_ID( 'D', 'S', 'M', 'F' ) ) else if (stream->type == DUMB_ID('D', 'S', 'M', 'F'))
duh = dumb_read_riff_dsmf( f, stream ); duh = dumb_read_riff_dsmf(f, stream);
else duh = 0; else
duh = 0;
riff_free( stream ); riff_free(stream);
return duh; return duh;
} }

View file

@ -24,8 +24,9 @@
#include "dumb.h" #include "dumb.h"
#include "internal/it.h" #include "internal/it.h"
static int it_s3m_read_sample_header(IT_SAMPLE *sample, long *offset, unsigned char *pack, int cwtv, DUMBFILE *f) static int it_s3m_read_sample_header(IT_SAMPLE *sample, long *offset,
{ unsigned char *pack, int cwtv,
DUMBFILE *f) {
unsigned char type; unsigned char type;
int flags; int flags;
@ -70,7 +71,7 @@ static int it_s3m_read_sample_header(IT_SAMPLE *sample, long *offset, unsigned c
sample->C5_speed = dumbfile_igetl(f) << 1; sample->C5_speed = dumbfile_igetl(f) << 1;
/* Skip four unused bytes and three internal variables. */ /* Skip four unused bytes and three internal variables. */
dumbfile_skip(f, 4+2+2+4); dumbfile_skip(f, 4 + 2 + 2 + 4);
dumbfile_getnc((char *)sample->name, 28, f); dumbfile_getnc((char *)sample->name, 28, f);
sample->name[28] = 0; sample->name[28] = 0;
@ -81,15 +82,17 @@ static int it_s3m_read_sample_header(IT_SAMPLE *sample, long *offset, unsigned c
return dumbfile_error(f); return dumbfile_error(f);
} }
if (dumbfile_mgetl(f) != DUMB_ID('S','C','R','S')) if (dumbfile_mgetl(f) != DUMB_ID('S', 'C', 'R', 'S'))
return -1; return -1;
sample->global_volume = 64; sample->global_volume = 64;
sample->flags = IT_SAMPLE_EXISTS; sample->flags = IT_SAMPLE_EXISTS;
if (flags & 1) sample->flags |= IT_SAMPLE_LOOP; if (flags & 1)
sample->flags |= IT_SAMPLE_LOOP;
/* The ST3 TECH.DOC is unclear on this, but IMAGO Orpheus is not. Piece of crap. */ /* The ST3 TECH.DOC is unclear on this, but IMAGO Orpheus is not. Piece of
* crap. */
if (flags & 2) { if (flags & 2) {
sample->flags |= IT_SAMPLE_STEREO; sample->flags |= IT_SAMPLE_STEREO;
@ -117,7 +120,8 @@ static int it_s3m_read_sample_header(IT_SAMPLE *sample, long *offset, unsigned c
if ((unsigned int)sample->loop_end > (unsigned int)sample->length) if ((unsigned int)sample->loop_end > (unsigned int)sample->length)
/*sample->flags &= ~IT_SAMPLE_LOOP;*/ /*sample->flags &= ~IT_SAMPLE_LOOP;*/
sample->loop_end = sample->length; sample->loop_end = sample->length;
else if ((unsigned int)sample->loop_start >= (unsigned int)sample->loop_end) else if ((unsigned int)sample->loop_start >=
(unsigned int)sample->loop_end)
sample->flags &= ~IT_SAMPLE_LOOP; sample->flags &= ~IT_SAMPLE_LOOP;
else else
/* ScreamTracker seems not to save what comes after the loop end /* ScreamTracker seems not to save what comes after the loop end
@ -128,8 +132,7 @@ static int it_s3m_read_sample_header(IT_SAMPLE *sample, long *offset, unsigned c
sample->length = sample->loop_end; sample->length = sample->loop_end;
} }
// Do we need to set all these?
//Do we need to set all these?
sample->vibrato_speed = 0; sample->vibrato_speed = 0;
sample->vibrato_depth = 0; sample->vibrato_depth = 0;
sample->vibrato_rate = 0; sample->vibrato_rate = 0;
@ -140,14 +143,13 @@ static int it_s3m_read_sample_header(IT_SAMPLE *sample, long *offset, unsigned c
return dumbfile_error(f); return dumbfile_error(f);
} }
static int it_s3m_read_sample_data(IT_SAMPLE *sample, int ffi,
unsigned char pack, DUMBFILE *f) {
static int it_s3m_read_sample_data(IT_SAMPLE *sample, int ffi, unsigned char pack, DUMBFILE *f)
{
long n; long n;
long datasize = sample->length; long datasize = sample->length;
if (sample->flags & IT_SAMPLE_STEREO) datasize <<= 1; if (sample->flags & IT_SAMPLE_STEREO)
datasize <<= 1;
sample->data = malloc(datasize * (sample->flags & IT_SAMPLE_16BIT ? 2 : 1)); sample->data = malloc(datasize * (sample->flags & IT_SAMPLE_16BIT ? 2 : 1));
if (!sample->data) if (!sample->data)
@ -156,8 +158,7 @@ static int it_s3m_read_sample_data(IT_SAMPLE *sample, int ffi, unsigned char pac
if (pack == 4) { if (pack == 4) {
if (_dumb_it_read_sample_data_adpcm4(sample, f) < 0) if (_dumb_it_read_sample_data_adpcm4(sample, f) < 0)
return -1; return -1;
} } else if (sample->flags & IT_SAMPLE_STEREO) {
else if (sample->flags & IT_SAMPLE_STEREO) {
if (sample->flags & IT_SAMPLE_16BIT) { if (sample->flags & IT_SAMPLE_16BIT) {
for (n = 0; n < datasize; n += 2) for (n = 0; n < datasize; n += 2)
((short *)sample->data)[n] = dumbfile_igetw(f); ((short *)sample->data)[n] = dumbfile_igetw(f);
@ -192,10 +193,8 @@ static int it_s3m_read_sample_data(IT_SAMPLE *sample, int ffi, unsigned char pac
return 0; return 0;
} }
static int it_s3m_read_pattern(IT_PATTERN *pattern, DUMBFILE *f,
unsigned char *buffer) {
static int it_s3m_read_pattern(IT_PATTERN *pattern, DUMBFILE *f, unsigned char *buffer)
{
int length; int length;
int buflen = 0; int buflen = 0;
int bufpos = 0; int bufpos = 0;
@ -251,7 +250,8 @@ static int it_s3m_read_pattern(IT_PATTERN *pattern, DUMBFILE *f, unsigned char *
b >>= 5; b >>= 5;
pattern->n_entries++; pattern->n_entries++;
if (b) { if (b) {
if (buflen + used[b] >= 65536) return -1; if (buflen + used[b] >= 65536)
return -1;
if (buflen + used[b] <= length) if (buflen + used[b] <= length)
dumbfile_getnc((char *)buffer + buflen, used[b], f); dumbfile_getnc((char *)buffer + buflen, used[b], f);
else else
@ -259,22 +259,27 @@ static int it_s3m_read_pattern(IT_PATTERN *pattern, DUMBFILE *f, unsigned char *
buflen += used[b]; buflen += used[b];
} else { } else {
/* End of row */ /* End of row */
if (++pattern->n_rows == 64) break; if (++pattern->n_rows == 64)
if (buflen >= 65536) return -1; break;
if (buflen >= 65536)
return -1;
} }
#else #else
if (b == 0) { if (b == 0) {
/* End of row */ /* End of row */
pattern->n_entries++; pattern->n_entries++;
if (++pattern->n_rows == 64) break; if (++pattern->n_rows == 64)
if (buflen >= 65536) return -1; break;
if (buflen >= 65536)
return -1;
} else { } else {
static const unsigned char used[8] = {0, 2, 1, 3, 2, 4, 3, 5}; static const unsigned char used[8] = {0, 2, 1, 3, 2, 4, 3, 5};
channel = b & 31; channel = b & 31;
b >>= 5; b >>= 5;
if (b) { if (b) {
pattern->n_entries++; pattern->n_entries++;
if (buflen + used[b] >= 65536) return -1; if (buflen + used[b] >= 65536)
return -1;
dumbfile_getnc(buffer + buflen, used[b], f); dumbfile_getnc(buffer + buflen, used[b], f);
buflen += used[b]; buflen += used[b];
} }
@ -293,11 +298,10 @@ static int it_s3m_read_pattern(IT_PATTERN *pattern, DUMBFILE *f, unsigned char *
/* Great. We ran out of data, but there should be data for more rows. /* Great. We ran out of data, but there should be data for more rows.
* Fill the rest with null data... * Fill the rest with null data...
*/ */
if (buflen >= length && pattern->n_rows < 64) if (buflen >= length && pattern->n_rows < 64) {
{ while (pattern->n_rows < 64) {
while (pattern->n_rows < 64) if (buflen >= 65536)
{ return -1;
if (buflen >= 65536) return -1;
buffer[buflen++] = 0; buffer[buflen++] = 0;
pattern->n_entries++; pattern->n_entries++;
pattern->n_rows++; pattern->n_rows++;
@ -400,9 +404,8 @@ static int it_s3m_read_pattern(IT_PATTERN *pattern, DUMBFILE *f, unsigned char *
return 0; return 0;
} }
/** WARNING: this is duplicated in itread.c - also bad practice to use the same
* struct name unless they are unified in a header */
/** WARNING: this is duplicated in itread.c - also bad practice to use the same struct name unless they are unified in a header */
/* Currently we assume the sample data are stored after the sample headers in /* Currently we assume the sample data are stored after the sample headers in
* module files. This assumption may be unjustified; let me know if you have * module files. This assumption may be unjustified; let me know if you have
* trouble. * trouble.
@ -412,28 +415,20 @@ static int it_s3m_read_pattern(IT_PATTERN *pattern, DUMBFILE *f, unsigned char *
#define S3M_COMPONENT_PATTERN 2 #define S3M_COMPONENT_PATTERN 2
#define S3M_COMPONENT_SAMPLE 3 #define S3M_COMPONENT_SAMPLE 3
typedef struct S3M_COMPONENT typedef struct S3M_COMPONENT {
{
unsigned char type; unsigned char type;
unsigned char n; unsigned char n;
long offset; long offset;
short sampfirst; /* component[sampfirst] = first sample data after this */ short sampfirst; /* component[sampfirst] = first sample data after this */
short sampnext; /* sampnext is used to create linked lists of sample data */ short sampnext; /* sampnext is used to create linked lists of sample data */
} } S3M_COMPONENT;
S3M_COMPONENT;
static int s3m_component_compare(const void *e1, const void *e2) {
return (int)(((const S3M_COMPONENT *)e1)->offset -
static int s3m_component_compare(const void *e1, const void *e2) ((const S3M_COMPONENT *)e2)->offset);
{
return ((const S3M_COMPONENT *)e1)->offset -
((const S3M_COMPONENT *)e2)->offset;
} }
static DUMB_IT_SIGDATA *it_s3m_load_sigdata(DUMBFILE *f, int *cwtv) {
static DUMB_IT_SIGDATA *it_s3m_load_sigdata(DUMBFILE *f, int * cwtv)
{
DUMB_IT_SIGDATA *sigdata; DUMB_IT_SIGDATA *sigdata;
int flags, ffi; int flags, ffi;
@ -451,7 +446,8 @@ static DUMB_IT_SIGDATA *it_s3m_load_sigdata(DUMBFILE *f, int * cwtv)
unsigned char *buffer; unsigned char *buffer;
sigdata = malloc(sizeof(*sigdata)); sigdata = malloc(sizeof(*sigdata));
if (!sigdata) return NULL; if (!sigdata)
return NULL;
dumbfile_getnc((char *)sigdata->name, 28, f); dumbfile_getnc((char *)sigdata->name, 28, f);
sigdata->name[28] = 0; sigdata->name[28] = 0;
@ -483,7 +479,8 @@ static DUMB_IT_SIGDATA *it_s3m_load_sigdata(DUMBFILE *f, int * cwtv)
sigdata->n_samples = dumbfile_igetw(f); sigdata->n_samples = dumbfile_igetw(f);
sigdata->n_patterns = dumbfile_igetw(f); sigdata->n_patterns = dumbfile_igetw(f);
if (dumbfile_error(f) || sigdata->n_orders <= 0 || sigdata->n_samples > 256 || sigdata->n_patterns > 256) { if (dumbfile_error(f) || sigdata->n_orders <= 0 ||
sigdata->n_samples > 256 || sigdata->n_patterns > 256) {
_dumb_it_unload_sigdata(sigdata); _dumb_it_unload_sigdata(sigdata);
return NULL; return NULL;
} }
@ -505,7 +502,8 @@ static DUMB_IT_SIGDATA *it_s3m_load_sigdata(DUMBFILE *f, int * cwtv)
} }
if (sigdata->n_patterns) { if (sigdata->n_patterns) {
sigdata->pattern = malloc(sigdata->n_patterns * sizeof(*sigdata->pattern)); sigdata->pattern =
malloc(sigdata->n_patterns * sizeof(*sigdata->pattern));
if (!sigdata->pattern) { if (!sigdata->pattern) {
_dumb_it_unload_sigdata(sigdata); _dumb_it_unload_sigdata(sigdata);
return NULL; return NULL;
@ -527,20 +525,23 @@ static DUMB_IT_SIGDATA *it_s3m_load_sigdata(DUMBFILE *f, int * cwtv)
/** WARNING: which ones? */ /** WARNING: which ones? */
sigdata->flags = IT_OLD_EFFECTS | IT_COMPATIBLE_GXX | IT_WAS_AN_S3M; sigdata->flags = IT_OLD_EFFECTS | IT_COMPATIBLE_GXX | IT_WAS_AN_S3M;
if (dumbfile_mgetl(f) != DUMB_ID('S','C','R','M')) { if (dumbfile_mgetl(f) != DUMB_ID('S', 'C', 'R', 'M')) {
_dumb_it_unload_sigdata(sigdata); _dumb_it_unload_sigdata(sigdata);
return NULL; return NULL;
} }
sigdata->global_volume = dumbfile_getc(f); sigdata->global_volume = dumbfile_getc(f);
if ( !sigdata->global_volume || sigdata->global_volume > 64 ) sigdata->global_volume = 64; if (!sigdata->global_volume || sigdata->global_volume > 64)
sigdata->global_volume = 64;
sigdata->speed = dumbfile_getc(f); sigdata->speed = dumbfile_getc(f);
if (sigdata->speed == 0) sigdata->speed = 6; // Should we? What about tempo? if (sigdata->speed == 0)
sigdata->speed = 6; // Should we? What about tempo?
sigdata->tempo = dumbfile_getc(f); sigdata->tempo = dumbfile_getc(f);
master_volume = dumbfile_getc(f); // 7 bits; +128 for stereo master_volume = dumbfile_getc(f); // 7 bits; +128 for stereo
sigdata->mixing_volume = master_volume & 127; sigdata->mixing_volume = master_volume & 127;
if (master_volume & 128) sigdata->flags |= IT_STEREO; if (master_volume & 128)
sigdata->flags |= IT_STEREO;
/* Skip GUS Ultra Click Removal byte. */ /* Skip GUS Ultra Click Removal byte. */
dumbfile_getc(f); dumbfile_getc(f);
@ -561,12 +562,14 @@ static DUMB_IT_SIGDATA *it_s3m_load_sigdata(DUMBFILE *f, int * cwtv)
for (i = 0; i < 32; i++) { for (i = 0; i < 32; i++) {
int c = dumbfile_getc(f); int c = dumbfile_getc(f);
if (!(c & (128 | 16))) { /* +128=disabled, +16=Adlib */ if (!(c & (128 | 16))) { /* +128=disabled, +16=Adlib */
if (sigdata->n_pchannels < i + 1) sigdata->n_pchannels = i + 1; if (sigdata->n_pchannels < i + 1)
sigdata->n_pchannels = i + 1;
sigdata->channel_volume[i] = 64; sigdata->channel_volume[i] = 64;
sigdata->channel_pan[i] = c & 8 ? 7 + sep : 7 - sep; sigdata->channel_pan[i] = c & 8 ? 7 + sep : 7 - sep;
/** WARNING: ah, but it should be 7 for mono... */ /** WARNING: ah, but it should be 7 for mono... */
} else { } else {
/** WARNING: this could be improved if we support channel muting... */ /** WARNING: this could be improved if we support channel
* muting... */
sigdata->channel_volume[i] = 0; sigdata->channel_volume[i] = 0;
sigdata->channel_pan[i] = 7; sigdata->channel_pan[i] = 7;
} }
@ -577,7 +580,7 @@ static DUMB_IT_SIGDATA *it_s3m_load_sigdata(DUMBFILE *f, int * cwtv)
dumbfile_getnc((char *)sigdata->order, sigdata->n_orders, f); dumbfile_getnc((char *)sigdata->order, sigdata->n_orders, f);
sigdata->restart_position = 0; sigdata->restart_position = 0;
component = malloc(768*sizeof(*component)); component = malloc(768 * sizeof(*component));
if (!component) { if (!component) {
_dumb_it_unload_sigdata(sigdata); _dumb_it_unload_sigdata(sigdata);
return NULL; return NULL;
@ -606,7 +609,8 @@ static DUMB_IT_SIGDATA *it_s3m_load_sigdata(DUMBFILE *f, int * cwtv)
} }
} }
qsort(component, n_components, sizeof(S3M_COMPONENT), &s3m_component_compare); qsort(component, n_components, sizeof(S3M_COMPONENT),
&s3m_component_compare);
/* I found a really dumb S3M file that claimed to contain default pan /* I found a really dumb S3M file that claimed to contain default pan
* data but didn't contain any. Programs would load it by reading part of * data but didn't contain any. Programs would load it by reading part of
@ -615,7 +619,8 @@ static DUMB_IT_SIGDATA *it_s3m_load_sigdata(DUMBFILE *f, int * cwtv)
* without obfuscating the file input model, so we insert an extra check * without obfuscating the file input model, so we insert an extra check
* here that we won't overrun the start of the first component. * here that we won't overrun the start of the first component.
*/ */
if (default_pan_present == 252 && component[0].offset >= dumbfile_pos(f) + 32) { if (default_pan_present == 252 &&
component[0].offset >= dumbfile_pos(f) + 32) {
/* Channel default pan positions */ /* Channel default pan positions */
int i; int i;
for (i = 0; i < 32; i++) { for (i = 0; i < 32; i++) {
@ -663,7 +668,8 @@ static DUMB_IT_SIGDATA *it_s3m_load_sigdata(DUMBFILE *f, int * cwtv)
switch (component[n].type) { switch (component[n].type) {
case S3M_COMPONENT_PATTERN: case S3M_COMPONENT_PATTERN:
if (it_s3m_read_pattern(&sigdata->pattern[component[n].n], f, buffer)) { if (it_s3m_read_pattern(&sigdata->pattern[component[n].n], f,
buffer)) {
free(buffer); free(buffer);
free(component); free(component);
_dumb_it_unload_sigdata(sigdata); _dumb_it_unload_sigdata(sigdata);
@ -672,7 +678,9 @@ static DUMB_IT_SIGDATA *it_s3m_load_sigdata(DUMBFILE *f, int * cwtv)
break; break;
case S3M_COMPONENT_SAMPLE: case S3M_COMPONENT_SAMPLE:
if (it_s3m_read_sample_header(&sigdata->sample[component[n].n], &offset, &sample_pack[component[n].n], *cwtv, f)) { if (it_s3m_read_sample_header(&sigdata->sample[component[n].n],
&offset, &sample_pack[component[n].n],
*cwtv, f)) {
free(buffer); free(buffer);
free(component); free(component);
_dumb_it_unload_sigdata(sigdata); _dumb_it_unload_sigdata(sigdata);
@ -710,7 +718,8 @@ static DUMB_IT_SIGDATA *it_s3m_load_sigdata(DUMBFILE *f, int * cwtv)
return NULL; return NULL;
} }
if (it_s3m_read_sample_data(&sigdata->sample[component[m].n], ffi, sample_pack[component[m].n], f)) { if (it_s3m_read_sample_data(&sigdata->sample[component[m].n], ffi,
sample_pack[component[m].n], f)) {
free(buffer); free(buffer);
free(component); free(component);
_dumb_it_unload_sigdata(sigdata); _dumb_it_unload_sigdata(sigdata);
@ -729,14 +738,14 @@ static DUMB_IT_SIGDATA *it_s3m_load_sigdata(DUMBFILE *f, int * cwtv)
return sigdata; return sigdata;
} }
static char hexdigit(int in) static char hexdigit(int in) {
{ if (in < 10)
if (in < 10) return in + '0'; return in + '0';
else return in + 'A' - 10; else
return in + 'A' - 10;
} }
DUH *dumb_read_s3m_quick(DUMBFILE *f) DUH *dumb_read_s3m_quick(DUMBFILE *f) {
{
sigdata_t *sigdata; sigdata_t *sigdata;
int cwtv; int cwtv;
@ -760,7 +769,8 @@ DUH *dumb_read_s3m_quick(DUMBFILE *f)
version[2] = hexdigit((cwtv >> 4) & 15); version[2] = hexdigit((cwtv >> 4) & 15);
version[3] = hexdigit(cwtv & 15); version[3] = hexdigit(cwtv & 15);
version[4] = 0; version[4] = 0;
tag[2][1] = (const char *) &version; tag[2][1] = (const char *)&version;
return make_duh(-1, 3, (const char *const (*)[2])tag, 1, &descptr, &sigdata); return make_duh(-1, 3, (const char *const(*)[2])tag, 1, &descptr,
&sigdata);
} }
} }

Some files were not shown because too many files have changed in this diff Show more