Updated DUMB.
This commit is contained in:
parent
2f9eb42e24
commit
e3b65daa6e
24 changed files with 960 additions and 463 deletions
|
@ -36,24 +36,24 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#define DUMB_MAJOR_VERSION 0
|
#define DUMB_MAJOR_VERSION 1
|
||||||
#define DUMB_MINOR_VERSION 9
|
#define DUMB_MINOR_VERSION 0
|
||||||
#define DUMB_REVISION_VERSION 3
|
#define DUMB_REVISION_VERSION 0
|
||||||
|
|
||||||
#define DUMB_VERSION (DUMB_MAJOR_VERSION*10000 + DUMB_MINOR_VERSION*100 + DUMB_REVISION_VERSION)
|
#define DUMB_VERSION (DUMB_MAJOR_VERSION*10000 + DUMB_MINOR_VERSION*100 + 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_NAME "DUMB v" DUMB_VERSION_STR
|
||||||
|
|
||||||
#define DUMB_YEAR 2005
|
#define DUMB_YEAR 2015
|
||||||
#define DUMB_MONTH 8
|
#define DUMB_MONTH 1
|
||||||
#define DUMB_DAY 7
|
#define DUMB_DAY 17
|
||||||
|
|
||||||
#define DUMB_YEAR_STR2 "05"
|
#define DUMB_YEAR_STR2 "15"
|
||||||
#define DUMB_YEAR_STR4 "2005"
|
#define DUMB_YEAR_STR4 "2015"
|
||||||
#define DUMB_MONTH_STR1 "8"
|
#define DUMB_MONTH_STR1 "1"
|
||||||
#define DUMB_DAY_STR1 "7"
|
#define DUMB_DAY_STR1 "17"
|
||||||
|
|
||||||
#if DUMB_MONTH < 10
|
#if DUMB_MONTH < 10
|
||||||
#define DUMB_MONTH_STR2 "0" DUMB_MONTH_STR1
|
#define DUMB_MONTH_STR2 "0" DUMB_MONTH_STR1
|
||||||
|
@ -228,6 +228,8 @@ DUH *read_duh(DUMBFILE *f);
|
||||||
long duh_get_length(DUH *duh);
|
long duh_get_length(DUH *duh);
|
||||||
|
|
||||||
const char *duh_get_tag(DUH *duh, const char *key);
|
const char *duh_get_tag(DUH *duh, const char *key);
|
||||||
|
int duh_get_tag_iterator_size(DUH *duh);
|
||||||
|
int duh_get_tag_iterator_get(DUH *duh, const char **key, const char **tag, int i);
|
||||||
|
|
||||||
/* Signal Rendering Functions */
|
/* Signal Rendering Functions */
|
||||||
|
|
||||||
|
@ -317,15 +319,41 @@ void duh_end_sigrenderer(DUH_SIGRENDERER *sigrenderer);
|
||||||
|
|
||||||
/* DUH Rendering Functions */
|
/* 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,
|
DUH_SIGRENDERER *sigrenderer,
|
||||||
|
sample_t ***sig_samples,
|
||||||
|
long *sig_samples_size,
|
||||||
int bits, int unsign,
|
int bits, int unsign,
|
||||||
float volume, float delta,
|
float volume, float delta,
|
||||||
long size, void *sptr
|
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
|
#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(
|
long duh_render_signal(
|
||||||
DUH_SIGRENDERER *sigrenderer,
|
DUH_SIGRENDERER *sigrenderer,
|
||||||
float volume, float delta,
|
float volume, float delta,
|
||||||
|
|
|
@ -18,13 +18,7 @@
|
||||||
#ifndef _V_LPC_H_
|
#ifndef _V_LPC_H_
|
||||||
#define _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;
|
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
|
#endif
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
#define resampler_get_free_count EVALUATE(RESAMPLER_DECORATE,_resampler_get_free_count)
|
#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 EVALUATE(RESAMPLER_DECORATE,_resampler_write_sample)
|
||||||
#define resampler_write_sample_fixed EVALUATE(RESAMPLER_DECORATE,_resampler_write_sample_fixed)
|
#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_set_rate EVALUATE(RESAMPLER_DECORATE,_resampler_set_rate)
|
||||||
#define resampler_ready EVALUATE(RESAMPLER_DECORATE,_resampler_ready)
|
#define resampler_ready EVALUATE(RESAMPLER_DECORATE,_resampler_ready)
|
||||||
#define resampler_clear EVALUATE(RESAMPLER_DECORATE,_resampler_clear)
|
#define resampler_clear EVALUATE(RESAMPLER_DECORATE,_resampler_clear)
|
||||||
|
@ -49,6 +50,7 @@ void resampler_set_quality(void *, int quality);
|
||||||
int resampler_get_free_count(void *);
|
int resampler_get_free_count(void *);
|
||||||
void resampler_write_sample(void *, short sample);
|
void resampler_write_sample(void *, short sample);
|
||||||
void resampler_write_sample_fixed(void *, int sample, unsigned char depth);
|
void resampler_write_sample_fixed(void *, int sample, unsigned char depth);
|
||||||
|
void resampler_write_sample_float(void *, float sample);
|
||||||
void resampler_set_rate( void *, double new_factor );
|
void resampler_set_rate( void *, double new_factor );
|
||||||
int resampler_ready(void *);
|
int resampler_ready(void *);
|
||||||
void resampler_clear(void *);
|
void resampler_clear(void *);
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
/* Copyright (C) 2002-2003 Jean-Marc Valin
|
/* Copyright (C) 2002 Jean-Marc Valin */
|
||||||
Copyright (C) 2007-2009 Xiph.Org Foundation */
|
|
||||||
/**
|
/**
|
||||||
@file stack_alloc.h
|
@file stack_alloc.h
|
||||||
@brief Temporary memory allocation on stack
|
@brief Temporary memory allocation on stack
|
||||||
|
@ -16,11 +15,15 @@
|
||||||
notice, this list of conditions and the following disclaimer in the
|
notice, this list of conditions and the following disclaimer in the
|
||||||
documentation and/or other materials provided with the distribution.
|
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
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
|
||||||
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||||
|
@ -32,11 +35,6 @@
|
||||||
#ifndef STACK_ALLOC_H
|
#ifndef STACK_ALLOC_H
|
||||||
#define 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
|
#ifdef WIN32
|
||||||
# include <malloc.h>
|
# include <malloc.h>
|
||||||
#else
|
#else
|
||||||
|
@ -46,7 +44,6 @@
|
||||||
# include <stdlib.h>
|
# include <stdlib.h>
|
||||||
# endif
|
# endif
|
||||||
#endif
|
#endif
|
||||||
#endif
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @def ALIGN(stack, size)
|
* @def ALIGN(stack, size)
|
||||||
|
@ -85,28 +82,32 @@
|
||||||
* @param type Type of element
|
* @param type Type of element
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#if defined(VAR_ARRAYS)
|
#ifdef ENABLE_VALGRIND
|
||||||
|
|
||||||
#define VARDECL(type, var)
|
#include <valgrind/memcheck.h>
|
||||||
#define ALLOC(var, size, type) type var[size]
|
|
||||||
#define SAVE_STACK
|
|
||||||
#define RESTORE_STACK
|
|
||||||
#define ALLOC_STACK
|
|
||||||
|
|
||||||
#elif defined(USE_ALLOCA)
|
#define ALIGN(stack, size) ((stack) += ((size) - (long)(stack)) & ((size) - 1))
|
||||||
|
|
||||||
#define VARDECL(type, var) type *var
|
#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))))
|
||||||
|
|
||||||
# ifdef WIN32
|
|
||||||
# define ALLOC(var, size, type) var = ((type*)_alloca(sizeof(type)*(size)))
|
|
||||||
#else
|
#else
|
||||||
# define ALLOC(var, size, type) var = ((type*)alloca(sizeof(type)*(size)))
|
|
||||||
|
#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
|
#endif
|
||||||
|
|
||||||
#define SAVE_STACK
|
#if defined(VAR_ARRAYS)
|
||||||
#define RESTORE_STACK
|
#define VARDECL(var)
|
||||||
#define ALLOC_STACK
|
#define ALLOC(var, size, type) type var[size]
|
||||||
|
#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
|
||||||
|
|
||||||
#endif /* VAR_ARRAYS */
|
|
||||||
|
|
||||||
#endif /* STACK_ALLOC_H */
|
#endif
|
||||||
|
|
|
@ -36,3 +36,23 @@ const char *duh_get_tag(DUH *duh, const char *key)
|
||||||
|
|
||||||
return NULL;
|
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
|
#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 */
|
/* DEPRECATED */
|
||||||
|
@ -79,7 +94,7 @@ DUH_SIGRENDERER *duh_start_renderer(DUH *duh, int n_channels, long pos)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* DEPRECATED */
|
||||||
long duh_render(
|
long duh_render(
|
||||||
DUH_SIGRENDERER *sigrenderer,
|
DUH_SIGRENDERER *sigrenderer,
|
||||||
int bits, int unsign,
|
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 */
|
/* DEPRECATED */
|
||||||
int duh_renderer_get_n_channels(DUH_SIGRENDERER *dr)
|
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)
|
int bit_array_test(void * array, size_t bit)
|
||||||
{
|
{
|
||||||
if (array)
|
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)
|
void bit_array_merge(void * dest, void * source, size_t offset)
|
||||||
{
|
{
|
||||||
if (dest && source)
|
if (dest && source)
|
||||||
|
|
|
@ -55,14 +55,12 @@ Carsten Bormann
|
||||||
/* Input : n elements of time doamin data
|
/* Input : n elements of time doamin data
|
||||||
Output: m lpc coefficients, excitation energy */
|
Output: m lpc coefficients, excitation energy */
|
||||||
|
|
||||||
float vorbis_lpc_from_data(float *data,float *lpci,int n,int m){
|
static float vorbis_lpc_from_data(float *data,float *lpci,long n,long m){
|
||||||
VARDECL(double, aut);
|
double *aut=alloca(sizeof(*aut)*(m+1));
|
||||||
VARDECL(double, lpc);
|
double *lpc=alloca(sizeof(*lpc)*(m));
|
||||||
ALLOC(aut, m+1, double);
|
|
||||||
ALLOC(lpc, m, double);
|
|
||||||
double error;
|
double error;
|
||||||
double epsilon;
|
double epsilon;
|
||||||
int i,j;
|
long i,j;
|
||||||
|
|
||||||
/* autocorrelation, p+1 lag coefficients */
|
/* autocorrelation, p+1 lag coefficients */
|
||||||
j=m+1;
|
j=m+1;
|
||||||
|
@ -129,7 +127,7 @@ float vorbis_lpc_from_data(float *data,float *lpci,int n,int m){
|
||||||
return error;
|
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){
|
float *data,long n){
|
||||||
|
|
||||||
/* in: coeff[0...m-1] LPC coefficients
|
/* 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. */
|
/* 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[lpc_order * 2];
|
||||||
float lpc_input[lpc_max * 2];
|
float lpc_input[lpc_max * 2];
|
||||||
float lpc_output[lpc_extra * 2];
|
float lpc_output[lpc_extra * 2];
|
||||||
|
@ -177,11 +175,12 @@ void dumb_it_add_lpc(struct DUMB_IT_SIGDATA *sigdata){
|
||||||
signed char * s8;
|
signed char * s8;
|
||||||
signed short * s16;
|
signed short * s16;
|
||||||
|
|
||||||
int n, o, offset, lpc_samples;
|
long n, o, offset, lpc_samples;
|
||||||
|
|
||||||
for ( n = 0; n < sigdata->n_samples; n++ ) {
|
for ( n = 0; n < sigdata->n_samples; n++ ) {
|
||||||
IT_SAMPLE * sample = sigdata->sample + n;
|
IT_SAMPLE * sample = sigdata->sample + n;
|
||||||
if ( ( sample->flags & ( IT_SAMPLE_EXISTS | IT_SAMPLE_LOOP) ) == IT_SAMPLE_EXISTS ) {
|
if ( ( sample->flags & ( IT_SAMPLE_EXISTS | IT_SAMPLE_LOOP) ) == IT_SAMPLE_EXISTS &&
|
||||||
|
sample->data != NULL ) {
|
||||||
/* If we have enough sample data to train the filter, use the filter to generate the padding */
|
/* If we have enough sample data to train the filter, use the filter to generate the padding */
|
||||||
if ( sample->length >= lpc_order ) {
|
if ( sample->length >= lpc_order ) {
|
||||||
lpc_samples = sample->length;
|
lpc_samples = sample->length;
|
||||||
|
@ -220,6 +219,9 @@ void dumb_it_add_lpc(struct DUMB_IT_SIGDATA *sigdata){
|
||||||
if ( sample->flags & IT_SAMPLE_16BIT )
|
if ( sample->flags & IT_SAMPLE_16BIT )
|
||||||
{
|
{
|
||||||
s16 = ( signed short * ) realloc( sample->data, ( sample->length + lpc_extra ) * 2 * sizeof(short) );
|
s16 = ( signed short * ) realloc( sample->data, ( sample->length + lpc_extra ) * 2 * sizeof(short) );
|
||||||
|
if ( !s16 )
|
||||||
|
return -1;
|
||||||
|
|
||||||
sample->data = s16;
|
sample->data = s16;
|
||||||
|
|
||||||
s16 += sample->length * 2;
|
s16 += sample->length * 2;
|
||||||
|
@ -234,6 +236,9 @@ void dumb_it_add_lpc(struct DUMB_IT_SIGDATA *sigdata){
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
s8 = ( signed char * ) realloc( sample->data, ( sample->length + lpc_extra ) * 2 );
|
s8 = ( signed char * ) realloc( sample->data, ( sample->length + lpc_extra ) * 2 );
|
||||||
|
if ( !s8 )
|
||||||
|
return -1;
|
||||||
|
|
||||||
sample->data = s8;
|
sample->data = s8;
|
||||||
|
|
||||||
s8 += sample->length * 2;
|
s8 += sample->length * 2;
|
||||||
|
@ -274,6 +279,9 @@ void dumb_it_add_lpc(struct DUMB_IT_SIGDATA *sigdata){
|
||||||
if ( sample->flags & IT_SAMPLE_16BIT )
|
if ( sample->flags & IT_SAMPLE_16BIT )
|
||||||
{
|
{
|
||||||
s16 = ( signed short * ) realloc( sample->data, ( sample->length + lpc_extra ) * sizeof(short) );
|
s16 = ( signed short * ) realloc( sample->data, ( sample->length + lpc_extra ) * sizeof(short) );
|
||||||
|
if (!s16)
|
||||||
|
return -1;
|
||||||
|
|
||||||
sample->data = s16;
|
sample->data = s16;
|
||||||
|
|
||||||
s16 += sample->length;
|
s16 += sample->length;
|
||||||
|
@ -287,6 +295,9 @@ void dumb_it_add_lpc(struct DUMB_IT_SIGDATA *sigdata){
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
s8 = ( signed char * ) realloc( sample->data, sample->length + lpc_extra );
|
s8 = ( signed char * ) realloc( sample->data, sample->length + lpc_extra );
|
||||||
|
if ( !s8 )
|
||||||
|
return -1;
|
||||||
|
|
||||||
sample->data = s8;
|
sample->data = s8;
|
||||||
|
|
||||||
s8 += sample->length;
|
s8 += sample->length;
|
||||||
|
@ -302,6 +313,7 @@ void dumb_it_add_lpc(struct DUMB_IT_SIGDATA *sigdata){
|
||||||
else
|
else
|
||||||
/* Otherwise, pad with silence. */
|
/* Otherwise, pad with silence. */
|
||||||
{
|
{
|
||||||
|
void *data;
|
||||||
offset = sample->length;
|
offset = sample->length;
|
||||||
lpc_samples = lpc_extra;
|
lpc_samples = lpc_extra;
|
||||||
|
|
||||||
|
@ -314,9 +326,15 @@ void dumb_it_add_lpc(struct DUMB_IT_SIGDATA *sigdata){
|
||||||
offset *= n;
|
offset *= n;
|
||||||
lpc_samples *= n;
|
lpc_samples *= n;
|
||||||
|
|
||||||
sample->data = realloc( sample->data, offset + lpc_samples );
|
data = realloc( sample->data, offset + lpc_samples );
|
||||||
memset( (char*)sample->data + offset, 0, 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 VOLUME_VARIABLES lvol, lvolr, lvold, lvolt, lvolm, rvol, rvolr, rvold, rvolt, rvolm
|
||||||
#define SET_VOLUME_VARIABLES { \
|
#define SET_VOLUME_VARIABLES { \
|
||||||
if ( volume_left ) { \
|
if ( volume_left ) { \
|
||||||
lvolr = (int)(volume_left->volume * 16777216.0); \
|
lvolr = volume_left->volume; \
|
||||||
lvold = (int)(volume_left->delta * 16777216.0); \
|
lvold = volume_left->delta; \
|
||||||
lvolt = (int)(volume_left->target * 16777216.0); \
|
lvolt = volume_left->target; \
|
||||||
lvolm = (int)(volume_left->mix * 16777216.0); \
|
lvolm = volume_left->mix; \
|
||||||
lvol = MULSCV( lvolr, lvolm ); \
|
lvol = lvolr * lvolm; \
|
||||||
if ( lvolr == lvolt ) volume_left = NULL; \
|
if ( lvolr == lvolt ) volume_left = NULL; \
|
||||||
} else { \
|
} else { \
|
||||||
lvol = 0; \
|
lvol = 0; \
|
||||||
|
@ -118,11 +118,11 @@ static int process_pickup(DUMB_RESAMPLER *resampler)
|
||||||
lvolm = 0; \
|
lvolm = 0; \
|
||||||
} \
|
} \
|
||||||
if ( volume_right ) { \
|
if ( volume_right ) { \
|
||||||
rvolr = (int)(volume_right->volume * 16777216.0); \
|
rvolr = volume_right->volume; \
|
||||||
rvold = (int)(volume_right->delta * 16777216.0); \
|
rvold = volume_right->delta; \
|
||||||
rvolt = (int)(volume_right->target * 16777216.0); \
|
rvolt = volume_right->target; \
|
||||||
rvolm = (int)(volume_right->mix * 16777216.0); \
|
rvolm = volume_right->mix; \
|
||||||
rvol = MULSCV( rvolr, rvolm ); \
|
rvol = rvolr * rvolm; \
|
||||||
if ( rvolr == rvolt ) volume_right = NULL; \
|
if ( rvolr == rvolt ) volume_right = NULL; \
|
||||||
} else { \
|
} else { \
|
||||||
rvol = 0; \
|
rvol = 0; \
|
||||||
|
@ -132,8 +132,8 @@ static int process_pickup(DUMB_RESAMPLER *resampler)
|
||||||
} \
|
} \
|
||||||
}
|
}
|
||||||
#define RETURN_VOLUME_VARIABLES { \
|
#define RETURN_VOLUME_VARIABLES { \
|
||||||
if ( volume_left ) volume_left->volume = (float)lvolr / 16777216.0f; \
|
if ( volume_left ) volume_left->volume = lvolr; \
|
||||||
if ( volume_right ) volume_right->volume = (float)rvolr / 16777216.0f; \
|
if ( volume_right ) volume_right->volume = rvolr; \
|
||||||
}
|
}
|
||||||
#define VOLUMES_ARE_ZERO (lvol == 0 && lvolt == 0 && rvol == 0 && rvolt == 0)
|
#define VOLUMES_ARE_ZERO (lvol == 0 && lvolt == 0 && rvol == 0 && rvolt == 0)
|
||||||
#define PEEK_FIR STEREO_DEST_PEEK_FIR
|
#define PEEK_FIR STEREO_DEST_PEEK_FIR
|
||||||
|
|
|
@ -47,12 +47,11 @@
|
||||||
long dumb_resample(DUMB_RESAMPLER *resampler, sample_t *dst, long dst_size, VOLUME_PARAMETERS, float delta)
|
long dumb_resample(DUMB_RESAMPLER *resampler, sample_t *dst, long dst_size, VOLUME_PARAMETERS, float delta)
|
||||||
{
|
{
|
||||||
int dt, inv_dt;
|
int dt, inv_dt;
|
||||||
int VOLUME_VARIABLES;
|
float VOLUME_VARIABLES;
|
||||||
long done;
|
long done;
|
||||||
long todo;
|
long todo;
|
||||||
LONG_LONG todo64;
|
LONG_LONG todo64;
|
||||||
int quality;
|
int quality;
|
||||||
/*int check;*/
|
|
||||||
|
|
||||||
if (!resampler || resampler->dir == 0) return 0;
|
if (!resampler || resampler->dir == 0) return 0;
|
||||||
ASSERT(resampler->dir == -1 || resampler->dir == 1);
|
ASSERT(resampler->dir == -1 || resampler->dir == 1);
|
||||||
|
@ -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)
|
void dumb_resample_get_current_sample(DUMB_RESAMPLER *resampler, VOLUME_PARAMETERS, sample_t *dst)
|
||||||
{
|
{
|
||||||
int VOLUME_VARIABLES;
|
float VOLUME_VARIABLES;
|
||||||
SRCTYPE *src;
|
SRCTYPE *src;
|
||||||
long pos;
|
long pos;
|
||||||
int subpos;
|
int subpos;
|
||||||
|
|
|
@ -81,7 +81,7 @@
|
||||||
* Values outside the range 0-4 will behave the same as the nearest
|
* Values outside the range 0-4 will behave the same as the nearest
|
||||||
* value within the range.
|
* 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 SUFFIX _16
|
||||||
#define SRCTYPE short
|
#define SRCTYPE short
|
||||||
#define SRCBITS 16
|
#define SRCBITS 16
|
||||||
#define FIR(x) (x)
|
#define FIR(x) (x * (1.0f / 32768.0f))
|
||||||
#include "resample.inc"
|
#include "resample.inc"
|
||||||
|
|
||||||
/* Create resamplers for 8-bit source samples. */
|
/* Create resamplers for 8-bit source samples. */
|
||||||
#define SUFFIX _8
|
#define SUFFIX _8
|
||||||
#define SRCTYPE signed char
|
#define SRCTYPE signed char
|
||||||
#define SRCBITS 8
|
#define SRCBITS 8
|
||||||
#define FIR(x) (x << 8)
|
#define FIR(x) (x * (1.0f / 256.0f))
|
||||||
#include "resample.inc"
|
#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 >= 3) \
|
||||||
pvol->declick_stage++; \
|
pvol->declick_stage++; \
|
||||||
pvol = NULL; \
|
pvol = NULL; \
|
||||||
vol = MULSCV( vol##t, vol##m ); \
|
vol = vol##t * vol##m; \
|
||||||
} else { \
|
} 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 MONO_DEST_VOLUME_ZEROS 0
|
||||||
#define SET_MONO_DEST_VOLUME_VARIABLES { \
|
#define SET_MONO_DEST_VOLUME_VARIABLES { \
|
||||||
if ( volume ) { \
|
if ( volume ) { \
|
||||||
volr = (int)(volume->volume * 16777216.0); \
|
volr = volume->volume; \
|
||||||
vold = (int)(volume->delta * 16777216.0); \
|
vold = volume->delta; \
|
||||||
volt = (int)(volume->target * 16777216.0); \
|
volt = volume->target; \
|
||||||
volm = (int)(volume->mix * 16777216.0); \
|
volm = volume->mix; \
|
||||||
vol = MULSCV( volr, volm ); \
|
vol = volr * volm; \
|
||||||
if ( volr == volt ) volume = NULL; \
|
if ( volr == volt ) volume = NULL; \
|
||||||
} else { \
|
} else { \
|
||||||
vol = 0; \
|
vol = 0; \
|
||||||
|
@ -131,26 +131,26 @@ DUMB_RESAMPLER *dumb_start_resampler(SRCTYPE *src, int src_channels, long pos, l
|
||||||
volm = 0; \
|
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 MONO_DEST_VOLUMES_ARE_ZERO (vol == 0 && volt == 0)
|
||||||
#define POKE_FIR(offset) { \
|
#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 { \
|
#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 ); \
|
UPDATE_VOLUME( volume, vol ); \
|
||||||
}
|
}
|
||||||
#define ADVANCE_FIR resampler_remove_sample( resampler->fir_resampler[0], 1 )
|
#define ADVANCE_FIR resampler_remove_sample( resampler->fir_resampler[0], 1 )
|
||||||
#define STEREO_DEST_PEEK_FIR { \
|
#define STEREO_DEST_PEEK_FIR { \
|
||||||
int sample = resampler_get_sample( resampler->fir_resampler[0] ); \
|
float sample = resampler_get_sample_float( resampler->fir_resampler[0] ); \
|
||||||
*dst++ = MULSC( sample, lvol ); \
|
*dst++ = sample * lvol * 16777216.0f; \
|
||||||
*dst++ = MULSC( sample, rvol ); \
|
*dst++ = sample * rvol * 16777216.0f; \
|
||||||
}
|
}
|
||||||
#define STEREO_DEST_MIX_FIR { \
|
#define STEREO_DEST_MIX_FIR { \
|
||||||
int sample = resampler_get_sample( resampler->fir_resampler[0] ); \
|
float sample = resampler_get_sample_float( resampler->fir_resampler[0] ); \
|
||||||
*dst++ += MULSC( sample, lvol ); \
|
*dst++ += sample * lvol * 16777216.0f; \
|
||||||
*dst++ += MULSC( sample, rvol ); \
|
*dst++ += sample * rvol * 16777216.0f; \
|
||||||
UPDATE_VOLUME( volume_left, lvol ); \
|
UPDATE_VOLUME( volume_left, lvol ); \
|
||||||
UPDATE_VOLUME( volume_right, rvol ); \
|
UPDATE_VOLUME( volume_right, rvol ); \
|
||||||
}
|
}
|
||||||
|
@ -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 MONO_DEST_VOLUME_ZEROS 0, 0
|
||||||
#define SET_MONO_DEST_VOLUME_VARIABLES { \
|
#define SET_MONO_DEST_VOLUME_VARIABLES { \
|
||||||
if ( volume_left ) { \
|
if ( volume_left ) { \
|
||||||
lvolr = (int)(volume_left->volume * 16777216.0); \
|
lvolr = volume_left->volume; \
|
||||||
lvold = (int)(volume_left->delta * 16777216.0); \
|
lvold = volume_left->delta; \
|
||||||
lvolt = (int)(volume_left->target * 16777216.0); \
|
lvolt = volume_left->target; \
|
||||||
lvolm = (int)(volume_left->mix * 16777216.0); \
|
lvolm = volume_left->mix; \
|
||||||
lvol = MULSCV( lvolr, lvolm ); \
|
lvol = lvolr * lvolm; \
|
||||||
if ( lvolr == lvolt ) volume_left = NULL; \
|
if ( lvolr == lvolt ) volume_left = NULL; \
|
||||||
} else { \
|
} else { \
|
||||||
lvol = 0; \
|
lvol = 0; \
|
||||||
|
@ -192,11 +192,11 @@ DUMB_RESAMPLER *dumb_start_resampler(SRCTYPE *src, int src_channels, long pos, l
|
||||||
lvolm = 0; \
|
lvolm = 0; \
|
||||||
} \
|
} \
|
||||||
if ( volume_right ) { \
|
if ( volume_right ) { \
|
||||||
rvolr = (int)(volume_right->volume * 16777216.0); \
|
rvolr = volume_right->volume; \
|
||||||
rvold = (int)(volume_right->delta * 16777216.0); \
|
rvold = volume_right->delta; \
|
||||||
rvolt = (int)(volume_right->target * 16777216.0); \
|
rvolt = volume_right->target; \
|
||||||
rvolm = (int)(volume_right->mix * 16777216.0); \
|
rvolm = volume_right->mix; \
|
||||||
rvol = MULSCV( rvolr, rvolm ); \
|
rvol = rvolr * rvolm; \
|
||||||
if ( rvolr == rvolt ) volume_right = NULL; \
|
if ( rvolr == rvolt ) volume_right = NULL; \
|
||||||
} else { \
|
} else { \
|
||||||
rvol = 0; \
|
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 { \
|
#define RETURN_MONO_DEST_VOLUME_VARIABLES { \
|
||||||
if ( volume_left ) volume_left->volume = (float)lvolr / 16777216.0f; \
|
if ( volume_left ) volume_left->volume = lvolr; \
|
||||||
if ( volume_right ) volume_right->volume = (float)rvolr / 16777216.0f; \
|
if ( volume_right ) volume_right->volume = rvolr; \
|
||||||
}
|
}
|
||||||
#define MONO_DEST_VOLUMES_ARE_ZERO (lvol == 0 && lvolt == 0 && rvol == 0 && rvolt == 0)
|
#define MONO_DEST_VOLUMES_ARE_ZERO (lvol == 0 && lvolt == 0 && rvol == 0 && rvolt == 0)
|
||||||
#define POKE_FIR(offset) { \
|
#define POKE_FIR(offset) { \
|
||||||
resampler_write_sample( resampler->fir_resampler[0], FIR(x[(offset)*2+0]) ); \
|
resampler_write_sample_float( 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[1], FIR(x[(offset)*2+1]) ); \
|
||||||
}
|
}
|
||||||
#define MONO_DEST_PEEK_FIR { \
|
#define MONO_DEST_PEEK_FIR { \
|
||||||
*dst = MULSC( resampler_get_sample( resampler->fir_resampler[0] ), lvol ) + \
|
*dst = (resampler_get_sample_float( resampler->fir_resampler[0] ) * lvol + \
|
||||||
MULSC( resampler_get_sample( resampler->fir_resampler[1] ), rvol ); \
|
resampler_get_sample_float( resampler->fir_resampler[1] ) * rvol) * 16777216.0f; \
|
||||||
}
|
}
|
||||||
#define MONO_DEST_MIX_FIR { \
|
#define MONO_DEST_MIX_FIR { \
|
||||||
*dst++ += MULSC( resampler_get_sample( resampler->fir_resampler[0] ), lvol ) + \
|
*dst++ += (resampler_get_sample_float( resampler->fir_resampler[0] ) * lvol + \
|
||||||
MULSC( resampler_get_sample( resampler->fir_resampler[1] ), rvol ); \
|
resampler_get_sample_float( resampler->fir_resampler[1] ) * rvol) * 16777216.0f; \
|
||||||
UPDATE_VOLUME( volume_left, lvol ); \
|
UPDATE_VOLUME( volume_left, lvol ); \
|
||||||
UPDATE_VOLUME( volume_right, rvol ); \
|
UPDATE_VOLUME( volume_right, rvol ); \
|
||||||
}
|
}
|
||||||
|
@ -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 ); \
|
resampler_remove_sample( resampler->fir_resampler[1], 1 ); \
|
||||||
}
|
}
|
||||||
#define STEREO_DEST_PEEK_FIR { \
|
#define STEREO_DEST_PEEK_FIR { \
|
||||||
*dst++ = MULSC( resampler_get_sample( resampler->fir_resampler[0] ), lvol ); \
|
*dst++ = resampler_get_sample_float( resampler->fir_resampler[0] ) * lvol * 16777216.0f; \
|
||||||
*dst++ = MULSC( resampler_get_sample( resampler->fir_resampler[1] ), rvol ); \
|
*dst++ = resampler_get_sample_float( resampler->fir_resampler[1] ) * rvol * 16777216.0f; \
|
||||||
}
|
}
|
||||||
#define STEREO_DEST_MIX_FIR { \
|
#define STEREO_DEST_MIX_FIR { \
|
||||||
*dst++ += MULSC( resampler_get_sample( resampler->fir_resampler[0] ), lvol ); \
|
*dst++ += resampler_get_sample_float( resampler->fir_resampler[0] ) * lvol * 16777216.0f; \
|
||||||
*dst++ += MULSC( resampler_get_sample( resampler->fir_resampler[1] ), rvol ); \
|
*dst++ += resampler_get_sample_float( resampler->fir_resampler[1] ) * rvol * 16777216.0f; \
|
||||||
UPDATE_VOLUME( volume_left, lvol ); \
|
UPDATE_VOLUME( volume_left, lvol ); \
|
||||||
UPDATE_VOLUME( volume_right, rvol ); \
|
UPDATE_VOLUME( volume_right, rvol ); \
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#define _USE_MATH_DEFINES
|
#define _USE_MATH_DEFINES
|
||||||
#include <math.h>
|
#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>
|
#include <xmmintrin.h>
|
||||||
#define RESAMPLER_SSE
|
#define RESAMPLER_SSE
|
||||||
#endif
|
#endif
|
||||||
|
@ -11,6 +11,8 @@
|
||||||
#if TARGET_CPU_ARM || TARGET_CPU_ARM64
|
#if TARGET_CPU_ARM || TARGET_CPU_ARM64
|
||||||
#define RESAMPLER_NEON
|
#define RESAMPLER_NEON
|
||||||
#endif
|
#endif
|
||||||
|
#elif (defined(__arm__) && defined(__ARM_NEON__))
|
||||||
|
#define RESAMPLER_NEON
|
||||||
#endif
|
#endif
|
||||||
#ifdef RESAMPLER_NEON
|
#ifdef RESAMPLER_NEON
|
||||||
#include <arm_neon.h>
|
#include <arm_neon.h>
|
||||||
|
@ -35,9 +37,9 @@ enum { RESAMPLER_RESOLUTION_EXTRA = 1 << (RESAMPLER_SHIFT + RESAMPLER_SHIFT_EXTR
|
||||||
enum { SINC_WIDTH = 16 };
|
enum { SINC_WIDTH = 16 };
|
||||||
enum { SINC_SAMPLES = RESAMPLER_RESOLUTION * SINC_WIDTH };
|
enum { SINC_SAMPLES = RESAMPLER_RESOLUTION * SINC_WIDTH };
|
||||||
enum { CUBIC_SAMPLES = RESAMPLER_RESOLUTION * 4 };
|
enum { CUBIC_SAMPLES = RESAMPLER_RESOLUTION * 4 };
|
||||||
enum { IIR_ORDER = 6 };
|
|
||||||
|
|
||||||
static const float RESAMPLER_BLEP_CUTOFF = 0.90f;
|
static const float RESAMPLER_BLEP_CUTOFF = 0.90f;
|
||||||
|
static const float RESAMPLER_BLAM_CUTOFF = 0.93f;
|
||||||
static const float RESAMPLER_SINC_CUTOFF = 0.999f;
|
static const float RESAMPLER_SINC_CUTOFF = 0.999f;
|
||||||
|
|
||||||
ALIGNED static float cubic_lut[CUBIC_SAMPLES];
|
ALIGNED static float cubic_lut[CUBIC_SAMPLES];
|
||||||
|
@ -138,54 +140,6 @@ void resampler_init(void)
|
||||||
#endif
|
#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
|
typedef struct resampler
|
||||||
{
|
{
|
||||||
int write_pos, write_filled;
|
int write_pos, write_filled;
|
||||||
|
@ -197,12 +151,10 @@ typedef struct resampler
|
||||||
unsigned char quality;
|
unsigned char quality;
|
||||||
signed char delay_added;
|
signed char delay_added;
|
||||||
signed char delay_removed;
|
signed char delay_removed;
|
||||||
unsigned char output_stage;
|
|
||||||
float last_amp;
|
float last_amp;
|
||||||
float accumulator;
|
float accumulator;
|
||||||
float buffer_in[resampler_buffer_size * 2];
|
float buffer_in[resampler_buffer_size * 2];
|
||||||
float buffer_out[resampler_buffer_size + SINC_WIDTH * 2 - 1];
|
float buffer_out[resampler_buffer_size + SINC_WIDTH * 2 - 1];
|
||||||
iir filter[IIR_ORDER / 2];
|
|
||||||
} resampler;
|
} resampler;
|
||||||
|
|
||||||
void * resampler_create(void)
|
void * resampler_create(void)
|
||||||
|
@ -221,12 +173,10 @@ void * resampler_create(void)
|
||||||
r->quality = RESAMPLER_QUALITY_MAX;
|
r->quality = RESAMPLER_QUALITY_MAX;
|
||||||
r->delay_added = -1;
|
r->delay_added = -1;
|
||||||
r->delay_removed = -1;
|
r->delay_removed = -1;
|
||||||
r->output_stage = 0;
|
|
||||||
r->last_amp = 0;
|
r->last_amp = 0;
|
||||||
r->accumulator = 0;
|
r->accumulator = 0;
|
||||||
memset( r->buffer_in, 0, sizeof(r->buffer_in) );
|
memset( r->buffer_in, 0, sizeof(r->buffer_in) );
|
||||||
memset( r->buffer_out, 0, sizeof(r->buffer_out) );
|
memset( r->buffer_out, 0, sizeof(r->buffer_out) );
|
||||||
memset( r->filter, 0, sizeof(r->filter) );
|
|
||||||
|
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
@ -262,12 +212,10 @@ void resampler_dup_inplace(void *_d, const void *_s)
|
||||||
r_out->quality = r_in->quality;
|
r_out->quality = r_in->quality;
|
||||||
r_out->delay_added = r_in->delay_added;
|
r_out->delay_added = r_in->delay_added;
|
||||||
r_out->delay_removed = r_in->delay_removed;
|
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->last_amp = r_in->last_amp;
|
||||||
r_out->accumulator = r_in->accumulator;
|
r_out->accumulator = r_in->accumulator;
|
||||||
memcpy( r_out->buffer_in, r_in->buffer_in, sizeof(r_in->buffer_in) );
|
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->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)
|
void resampler_set_quality(void *_r, int quality)
|
||||||
|
@ -279,7 +227,8 @@ void resampler_set_quality(void *_r, int quality)
|
||||||
quality = RESAMPLER_QUALITY_MAX;
|
quality = RESAMPLER_QUALITY_MAX;
|
||||||
if ( r->quality != quality )
|
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_pos = 0;
|
||||||
r->read_filled = 0;
|
r->read_filled = 0;
|
||||||
|
@ -289,8 +238,6 @@ void resampler_set_quality(void *_r, int quality)
|
||||||
}
|
}
|
||||||
r->delay_added = -1;
|
r->delay_added = -1;
|
||||||
r->delay_removed = -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;
|
r->quality = (unsigned char)quality;
|
||||||
}
|
}
|
||||||
|
@ -348,21 +295,16 @@ static int resampler_output_delay(resampler *r)
|
||||||
default:
|
default:
|
||||||
case RESAMPLER_QUALITY_ZOH:
|
case RESAMPLER_QUALITY_ZOH:
|
||||||
case RESAMPLER_QUALITY_LINEAR:
|
case RESAMPLER_QUALITY_LINEAR:
|
||||||
case RESAMPLER_QUALITY_BLAM:
|
|
||||||
case RESAMPLER_QUALITY_CUBIC:
|
case RESAMPLER_QUALITY_CUBIC:
|
||||||
case RESAMPLER_QUALITY_SINC:
|
case RESAMPLER_QUALITY_SINC:
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
case RESAMPLER_QUALITY_BLEP:
|
case RESAMPLER_QUALITY_BLEP:
|
||||||
|
case RESAMPLER_QUALITY_BLAM:
|
||||||
return SINC_WIDTH - 1;
|
return SINC_WIDTH - 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int resampler_get_padding_size()
|
|
||||||
{
|
|
||||||
return SINC_WIDTH - 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int resampler_ready(void *_r)
|
int resampler_ready(void *_r)
|
||||||
{
|
{
|
||||||
resampler * r = ( resampler * ) _r;
|
resampler * r = ( resampler * ) _r;
|
||||||
|
@ -381,48 +323,21 @@ void resampler_clear(void *_r)
|
||||||
r->delay_removed = -1;
|
r->delay_removed = -1;
|
||||||
memset(r->buffer_in, 0, (SINC_WIDTH - 1) * sizeof(r->buffer_in[0]));
|
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]));
|
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->inv_phase = 0;
|
||||||
r->last_amp = 0;
|
r->last_amp = 0;
|
||||||
r->accumulator = 0;
|
r->accumulator = 0;
|
||||||
memset(r->buffer_out, 0, sizeof(r->buffer_out));
|
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)
|
void resampler_set_rate(void *_r, double new_factor)
|
||||||
{
|
{
|
||||||
resampler * r = ( resampler * ) _r;
|
resampler * r = ( resampler * ) _r;
|
||||||
float old_phase_inc = r->phase_inc;
|
|
||||||
r->phase_inc = new_factor;
|
r->phase_inc = new_factor;
|
||||||
new_factor = 1.0 / new_factor;
|
new_factor = 1.0 / new_factor;
|
||||||
r->inv_phase_inc = 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)
|
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 )
|
if ( r->write_filled < resampler_buffer_size )
|
||||||
{
|
{
|
||||||
double s32 = s;
|
float s32 = s;
|
||||||
s32 *= 256.0;
|
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 ] = s32;
|
||||||
r->buffer_in[ r->write_pos + resampler_buffer_size ] = s32;
|
r->buffer_in[ r->write_pos + resampler_buffer_size ] = s32;
|
||||||
|
@ -469,16 +376,8 @@ void resampler_write_sample_fixed(void *_r, int s, unsigned char depth)
|
||||||
|
|
||||||
if ( r->write_filled < resampler_buffer_size )
|
if ( r->write_filled < resampler_buffer_size )
|
||||||
{
|
{
|
||||||
double s32 = s;
|
float s32 = s;
|
||||||
s32 /= (double)(1 << (depth - 1));
|
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 ] = s32;
|
||||||
r->buffer_in[ r->write_pos + resampler_buffer_size ] = 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)
|
static int resampler_run_zoh(resampler * r, float ** out_, float * out_end)
|
||||||
{
|
{
|
||||||
int in_size = r->write_filled;
|
int in_size = r->write_filled;
|
||||||
|
@ -800,11 +720,11 @@ static int resampler_run_linear(resampler * r, float ** out_, float * out_end)
|
||||||
return used;
|
return used;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef RESAMPLER_NEON
|
||||||
static int resampler_run_blam(resampler * r, float ** out_, float * out_end)
|
static int resampler_run_blam(resampler * r, float ** out_, float * out_end)
|
||||||
{
|
{
|
||||||
int in_size = r->write_filled;
|
int in_size = r->write_filled;
|
||||||
float const* in_ = r->buffer_in + resampler_buffer_size + r->write_pos - 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;
|
int used = 0;
|
||||||
in_size -= 2;
|
in_size -= 2;
|
||||||
if ( in_size > 0 )
|
if ( in_size > 0 )
|
||||||
|
@ -812,36 +732,66 @@ static int resampler_run_blam(resampler * r, float ** out_, float * out_end)
|
||||||
float* out = *out_;
|
float* out = *out_;
|
||||||
float const* in = in_;
|
float const* in = in_;
|
||||||
float const* const in_end = in + in_size;
|
float const* const in_end = in + in_size;
|
||||||
|
float last_amp = r->last_amp;
|
||||||
float phase = r->phase;
|
float phase = r->phase;
|
||||||
float phase_inc = r->phase_inc;
|
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
|
do
|
||||||
{
|
{
|
||||||
float sample;
|
float sample;
|
||||||
|
|
||||||
if ( out >= out_end )
|
if ( out + SINC_WIDTH * 2 > out_end )
|
||||||
break;
|
break;
|
||||||
|
|
||||||
sample = in[0] + (in[1] - in[0]) * phase;
|
sample = in[0];
|
||||||
|
if (phase_inc < 1.0f)
|
||||||
|
sample += (in[1] - in[0]) * phase;
|
||||||
|
sample -= last_amp;
|
||||||
|
|
||||||
if ( output_stage )
|
if (sample)
|
||||||
{
|
{
|
||||||
unsigned int i, j;
|
float kernel[SINC_WIDTH * 2], kernel_sum = 0.0f;
|
||||||
for (i = 0, j = IIR_ORDER / 2; i < j; ++i)
|
int phase_reduced = (int)(inv_phase * RESAMPLER_RESOLUTION);
|
||||||
sample = iir_process(r->filter + i, sample);
|
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 += 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];
|
||||||
}
|
}
|
||||||
|
|
||||||
*out++ = sample;
|
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;
|
phase += phase_inc;
|
||||||
|
++out;
|
||||||
in += (int)phase;
|
in += (int)phase;
|
||||||
|
|
||||||
phase = fmod(phase, 1.0f);
|
phase = fmod(phase, 1.0f);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
while ( in < in_end );
|
while ( in < in_end );
|
||||||
|
|
||||||
r->phase = phase;
|
r->phase = phase;
|
||||||
|
r->inv_phase = inv_phase;
|
||||||
|
r->last_amp = last_amp;
|
||||||
*out_ = out;
|
*out_ = out;
|
||||||
|
|
||||||
used = (int)(in - in_);
|
used = (int)(in - in_);
|
||||||
|
@ -851,6 +801,204 @@ static int resampler_run_blam(resampler * r, float ** out_, float * out_end)
|
||||||
|
|
||||||
return used;
|
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
|
#ifndef RESAMPLER_NEON
|
||||||
static int resampler_run_cubic(resampler * r, float ** out_, float * out_end)
|
static int resampler_run_cubic(resampler * r, float ** out_, float * out_end)
|
||||||
|
@ -1257,8 +1405,25 @@ static void resampler_fill(resampler * r)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case RESAMPLER_QUALITY_BLAM:
|
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;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case RESAMPLER_QUALITY_CUBIC:
|
case RESAMPLER_QUALITY_CUBIC:
|
||||||
#ifdef RESAMPLER_SSE
|
#ifdef RESAMPLER_SSE
|
||||||
|
@ -1297,7 +1462,7 @@ static void resampler_fill_and_remove_delay(resampler * r)
|
||||||
int resampler_get_sample_count(void *_r)
|
int resampler_get_sample_count(void *_r)
|
||||||
{
|
{
|
||||||
resampler * r = ( resampler * ) _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 );
|
resampler_fill_and_remove_delay( r );
|
||||||
return r->read_filled;
|
return r->read_filled;
|
||||||
}
|
}
|
||||||
|
@ -1309,7 +1474,7 @@ int resampler_get_sample(void *_r)
|
||||||
resampler_fill_and_remove_delay( r );
|
resampler_fill_and_remove_delay( r );
|
||||||
if ( r->read_filled < 1 )
|
if ( r->read_filled < 1 )
|
||||||
return 0;
|
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);
|
return (int)(r->buffer_out[ r->read_pos ] + r->accumulator);
|
||||||
else
|
else
|
||||||
return (int)r->buffer_out[ r->read_pos ];
|
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 );
|
resampler_fill_and_remove_delay( r );
|
||||||
if ( r->read_filled < 1 )
|
if ( r->read_filled < 1 )
|
||||||
return 0;
|
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;
|
return r->buffer_out[ r->read_pos ] + r->accumulator;
|
||||||
else
|
else
|
||||||
return r->buffer_out[ r->read_pos ];
|
return r->buffer_out[ r->read_pos ];
|
||||||
|
@ -1333,7 +1498,7 @@ void resampler_remove_sample(void *_r, int decay)
|
||||||
resampler * r = ( resampler * ) _r;
|
resampler * r = ( resampler * ) _r;
|
||||||
if ( r->read_filled > 0 )
|
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->accumulator += r->buffer_out[ r->read_pos ];
|
||||||
r->buffer_out[ r->read_pos ] = 0;
|
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) );
|
dumb_stdfile * file = ( dumb_stdfile * ) malloc( sizeof(dumb_stdfile) );
|
||||||
if ( !file ) return 0;
|
if ( !file ) return 0;
|
||||||
file->file = fopen(filename, "rb");
|
file->file = fopen(filename, "rb");
|
||||||
|
if ( !file->file )
|
||||||
|
{
|
||||||
|
free( file );
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
fseek(file->file, 0, SEEK_END);
|
fseek(file->file, 0, SEEK_END);
|
||||||
file->size = ftell(file->file);
|
file->size = ftell(file->file);
|
||||||
fseek(file->file, 0, SEEK_SET);
|
fseek(file->file, 0, SEEK_SET);
|
||||||
|
|
|
@ -28,7 +28,7 @@
|
||||||
#endif
|
#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->flags = dumbfile_getc(f);
|
||||||
envelope->n_nodes = 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_start = dumbfile_getc(f);
|
||||||
envelope->loop_end = dumbfile_getc(f);
|
envelope->loop_end = dumbfile_getc(f);
|
||||||
envelope->sus_loop_start = dumbfile_getc(f);
|
envelope->sus_loop_start = dumbfile_getc(f);
|
||||||
envelope->sus_loop_end = 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++) {
|
for (n = 0; n < envelope->n_nodes; n++) {
|
||||||
envelope->node_y[n] = dumbfile_getc(f);
|
envelope->node_y[n] = dumbfile_getc(f);
|
||||||
envelope->node_t[n] = dumbfile_igetw(f);
|
envelope->node_t[n] = dumbfile_igetw(f);
|
||||||
|
@ -838,31 +841,46 @@ static int it_read_pattern(IT_PATTERN *pattern, DUMBFILE *f, unsigned char *buff
|
||||||
|
|
||||||
channel = (b - 1) & 63;
|
channel = (b - 1) & 63;
|
||||||
|
|
||||||
if (b & 128)
|
if (b & 128) {
|
||||||
|
if (bufpos >= buflen)
|
||||||
|
return -1;
|
||||||
|
|
||||||
cmask[channel] = mask = buffer[bufpos++];
|
cmask[channel] = mask = buffer[bufpos++];
|
||||||
else
|
} else
|
||||||
mask = cmask[channel];
|
mask = cmask[channel];
|
||||||
|
|
||||||
if (mask) {
|
if (mask) {
|
||||||
entry->mask = (mask & 15) | (mask >> 4);
|
entry->mask = (mask & 15) | (mask >> 4);
|
||||||
entry->channel = channel;
|
entry->channel = channel;
|
||||||
|
|
||||||
if (mask & IT_ENTRY_NOTE)
|
if (mask & IT_ENTRY_NOTE) {
|
||||||
|
if (bufpos >= buflen)
|
||||||
|
return -1;
|
||||||
|
|
||||||
cnote[channel] = entry->note = buffer[bufpos++];
|
cnote[channel] = entry->note = buffer[bufpos++];
|
||||||
else if (mask & (IT_ENTRY_NOTE << 4))
|
} else if (mask & (IT_ENTRY_NOTE << 4))
|
||||||
entry->note = cnote[channel];
|
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++];
|
cinstrument[channel] = entry->instrument = buffer[bufpos++];
|
||||||
else if (mask & (IT_ENTRY_INSTRUMENT << 4))
|
} else if (mask & (IT_ENTRY_INSTRUMENT << 4))
|
||||||
entry->instrument = cinstrument[channel];
|
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++];
|
cvolpan[channel] = entry->volpan = buffer[bufpos++];
|
||||||
else if (mask & (IT_ENTRY_VOLPAN << 4))
|
} else if (mask & (IT_ENTRY_VOLPAN << 4))
|
||||||
entry->volpan = cvolpan[channel];
|
entry->volpan = cvolpan[channel];
|
||||||
|
|
||||||
if (mask & IT_ENTRY_EFFECT) {
|
if (mask & IT_ENTRY_EFFECT) {
|
||||||
|
if (bufpos + 1 >= buflen)
|
||||||
|
return -1;
|
||||||
|
|
||||||
ceffect[channel] = entry->effect = buffer[bufpos++];
|
ceffect[channel] = entry->effect = buffer[bufpos++];
|
||||||
ceffectvalue[channel] = entry->effectvalue = buffer[bufpos++];
|
ceffectvalue[channel] = entry->effectvalue = buffer[bufpos++];
|
||||||
} else {
|
} else {
|
||||||
|
@ -940,6 +958,7 @@ static sigdata_t *it_load_sigdata(DUMBFILE *f)
|
||||||
int message_length, message_offset;
|
int message_length, message_offset;
|
||||||
|
|
||||||
IT_COMPONENT *component;
|
IT_COMPONENT *component;
|
||||||
|
int min_components;
|
||||||
int n_components = 0;
|
int n_components = 0;
|
||||||
|
|
||||||
unsigned char sample_convert[4096];
|
unsigned char sample_convert[4096];
|
||||||
|
@ -1044,10 +1063,15 @@ static sigdata_t *it_load_sigdata(DUMBFILE *f)
|
||||||
sigdata->pattern[n].entry = NULL;
|
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;
|
sigdata->restart_position = 0;
|
||||||
|
|
||||||
component = malloc(769 * sizeof(*component));
|
min_components = (special & 1) + sigdata->n_instruments + sigdata->n_samples + sigdata->n_patterns;
|
||||||
|
|
||||||
|
component = malloc(min_components * sizeof(*component));
|
||||||
if (!component) {
|
if (!component) {
|
||||||
_dumb_it_unload_sigdata(sigdata);
|
_dumb_it_unload_sigdata(sigdata);
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -1236,7 +1260,7 @@ static sigdata_t *it_load_sigdata(DUMBFILE *f)
|
||||||
switch (component[n].type) {
|
switch (component[n].type) {
|
||||||
|
|
||||||
case IT_COMPONENT_SONG_MESSAGE:
|
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) );
|
message_length = min( message_length, (int)(component[n+1].offset - component[n].offset) );
|
||||||
}
|
}
|
||||||
sigdata->song_message = malloc(message_length + 1);
|
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--;
|
channel->note_delay_count--;
|
||||||
if (channel->note_delay_count == 0)
|
if (channel->note_delay_count == 0)
|
||||||
process_note_data(sigrenderer, channel->note_delay_entry, 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;
|
tick = 0;
|
||||||
else
|
else
|
||||||
++tick;
|
++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]]);
|
playing->delta *= (float)pow(DUMB_SEMITONE_BASE, channel->arpeggio_offsets[channel->arpeggio_table[tick&31]]);
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
|
@ -4300,6 +4302,9 @@ static int process_tick(DUMB_IT_SIGRENDERER *sigrenderer)
|
||||||
{
|
{
|
||||||
DUMB_IT_SIGDATA *sigdata = sigrenderer->sigdata;
|
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
|
// Set note vol/freq to vol/freq set for each channel
|
||||||
|
|
||||||
if (sigrenderer->speed && --sigrenderer->tick == 0) {
|
if (sigrenderer->speed && --sigrenderer->tick == 0) {
|
||||||
|
@ -4440,8 +4445,13 @@ static int process_tick(DUMB_IT_SIGRENDERER *sigrenderer)
|
||||||
|
|
||||||
/** WARNING - everything pertaining to a new pattern initialised? */
|
/** WARNING - everything pertaining to a new pattern initialised? */
|
||||||
|
|
||||||
|
if ( pattern->entry ) {
|
||||||
sigrenderer->entry = sigrenderer->entry_start = pattern->entry;
|
sigrenderer->entry = sigrenderer->entry_start = pattern->entry;
|
||||||
sigrenderer->entry_end = sigrenderer->entry + pattern->n_entries;
|
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. */
|
/* 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 */
|
/* 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))
|
if (!(sigdata->flags & IT_WAS_A_669))
|
||||||
reset_effects(sigrenderer);
|
reset_effects(sigrenderer);
|
||||||
|
|
||||||
|
if ( sigrenderer->entry )
|
||||||
{
|
{
|
||||||
IT_ENTRY *entry = sigrenderer->entry;
|
IT_ENTRY *entry = sigrenderer->entry;
|
||||||
int ignore_cxx = 0;
|
int ignore_cxx = 0;
|
||||||
|
@ -4525,6 +4536,7 @@ static int process_tick(DUMB_IT_SIGRENDERER *sigrenderer)
|
||||||
else if (!(sigdata->flags & IT_OLD_EFFECTS))
|
else if (!(sigdata->flags & IT_OLD_EFFECTS))
|
||||||
update_smooth_effects(sigrenderer);
|
update_smooth_effects(sigrenderer);
|
||||||
} else {
|
} else {
|
||||||
|
if ( sigrenderer->entry )
|
||||||
{
|
{
|
||||||
IT_ENTRY *entry = 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_speed = 0;
|
||||||
channel->inv_loop_offset = 0;
|
channel->inv_loop_offset = 0;
|
||||||
channel->playing = NULL;
|
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
|
#ifdef BIT_ARRAY_BULLSHIT
|
||||||
channel->played_patjump = NULL;
|
channel->played_patjump = NULL;
|
||||||
channel->played_patjump_order = 0xFFFE;
|
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;
|
//sigrenderer->max_output = 0;
|
||||||
|
|
||||||
if ( !(sigdata->flags & IT_WAS_PROCESSED) ) {
|
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;
|
sigdata->flags |= IT_WAS_PROCESSED;
|
||||||
}
|
}
|
||||||
|
@ -5597,6 +5616,8 @@ static long it_sigrenderer_get_samples(
|
||||||
|
|
||||||
if (sigrenderer->order < 0) return 0; // problematic
|
if (sigrenderer->order < 0) return 0; // problematic
|
||||||
|
|
||||||
|
if (!sigrenderer->tempo) return 0; // also problematic
|
||||||
|
|
||||||
pos = 0;
|
pos = 0;
|
||||||
dt = (int)(delta * 65536.0f + 0.5f);
|
dt = (int)(delta * 65536.0f + 0.5f);
|
||||||
|
|
||||||
|
|
|
@ -261,6 +261,9 @@ static int it_amf_read_sample_data( IT_SAMPLE *sample, DUMBFILE *f )
|
||||||
if ( sample->length )
|
if ( sample->length )
|
||||||
read_length = (int)dumbfile_getnc( sample->data, sample->length, f );
|
read_length = (int)dumbfile_getnc( sample->data, sample->length, f );
|
||||||
|
|
||||||
|
if ( read_length < 0 )
|
||||||
|
read_length = 0;
|
||||||
|
|
||||||
for ( i = 0; i < read_length; i++ ) {
|
for ( i = 0; i < read_length; i++ ) {
|
||||||
( ( signed char * ) sample->data )[ i ] ^= 0x80;
|
( ( signed char * ) sample->data )[ i ] ^= 0x80;
|
||||||
}
|
}
|
||||||
|
@ -321,6 +324,8 @@ static DUMB_IT_SIGDATA *it_amf_load_sigdata(DUMBFILE *f, int * version)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sigdata->n_pchannels = nchannels;
|
||||||
|
|
||||||
memset( sigdata->channel_volume, 64, DUMB_IT_N_CHANNELS );
|
memset( sigdata->channel_volume, 64, DUMB_IT_N_CHANNELS );
|
||||||
|
|
||||||
if ( ver >= 11 ) {
|
if ( ver >= 11 ) {
|
||||||
|
|
|
@ -39,7 +39,7 @@ DUH *dumb_read_any_quick(DUMBFILE *f, int restrict_, int subsong)
|
||||||
unsigned long signature_size;
|
unsigned long signature_size;
|
||||||
DUH * duh = NULL;
|
DUH * duh = NULL;
|
||||||
|
|
||||||
signature_size = dumbfile_get_size(f);
|
/* signature_size = dumbfile_get_size(f); */
|
||||||
|
|
||||||
signature_size = dumbfile_getnc( (char *)signature, maximum_signature_size, f );
|
signature_size = dumbfile_getnc( (char *)signature, maximum_signature_size, f );
|
||||||
dumbfile_seek( f, 0, DFS_SEEK_SET );
|
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;
|
int finetune, loop_start, loop_length;
|
||||||
|
|
||||||
|
@ -137,6 +137,9 @@ assumed not to be an instrument name, and is probably a message.
|
||||||
sample->filename[0] = 0;
|
sample->filename[0] = 0;
|
||||||
|
|
||||||
sample->length = dumbfile_mgetw(f) << 1;
|
sample->length = dumbfile_mgetw(f) << 1;
|
||||||
|
if (fft == DUMB_ID('F','E','S','T'))
|
||||||
|
finetune = (signed char)((-dumbfile_getc(f) & 0x1F) << 3) >> 3;
|
||||||
|
else
|
||||||
finetune = (signed char)(dumbfile_getc(f) << 4) >> 4; /* signed nibble */
|
finetune = (signed char)(dumbfile_getc(f) << 4) >> 4; /* signed nibble */
|
||||||
/** Each finetune step changes the note 1/8th of a semitone. */
|
/** Each finetune step changes the note 1/8th of a semitone. */
|
||||||
sample->global_volume = 64;
|
sample->global_volume = 64;
|
||||||
|
@ -166,7 +169,7 @@ told to stop.
|
||||||
|
|
||||||
sample->default_pan = 0;
|
sample->default_pan = 0;
|
||||||
sample->C5_speed = (int)( AMIGA_CLOCK / 214.0 ); //(long)(16726.0*pow(DUMB_PITCH_BASE, finetune*32));
|
sample->C5_speed = (int)( AMIGA_CLOCK / 214.0 ); //(long)(16726.0*pow(DUMB_PITCH_BASE, finetune*32));
|
||||||
sample->finetune = finetune * 32;
|
sample->finetune = finetune * ((fft == DUMB_ID('F','E','S','T')) ? 16 : 32);
|
||||||
// the above line might be wrong
|
// the above line might be wrong
|
||||||
|
|
||||||
if (sample->loop_end > sample->length)
|
if (sample->loop_end > sample->length)
|
||||||
|
@ -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('F','L','T','4'):
|
||||||
case DUMB_ID('M',0,0,0):
|
case DUMB_ID('M',0,0,0):
|
||||||
case DUMB_ID('8',0,0,0):
|
case DUMB_ID('8',0,0,0):
|
||||||
|
case DUMB_ID('F','E','S','T'):
|
||||||
n_channels = 4;
|
n_channels = 4;
|
||||||
break;
|
break;
|
||||||
case DUMB_ID('F','L','T','8'):
|
case DUMB_ID('F','L','T','8'):
|
||||||
|
@ -381,6 +385,7 @@ static DUMB_IT_SIGDATA *it_mod_load_sigdata(DUMBFILE *f, int restrict_)
|
||||||
} else {
|
} else {
|
||||||
n_channels = 4;
|
n_channels = 4;
|
||||||
sigdata->n_samples = 15;
|
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;
|
sigdata->sample[i].data = NULL;
|
||||||
|
|
||||||
for (i = 0; i < sigdata->n_samples; i++) {
|
for (i = 0; i < sigdata->n_samples; i++) {
|
||||||
if (it_mod_read_sample_header(&sigdata->sample[i], f, sigdata->n_samples == 15)) {
|
if (it_mod_read_sample_header(&sigdata->sample[i], f, fft, sigdata->n_samples == 15)) {
|
||||||
_dumb_it_unload_sigdata(sigdata);
|
_dumb_it_unload_sigdata(sigdata);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,7 +30,7 @@ size_t strlen_max(const char * ptr, size_t max)
|
||||||
if (ptr==0) return 0;
|
if (ptr==0) return 0;
|
||||||
start = ptr;
|
start = ptr;
|
||||||
end = ptr + max;
|
end = ptr + max;
|
||||||
while(*ptr && ptr < end) ptr++;
|
while(ptr < end && *ptr) ptr++;
|
||||||
return ptr - start;
|
return ptr - start;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -92,7 +92,7 @@ static int it_mtm_assemble_pattern(IT_PATTERN *pattern, const unsigned char * tr
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int it_mtm_read_sample_header(IT_SAMPLE *sample, DUMBFILE *f)
|
static int it_mtm_read_sample_header(IT_SAMPLE *sample, DUMBFILE *f, int * skip_bytes)
|
||||||
{
|
{
|
||||||
int finetune, flags;
|
int finetune, flags;
|
||||||
|
|
||||||
|
@ -117,7 +117,9 @@ static int it_mtm_read_sample_header(IT_SAMPLE *sample, DUMBFILE *f)
|
||||||
|
|
||||||
sample->flags = IT_SAMPLE_EXISTS;
|
sample->flags = IT_SAMPLE_EXISTS;
|
||||||
|
|
||||||
|
*skip_bytes = 0;
|
||||||
if (flags & 1) {
|
if (flags & 1) {
|
||||||
|
*skip_bytes = sample->length & 1;
|
||||||
sample->flags |= IT_SAMPLE_16BIT;
|
sample->flags |= IT_SAMPLE_16BIT;
|
||||||
sample->length >>= 1;
|
sample->length >>= 1;
|
||||||
sample->loop_start >>= 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);
|
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 i;
|
||||||
long truncated_size;
|
long truncated_size;
|
||||||
|
long bytes_per_sample;
|
||||||
|
|
||||||
/* let's get rid of the sample data coming after the end of the loop */
|
/* let's get rid of the sample data coming after the end of the loop */
|
||||||
if ((sample->flags & IT_SAMPLE_LOOP) && sample->loop_end < sample->length) {
|
if ((sample->flags & IT_SAMPLE_LOOP) && sample->loop_end < sample->length) {
|
||||||
|
@ -157,17 +160,21 @@ static int it_mtm_read_sample_data(IT_SAMPLE *sample, DUMBFILE *f)
|
||||||
truncated_size = 0;
|
truncated_size = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
sample->data = malloc(sample->length);
|
bytes_per_sample = (sample->flags & IT_SAMPLE_16BIT) ? 2 : 1;
|
||||||
|
|
||||||
|
sample->data = malloc(sample->length * bytes_per_sample);
|
||||||
|
|
||||||
if (!sample->data)
|
if (!sample->data)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
dumbfile_getnc((char *)sample->data, sample->length, f);
|
dumbfile_getnc((char *)sample->data, sample->length * bytes_per_sample, f);
|
||||||
dumbfile_skip(f, truncated_size);
|
dumbfile_skip(f, truncated_size * bytes_per_sample);
|
||||||
|
dumbfile_skip(f, skip_bytes);
|
||||||
|
|
||||||
if (dumbfile_error(f))
|
if (dumbfile_error(f))
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
if (bytes_per_sample == 1)
|
||||||
for (i = 0; i < sample->length; i++)
|
for (i = 0; i < sample->length; i++)
|
||||||
((signed char *)sample->data)[i] ^= 0x80;
|
((signed char *)sample->data)[i] ^= 0x80;
|
||||||
|
|
||||||
|
@ -186,6 +193,8 @@ static DUMB_IT_SIGDATA *it_mtm_load_sigdata(DUMBFILE *f, int * version)
|
||||||
|
|
||||||
char * comment;
|
char * comment;
|
||||||
|
|
||||||
|
int * skip_bytes;
|
||||||
|
|
||||||
if (dumbfile_getc(f) != 'M' ||
|
if (dumbfile_getc(f) != 'M' ||
|
||||||
dumbfile_getc(f) != 'T' ||
|
dumbfile_getc(f) != 'T' ||
|
||||||
dumbfile_getc(f) != 'M') goto error;
|
dumbfile_getc(f) != 'M') goto error;
|
||||||
|
@ -262,19 +271,22 @@ static DUMB_IT_SIGDATA *it_mtm_load_sigdata(DUMBFILE *f, int * version)
|
||||||
for (n = 0; n < sigdata->n_samples; n++)
|
for (n = 0; n < sigdata->n_samples; n++)
|
||||||
sigdata->sample[n].data = NULL;
|
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++) {
|
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);
|
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 (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);
|
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;
|
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;
|
int l, m;
|
||||||
|
|
||||||
for (l = 0, n = 0; n <= o; n += 40) {
|
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;
|
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;
|
if (!sigdata->song_message) goto error_fc;
|
||||||
|
|
||||||
for (m = 0, n = 0; n <= o; n += 40) {
|
for (m = 0, n = 0; n <= o; n += 40) {
|
||||||
int 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) {
|
if (p) {
|
||||||
memcpy(sigdata->song_message + m, &comment[n], p);
|
memcpy(sigdata->song_message + m, &comment[n], p);
|
||||||
m += 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++) {
|
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);
|
_dumb_it_fix_invalid_orders(sigdata);
|
||||||
|
|
||||||
free(sequence);
|
free(sequence);
|
||||||
free(track);
|
free(track);
|
||||||
|
free(skip_bytes);
|
||||||
|
|
||||||
return sigdata;
|
return sigdata;
|
||||||
|
|
||||||
|
@ -364,6 +379,8 @@ error_fs:
|
||||||
free(sequence);
|
free(sequence);
|
||||||
error_ft:
|
error_ft:
|
||||||
free(track);
|
free(track);
|
||||||
|
error_sb:
|
||||||
|
free(skip_bytes);
|
||||||
error_usd:
|
error_usd:
|
||||||
_dumb_it_unload_sigdata(sigdata);
|
_dumb_it_unload_sigdata(sigdata);
|
||||||
return NULL;
|
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);
|
qsort(buffer, count, 64, &psm_sample_compare);
|
||||||
|
|
||||||
for (n = 0; n < true_num; n++) {
|
for (n = 0; n < *num; n++) {
|
||||||
(*sample)[n].flags = 0;
|
(*sample)[n].flags = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (n = 0; n < count; n++) {
|
for (n = 0; n < count; n++) {
|
||||||
|
IT_SAMPLE smp;
|
||||||
IT_SAMPLE * s;
|
IT_SAMPLE * s;
|
||||||
snum = buffer[(n * 64) + 45] | (buffer[(n * 64) + 46] << 8);
|
snum = buffer[(n * 64) + 45] | (buffer[(n * 64) + 46] << 8);
|
||||||
s = &((*sample)[snum - 1]);
|
s = &((*sample)[snum - 1]);
|
||||||
memcpy(s->filename, buffer + (n * 64), 13);
|
memcpy(smp.filename, buffer + (n * 64), 13);
|
||||||
s->filename[13] = 0;
|
smp.filename[13] = 0;
|
||||||
memcpy(s->name, buffer + (n * 64) + 13, 24);
|
memcpy(smp.name, buffer + (n * 64) + 13, 24);
|
||||||
s->name[24] = 0;
|
smp.name[24] = 0;
|
||||||
offset = buffer[(n * 64) + 37] | (buffer[(n * 64) + 38] << 8) |
|
offset = buffer[(n * 64) + 37] | (buffer[(n * 64) + 38] << 8) |
|
||||||
(buffer[(n * 64) + 39] << 16) | (buffer[(n * 64) + 40] << 24);
|
(buffer[(n * 64) + 39] << 16) | (buffer[(n * 64) + 40] << 24);
|
||||||
flags = buffer[(n * 64) + 47];
|
flags = buffer[(n * 64) + 47];
|
||||||
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);
|
(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);
|
(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);
|
(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];
|
finetune = buffer[(n * 64) + 60];
|
||||||
s->default_volume = buffer[(n * 64) + 61];
|
smp.default_volume = buffer[(n * 64) + 61];
|
||||||
s->C5_speed = buffer[(n * 64) + 62] | (buffer[(n * 64) + 63] << 8);
|
smp.C5_speed = buffer[(n * 64) + 62] | (buffer[(n * 64) + 63] << 8);
|
||||||
if (finetune & 15) {
|
if (finetune & 15) {
|
||||||
finetune &= 15;
|
finetune &= 15;
|
||||||
if (finetune >= 8) finetune -= 16;
|
if (finetune >= 8) finetune -= 16;
|
||||||
//s->C5_speed = (long)((double)s->C5_speed * pow(DUMB_PITCH_BASE, finetune*32));
|
//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;
|
smp.flags |= IT_SAMPLE_EXISTS;
|
||||||
if (flags & 0x41) {
|
if (flags & 0x41)
|
||||||
s->flags &= ~IT_SAMPLE_EXISTS;
|
|
||||||
continue;
|
continue;
|
||||||
}
|
if (flags & 0x20) smp.flags |= IT_SAMPLE_PINGPONG_LOOP;
|
||||||
if (flags & 0x20) s->flags |= IT_SAMPLE_PINGPONG_LOOP;
|
if (flags & 4) smp.flags |= IT_SAMPLE_16BIT;
|
||||||
if (flags & 4) s->flags |= IT_SAMPLE_16BIT;
|
|
||||||
|
|
||||||
if (flags & 0x80) {
|
if (flags & 0x80) {
|
||||||
s->flags |= IT_SAMPLE_LOOP;
|
smp.flags |= IT_SAMPLE_LOOP;
|
||||||
if ((unsigned int)s->loop_end > (unsigned int)s->length)
|
if ((unsigned int)smp.loop_end > (unsigned int)smp.length)
|
||||||
s->loop_end = s->length;
|
smp.loop_end = smp.length;
|
||||||
else if ((unsigned int)s->loop_start >= (unsigned int)s->loop_end)
|
else if ((unsigned int)smp.loop_start >= (unsigned int)smp.loop_end)
|
||||||
s->flags &= ~IT_SAMPLE_LOOP;
|
smp.flags &= ~IT_SAMPLE_LOOP;
|
||||||
else
|
else
|
||||||
s->length = s->loop_end;
|
smp.length = smp.loop_end;
|
||||||
}
|
}
|
||||||
|
|
||||||
s->global_volume = 64;
|
smp.global_volume = 64;
|
||||||
|
|
||||||
s->vibrato_speed = 0;
|
smp.vibrato_speed = 0;
|
||||||
s->vibrato_depth = 0;
|
smp.vibrato_depth = 0;
|
||||||
s->vibrato_rate = 0;
|
smp.vibrato_rate = 0;
|
||||||
s->vibrato_waveform = IT_VIBRATO_SINE;
|
smp.vibrato_waveform = IT_VIBRATO_SINE;
|
||||||
s->max_resampling_quality = -1;
|
smp.max_resampling_quality = -1;
|
||||||
|
|
||||||
sample_bytes = s->length * ((flags & 4) ? 2 : 1);
|
sample_bytes = smp.length * ((flags & 4) ? 2 : 1);
|
||||||
s->data = malloc(sample_bytes);
|
smp.data = malloc(sample_bytes);
|
||||||
if (!s->data) goto error_fb;
|
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;
|
if (dumbfile_seek(f, offset, DFS_SEEK_SET) || dumbfile_getnc(smp.data, sample_bytes, f) < sample_bytes) goto error_fd;
|
||||||
sdata = ( const unsigned char * ) s->data;
|
|
||||||
|
|
||||||
if (flags & 0x10) {
|
if (flags & 0x10) {
|
||||||
if (flags & 8) {
|
if (flags & 8) {
|
||||||
if (flags & 4) {
|
if (flags & 4) {
|
||||||
for (o = 0; o < s->length; o++)
|
for (o = 0; o < smp.length; o++)
|
||||||
((short *)s->data)[o] = (sdata[o * 2] | (sdata[(o * 2) + 1] << 8)) ^ 0x8000;
|
((short *)smp.data)[o] = (sdata[o * 2] | (sdata[(o * 2) + 1] << 8)) ^ 0x8000;
|
||||||
} else {
|
} else {
|
||||||
for (o = 0; o < s->length; o++)
|
for (o = 0; o < smp.length; o++)
|
||||||
((signed char *)s->data)[o] = sdata[o] ^ 0x80;
|
((signed char *)smp.data)[o] = sdata[o] ^ 0x80;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (flags & 4) {
|
if (flags & 4) {
|
||||||
for (o = 0; o < s->length; o++)
|
for (o = 0; o < smp.length; o++)
|
||||||
((short *)s->data)[o] = sdata[o * 2] | (sdata[(o * 2) + 1] << 8);
|
((short *)smp.data)[o] = sdata[o * 2] | (sdata[(o * 2) + 1] << 8);
|
||||||
} else {
|
} else {
|
||||||
memcpy(s->data, sdata, s->length);
|
memcpy(smp.data, sdata, smp.length);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -156,36 +155,41 @@ static int it_old_psm_read_samples(IT_SAMPLE ** sample, DUMBFILE * f, int * num)
|
||||||
if (flags & 8) {
|
if (flags & 8) {
|
||||||
/* unsigned delta? mehhh, does anything even use this? */
|
/* unsigned delta? mehhh, does anything even use this? */
|
||||||
if (flags & 4) {
|
if (flags & 4) {
|
||||||
for (o = 0; o < s->length; o++) {
|
for (o = 0; o < smp.length; o++) {
|
||||||
delta += (short)(sdata[o * 2] | (sdata[(o * 2) + 1] << 8));
|
delta += (short)(sdata[o * 2] | (sdata[(o * 2) + 1] << 8));
|
||||||
((short *)s->data)[o] = delta ^ 0x8000;
|
((short *)smp.data)[o] = delta ^ 0x8000;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for (o = 0; o < s->length; o++) {
|
for (o = 0; o < smp.length; o++) {
|
||||||
delta += (signed char)sdata[o];
|
delta += (signed char)sdata[o];
|
||||||
((signed char *)s->data)[o] = delta ^ 0x80;
|
((signed char *)smp.data)[o] = delta ^ 0x80;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (flags & 4) {
|
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));
|
delta += (signed short)(sdata[o * 2] | (sdata[(o * 2) + 1] << 8));
|
||||||
((signed short *)s->data)[o] = delta;
|
((signed short *)smp.data)[o] = delta;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for (o = 0; o < s->length; o++) {
|
for (o = 0; o < smp.length; o++) {
|
||||||
delta += (signed char)sdata[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);
|
free(buffer);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
error_fd:
|
||||||
|
free((void *)sdata);
|
||||||
error_fb:
|
error_fb:
|
||||||
free(buffer);
|
free(buffer);
|
||||||
error:
|
error:
|
||||||
|
@ -225,6 +229,8 @@ static int it_old_psm_read_patterns(IT_PATTERN * pattern, DUMBFILE * f, int num,
|
||||||
|
|
||||||
psize = (psize + 15) & ~15;
|
psize = (psize + 15) & ~15;
|
||||||
|
|
||||||
|
if (offset + psize > size) goto error_fb;
|
||||||
|
|
||||||
end = ptr + psize;
|
end = ptr + psize;
|
||||||
ptr += 4;
|
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 & 0x80) ptr += 2;
|
||||||
if (flags & 0x40) ptr++;
|
if (flags & 0x40) ptr++;
|
||||||
if (flags & 0x20) {
|
if (flags & 0x20) {
|
||||||
ptr++;
|
if (*ptr == 40) ptr += 4;
|
||||||
if (*ptr == 40) ptr += 3;
|
else ptr += 2;
|
||||||
else ptr++;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -96,7 +96,7 @@ static int it_psm_process_sample(IT_SAMPLE * sample, const unsigned char * data,
|
||||||
|
|
||||||
if (insno != id) return -1;
|
if (insno != id) return -1;
|
||||||
|
|
||||||
if (!length) {
|
if (length <= 0) {
|
||||||
sample->flags &= ~IT_SAMPLE_EXISTS;
|
sample->flags &= ~IT_SAMPLE_EXISTS;
|
||||||
return 0;
|
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);
|
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;
|
pattern->n_rows = nrows;
|
||||||
|
|
||||||
|
@ -461,7 +466,7 @@ static DUMB_IT_SIGDATA *it_psm_load_sigdata(DUMBFILE *f, int * ver, int subsong)
|
||||||
PSMCHUNK *chunk;
|
PSMCHUNK *chunk;
|
||||||
int n_chunks = 0;
|
int n_chunks = 0;
|
||||||
|
|
||||||
PSMCHUNK *songchunk;
|
PSMCHUNK *songchunk = 0;
|
||||||
int n_song_chunks = 0;
|
int n_song_chunks = 0;
|
||||||
|
|
||||||
PSMEVENT *event = 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));
|
chunk = calloc(768, sizeof(*chunk));
|
||||||
|
|
||||||
while (length >= 8) {
|
while (length >= 8) {
|
||||||
|
if (n_chunks >= 768) goto error_fc;
|
||||||
chunk[n_chunks].id = dumbfile_mgetl(f);
|
chunk[n_chunks].id = dumbfile_mgetl(f);
|
||||||
n = dumbfile_igetl(f);
|
n = dumbfile_igetl(f);
|
||||||
length -= 8;
|
length -= 8;
|
||||||
|
@ -584,13 +590,14 @@ static DUMB_IT_SIGDATA *it_psm_load_sigdata(DUMBFILE *f, int * ver, int subsong)
|
||||||
ptr += 11;
|
ptr += 11;
|
||||||
songchunk = 0;
|
songchunk = 0;
|
||||||
if (length >= 8) {
|
if (length >= 8) {
|
||||||
songchunk = malloc(128 * sizeof(*songchunk));
|
songchunk = malloc(256 * sizeof(*songchunk));
|
||||||
if (!songchunk) goto error_usd;
|
if (!songchunk) goto error_usd;
|
||||||
while (length >= 8) {
|
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]);
|
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);
|
n = ptr[4] | (ptr[5] << 8) | (ptr[6] << 16) | (ptr[7] << 24);
|
||||||
length -= 8;
|
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].len = n;
|
||||||
songchunk[n_song_chunks].data = ptr + 8;
|
songchunk[n_song_chunks].data = ptr + 8;
|
||||||
n_song_chunks++;
|
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;
|
if ( i < j ) return -1;
|
||||||
else if ( j > i ) return 1;
|
else if ( i > j ) return 1;
|
||||||
|
|
||||||
i = memcmp( a, b, j );
|
i = memcmp( a, b, j );
|
||||||
if ( i ) return i;
|
if ( i ) return i;
|
||||||
|
@ -1279,7 +1286,7 @@ DUH *dumb_read_psm_quick(DUMBFILE *f, int subsong)
|
||||||
if ( ver )
|
if ( ver )
|
||||||
{
|
{
|
||||||
tag[2][0] = "FORMATVERSION";
|
tag[2][0] = "FORMATVERSION";
|
||||||
snprintf( version, 15, "%u", ver );
|
snprintf( version, 15, "%d", ver );
|
||||||
version[15] = 0;
|
version[15] = 0;
|
||||||
tag[2][1] = (const char *) &version;
|
tag[2][1] = (const char *) &version;
|
||||||
++n_tags;
|
++n_tags;
|
||||||
|
|
|
@ -371,6 +371,8 @@ static int limit_xm_resize(void *f, long n)
|
||||||
{
|
{
|
||||||
DUMBFILE *df = f;
|
DUMBFILE *df = f;
|
||||||
LIMITED_XM *lx = df->file;
|
LIMITED_XM *lx = df->file;
|
||||||
|
if (n < 0)
|
||||||
|
return -1;
|
||||||
if (lx->buffered || n) {
|
if (lx->buffered || n) {
|
||||||
if (n > lx->allocated) {
|
if (n > lx->allocated) {
|
||||||
unsigned char *buffered = realloc( lx->buffered, n );
|
unsigned char *buffered = realloc( lx->buffered, n );
|
||||||
|
@ -910,7 +912,7 @@ static DUMB_IT_SIGDATA *it_xm_load_sigdata(DUMBFILE *f, int * version)
|
||||||
/* sanity checks */
|
/* sanity checks */
|
||||||
// XXX
|
// XXX
|
||||||
i = header_size - 4 - 2 * 8; /* Maximum number of orders expected */
|
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);
|
_dumb_it_unload_sigdata(sigdata);
|
||||||
return NULL;
|
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));
|
sigdata->instrument = malloc(sigdata->n_instruments * sizeof(*sigdata->instrument));
|
||||||
if (!sigdata->instrument) {
|
if (!sigdata->instrument) {
|
||||||
|
free(roguebytes);
|
||||||
_dumb_it_unload_sigdata(sigdata);
|
_dumb_it_unload_sigdata(sigdata);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue