Updated DUMB.

CQTexperiment
Christopher Snowhill 2017-09-16 21:37:49 -07:00
parent 2f9eb42e24
commit e3b65daa6e
24 changed files with 960 additions and 463 deletions

View File

@ -36,24 +36,24 @@
#endif
#define DUMB_MAJOR_VERSION 0
#define DUMB_MINOR_VERSION 9
#define DUMB_REVISION_VERSION 3
#define DUMB_MAJOR_VERSION 1
#define DUMB_MINOR_VERSION 0
#define DUMB_REVISION_VERSION 0
#define DUMB_VERSION (DUMB_MAJOR_VERSION*10000 + DUMB_MINOR_VERSION*100 + DUMB_REVISION_VERSION)
#define DUMB_VERSION_STR "0.9.3"
#define DUMB_VERSION_STR "1.0.0"
#define DUMB_NAME "DUMB v" DUMB_VERSION_STR
#define DUMB_YEAR 2005
#define DUMB_MONTH 8
#define DUMB_DAY 7
#define DUMB_YEAR 2015
#define DUMB_MONTH 1
#define DUMB_DAY 17
#define DUMB_YEAR_STR2 "05"
#define DUMB_YEAR_STR4 "2005"
#define DUMB_MONTH_STR1 "8"
#define DUMB_DAY_STR1 "7"
#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
@ -228,6 +228,8 @@ DUH *read_duh(DUMBFILE *f);
long duh_get_length(DUH *duh);
const char *duh_get_tag(DUH *duh, const char *key);
int duh_get_tag_iterator_size(DUH *duh);
int duh_get_tag_iterator_get(DUH *duh, const char **key, const char **tag, int i);
/* Signal Rendering Functions */
@ -317,15 +319,41 @@ void duh_end_sigrenderer(DUH_SIGRENDERER *sigrenderer);
/* DUH Rendering Functions */
long duh_render(
/* For packed integers: 8, 16, 24-bit wide.
* Intermediary buffer sig_samples must be freed with destroy_sample_buffer()
* in the end of the rendering loop.
*/
long duh_render_int(
DUH_SIGRENDERER *sigrenderer,
sample_t ***sig_samples,
long *sig_samples_size,
int bits, int unsign,
float volume, float delta,
long size, void *sptr
);
/* For floats: 32, 64-bit wide.
* Intermediary buffer sig_samples must be freed with destroy_sample_buffer()
* in the end of the rendering loop.
*/
long duh_render_float(
DUH_SIGRENDERER *sigrenderer,
sample_t ***sig_samples,
long *sig_samples_size,
int bits,
float volume, float delta,
long size, void *sptr
);
#ifdef DUMB_DECLARE_DEPRECATED
long duh_render(
DUH_SIGRENDERER *sigrenderer,
int bits, int unsign,
float volume, float delta,
long size, void *sptr
) DUMB_DEPRECATED;
long duh_render_signal(
DUH_SIGRENDERER *sigrenderer,
float volume, float delta,
@ -385,9 +413,9 @@ enum
DUMB_IT_RAMP_ONOFF_ONLY = 1,
DUMB_IT_RAMP_FULL = 2
};
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_xm_speed_zero_callback(DUMB_IT_SIGRENDERER *sigrenderer, 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);

View File

@ -18,13 +18,7 @@
#ifndef _V_LPC_H_
#define _V_LPC_H_
/* simple linear scale LPC code */
extern float vorbis_lpc_from_data(float *data,float *lpc,int n,int m);
extern void vorbis_lpc_predict(float *coeff,float *prime,int m,
float *data,long n);
struct DUMB_IT_SIGDATA;
extern void dumb_it_add_lpc(struct DUMB_IT_SIGDATA *sigdata);
extern int dumb_it_add_lpc(struct DUMB_IT_SIGDATA *sigdata);
#endif

View File

@ -1,60 +1,62 @@
#ifndef _RESAMPLER_H_
#define _RESAMPLER_H_
// Ugglay
#ifdef RESAMPLER_DECORATE
#ifndef _RESAMPLER_H_
#define _RESAMPLER_H_
// Ugglay
#ifdef RESAMPLER_DECORATE
#undef PASTE
#undef EVALUATE
#define PASTE(a,b) a ## b
#define EVALUATE(a,b) PASTE(a,b)
#define resampler_init EVALUATE(RESAMPLER_DECORATE,_resampler_init)
#define resampler_create EVALUATE(RESAMPLER_DECORATE,_resampler_create)
#define resampler_delete EVALUATE(RESAMPLER_DECORATE,_resampler_delete)
#define resampler_dup EVALUATE(RESAMPLER_DECORATE,_resampler_dup)
#define resampler_dup_inplace EVALUATE(RESAMPLER_DECORATE,_resampler_dup_inplace)
#define resampler_set_quality EVALUATE(RESAMPLER_DECORATE,_resampler_set_quality)
#define resampler_get_free_count EVALUATE(RESAMPLER_DECORATE,_resampler_get_free_count)
#define resampler_write_sample EVALUATE(RESAMPLER_DECORATE,_resampler_write_sample)
#define resampler_write_sample_fixed EVALUATE(RESAMPLER_DECORATE,_resampler_write_sample_fixed)
#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
void resampler_init(void);
void * resampler_create(void);
void resampler_delete(void *);
void * resampler_dup(const void *);
void resampler_dup_inplace(void *, const void *);
enum
{
RESAMPLER_QUALITY_MIN = 0,
RESAMPLER_QUALITY_ZOH = 0,
RESAMPLER_QUALITY_BLEP = 1,
RESAMPLER_QUALITY_LINEAR = 2,
RESAMPLER_QUALITY_BLAM = 3,
RESAMPLER_QUALITY_CUBIC = 4,
RESAMPLER_QUALITY_SINC = 5,
RESAMPLER_QUALITY_MAX = 5
};
void resampler_set_quality(void *, int quality);
int resampler_get_free_count(void *);
void resampler_write_sample(void *, short sample);
void resampler_write_sample_fixed(void *, int sample, unsigned char depth);
void resampler_set_rate( void *, double new_factor );
int resampler_ready(void *);
void resampler_clear(void *);
int resampler_get_sample_count(void *);
int resampler_get_sample(void *);
float resampler_get_sample_float(void *);
void resampler_remove_sample(void *, int decay);
#endif
#undef EVALUATE
#define PASTE(a,b) a ## b
#define EVALUATE(a,b) PASTE(a,b)
#define resampler_init EVALUATE(RESAMPLER_DECORATE,_resampler_init)
#define resampler_create EVALUATE(RESAMPLER_DECORATE,_resampler_create)
#define resampler_delete EVALUATE(RESAMPLER_DECORATE,_resampler_delete)
#define resampler_dup EVALUATE(RESAMPLER_DECORATE,_resampler_dup)
#define resampler_dup_inplace EVALUATE(RESAMPLER_DECORATE,_resampler_dup_inplace)
#define resampler_set_quality EVALUATE(RESAMPLER_DECORATE,_resampler_set_quality)
#define resampler_get_free_count EVALUATE(RESAMPLER_DECORATE,_resampler_get_free_count)
#define resampler_write_sample EVALUATE(RESAMPLER_DECORATE,_resampler_write_sample)
#define resampler_write_sample_fixed EVALUATE(RESAMPLER_DECORATE,_resampler_write_sample_fixed)
#define resampler_write_sample_float EVALUATE(RESAMPLER_DECORATE,_resampler_write_sample_float)
#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
void resampler_init(void);
void * resampler_create(void);
void resampler_delete(void *);
void * resampler_dup(const void *);
void resampler_dup_inplace(void *, const void *);
enum
{
RESAMPLER_QUALITY_MIN = 0,
RESAMPLER_QUALITY_ZOH = 0,
RESAMPLER_QUALITY_BLEP = 1,
RESAMPLER_QUALITY_LINEAR = 2,
RESAMPLER_QUALITY_BLAM = 3,
RESAMPLER_QUALITY_CUBIC = 4,
RESAMPLER_QUALITY_SINC = 5,
RESAMPLER_QUALITY_MAX = 5
};
void resampler_set_quality(void *, int quality);
int resampler_get_free_count(void *);
void resampler_write_sample(void *, short sample);
void resampler_write_sample_fixed(void *, int sample, unsigned char depth);
void resampler_write_sample_float(void *, float sample);
void resampler_set_rate( void *, double new_factor );
int resampler_ready(void *);
void resampler_clear(void *);
int resampler_get_sample_count(void *);
int resampler_get_sample(void *);
float resampler_get_sample_float(void *);
void resampler_remove_sample(void *, int decay);
#endif

View File

@ -1,50 +1,47 @@
/* Copyright (C) 2002-2003 Jean-Marc Valin
Copyright (C) 2007-2009 Xiph.Org Foundation */
/* Copyright (C) 2002 Jean-Marc Valin */
/**
@file stack_alloc.h
@brief Temporary memory allocation on stack
*/
@file stack_alloc.h
@brief Temporary memory allocation on stack
*/
/*
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
- Neither the name of the Xiph.org Foundation nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef STACK_ALLOC_H
#define STACK_ALLOC_H
#if (!defined (VAR_ARRAYS) && !defined (USE_ALLOCA))
#error "Dumb requires one of VAR_ARRAYS or USE_ALLOCA be defined to select the temporary allocation mode."
#endif
#ifdef USE_ALLOCA
# ifdef WIN32
# include <malloc.h>
#ifdef WIN32
# include <malloc.h>
#else
# ifdef HAVE_ALLOCA_H
# include <alloca.h>
# else
# ifdef HAVE_ALLOCA_H
# include <alloca.h>
# else
# include <stdlib.h>
# endif
# include <stdlib.h>
# endif
#endif
@ -85,28 +82,32 @@
* @param type Type of element
*/
#ifdef ENABLE_VALGRIND
#include <valgrind/memcheck.h>
#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))))
#else
#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))))
#endif
#if defined(VAR_ARRAYS)
#define VARDECL(type, var)
#define VARDECL(var)
#define ALLOC(var, size, type) type var[size]
#define SAVE_STACK
#define RESTORE_STACK
#define ALLOC_STACK
#elif defined(USE_ALLOCA)
#define VARDECL(var) var
#define ALLOC(var, size, type) var = alloca(sizeof(type)*(size))
#else
#define VARDECL(var) var
#define ALLOC(var, size, type) var = PUSH(stack, size, type)
#endif
#define VARDECL(type, var) type *var
# ifdef WIN32
# define ALLOC(var, size, type) var = ((type*)_alloca(sizeof(type)*(size)))
# else
# define ALLOC(var, size, type) var = ((type*)alloca(sizeof(type)*(size)))
# endif
#define SAVE_STACK
#define RESTORE_STACK
#define ALLOC_STACK
#endif /* VAR_ARRAYS */
#endif /* STACK_ALLOC_H */
#endif

View File

@ -36,3 +36,23 @@ const char *duh_get_tag(DUH *duh, const char *key)
return NULL;
}
int duh_get_tag_iterator_size(DUH *duh)
{
return (duh && duh->tag ? duh->n_tags : 0);
}
int duh_get_tag_iterator_get(DUH *duh, const char **key, const char **tag, int i)
{
ASSERT(key);
ASSERT(tag);
if (!duh || !duh->tag || i >= duh->n_tags) return -1;
*key = duh->tag[i][0];
*tag = duh->tag[i][1];
return 0;
}

