Updated DUMB.
parent
2f9eb42e24
commit
e3b65daa6e
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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"
|
||||
|
||||
|
||||
|
|
|
@ -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 ); \
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 );
|
||||
|
||||
|
|
|
@ -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 );
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
|
|
Loading…
Reference in New Issue