Update DUMB to version 2.0.0.
This commit is contained in:
parent
78b69b010d
commit
47a6afe62c
106 changed files with 19176 additions and 19508 deletions
|
@ -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
|
35
Frameworks/Dumb/dumb/COMPILING.md
Normal file
35
Frameworks/Dumb/dumb/COMPILING.md
Normal 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
|
226
Frameworks/Dumb/dumb/DUMBFILE_SYSTEM.md
Normal file
226
Frameworks/Dumb/dumb/DUMBFILE_SYSTEM.md
Normal 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.
|
96
Frameworks/Dumb/dumb/README.md
Normal file
96
Frameworks/Dumb/dumb/README.md
Normal 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/.
|
|
@ -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 */
|
||||||
|
|
|
@ -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 */
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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 */
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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
|
|
|
@ -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 */
|
||||||
|
|
|
@ -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 *);
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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.
|
|
|
@ -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
|
|
|
@ -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)();
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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];
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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;
|
|
||||||
}
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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++;
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
@ -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
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
Loading…
Reference in a new issue