View File

@ -70,6 +70,21 @@
#endif
#define CONVERT24(src, pos) { \
signed int f = src; \
f = MID(-8388608, f, 8388607); \
((unsigned char*)sptr)[pos ] = (f) & 0xFF; \
((unsigned char*)sptr)[pos+1] = (f >> 8) & 0xFF; \
((unsigned char*)sptr)[pos+2] = (f >> 16) & 0xFF; \
}
#define CONVERT32F(src, pos) { \
((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)); \
}
/* DEPRECATED */
@ -79,7 +94,7 @@ DUH_SIGRENDERER *duh_start_renderer(DUH *duh, int n_channels, long pos)
}
/* DEPRECATED */
long duh_render(
DUH_SIGRENDERER *sigrenderer,
int bits, int unsign,
@ -136,6 +151,138 @@ long duh_render(
}
long duh_render_int(
DUH_SIGRENDERER *sigrenderer,
sample_t ***sig_samples,
long *sig_samples_size,
int bits, int unsign,
float volume, float delta,
long size, void *sptr
)
{
long n;
sample_t **sampptr;
int n_channels;
ASSERT(bits == 8 || bits == 16 || bits == 24);
ASSERT(sptr);
ASSERT(sig_samples);
ASSERT(sig_samples_size);
if (!sigrenderer)
return 0;
n_channels = duh_sigrenderer_get_n_channels(sigrenderer);
ASSERT(n_channels > 0);
/* This restriction will be removed when need be. At the moment, tightly
* optimised loops exist for exactly one or two channels.
*/
ASSERT(n_channels <= 2);
if ((*sig_samples == NULL) || (*sig_samples_size != size))
{
destroy_sample_buffer(*sig_samples);
*sig_samples = allocate_sample_buffer(n_channels, size);
*sig_samples_size = size;
}
sampptr = *sig_samples;
if (!sampptr)
return 0;
dumb_silence(sampptr[0], n_channels * size);
size = duh_sigrenderer_generate_samples(sigrenderer, volume, delta, size, sampptr);
if (bits == 24) {
long i = 0;
ASSERT(unsign == 0);
for (n = 0; n < size * n_channels; n++, i += 3) {
CONVERT24(sampptr[0][n], i);
}
} else
if (bits == 16) {
int signconv = unsign ? 0x8000 : 0x0000;
for (n = 0; n < size * n_channels; n++) {
CONVERT16(sampptr[0][n], n, signconv);
}
} else {
char signconv = unsign ? 0x80 : 0x00;
for (n = 0; n < size * n_channels; n++) {
CONVERT8(sampptr[0][n], n, signconv);
}
}
return size;
}
long duh_render_float(
DUH_SIGRENDERER *sigrenderer,
sample_t ***sig_samples,
long *sig_samples_size,
int bits,
float volume, float delta,
long size, void *sptr
)
{
long n;
sample_t **sampptr;
int n_channels;
ASSERT(bits == 32 || bits == 64);
ASSERT(sptr);
ASSERT(sig_samples);
ASSERT(sig_samples_size);
if (!sigrenderer)
return 0;
n_channels = duh_sigrenderer_get_n_channels(sigrenderer);
ASSERT(n_channels > 0);
/* This restriction will be removed when need be. At the moment, tightly
* optimised loops exist for exactly one or two channels.
*/
ASSERT(n_channels <= 2);
if ((*sig_samples == NULL) || (*sig_samples_size != size))
{
destroy_sample_buffer(*sig_samples);
*sig_samples = allocate_sample_buffer(n_channels, size);
*sig_samples_size = size;
}
sampptr = *sig_samples;
if (!sampptr)
return 0;
dumb_silence(sampptr[0], n_channels * size);
size = duh_sigrenderer_generate_samples(sigrenderer, volume, delta, size, sampptr);
if (bits == 64) {
for (n = 0; n < size * n_channels; n++) {
CONVERT64F(sampptr[0][n], n);
}
} else
if (bits == 32) {
for (n = 0; n < size * n_channels; n++) {
CONVERT32F(sampptr[0][n], n);
}
}
return size;
}
/* DEPRECATED */
int duh_renderer_get_n_channels(DUH_SIGRENDERER *dr)

View File

@ -53,6 +53,21 @@ void bit_array_set(void * array, size_t bit)
}
}
void bit_array_set_range(void * array, size_t bit, size_t count)
{
if (array && count)
{
size_t * size = (size_t *) array;
if (bit < *size)
{
unsigned char * ptr = (unsigned char *)(size + 1);
size_t i;
for (i = bit; i < *size && i < bit + count; ++i)
ptr[i >> 3] |= (1U << (i & 7));
}
}
}
int bit_array_test(void * array, size_t bit)
{
if (array)
@ -120,6 +135,21 @@ void bit_array_clear(void * array, size_t bit)
}
}
void bit_array_clear_range(void * array, size_t bit, size_t count)
{
if (array && count)
{
size_t * size = (size_t *) array;
if (bit < *size)
{
unsigned char * ptr = (unsigned char *)(size + 1);
size_t i;
for (i = bit; i < *size && i < bit + count; ++i)
ptr[i >> 3] &= ~(1U << (i & 7));
}
}
}
void bit_array_merge(void * dest, void * source, size_t offset)
{
if (dest && source)

View File

@ -55,14 +55,12 @@ Carsten Bormann
/* Input : n elements of time doamin data
Output: m lpc coefficients, excitation energy */
float vorbis_lpc_from_data(float *data,float *lpci,int n,int m){
VARDECL(double, aut);
VARDECL(double, lpc);
ALLOC(aut, m+1, double);
ALLOC(lpc, m, double);
static float vorbis_lpc_from_data(float *data,float *lpci,long n,long m){
double *aut=alloca(sizeof(*aut)*(m+1));
double *lpc=alloca(sizeof(*lpc)*(m));
double error;
double epsilon;
int i,j;
long i,j;
/* autocorrelation, p+1 lag coefficients */
j=m+1;
@ -129,7 +127,7 @@ float vorbis_lpc_from_data(float *data,float *lpci,int n,int m){
return error;
}
void vorbis_lpc_predict(float *coeff,float *prime,int m,
static void vorbis_lpc_predict(float *coeff,float *prime,long m,
float *data,long n){
/* in: coeff[0...m-1] LPC coefficients
@ -169,7 +167,7 @@ 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. */
void 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_input[lpc_max * 2];
float lpc_output[lpc_extra * 2];
@ -177,11 +175,12 @@ void dumb_it_add_lpc(struct DUMB_IT_SIGDATA *sigdata){
signed char * s8;
signed short * s16;
int n, o, offset, lpc_samples;
long n, o, offset, lpc_samples;
for ( n = 0; n < sigdata->n_samples; 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) ) == IT_SAMPLE_EXISTS &&
sample->data != NULL ) {
/* 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;
@ -220,6 +219,9 @@ void dumb_it_add_lpc(struct DUMB_IT_SIGDATA *sigdata){
if ( sample->flags & IT_SAMPLE_16BIT )
{
s16 = ( signed short * ) realloc( sample->data, ( sample->length + lpc_extra ) * 2 * sizeof(short) );
if ( !s16 )
return -1;
sample->data = s16;
s16 += sample->length * 2;
@ -234,6 +236,9 @@ void dumb_it_add_lpc(struct DUMB_IT_SIGDATA *sigdata){
else
{
s8 = ( signed char * ) realloc( sample->data, ( sample->length + lpc_extra ) * 2 );
if ( !s8 )
return -1;
sample->data = s8;
s8 += sample->length * 2;
@ -274,6 +279,9 @@ void dumb_it_add_lpc(struct DUMB_IT_SIGDATA *sigdata){
if ( sample->flags & IT_SAMPLE_16BIT )
{
s16 = ( signed short * ) realloc( sample->data, ( sample->length + lpc_extra ) * sizeof(short) );
if (!s16)
return -1;
sample->data = s16;
s16 += sample->length;
@ -287,6 +295,9 @@ void dumb_it_add_lpc(struct DUMB_IT_SIGDATA *sigdata){
else
{
s8 = ( signed char * ) realloc( sample->data, sample->length + lpc_extra );
if ( !s8 )
return -1;
sample->data = s8;
s8 += sample->length;
@ -302,6 +313,7 @@ void dumb_it_add_lpc(struct DUMB_IT_SIGDATA *sigdata){
else
/* Otherwise, pad with silence. */
{
void *data;
offset = sample->length;
lpc_samples = lpc_extra;
@ -314,9 +326,15 @@ void dumb_it_add_lpc(struct DUMB_IT_SIGDATA *sigdata){
offset *= n;
lpc_samples *= n;
sample->data = realloc( sample->data, offset + lpc_samples );
memset( (char*)sample->data + offset, 0, lpc_samples );
data = realloc( sample->data, offset + lpc_samples );
if (!data)
return -1;
sample->data = data;
memset( (char*)data + offset, 0, lpc_samples );
}
}
}
return 0;
}

View File

@ -105,11 +105,11 @@ static int process_pickup(DUMB_RESAMPLER *resampler)
#define VOLUME_VARIABLES lvol, lvolr, lvold, lvolt, lvolm, rvol, rvolr, rvold, rvolt, rvolm
#define SET_VOLUME_VARIABLES { \
if ( volume_left ) { \
lvolr = (int)(volume_left->volume * 16777216.0); \
lvold = (int)(volume_left->delta * 16777216.0); \
lvolt = (int)(volume_left->target * 16777216.0); \
lvolm = (int)(volume_left->mix * 16777216.0); \
lvol = MULSCV( lvolr, lvolm ); \
lvolr = volume_left->volume; \
lvold = volume_left->delta; \
lvolt = volume_left->target; \
lvolm = volume_left->mix; \
lvol = lvolr * lvolm; \
if ( lvolr == lvolt ) volume_left = NULL; \
} else { \
lvol = 0; \
@ -118,11 +118,11 @@ static int process_pickup(DUMB_RESAMPLER *resampler)
lvolm = 0; \
} \
if ( volume_right ) { \
rvolr = (int)(volume_right->volume * 16777216.0); \
rvold = (int)(volume_right->delta * 16777216.0); \
rvolt = (int)(volume_right->target * 16777216.0); \
rvolm = (int)(volume_right->mix * 16777216.0); \
rvol = MULSCV( rvolr, rvolm ); \
rvolr = volume_right->volume; \
rvold = volume_right->delta; \
rvolt = volume_right->target; \
rvolm = volume_right->mix; \
rvol = rvolr * rvolm; \
if ( rvolr == rvolt ) volume_right = NULL; \
} else { \
rvol = 0; \
@ -132,8 +132,8 @@ static int process_pickup(DUMB_RESAMPLER *resampler)
} \
}
#define RETURN_VOLUME_VARIABLES { \
if ( volume_left ) volume_left->volume = (float)lvolr / 16777216.0f; \
if ( volume_right ) volume_right->volume = (float)rvolr / 16777216.0f; \
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 PEEK_FIR STEREO_DEST_PEEK_FIR

View File

@ -47,12 +47,11 @@
long dumb_resample(DUMB_RESAMPLER *resampler, sample_t *dst, long dst_size, VOLUME_PARAMETERS, float delta)
{
int dt, inv_dt;
int VOLUME_VARIABLES;
float VOLUME_VARIABLES;
long done;
long todo;
LONG_LONG todo64;
int quality;
/*int check;*/
if (!resampler || resampler->dir == 0) return 0;
ASSERT(resampler->dir == -1 || resampler->dir == 1);
@ -210,7 +209,7 @@ long dumb_resample(DUMB_RESAMPLER *resampler, sample_t *dst, long dst_size, VOLU
void dumb_resample_get_current_sample(DUMB_RESAMPLER *resampler, VOLUME_PARAMETERS, sample_t *dst)
{
int VOLUME_VARIABLES;
float VOLUME_VARIABLES;
SRCTYPE *src;
long pos;
int subpos;

View File

@ -81,7 +81,7 @@
* Values outside the range 0-4 will behave the same as the nearest
* value within the range.
*/
int dumb_resampling_quality = DUMB_RQ_BLAM;
int dumb_resampling_quality = DUMB_RQ_CUBIC;
@ -179,14 +179,14 @@ void _dumb_init_cubic(void)
#define SUFFIX _16
#define SRCTYPE short
#define SRCBITS 16
#define FIR(x) (x)
#define FIR(x) (x * (1.0f / 32768.0f))
#include "resample.inc"
/* Create resamplers for 8-bit source samples. */
#define SUFFIX _8
#define SRCTYPE signed char
#define SRCBITS 8
#define FIR(x) (x << 8)
#define FIR(x) (x * (1.0f / 256.0f))
#include "resample.inc"

View File

@ -98,9 +98,9 @@ DUMB_RESAMPLER *dumb_start_resampler(SRCTYPE *src, int src_channels, long pos, l
pvol->declick_stage >= 3) \
pvol->declick_stage++; \
pvol = NULL; \
vol = MULSCV( vol##t, vol##m ); \
vol = vol##t * vol##m; \
} else { \
vol = MULSCV( vol##r, vol##m ); \
vol = vol##r * vol##m; \
} \
} \
}
@ -118,11 +118,11 @@ DUMB_RESAMPLER *dumb_start_resampler(SRCTYPE *src, int src_channels, long pos, l
#define MONO_DEST_VOLUME_ZEROS 0
#define SET_MONO_DEST_VOLUME_VARIABLES { \
if ( volume ) { \
volr = (int)(volume->volume * 16777216.0); \
vold = (int)(volume->delta * 16777216.0); \
volt = (int)(volume->target * 16777216.0); \
volm = (int)(volume->mix * 16777216.0); \
vol = MULSCV( volr, volm ); \
volr = volume->volume; \
vold = volume->delta; \
volt = volume->target; \
volm = volume->mix; \
vol = volr * volm; \
if ( volr == volt ) volume = NULL; \
} else { \
vol = 0; \
@ -131,26 +131,26 @@ DUMB_RESAMPLER *dumb_start_resampler(SRCTYPE *src, int src_channels, long pos, l
volm = 0; \
} \
}
#define RETURN_MONO_DEST_VOLUME_VARIABLES if ( volume ) volume->volume = (float)volr / 16777216.0f
#define RETURN_MONO_DEST_VOLUME_VARIABLES if ( volume ) volume->volume = volr
#define MONO_DEST_VOLUMES_ARE_ZERO (vol == 0 && volt == 0)
#define POKE_FIR(offset) { \
resampler_write_sample( resampler->fir_resampler[0], FIR(x[offset]) ); \
resampler_write_sample_float( resampler->fir_resampler[0], FIR(x[offset]) ); \
}
#define MONO_DEST_PEEK_FIR *dst = MULSC( resampler_get_sample( resampler->fir_resampler[0] ), vol )
#define MONO_DEST_PEEK_FIR *dst = resampler_get_sample_float( resampler->fir_resampler[0] ) * vol * 16777216.0f
#define MONO_DEST_MIX_FIR { \
*dst++ += MULSC( resampler_get_sample( resampler->fir_resampler[0] ), vol ); \
*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 { \
int sample = resampler_get_sample( resampler->fir_resampler[0] ); \
*dst++ = MULSC( sample, lvol ); \
*dst++ = MULSC( sample, rvol ); \
float sample = resampler_get_sample_float( resampler->fir_resampler[0] ); \
*dst++ = sample * lvol * 16777216.0f; \
*dst++ = sample * rvol * 16777216.0f; \
}
#define STEREO_DEST_MIX_FIR { \
int sample = resampler_get_sample( resampler->fir_resampler[0] ); \
*dst++ += MULSC( sample, lvol ); \
*dst++ += MULSC( sample, rvol ); \
float sample = resampler_get_sample_float( resampler->fir_resampler[0] ); \
*dst++ += sample * lvol * 16777216.0f; \
*dst++ += sample * rvol * 16777216.0f; \
UPDATE_VOLUME( volume_left, lvol ); \
UPDATE_VOLUME( volume_right, rvol ); \
}
@ -179,11 +179,11 @@ DUMB_RESAMPLER *dumb_start_resampler(SRCTYPE *src, int src_channels, long pos, l
#define MONO_DEST_VOLUME_ZEROS 0, 0
#define SET_MONO_DEST_VOLUME_VARIABLES { \
if ( volume_left ) { \
lvolr = (int)(volume_left->volume * 16777216.0); \
lvold = (int)(volume_left->delta * 16777216.0); \
lvolt = (int)(volume_left->target * 16777216.0); \
lvolm = (int)(volume_left->mix * 16777216.0); \
lvol = MULSCV( lvolr, lvolm ); \
lvolr = volume_left->volume; \
lvold = volume_left->delta; \
lvolt = volume_left->target; \
lvolm = volume_left->mix; \
lvol = lvolr * lvolm; \
if ( lvolr == lvolt ) volume_left = NULL; \
} else { \
lvol = 0; \
@ -192,11 +192,11 @@ DUMB_RESAMPLER *dumb_start_resampler(SRCTYPE *src, int src_channels, long pos, l
lvolm = 0; \
} \
if ( volume_right ) { \
rvolr = (int)(volume_right->volume * 16777216.0); \
rvold = (int)(volume_right->delta * 16777216.0); \
rvolt = (int)(volume_right->target * 16777216.0); \
rvolm = (int)(volume_right->mix * 16777216.0); \
rvol = MULSCV( rvolr, rvolm ); \
rvolr = volume_right->volume; \
rvold = volume_right->delta; \
rvolt = volume_right->target; \
rvolm = volume_right->mix; \
rvol = rvolr * rvolm; \
if ( rvolr == rvolt ) volume_right = NULL; \
} else { \
rvol = 0; \
@ -206,21 +206,21 @@ DUMB_RESAMPLER *dumb_start_resampler(SRCTYPE *src, int src_channels, long pos, l
} \
}
#define RETURN_MONO_DEST_VOLUME_VARIABLES { \
if ( volume_left ) volume_left->volume = (float)lvolr / 16777216.0f; \
if ( volume_right ) volume_right->volume = (float)rvolr / 16777216.0f; \
if ( volume_left ) volume_left->volume = lvolr; \
if ( volume_right ) volume_right->volume = rvolr; \
}
#define MONO_DEST_VOLUMES_ARE_ZERO (lvol == 0 && lvolt == 0 && rvol == 0 && rvolt == 0)
#define POKE_FIR(offset) { \
resampler_write_sample( resampler->fir_resampler[0], FIR(x[(offset)*2+0]) ); \
resampler_write_sample( resampler->fir_resampler[1], FIR(x[(offset)*2+1]) ); \
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_PEEK_FIR { \
*dst = MULSC( resampler_get_sample( resampler->fir_resampler[0] ), lvol ) + \
MULSC( resampler_get_sample( resampler->fir_resampler[1] ), rvol ); \
*dst = (resampler_get_sample_float( resampler->fir_resampler[0] ) * lvol + \
resampler_get_sample_float( resampler->fir_resampler[1] ) * rvol) * 16777216.0f; \
}
#define MONO_DEST_MIX_FIR { \
*dst++ += MULSC( resampler_get_sample( resampler->fir_resampler[0] ), lvol ) + \
MULSC( resampler_get_sample( resampler->fir_resampler[1] ), rvol ); \
*dst++ += (resampler_get_sample_float( resampler->fir_resampler[0] ) * lvol + \
resampler_get_sample_float( resampler->fir_resampler[1] ) * rvol) * 16777216.0f; \
UPDATE_VOLUME( volume_left, lvol ); \
UPDATE_VOLUME( volume_right, rvol ); \
}
@ -229,12 +229,12 @@ DUMB_RESAMPLER *dumb_start_resampler(SRCTYPE *src, int src_channels, long pos, l
resampler_remove_sample( resampler->fir_resampler[1], 1 ); \
}
#define STEREO_DEST_PEEK_FIR { \
*dst++ = MULSC( resampler_get_sample( resampler->fir_resampler[0] ), lvol ); \
*dst++ = MULSC( resampler_get_sample( resampler->fir_resampler[1] ), rvol ); \
*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++ += MULSC( resampler_get_sample( resampler->fir_resampler[0] ), lvol ); \
*dst++ += MULSC( resampler_get_sample( resampler->fir_resampler[1] ), rvol ); \
*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 ); \
}

View File

@ -2,7 +2,7 @@
#include <string.h>
#define _USE_MATH_DEFINES
#include <math.h>
#if (defined(_M_IX86) || defined(__i386__) || defined(_M_X64) || defined(__amd64__))
#if defined(_USE_SSE) && (defined(_M_IX86) || defined(__i386__) || defined(_M_X64) || defined(__amd64__))
#include <xmmintrin.h>
#define RESAMPLER_SSE
#endif
@ -11,6 +11,8 @@
#if TARGET_CPU_ARM || TARGET_CPU_ARM64
#define RESAMPLER_NEON
#endif
#elif (defined(__arm__) && defined(__ARM_NEON__))
#define RESAMPLER_NEON
#endif
#ifdef RESAMPLER_NEON
#include <arm_neon.h>
@ -35,9 +37,9 @@ enum { RESAMPLER_RESOLUTION_EXTRA = 1 << (RESAMPLER_SHIFT + RESAMPLER_SHIFT_EXTR
enum { SINC_WIDTH = 16 };
enum { SINC_SAMPLES = RESAMPLER_RESOLUTION * SINC_WIDTH };
enum { CUBIC_SAMPLES = RESAMPLER_RESOLUTION * 4 };
enum { IIR_ORDER = 6 };
static const float RESAMPLER_BLEP_CUTOFF = 0.90f;
static const float RESAMPLER_BLAM_CUTOFF = 0.93f;
static const float RESAMPLER_SINC_CUTOFF = 0.999f;
ALIGNED static float cubic_lut[CUBIC_SAMPLES];
@ -138,54 +140,6 @@ void resampler_init(void)
#endif
}
typedef struct iir
{
double cutoff; //frequency cutoff
double quality; //frequency response quality
double gain; //peak gain
double a0, a1, a2, b1, b2; //coefficients
double z1, z2; //second-order IIR
} iir;
static void iir_reset(iir * i, double cutoff, double quality, double gain)
{
double v, k, q, n;
i->cutoff = cutoff;
i->quality = quality;
i->gain = gain;
v = pow(10, fabs(gain) / 20.0);
k = tan(M_PI * cutoff);
q = quality;
n = 1 / (1 + k / q + k * k);
i->a0 = k * k * n;
i->a1 = 2 * i->a0;
i->a2 = i->a0;
i->b1 = 2 * (k * k - 1) * n;
i->b2 = (1 - k / q + k * k) * n;
}
static void iir_clear(iir * i)
{
i->z1 = 0.0;
i->z2 = 0.0;
}
static double iir_process(iir * i, double in)
{
double out = in * i->a0 + i->z1;
i->z1 = in * i->a1 + i->z2 - i->b1 * out;
i->z2 = in * i->a2 - i->b2 * out;
return out;
}
static double butterworth(unsigned int order, unsigned int phase)
{
return -0.5 / cos(M_PI / 2.0 * (1.0 + (1.0 + (2.0 * phase + 1.0) / order)));
}
typedef struct resampler
{
int write_pos, write_filled;
@ -197,12 +151,10 @@ typedef struct resampler
unsigned char quality;
signed char delay_added;
signed char delay_removed;
unsigned char output_stage;
float last_amp;
float accumulator;
float buffer_in[resampler_buffer_size * 2];
float buffer_out[resampler_buffer_size + SINC_WIDTH * 2 - 1];
iir filter[IIR_ORDER / 2];
} resampler;
void * resampler_create(void)
@ -221,12 +173,10 @@ void * resampler_create(void)
r->quality = RESAMPLER_QUALITY_MAX;
r->delay_added = -1;
r->delay_removed = -1;
r->output_stage = 0;
r->last_amp = 0;
r->accumulator = 0;
memset( r->buffer_in, 0, sizeof(r->buffer_in) );
memset( r->buffer_out, 0, sizeof(r->buffer_out) );
memset( r->filter, 0, sizeof(r->filter) );
return r;
}
@ -262,12 +212,10 @@ void resampler_dup_inplace(void *_d, const void *_s)
r_out->quality = r_in->quality;
r_out->delay_added = r_in->delay_added;
r_out->delay_removed = r_in->delay_removed;
r_out->output_stage = r_in->output_stage;
r_out->last_amp = r_in->last_amp;
r_out->accumulator = r_in->accumulator;
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) );
memcpy( r_out->filter, r_in->filter, sizeof(r_in->filter) );
}
void resampler_set_quality(void *_r, int quality)
@ -279,7 +227,8 @@ void resampler_set_quality(void *_r, int quality)
quality = RESAMPLER_QUALITY_MAX;
if ( r->quality != quality )
{
if ( quality == RESAMPLER_QUALITY_BLEP || r->quality == RESAMPLER_QUALITY_BLEP )
if ( quality == RESAMPLER_QUALITY_BLEP || r->quality == RESAMPLER_QUALITY_BLEP ||
quality == RESAMPLER_QUALITY_BLAM || r->quality == RESAMPLER_QUALITY_BLAM )
{
r->read_pos = 0;
r->read_filled = 0;
@ -289,8 +238,6 @@ void resampler_set_quality(void *_r, int quality)
}
r->delay_added = -1;
r->delay_removed = -1;
if ( quality == RESAMPLER_QUALITY_BLAM && r->phase_inc )
resampler_set_rate( r, r->phase_inc );
}
r->quality = (unsigned char)quality;
}
@ -348,21 +295,16 @@ static int resampler_output_delay(resampler *r)
default:
case RESAMPLER_QUALITY_ZOH:
case RESAMPLER_QUALITY_LINEAR:
case RESAMPLER_QUALITY_BLAM:
case RESAMPLER_QUALITY_CUBIC:
case RESAMPLER_QUALITY_SINC:
return 0;
case RESAMPLER_QUALITY_BLEP:
case RESAMPLER_QUALITY_BLAM:
return SINC_WIDTH - 1;
}
}
int resampler_get_padding_size()
{
return SINC_WIDTH - 1;
}
int resampler_ready(void *_r)
{
resampler * r = ( resampler * ) _r;
@ -381,48 +323,21 @@ void resampler_clear(void *_r)
r->delay_removed = -1;
memset(r->buffer_in, 0, (SINC_WIDTH - 1) * sizeof(r->buffer_in[0]));
memset(r->buffer_in + resampler_buffer_size, 0, (SINC_WIDTH - 1) * sizeof(r->buffer_in[0]));
if (r->quality == RESAMPLER_QUALITY_BLEP)
if (r->quality == RESAMPLER_QUALITY_BLEP || r->quality == RESAMPLER_QUALITY_BLAM)
{
r->inv_phase = 0;
r->last_amp = 0;
r->accumulator = 0;
memset(r->buffer_out, 0, sizeof(r->buffer_out));
}
if (r->quality == RESAMPLER_QUALITY_BLAM)
{
unsigned int i, j;
for (i = 0, j = IIR_ORDER / 2; i < j; ++i)
iir_clear(r->filter + i);
}
}
void resampler_set_rate(void *_r, double new_factor)
{
resampler * r = ( resampler * ) _r;
float old_phase_inc = r->phase_inc;
r->phase_inc = new_factor;
new_factor = 1.0 / new_factor;
r->inv_phase_inc = new_factor;
if (r->quality == RESAMPLER_QUALITY_BLAM && old_phase_inc != r->phase_inc)
{
double ratio_ = new_factor;
unsigned int i, j;
r->output_stage = (ratio_ >= 1.0);
if (!r->output_stage)
{
ratio_ *= 0.45;
}
else
{
ratio_ = (1.0 / ratio_) * 0.45;
}
if (ratio_ > 0.45)
{
ratio_ = 0.45;
}
for (i = 0, j = IIR_ORDER / 2; i < j; ++i)
iir_reset(r->filter + i, ratio_, butterworth(IIR_ORDER, i), 0.0);
}
}
void resampler_write_sample(void *_r, short s)
@ -437,16 +352,8 @@ void resampler_write_sample(void *_r, short s)
if ( r->write_filled < resampler_buffer_size )
{
double s32 = s;
float s32 = s;
s32 *= 256.0;
s32 += 1e-25;
if ( r->quality == RESAMPLER_QUALITY_BLAM && !r->output_stage )
{
unsigned int i, j;
for (i = 0, j = IIR_ORDER / 2; i < j; ++i)
s32 = iir_process(r->filter + i, s32);
}
r->buffer_in[ r->write_pos ] = s32;
r->buffer_in[ r->write_pos + resampler_buffer_size ] = s32;
@ -469,17 +376,9 @@ void resampler_write_sample_fixed(void *_r, int s, unsigned char depth)
if ( r->write_filled < resampler_buffer_size )
{
double s32 = s;
float s32 = s;
s32 /= (double)(1 << (depth - 1));
s32 += 1e-25;
if ( r->quality == RESAMPLER_QUALITY_BLAM && !r->output_stage )
{
unsigned int i, j;
for (i = 0, j = IIR_ORDER / 2; i < j; ++i)
s32 = iir_process(r->filter + i, s32);
}
r->buffer_in[ r->write_pos ] = s32;
r->buffer_in[ r->write_pos + resampler_buffer_size ] = s32;
@ -489,6 +388,27 @@ void resampler_write_sample_fixed(void *_r, int s, unsigned char depth)
}
}
void resampler_write_sample_float(void *_r, float s)
{
resampler * r = ( resampler * ) _r;
if ( r->delay_added < 0 )
{
r->delay_added = 0;
r->write_filled = resampler_input_delay( r );
}
if ( r->write_filled < resampler_buffer_size )
{
r->buffer_in[ r->write_pos ] = s;
r->buffer_in[ r->write_pos + resampler_buffer_size ] = s;
++r->write_filled;
r->write_pos = ( r->write_pos + 1 ) % resampler_buffer_size;
}
}
static int resampler_run_zoh(resampler * r, float ** out_, float * out_end)
{
int in_size = r->write_filled;
@ -800,11 +720,11 @@ static int resampler_run_linear(resampler * r, float ** out_, float * out_end)
return used;
}
#ifndef RESAMPLER_NEON
static int resampler_run_blam(resampler * r, float ** out_, float * out_end)
{
int in_size = r->write_filled;
float const* in_ = r->buffer_in + resampler_buffer_size + r->write_pos - r->write_filled;
unsigned int output_stage = r->output_stage;
int used = 0;
in_size -= 2;
if ( in_size > 0 )
@ -812,36 +732,66 @@ static int resampler_run_blam(resampler * r, float ** out_, float * out_end)
float* out = *out_;
float const* in = in_;
float const* const in_end = in + in_size;
float last_amp = r->last_amp;
float phase = r->phase;
float phase_inc = r->phase_inc;
float inv_phase = r->inv_phase;
float inv_phase_inc = r->inv_phase_inc;
const int step = RESAMPLER_BLAM_CUTOFF * RESAMPLER_RESOLUTION;
const int window_step = RESAMPLER_RESOLUTION;
do
{
float sample;
if ( out >= out_end )
if ( out + SINC_WIDTH * 2 > out_end )
break;
sample = in[0] + (in[1] - in[0]) * phase;
if ( output_stage )
sample = in[0];
if (phase_inc < 1.0f)
sample += (in[1] - in[0]) * phase;
sample -= last_amp;
if (sample)
{
unsigned int i, j;
for (i = 0, j = IIR_ORDER / 2; i < j; ++i)
sample = iir_process(r->filter + i, sample);
}
float kernel[SINC_WIDTH * 2], kernel_sum = 0.0f;
int phase_reduced = (int)(inv_phase * RESAMPLER_RESOLUTION);
int phase_adj = phase_reduced * step / RESAMPLER_RESOLUTION;
int i = SINC_WIDTH;
*out++ = sample;
for (; i >= -SINC_WIDTH + 1; --i)
{
int pos = i * step;
int window_pos = i * window_step;
kernel_sum += kernel[i + SINC_WIDTH - 1] = sinc_lut[abs(phase_adj - pos)] * window_lut[abs(phase_reduced - window_pos)];
}
last_amp += sample;
sample /= kernel_sum;
for (i = 0; i < SINC_WIDTH * 2; ++i)
out[i] += sample * kernel[i];
}
phase += phase_inc;
in += (int)phase;
phase = fmod(phase, 1.0f);
if (inv_phase_inc < 1.0f)
{
++in;
inv_phase += inv_phase_inc;
out += (int)inv_phase;
inv_phase = fmod(inv_phase, 1.0f);
}
else
{
phase += phase_inc;
++out;
in += (int)phase;
phase = fmod(phase, 1.0f);
}
}
while ( in < in_end );
r->phase = phase;
r->inv_phase = inv_phase;
r->last_amp = last_amp;
*out_ = out;
used = (int)(in - in_);
@ -851,6 +801,204 @@ static int resampler_run_blam(resampler * r, float ** out_, float * out_end)
return used;
}
#endif
#ifdef RESAMPLER_SSE
static int resampler_run_blam_sse(resampler * r, float ** out_, float * out_end)
{
int in_size = r->write_filled;
float const* in_ = r->buffer_in + resampler_buffer_size + r->write_pos - r->write_filled;
int used = 0;
in_size -= 2;
if ( in_size > 0 )
{
float* out = *out_;
float const* in = in_;
float const* const in_end = in + in_size;
float last_amp = r->last_amp;
float phase = r->phase;
float phase_inc = r->phase_inc;
float inv_phase = r->inv_phase;
float inv_phase_inc = r->inv_phase_inc;
const int step = RESAMPLER_BLAM_CUTOFF * RESAMPLER_RESOLUTION;
const int window_step = RESAMPLER_RESOLUTION;
do
{
float sample;
if ( out + SINC_WIDTH * 2 > out_end )
break;
sample = in[0];
if (phase_inc < 1.0f)
{
sample += (in[1] - in[0]) * phase;
}
sample -= last_amp;
if (sample)
{
float kernel_sum = 0.0f;
__m128 kernel[SINC_WIDTH / 2];
__m128 temp1, temp2;
__m128 samplex;
float *kernelf = (float*)(&kernel);
int phase_reduced = (int)(inv_phase * RESAMPLER_RESOLUTION);
int phase_adj = phase_reduced * step / RESAMPLER_RESOLUTION;
int i = SINC_WIDTH;
for (; i >= -SINC_WIDTH + 1; --i)
{
int pos = i * step;
int window_pos = i * window_step;
kernel_sum += kernelf[i + SINC_WIDTH - 1] = sinc_lut[abs(phase_adj - pos)] * window_lut[abs(phase_reduced - window_pos)];
}
last_amp += sample;
sample /= kernel_sum;
samplex = _mm_set1_ps( sample );
for (i = 0; i < SINC_WIDTH / 2; ++i)
{
temp1 = _mm_load_ps( (const float *)( kernel + i ) );
temp1 = _mm_mul_ps( temp1, samplex );
temp2 = _mm_loadu_ps( (const float *) out + i * 4 );
temp1 = _mm_add_ps( temp1, temp2 );
_mm_storeu_ps( (float *) out + i * 4, temp1 );
}
}
if (inv_phase_inc < 1.0f)
{
++in;
inv_phase += inv_phase_inc;
out += (int)inv_phase;
inv_phase = fmod(inv_phase, 1.0f);
}
else
{
phase += phase_inc;
++out;
if (phase >= 1.0f)
{
++in;
phase = fmod(phase, 1.0f);
}
}
}
while ( in < in_end );
r->phase = phase;
r->inv_phase = inv_phase;
r->last_amp = last_amp;
*out_ = out;
used = (int)(in - in_);
r->write_filled -= used;
}
return used;
}
#endif
#ifdef RESAMPLER_NEON
static int resampler_run_blam(resampler * r, float ** out_, float * out_end)
{
int in_size = r->write_filled;
float const* in_ = r->buffer_in + resampler_buffer_size + r->write_pos - r->write_filled;
int used = 0;
in_size -= 2;
if ( in_size > 0 )
{
float* out = *out_;
float const* in = in_;
float const* const in_end = in + in_size;
float last_amp = r->last_amp;
float phase = r->phase;
float phase_inc = r->phase_inc;
float inv_phase = r->inv_phase;
float inv_phase_inc = r->inv_phase_inc;
const int step = RESAMPLER_BLAM_CUTOFF * RESAMPLER_RESOLUTION;
const int window_step = RESAMPLER_RESOLUTION;
do
{
float sample;
if ( out + SINC_WIDTH * 2 > out_end )
break;
sample = in[0];
if (phase_inc < 1.0f)
sample += (in[1] - in[0]) * phase;
sample -= last_amp;
if (sample)
{
float kernel_sum = 0.0;
float32x4_t kernel[SINC_WIDTH / 2];
float32x4_t temp1, temp2;
float32x4_t samplex;
float *kernelf = (float*)(&kernel);
int phase_reduced = (int)(inv_phase * RESAMPLER_RESOLUTION);
int phase_adj = phase_reduced * step / RESAMPLER_RESOLUTION;
int i = SINC_WIDTH;
for (; i >= -SINC_WIDTH + 1; --i)
{
int pos = i * step;
int window_pos = i * window_step;
kernel_sum += kernelf[i + SINC_WIDTH - 1] = sinc_lut[abs(phase_adj - pos)] * window_lut[abs(phase_reduced - window_pos)];
}
last_amp += sample;
sample /= kernel_sum;
samplex = vdupq_n_f32(sample);
for (i = 0; i < SINC_WIDTH / 2; ++i)
{
temp1 = vld1q_f32( (const float32_t *)( kernel + i ) );
temp2 = vld1q_f32( (const float32_t *) out + i * 4 );
temp2 = vmlaq_f32( temp2, temp1, samplex );
vst1q_f32( (float32_t *) out + i * 4, temp2 );
}
}
if (inv_phase_inc < 1.0f)
{
++in;
inv_phase += inv_phase_inc;
out += (int)inv_phase;
inv_phase = fmod(inv_phase, 1.0f);
}
else
{
phase += phase_inc;
++out;
if (phase >= 1.0f)
{
++in;
phase = fmod(phase, 1.0f);
}
}
}
while ( in < in_end );
r->phase = phase;
r->inv_phase = inv_phase;
r->last_amp = last_amp;
*out_ = out;
used = (int)(in - in_);
r->write_filled -= used;
}
return used;
}
#endif
#ifndef RESAMPLER_NEON
static int resampler_run_cubic(resampler * r, float ** out_, float * out_end)
@ -1257,8 +1405,25 @@ static void resampler_fill(resampler * r)
break;
case RESAMPLER_QUALITY_BLAM:
resampler_run_blam( r, &out, out + write_size );
{
float * out_ = out;
int write_extra = 0;
if ( write_pos >= r->read_pos )
write_extra = r->read_pos;
if ( write_extra > SINC_WIDTH * 2 - 1 )
write_extra = SINC_WIDTH * 2 - 1;
memcpy( r->buffer_out + resampler_buffer_size, r->buffer_out, write_extra * sizeof(r->buffer_out[0]) );
#ifdef RESAMPLER_SSE
if ( resampler_has_sse )
resampler_run_blam_sse( r, &out, out + write_size + write_extra );
else
#endif
resampler_run_blam( r, &out, out + write_size + write_extra );
memcpy( r->buffer_out, r->buffer_out + resampler_buffer_size, write_extra * sizeof(r->buffer_out[0]) );
if ( out == out_ )
return;
break;
}
case RESAMPLER_QUALITY_CUBIC:
#ifdef RESAMPLER_SSE
@ -1297,7 +1462,7 @@ static void resampler_fill_and_remove_delay(resampler * r)
int resampler_get_sample_count(void *_r)
{
resampler * r = ( resampler * ) _r;
if ( r->read_filled < 1 && (r->quality != RESAMPLER_QUALITY_BLEP || r->inv_phase_inc) )
if ( r->read_filled < 1 && ((r->quality != RESAMPLER_QUALITY_BLEP && r->quality != RESAMPLER_QUALITY_BLAM) || r->inv_phase_inc))
resampler_fill_and_remove_delay( r );
return r->read_filled;
}
@ -1309,7 +1474,7 @@ int resampler_get_sample(void *_r)
resampler_fill_and_remove_delay( r );
if ( r->read_filled < 1 )
return 0;
if ( r->quality == RESAMPLER_QUALITY_BLEP )
if ( r->quality == RESAMPLER_QUALITY_BLEP || r->quality == RESAMPLER_QUALITY_BLAM )
return (int)(r->buffer_out[ r->read_pos ] + r->accumulator);
else
return (int)r->buffer_out[ r->read_pos ];
@ -1322,7 +1487,7 @@ float resampler_get_sample_float(void *_r)
resampler_fill_and_remove_delay( r );
if ( r->read_filled < 1 )
return 0;
if ( r->quality == RESAMPLER_QUALITY_BLEP )
if ( r->quality == RESAMPLER_QUALITY_BLEP || r->quality == RESAMPLER_QUALITY_BLAM )
return r->buffer_out[ r->read_pos ] + r->accumulator;
else
return r->buffer_out[ r->read_pos ];
@ -1333,7 +1498,7 @@ void resampler_remove_sample(void *_r, int decay)
resampler * r = ( resampler * ) _r;
if ( r->read_filled > 0 )
{
if ( r->quality == RESAMPLER_QUALITY_BLEP )
if ( r->quality == RESAMPLER_QUALITY_BLEP || r->quality == RESAMPLER_QUALITY_BLAM )
{
r->accumulator += r->buffer_out[ r->read_pos ];
r->buffer_out[ r->read_pos ] = 0;

View File

@ -36,6 +36,11 @@ static void *dumb_stdfile_open(const char *filename)
dumb_stdfile * file = ( dumb_stdfile * ) malloc( sizeof(dumb_stdfile) );
if ( !file ) return 0;
file->file = fopen(filename, "rb");
if ( !file->file )
{
free( file );
return 0;
}
fseek(file->file, 0, SEEK_END);
file->size = ftell(file->file);
fseek(file->file, 0, SEEK_SET);

View File

@ -28,7 +28,7 @@
#endif
#define INVESTIGATE_OLD_INSTRUMENTS
//#define INVESTIGATE_OLD_INSTRUMENTS
@ -290,12 +290,15 @@ static int it_read_envelope(IT_ENVELOPE *envelope, DUMBFILE *f)
envelope->flags = dumbfile_getc(f);
envelope->n_nodes = dumbfile_getc(f);
if(envelope->n_nodes > 25) {
TRACE("IT error: wrong number of envelope nodes (%d)\n", envelope->n_nodes);
envelope->n_nodes = 0;
return -1;
}
envelope->loop_start = dumbfile_getc(f);
envelope->loop_end = dumbfile_getc(f);
envelope->sus_loop_start = dumbfile_getc(f);
envelope->sus_loop_end = dumbfile_getc(f);
if (envelope->n_nodes > 25)
envelope->n_nodes = 25;
for (n = 0; n < envelope->n_nodes; n++) {
envelope->node_y[n] = dumbfile_getc(f);
envelope->node_t[n] = dumbfile_igetw(f);
@ -620,8 +623,8 @@ long _dumb_it_read_sample_data_adpcm4(IT_SAMPLE *sample, DUMBFILE *f)
long n, len, delta;
signed char * ptr, * end;
signed char compression_table[16];
if (dumbfile_getnc((char *)compression_table, 16, f) != 16)
return -1;
if (dumbfile_getnc((char *)compression_table, 16, f) != 16)
return -1;
ptr = (signed char *) sample->data;
delta = 0;
@ -822,7 +825,7 @@ static int it_read_pattern(IT_PATTERN *pattern, DUMBFILE *f, unsigned char *buff
while (bufpos < buflen) {
unsigned char b = buffer[bufpos++];
if (b == 0) {
/* End of row */
IT_SET_END_ROW(entry);
@ -838,31 +841,46 @@ static int it_read_pattern(IT_PATTERN *pattern, DUMBFILE *f, unsigned char *buff
channel = (b - 1) & 63;
if (b & 128)
if (b & 128) {
if (bufpos >= buflen)
return -1;
cmask[channel] = mask = buffer[bufpos++];
else
} else
mask = cmask[channel];
if (mask) {
entry->mask = (mask & 15) | (mask >> 4);
entry->channel = channel;
if (mask & IT_ENTRY_NOTE)
if (mask & IT_ENTRY_NOTE) {
if (bufpos >= buflen)
return -1;
cnote[channel] = entry->note = buffer[bufpos++];
else if (mask & (IT_ENTRY_NOTE << 4))
} else if (mask & (IT_ENTRY_NOTE << 4))
entry->note = cnote[channel];
if (mask & IT_ENTRY_INSTRUMENT)
if (mask & IT_ENTRY_INSTRUMENT) {
if (bufpos >= buflen)
return -1;
cinstrument[channel] = entry->instrument = buffer[bufpos++];
else if (mask & (IT_ENTRY_INSTRUMENT << 4))
} else if (mask & (IT_ENTRY_INSTRUMENT << 4))
entry->instrument = cinstrument[channel];
if (mask & IT_ENTRY_VOLPAN)
if (mask & IT_ENTRY_VOLPAN) {
if (bufpos >= buflen)
return -1;
cvolpan[channel] = entry->volpan = buffer[bufpos++];
else if (mask & (IT_ENTRY_VOLPAN << 4))
} else if (mask & (IT_ENTRY_VOLPAN << 4))
entry->volpan = cvolpan[channel];
if (mask & IT_ENTRY_EFFECT) {
if (bufpos + 1 >= buflen)
return -1;
ceffect[channel] = entry->effect = buffer[bufpos++];
ceffectvalue[channel] = entry->effectvalue = buffer[bufpos++];
} else {
@ -940,6 +958,7 @@ static sigdata_t *it_load_sigdata(DUMBFILE *f)
int message_length, message_offset;
IT_COMPONENT *component;
int min_components;
int n_components = 0;
unsigned char sample_convert[4096];
@ -1044,10 +1063,15 @@ static sigdata_t *it_load_sigdata(DUMBFILE *f)
sigdata->pattern[n].entry = NULL;
}
dumbfile_getnc((char *)sigdata->order, sigdata->n_orders, f);
if ( dumbfile_getnc((char *)sigdata->order, sigdata->n_orders, f) < sigdata->n_orders ) {
_dumb_it_unload_sigdata(sigdata);
return NULL;
}
sigdata->restart_position = 0;
min_components = (special & 1) + sigdata->n_instruments + sigdata->n_samples + sigdata->n_patterns;
component = malloc(769 * sizeof(*component));
component = malloc(min_components * sizeof(*component));
if (!component) {
_dumb_it_unload_sigdata(sigdata);
return NULL;
@ -1236,7 +1260,7 @@ static sigdata_t *it_load_sigdata(DUMBFILE *f)
switch (component[n].type) {
case IT_COMPONENT_SONG_MESSAGE:
if ( n < n_components ) {
if ( n+1 < n_components ) {
message_length = min( message_length, (int)(component[n+1].offset - component[n].offset) );
}
sigdata->song_message = malloc(message_length + 1);

View File

@ -3789,7 +3789,7 @@ static void update_tick_counts(DUMB_IT_SIGRENDERER *sigrenderer)
}
}
}
} else if (channel->note_delay_count) {
} else if (channel->note_delay_count && channel->note_delay_entry) {
channel->note_delay_count--;
if (channel->note_delay_count == 0)
process_note_data(sigrenderer, channel->note_delay_entry, 0);
@ -4259,6 +4259,8 @@ static void process_all_playing(DUMB_IT_SIGRENDERER *sigrenderer)
tick = 0;
else
++tick;
if (sigrenderer->sigdata->flags & IT_WAS_AN_STM)
tick /= 16;
playing->delta *= (float)pow(DUMB_SEMITONE_BASE, channel->arpeggio_offsets[channel->arpeggio_table[tick&31]]);
}
/*
@ -4299,6 +4301,9 @@ static void process_all_playing(DUMB_IT_SIGRENDERER *sigrenderer)
static int process_tick(DUMB_IT_SIGRENDERER *sigrenderer)
{
DUMB_IT_SIGDATA *sigdata = sigrenderer->sigdata;
if ( sigrenderer->tempo < 32 || sigrenderer->tempo > 255 ) // problematic
return 1;
// Set note vol/freq to vol/freq set for each channel
@ -4440,8 +4445,13 @@ static int process_tick(DUMB_IT_SIGRENDERER *sigrenderer)
/** WARNING - everything pertaining to a new pattern initialised? */
sigrenderer->entry = sigrenderer->entry_start = pattern->entry;
sigrenderer->entry_end = sigrenderer->entry + pattern->n_entries;
if ( pattern->entry ) {
sigrenderer->entry = sigrenderer->entry_start = pattern->entry;
sigrenderer->entry_end = sigrenderer->entry + pattern->n_entries;
} else {
sigrenderer->entry = sigrenderer->entry_start = 0;
sigrenderer->entry_end = 0;
}
/* If n_rows was 0, we're only just starting. Don't do anything weird here. */
/* added: process row check, for break to row spooniness */
@ -4506,6 +4516,7 @@ static int process_tick(DUMB_IT_SIGRENDERER *sigrenderer)
if (!(sigdata->flags & IT_WAS_A_669))
reset_effects(sigrenderer);
if ( sigrenderer->entry )
{
IT_ENTRY *entry = sigrenderer->entry;
int ignore_cxx = 0;
@ -4525,6 +4536,7 @@ static int process_tick(DUMB_IT_SIGRENDERER *sigrenderer)
else if (!(sigdata->flags & IT_OLD_EFFECTS))
update_smooth_effects(sigrenderer);
} else {
if ( sigrenderer->entry )
{
IT_ENTRY *entry = sigrenderer->entry;
@ -5320,6 +5332,10 @@ static DUMB_IT_SIGRENDERER *init_sigrenderer(DUMB_IT_SIGDATA *sigdata, int n_cha
channel->inv_loop_speed = 0;
channel->inv_loop_offset = 0;
channel->playing = NULL;
channel->key_off_count = 0;
channel->note_cut_count = 0;
channel->note_delay_count = 0;
channel->note_delay_entry = 0;
#ifdef BIT_ARRAY_BULLSHIT
channel->played_patjump = NULL;
channel->played_patjump_order = 0xFFFE;
@ -5405,7 +5421,10 @@ static DUMB_IT_SIGRENDERER *init_sigrenderer(DUMB_IT_SIGDATA *sigdata, int n_cha
//sigrenderer->max_output = 0;
if ( !(sigdata->flags & IT_WAS_PROCESSED) ) {
dumb_it_add_lpc( sigdata );
if ( dumb_it_add_lpc( sigdata ) < 0 ) {
_dumb_it_end_sigrenderer( sigrenderer );
return NULL;
}
sigdata->flags |= IT_WAS_PROCESSED;
}
@ -5596,6 +5615,8 @@ static long it_sigrenderer_get_samples(
LONG_LONG t;
if (sigrenderer->order < 0) return 0; // problematic
if (!sigrenderer->tempo) return 0; // also problematic
pos = 0;
dt = (int)(delta * 65536.0f + 0.5f);

View File

@ -260,6 +260,9 @@ static int it_amf_read_sample_data( IT_SAMPLE *sample, DUMBFILE *f )
if ( sample->length )
read_length = (int)dumbfile_getnc( sample->data, sample->length, f );
if ( read_length < 0 )
read_length = 0;
for ( i = 0; i < read_length; i++ ) {
( ( signed char * ) sample->data )[ i ] ^= 0x80;
@ -320,6 +323,8 @@ static DUMB_IT_SIGDATA *it_amf_load_sigdata(DUMBFILE *f, int * version)
free( sigdata );
return NULL;
}
sigdata->n_pchannels = nchannels;
memset( sigdata->channel_volume, 64, DUMB_IT_N_CHANNELS );

View File

@ -39,7 +39,7 @@ DUH *dumb_read_any_quick(DUMBFILE *f, int restrict_, int subsong)
unsigned long signature_size;
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 );
dumbfile_seek( f, 0, DFS_SEEK_SET );

View File

@ -118,7 +118,7 @@ static int it_mod_read_pattern(IT_PATTERN *pattern, DUMBFILE *f, int n_channels,
static int it_mod_read_sample_header(IT_SAMPLE *sample, DUMBFILE *f, 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;
@ -137,7 +137,10 @@ assumed not to be an instrument name, and is probably a message.
sample->filename[0] = 0;
sample->length = dumbfile_mgetw(f) << 1;
finetune = (signed char)(dumbfile_getc(f) << 4) >> 4; /* signed nibble */
if (fft == DUMB_ID('F','E','S','T'))
finetune = (signed char)((-dumbfile_getc(f) & 0x1F) << 3) >> 3;
else
finetune = (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->default_volume = dumbfile_getc(f); // Should we be setting global_volume to this instead?
@ -166,7 +169,7 @@ told to stop.
sample->default_pan = 0;
sample->C5_speed = (int)( AMIGA_CLOCK / 214.0 ); //(long)(16726.0*pow(DUMB_PITCH_BASE, finetune*32));
sample->finetune = finetune * 32;
sample->finetune = finetune * ((fft == DUMB_ID('F','E','S','T')) ? 16 : 32);
// the above line might be wrong
if (sample->loop_end > sample->length)
@ -280,15 +283,15 @@ static DUMB_IT_SIGDATA *it_mod_load_sigdata(DUMBFILE *f, int restrict_)
int i;
unsigned long fft;
if ( dumbfile_seek(f, MOD_FFT_OFFSET, DFS_SEEK_SET) )
return NULL;
if ( dumbfile_seek(f, MOD_FFT_OFFSET, DFS_SEEK_SET) )
return NULL;
fft = dumbfile_mgetl(f);
if (dumbfile_error(f))
return NULL;
fft = dumbfile_mgetl(f);
if (dumbfile_error(f))
return NULL;
if ( dumbfile_seek(f, 0, DFS_SEEK_SET) )
return NULL;
if ( dumbfile_seek(f, 0, DFS_SEEK_SET) )
return NULL;
sigdata = malloc(sizeof(*sigdata));
if (!sigdata) {
@ -317,6 +320,7 @@ static DUMB_IT_SIGDATA *it_mod_load_sigdata(DUMBFILE *f, int restrict_)
case DUMB_ID('F','L','T','4'):
case DUMB_ID('M',0,0,0):
case DUMB_ID('8',0,0,0):
case DUMB_ID('F','E','S','T'):
n_channels = 4;
break;
case DUMB_ID('F','L','T','8'):
@ -381,6 +385,7 @@ static DUMB_IT_SIGDATA *it_mod_load_sigdata(DUMBFILE *f, int restrict_)
} else {
n_channels = 4;
sigdata->n_samples = 15;
fft = 0;
}
}
@ -412,7 +417,7 @@ static DUMB_IT_SIGDATA *it_mod_load_sigdata(DUMBFILE *f, int restrict_)
sigdata->sample[i].data = NULL;
for (i = 0; i < sigdata->n_samples; i++) {
if (it_mod_read_sample_header(&sigdata->sample[i], f, sigdata->n_samples == 15)) {
if (it_mod_read_sample_header(&sigdata->sample[i], f, fft, sigdata->n_samples == 15)) {
_dumb_it_unload_sigdata(sigdata);
return NULL;
}

View File

@ -30,7 +30,7 @@ size_t strlen_max(const char * ptr, size_t max)
if (ptr==0) return 0;
start = ptr;
end = ptr + max;
while(*ptr && ptr < end) ptr++;
while(ptr < end && *ptr) ptr++;
return ptr - start;
}
@ -92,7 +92,7 @@ static int it_mtm_assemble_pattern(IT_PATTERN *pattern, const unsigned char * tr
return 0;
}
static int it_mtm_read_sample_header(IT_SAMPLE *sample, DUMBFILE *f)
static int it_mtm_read_sample_header(IT_SAMPLE *sample, DUMBFILE *f, int * skip_bytes)
{
int finetune, flags;
@ -117,7 +117,9 @@ static int it_mtm_read_sample_header(IT_SAMPLE *sample, DUMBFILE *f)
sample->flags = IT_SAMPLE_EXISTS;
*skip_bytes = 0;
if (flags & 1) {
*skip_bytes = sample->length & 1;
sample->flags |= IT_SAMPLE_16BIT;
sample->length >>= 1;
sample->loop_start >>= 1;
@ -144,10 +146,11 @@ static int it_mtm_read_sample_header(IT_SAMPLE *sample, DUMBFILE *f)
return dumbfile_error(f);
}
static int it_mtm_read_sample_data(IT_SAMPLE *sample, DUMBFILE *f)
static int it_mtm_read_sample_data(IT_SAMPLE *sample, DUMBFILE *f, int skip_bytes)
{
long i;
long truncated_size;
long bytes_per_sample;
/* 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) {
@ -156,20 +159,24 @@ static int it_mtm_read_sample_data(IT_SAMPLE *sample, DUMBFILE *f)
} else {
truncated_size = 0;
}
bytes_per_sample = (sample->flags & IT_SAMPLE_16BIT) ? 2 : 1;
sample->data = malloc(sample->length);
sample->data = malloc(sample->length * bytes_per_sample);
if (!sample->data)
return -1;
dumbfile_getnc((char *)sample->data, sample->length, f);
dumbfile_skip(f, truncated_size);
dumbfile_getnc((char *)sample->data, sample->length * bytes_per_sample, f);
dumbfile_skip(f, truncated_size * bytes_per_sample);
dumbfile_skip(f, skip_bytes);
if (dumbfile_error(f))
return -1;
for (i = 0; i < sample->length; i++)
((signed char *)sample->data)[i] ^= 0x80;
if (bytes_per_sample == 1)
for (i = 0; i < sample->length; i++)
((signed char *)sample->data)[i] ^= 0x80;
return 0;
}
@ -185,6 +192,8 @@ static DUMB_IT_SIGDATA *it_mtm_load_sigdata(DUMBFILE *f, int * version)
unsigned short * sequence;
char * comment;
int * skip_bytes;
if (dumbfile_getc(f) != 'M' ||
dumbfile_getc(f) != 'T' ||
@ -258,23 +267,26 @@ static DUMB_IT_SIGDATA *it_mtm_load_sigdata(DUMBFILE *f, int * version)
sigdata->restart_position = 0;
sigdata->n_pchannels = n_channels;
for (n = 0; n < sigdata->n_samples; n++)
sigdata->sample[n].data = NULL;
skip_bytes = calloc(sizeof(int), sigdata->n_samples);
if (!skip_bytes) goto error_usd;
for (n = 0; n < sigdata->n_samples; n++) {
if (it_mtm_read_sample_header(&sigdata->sample[n], f)) goto error_usd;
if (it_mtm_read_sample_header(&sigdata->sample[n], f, skip_bytes + n)) goto error_sb;
}
sigdata->order = malloc(sigdata->n_orders);
if (!sigdata->order) goto error_usd;
if (!sigdata->order) goto error_sb;
if (dumbfile_getnc((char *)sigdata->order, sigdata->n_orders, f) < sigdata->n_orders) goto error_usd;
if (dumbfile_getnc((char *)sigdata->order, sigdata->n_orders, f) < sigdata->n_orders) goto error_sb;
if (sigdata->n_orders < 128)
if (dumbfile_skip(f, 128 - sigdata->n_orders)) goto error_usd;
if (dumbfile_skip(f, 128 - sigdata->n_orders)) goto error_sb;
track = malloc(192 * n_tracks);
if (!track) goto error_usd;
if (!track) goto error_sb;
if (dumbfile_getnc((char *)track, 192 * n_tracks, f) < 192 * n_tracks) goto error_ft;
@ -321,7 +333,8 @@ static DUMB_IT_SIGDATA *it_mtm_load_sigdata(DUMBFILE *f, int * version)
int l, m;
for (l = 0, n = 0; n <= o; n += 40) {
l += strlen_max(&comment[n], 40) + 2;
int maxlen = l_comment - n;
l += strlen_max(&comment[n], maxlen > 40 ? 40 : maxlen) + 2;
}
l -= 1;
@ -330,7 +343,8 @@ static DUMB_IT_SIGDATA *it_mtm_load_sigdata(DUMBFILE *f, int * version)
if (!sigdata->song_message) goto error_fc;
for (m = 0, n = 0; n <= o; n += 40) {
int p = (int) strlen_max(&comment[n], 40);
int maxlen = l_comment - n;
int p = (int) strlen_max(&comment[n], maxlen > 40 ? 40 : maxlen);
if (p) {
memcpy(sigdata->song_message + m, &comment[n], p);
m += p;
@ -348,13 +362,14 @@ static DUMB_IT_SIGDATA *it_mtm_load_sigdata(DUMBFILE *f, int * version)
}
for (n = 0; n < sigdata->n_samples; n++) {
if (it_mtm_read_sample_data(&sigdata->sample[n], f)) 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);
free(sequence);
free(track);
free(skip_bytes);
return sigdata;
@ -364,6 +379,8 @@ error_fs:
free(sequence);
error_ft:
free(track);
error_sb:
free(skip_bytes);
error_usd:
_dumb_it_unload_sigdata(sigdata);
return NULL;

View File

@ -66,89 +66,88 @@ static int it_old_psm_read_samples(IT_SAMPLE ** sample, DUMBFILE * f, int * num)
qsort(buffer, count, 64, &psm_sample_compare);
for (n = 0; n < true_num; n++) {
for (n = 0; n < *num; n++) {
(*sample)[n].flags = 0;
}
for (n = 0; n < count; n++) {
IT_SAMPLE smp;
IT_SAMPLE * s;
snum = buffer[(n * 64) + 45] | (buffer[(n * 64) + 46] << 8);
s = &((*sample)[snum - 1]);
memcpy(s->filename, buffer + (n * 64), 13);
s->filename[13] = 0;
memcpy(s->name, buffer + (n * 64) + 13, 24);
s->name[24] = 0;
memcpy(smp.filename, buffer + (n * 64), 13);
smp.filename[13] = 0;
memcpy(smp.name, buffer + (n * 64) + 13, 24);
smp.name[24] = 0;
offset = buffer[(n * 64) + 37] | (buffer[(n * 64) + 38] << 8) |
(buffer[(n * 64) + 39] << 16) | (buffer[(n * 64) + 40] << 24);
flags = buffer[(n * 64) + 47];
s->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);
s->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);
s->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);
if (s->length <= 0) continue;
if (smp.length <= 0) continue;
finetune = buffer[(n * 64) + 60];
s->default_volume = buffer[(n * 64) + 61];
s->C5_speed = buffer[(n * 64) + 62] | (buffer[(n * 64) + 63] << 8);
smp.default_volume = buffer[(n * 64) + 61];
smp.C5_speed = buffer[(n * 64) + 62] | (buffer[(n * 64) + 63] << 8);
if (finetune & 15) {
finetune &= 15;
if (finetune >= 8) finetune -= 16;
//s->C5_speed = (long)((double)s->C5_speed * pow(DUMB_PITCH_BASE, finetune*32));
s->finetune = finetune * 32;
smp.finetune = finetune * 32;
}
else s->finetune = 0;
else smp.finetune = 0;
s->flags |= IT_SAMPLE_EXISTS;
if (flags & 0x41) {
s->flags &= ~IT_SAMPLE_EXISTS;
smp.flags |= IT_SAMPLE_EXISTS;
if (flags & 0x41)
continue;
}
if (flags & 0x20) s->flags |= IT_SAMPLE_PINGPONG_LOOP;
if (flags & 4) s->flags |= IT_SAMPLE_16BIT;
if (flags & 0x20) smp.flags |= IT_SAMPLE_PINGPONG_LOOP;
if (flags & 4) smp.flags |= IT_SAMPLE_16BIT;
if (flags & 0x80) {
s->flags |= IT_SAMPLE_LOOP;
if ((unsigned int)s->loop_end > (unsigned int)s->length)
s->loop_end = s->length;
else if ((unsigned int)s->loop_start >= (unsigned int)s->loop_end)
s->flags &= ~IT_SAMPLE_LOOP;
smp.flags |= IT_SAMPLE_LOOP;
if ((unsigned int)smp.loop_end > (unsigned int)smp.length)
smp.loop_end = smp.length;
else if ((unsigned int)smp.loop_start >= (unsigned int)smp.loop_end)
smp.flags &= ~IT_SAMPLE_LOOP;
else
s->length = s->loop_end;
smp.length = smp.loop_end;
}
s->global_volume = 64;
smp.global_volume = 64;
s->vibrato_speed = 0;
s->vibrato_depth = 0;
s->vibrato_rate = 0;
s->vibrato_waveform = IT_VIBRATO_SINE;
s->max_resampling_quality = -1;
smp.vibrato_speed = 0;
smp.vibrato_depth = 0;
smp.vibrato_rate = 0;
smp.vibrato_waveform = IT_VIBRATO_SINE;
smp.max_resampling_quality = -1;
sample_bytes = s->length * ((flags & 4) ? 2 : 1);
s->data = malloc(sample_bytes);
if (!s->data) goto error_fb;
sample_bytes = smp.length * ((flags & 4) ? 2 : 1);
smp.data = malloc(sample_bytes);
if (!smp.data) goto error_fb;
sdata = (const unsigned char *) smp.data;
if (dumbfile_seek(f, offset, DFS_SEEK_SET) || dumbfile_getnc(s->data, sample_bytes, f) < sample_bytes) goto error_fb;
sdata = ( const unsigned char * ) s->data;
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 & 8) {
if (flags & 4) {
for (o = 0; o < s->length; o++)
((short *)s->data)[o] = (sdata[o * 2] | (sdata[(o * 2) + 1] << 8)) ^ 0x8000;
for (o = 0; o < smp.length; o++)
((short *)smp.data)[o] = (sdata[o * 2] | (sdata[(o * 2) + 1] << 8)) ^ 0x8000;
} else {
for (o = 0; o < s->length; o++)
((signed char *)s->data)[o] = sdata[o] ^ 0x80;
for (o = 0; o < smp.length; o++)
((signed char *)smp.data)[o] = sdata[o] ^ 0x80;
}
} else {
if (flags & 4) {
for (o = 0; o < s->length; o++)
((short *)s->data)[o] = sdata[o * 2] | (sdata[(o * 2) + 1] << 8);
for (o = 0; o < smp.length; o++)
((short *)smp.data)[o] = sdata[o * 2] | (sdata[(o * 2) + 1] << 8);
} else {
memcpy(s->data, sdata, s->length);
memcpy(smp.data, sdata, smp.length);
}
}
} else {
@ -156,36 +155,41 @@ static int it_old_psm_read_samples(IT_SAMPLE ** sample, DUMBFILE * f, int * num)
if (flags & 8) {
/* unsigned delta? mehhh, does anything even use this? */
if (flags & 4) {
for (o = 0; o < s->length; o++) {
for (o = 0; o < smp.length; o++) {
delta += (short)(sdata[o * 2] | (sdata[(o * 2) + 1] << 8));
((short *)s->data)[o] = delta ^ 0x8000;
((short *)smp.data)[o] = delta ^ 0x8000;
}
} else {
for (o = 0; o < s->length; o++) {
for (o = 0; o < smp.length; o++) {
delta += (signed char)sdata[o];
((signed char *)s->data)[o] = delta ^ 0x80;
((signed char *)smp.data)[o] = delta ^ 0x80;
}
}
} else {
if (flags & 4) {
for (o = 0; o < s->length; o++) {
for (o = 0; o < smp.length; o++) {
delta += (signed short)(sdata[o * 2] | (sdata[(o * 2) + 1] << 8));
((signed short *)s->data)[o] = delta;
((signed short *)smp.data)[o] = delta;
}
} else {
for (o = 0; o < s->length; o++) {
for (o = 0; o < smp.length; o++) {
delta += (signed char)sdata[o];
((signed char *)s->data)[o] = delta;
((signed char *)smp.data)[o] = delta;
}
}
}
}
if (s->data) free(s->data);
*s = smp;
}
free(buffer);
return 0;
error_fd:
free((void *)sdata);
error_fb:
free(buffer);
error:
@ -224,6 +228,8 @@ static int it_old_psm_read_patterns(IT_PATTERN * pattern, DUMBFILE * f, int num,
}
psize = (psize + 15) & ~15;
if (offset + psize > size) goto error_fb;
end = ptr + psize;
ptr += 4;
@ -243,9 +249,8 @@ static int it_old_psm_read_patterns(IT_PATTERN * pattern, DUMBFILE * f, int num,
if (flags & 0x80) ptr += 2;
if (flags & 0x40) ptr++;
if (flags & 0x20) {
ptr++;
if (*ptr == 40) ptr += 3;
else ptr++;
if (*ptr == 40) ptr += 4;
else ptr += 2;
}
}
}

View File

@ -96,7 +96,7 @@ static int it_psm_process_sample(IT_SAMPLE * sample, const unsigned char * data,
if (insno != id) return -1;
if (!length) {
if (length <= 0) {
sample->flags &= ~IT_SAMPLE_EXISTS;
return 0;
}
@ -162,7 +162,12 @@ static int it_psm_process_pattern(IT_PATTERN * pattern, const unsigned char * da
nrows = data[0] | (data[1] << 8);
if (!nrows) return 0;
if (!nrows) {
pattern->n_rows = 0;
pattern->n_entries = 0;
pattern->entry = NULL;
return 0;
}
pattern->n_rows = nrows;
@ -461,7 +466,7 @@ static DUMB_IT_SIGDATA *it_psm_load_sigdata(DUMBFILE *f, int * ver, int subsong)
PSMCHUNK *chunk;
int n_chunks = 0;
PSMCHUNK *songchunk;
PSMCHUNK *songchunk = 0;
int n_song_chunks = 0;
PSMEVENT *event = 0;
@ -491,6 +496,7 @@ static DUMB_IT_SIGDATA *it_psm_load_sigdata(DUMBFILE *f, int * ver, int subsong)
chunk = calloc(768, sizeof(*chunk));
while (length >= 8) {
if (n_chunks >= 768) goto error_fc;
chunk[n_chunks].id = dumbfile_mgetl(f);
n = dumbfile_igetl(f);
length -= 8;
@ -584,13 +590,14 @@ static DUMB_IT_SIGDATA *it_psm_load_sigdata(DUMBFILE *f, int * ver, int subsong)
ptr += 11;
songchunk = 0;
if (length >= 8) {
songchunk = malloc(128 * sizeof(*songchunk));
songchunk = malloc(256 * sizeof(*songchunk));
if (!songchunk) goto error_usd;
while (length >= 8) {
if (n_song_chunks >= 256) goto error_sc;
songchunk[n_song_chunks].id = DUMB_ID(ptr[0], ptr[1], ptr[2], ptr[3]);
n = ptr[4] | (ptr[5] << 8) | (ptr[6] << 16) | (ptr[7] << 24);
length -= 8;
if (n > length) goto error_sc;
if (n < 0 || n > length) goto error_sc;
songchunk[n_song_chunks].len = n;
songchunk[n_song_chunks].data = ptr + 8;
n_song_chunks++;
@ -1246,7 +1253,7 @@ int pattcmp( const unsigned char * a, const unsigned char * b, size_t l )
}
if ( i < j ) return -1;
else if ( j > i ) return 1;
else if ( i > j ) return 1;
i = memcmp( a, b, j );
if ( i ) return i;
@ -1279,7 +1286,7 @@ DUH *dumb_read_psm_quick(DUMBFILE *f, int subsong)
if ( ver )
{
tag[2][0] = "FORMATVERSION";
snprintf( version, 15, "%u", ver );
snprintf( version, 15, "%d", ver );
version[15] = 0;
tag[2][1] = (const char *) &version;
++n_tags;

View File

@ -371,6 +371,8 @@ static int limit_xm_resize(void *f, long n)
{
DUMBFILE *df = f;
LIMITED_XM *lx = df->file;
if (n < 0)
return -1;
if (lx->buffered || n) {
if (n > lx->allocated) {
unsigned char *buffered = realloc( lx->buffered, n );
@ -897,20 +899,20 @@ static DUMB_IT_SIGDATA *it_xm_load_sigdata(DUMBFILE *f, int * version)
if (sigdata->speed == 0) sigdata->speed = 6; // Should we? What about tempo?
sigdata->tempo = dumbfile_igetw(f);
// FT2 always clips restart position against the song length
if (sigdata->restart_position > sigdata->n_orders)
sigdata->restart_position = sigdata->n_orders;
// And FT2 starts playback on order 0, regardless of length,
// and only checks if the next order is greater than or equal
// to this, not the current pattern. Work around this with
// DUMB's playback core by overriding a zero length with one.
if (sigdata->n_orders == 0)
sigdata->n_orders = 1;
// FT2 always clips restart position against the song length
if (sigdata->restart_position > sigdata->n_orders)
sigdata->restart_position = sigdata->n_orders;
// And FT2 starts playback on order 0, regardless of length,
// and only checks if the next order is greater than or equal
// to this, not the current pattern. Work around this with
// DUMB's playback core by overriding a zero length with one.
if (sigdata->n_orders == 0)
sigdata->n_orders = 1;
/* sanity checks */
// XXX
i = header_size - 4 - 2 * 8; /* Maximum number of orders expected */
if (dumbfile_error(f) || sigdata->n_orders <= 0 || sigdata->n_orders > i || sigdata->n_patterns > 256 || sigdata->n_instruments > 256 || n_channels > DUMB_IT_N_CHANNELS) {
if (dumbfile_error(f) || sigdata->n_orders <= 0 || sigdata->n_orders > i || !sigdata->n_patterns || sigdata->n_patterns > 256 || !sigdata->n_instruments || sigdata->n_instruments > 256 || n_channels > DUMB_IT_N_CHANNELS) {
_dumb_it_unload_sigdata(sigdata);
return NULL;
}
@ -1095,6 +1097,7 @@ static DUMB_IT_SIGDATA *it_xm_load_sigdata(DUMBFILE *f, int * version)
sigdata->instrument = malloc(sigdata->n_instruments * sizeof(*sigdata->instrument));
if (!sigdata->instrument) {
free(roguebytes);
_dumb_it_unload_sigdata(sigdata);
return NULL;
}

View File

@ -19,6 +19,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>