mirror of
https://github.com/ZDoom/gzdoom.git
synced 2024-11-11 07:12:02 +00:00
Separate WildMidi mixing from event handling
- In order to use ZDoom's own MIDI sequencer event handling must be completely separate from mixing, but WildMidi had them intertwined because it wasn't designed for external sequencers. - Also remove all 'long's defining the output buffers to avoid having something that's 32 bits wide on Windows and 64 bits wide on Linux.
This commit is contained in:
parent
a2ebf771d3
commit
635b496165
3 changed files with 473 additions and 459 deletions
|
@ -269,23 +269,23 @@ _WM_init_reverb(int rate, float room_x, float room_y, float listen_x,
|
|||
double a1 = -2 * cs;
|
||||
double a2 = 1 - (alpha / A);
|
||||
|
||||
rtn_rvb->coeff[j][i][0] = (signed long int) ((b0 / a0) * 1024.0);
|
||||
rtn_rvb->coeff[j][i][1] = (signed long int) ((b1 / a0) * 1024.0);
|
||||
rtn_rvb->coeff[j][i][2] = (signed long int) ((b2 / a0) * 1024.0);
|
||||
rtn_rvb->coeff[j][i][3] = (signed long int) ((a1 / a0) * 1024.0);
|
||||
rtn_rvb->coeff[j][i][4] = (signed long int) ((a2 / a0) * 1024.0);
|
||||
rtn_rvb->coeff[j][i][0] = (signed int) ((b0 / a0) * 1024.0);
|
||||
rtn_rvb->coeff[j][i][1] = (signed int) ((b1 / a0) * 1024.0);
|
||||
rtn_rvb->coeff[j][i][2] = (signed int) ((b2 / a0) * 1024.0);
|
||||
rtn_rvb->coeff[j][i][3] = (signed int) ((a1 / a0) * 1024.0);
|
||||
rtn_rvb->coeff[j][i][4] = (signed int) ((a2 / a0) * 1024.0);
|
||||
}
|
||||
}
|
||||
|
||||
/* init the reverb buffers */
|
||||
rtn_rvb->l_buf_size = (int) ((float) rate * (MAXL_DST / 340.29));
|
||||
rtn_rvb->l_buf = (long*)malloc(
|
||||
sizeof(signed long int) * (rtn_rvb->l_buf_size + 1));
|
||||
rtn_rvb->l_buf = (int*)malloc(
|
||||
sizeof(signed int) * (rtn_rvb->l_buf_size + 1));
|
||||
rtn_rvb->l_out = 0;
|
||||
|
||||
rtn_rvb->r_buf_size = (int) ((float) rate * (MAXR_DST / 340.29));
|
||||
rtn_rvb->r_buf = (long*)malloc(
|
||||
sizeof(signed long int) * (rtn_rvb->r_buf_size + 1));
|
||||
rtn_rvb->r_buf = (int*)malloc(
|
||||
sizeof(signed int) * (rtn_rvb->r_buf_size + 1));
|
||||
rtn_rvb->r_out = 0;
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
|
@ -313,17 +313,17 @@ void _WM_free_reverb(struct _rvb *rvb) {
|
|||
free(rvb);
|
||||
}
|
||||
|
||||
void _WM_do_reverb(struct _rvb *rvb, signed long int *buffer, int size) {
|
||||
void _WM_do_reverb(struct _rvb *rvb, signed int *buffer, int size) {
|
||||
int i, j, k;
|
||||
signed long int l_buf_flt = 0;
|
||||
signed long int r_buf_flt = 0;
|
||||
signed long int l_rfl = 0;
|
||||
signed long int r_rfl = 0;
|
||||
signed int l_buf_flt = 0;
|
||||
signed int r_buf_flt = 0;
|
||||
signed int l_rfl = 0;
|
||||
signed int r_rfl = 0;
|
||||
int vol_div = 64;
|
||||
|
||||
for (i = 0; i < size; i += 2) {
|
||||
signed long int tmp_l_val = 0;
|
||||
signed long int tmp_r_val = 0;
|
||||
signed int tmp_l_val = 0;
|
||||
signed int tmp_r_val = 0;
|
||||
/*
|
||||
add the initial reflections
|
||||
from each speaker, 4 to go the left, 4 go to the right buffers
|
||||
|
|
|
@ -29,14 +29,14 @@
|
|||
|
||||
struct _rvb {
|
||||
/* filter data */
|
||||
signed long int l_buf_flt_in[8][6][2];
|
||||
signed long int l_buf_flt_out[8][6][2];
|
||||
signed long int r_buf_flt_in[8][6][2];
|
||||
signed long int r_buf_flt_out[8][6][2];
|
||||
signed long int coeff[8][6][5];
|
||||
signed int l_buf_flt_in[8][6][2];
|
||||
signed int l_buf_flt_out[8][6][2];
|
||||
signed int r_buf_flt_in[8][6][2];
|
||||
signed int r_buf_flt_out[8][6][2];
|
||||
signed int coeff[8][6][5];
|
||||
/* buffer data */
|
||||
signed long int *l_buf;
|
||||
signed long int *r_buf;
|
||||
signed int *l_buf;
|
||||
signed int *r_buf;
|
||||
int l_buf_size;
|
||||
int r_buf_size;
|
||||
int l_out;
|
||||
|
@ -52,6 +52,6 @@ struct _rvb {
|
|||
extern void _WM_reset_reverb (struct _rvb *rvb);
|
||||
extern struct _rvb *_WM_init_reverb(int rate, float room_x, float room_y, float listen_x, float listen_y);
|
||||
extern void _WM_free_reverb (struct _rvb *rvb);
|
||||
extern void _WM_do_reverb (struct _rvb *rvb, signed long int *buffer, int size);
|
||||
extern void _WM_do_reverb (struct _rvb *rvb, signed int *buffer, int size);
|
||||
|
||||
#endif /* __REVERB_H */
|
||||
|
|
|
@ -182,7 +182,7 @@ struct _mdi {
|
|||
unsigned long int patch_count;
|
||||
signed short int amp;
|
||||
|
||||
signed long int *mix_buffer;
|
||||
signed int *mix_buffer;
|
||||
unsigned long int mix_buffer_size;
|
||||
|
||||
struct _rvb *reverb;
|
||||
|
@ -3203,20 +3203,216 @@ _end: free(sysex_store);
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static int *WM_Mix_Linear(midi * handle, int * buffer, unsigned long int count)
|
||||
{
|
||||
struct _mdi *mdi = (struct _mdi *)handle;
|
||||
unsigned long int data_pos;
|
||||
signed int premix, left_mix, right_mix;
|
||||
signed int vol_mul;
|
||||
struct _note *note_data = NULL;
|
||||
|
||||
do {
|
||||
note_data = mdi->note;
|
||||
left_mix = right_mix = 0;
|
||||
if (__builtin_expect((note_data != NULL), 1)) {
|
||||
while (note_data) {
|
||||
/*
|
||||
* ===================
|
||||
* resample the sample
|
||||
* ===================
|
||||
*/
|
||||
data_pos = note_data->sample_pos >> FPBITS;
|
||||
vol_mul = ((note_data->vol_lvl
|
||||
* (note_data->env_level >> 12)) >> FPBITS);
|
||||
|
||||
premix = (note_data->sample->data[data_pos]
|
||||
+ ((note_data->sample->data[data_pos + 1]
|
||||
- note_data->sample->data[data_pos])
|
||||
* (signed long int) (note_data->sample_pos
|
||||
& FPMASK)>> FPBITS)) * vol_mul
|
||||
/ 1024;
|
||||
|
||||
left_mix += premix
|
||||
* mdi->channel[note_data->noteid >> 8].left_adjust;
|
||||
right_mix += premix
|
||||
* mdi->channel[note_data->noteid >> 8].right_adjust;
|
||||
|
||||
/*
|
||||
* ========================
|
||||
* sample position checking
|
||||
* ========================
|
||||
*/
|
||||
note_data->sample_pos += note_data->sample_inc;
|
||||
if (__builtin_expect(
|
||||
(note_data->sample_pos > note_data->sample->loop_end),
|
||||
0)) {
|
||||
if (note_data->modes & SAMPLE_LOOP) {
|
||||
note_data->sample_pos =
|
||||
note_data->sample->loop_start
|
||||
+ ((note_data->sample_pos
|
||||
- note_data->sample->loop_start)
|
||||
% note_data->sample->loop_size);
|
||||
} else if (__builtin_expect(
|
||||
(note_data->sample_pos
|
||||
>= note_data->sample->data_length),
|
||||
0)) {
|
||||
if (__builtin_expect((note_data->replay == NULL), 1)) {
|
||||
goto KILL_NOTE;
|
||||
}
|
||||
goto RESTART_NOTE;
|
||||
}
|
||||
}
|
||||
|
||||
if (__builtin_expect((note_data->env_inc == 0), 0)) {
|
||||
note_data = note_data->next;
|
||||
continue;
|
||||
}
|
||||
|
||||
note_data->env_level += note_data->env_inc;
|
||||
if (__builtin_expect((note_data->env_level > 4194304), 0)) {
|
||||
note_data->env_level =
|
||||
note_data->sample->env_target[note_data->env];
|
||||
}
|
||||
if (__builtin_expect(
|
||||
((note_data->env_inc < 0)
|
||||
&& (note_data->env_level
|
||||
> note_data->sample->env_target[note_data->env]))
|
||||
|| ((note_data->env_inc > 0)
|
||||
&& (note_data->env_level
|
||||
< note_data->sample->env_target[note_data->env])),
|
||||
1)) {
|
||||
note_data = note_data->next;
|
||||
continue;
|
||||
}
|
||||
|
||||
note_data->env_level =
|
||||
note_data->sample->env_target[note_data->env];
|
||||
switch (note_data->env) {
|
||||
case 0:
|
||||
#if 0
|
||||
if (!(note_data->modes & SAMPLE_ENVELOPE)) {
|
||||
note_data->env_inc = 0;
|
||||
note_data = note_data->next;
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
case 2:
|
||||
if (note_data->modes & SAMPLE_SUSTAIN) {
|
||||
note_data->env_inc = 0;
|
||||
note_data = note_data->next;
|
||||
continue;
|
||||
} else if (note_data->modes & SAMPLE_CLAMPED) {
|
||||
note_data->env = 5;
|
||||
if (note_data->env_level
|
||||
> note_data->sample->env_target[5]) {
|
||||
note_data->env_inc =
|
||||
-note_data->sample->env_rate[5];
|
||||
} else {
|
||||
note_data->env_inc =
|
||||
note_data->sample->env_rate[5];
|
||||
}
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
case 5:
|
||||
if (__builtin_expect((note_data->env_level == 0), 1)) {
|
||||
goto KILL_NOTE;
|
||||
}
|
||||
/* sample release */
|
||||
if (note_data->modes & SAMPLE_LOOP)
|
||||
note_data->modes ^= SAMPLE_LOOP;
|
||||
note_data->env_inc = 0;
|
||||
note_data = note_data->next;
|
||||
continue;
|
||||
case 6:
|
||||
if (__builtin_expect((note_data->replay != NULL), 1)) {
|
||||
RESTART_NOTE: note_data->active = 0;
|
||||
{
|
||||
struct _note *prev_note = NULL;
|
||||
struct _note *nte_array = mdi->note;
|
||||
|
||||
if (nte_array != note_data) {
|
||||
do {
|
||||
prev_note = nte_array;
|
||||
nte_array = nte_array->next;
|
||||
} while (nte_array != note_data);
|
||||
}
|
||||
if (prev_note) {
|
||||
prev_note->next = note_data->replay;
|
||||
} else {
|
||||
mdi->note = note_data->replay;
|
||||
}
|
||||
note_data->replay->next = note_data->next;
|
||||
note_data = note_data->replay;
|
||||
note_data->active = 1;
|
||||
}
|
||||
} else {
|
||||
KILL_NOTE: note_data->active = 0;
|
||||
{
|
||||
struct _note *prev_note = NULL;
|
||||
struct _note *nte_array = mdi->note;
|
||||
|
||||
if (nte_array != note_data) {
|
||||
do {
|
||||
prev_note = nte_array;
|
||||
nte_array = nte_array->next;
|
||||
} while ((nte_array != note_data)
|
||||
&& (nte_array));
|
||||
}
|
||||
if (prev_note) {
|
||||
prev_note->next = note_data->next;
|
||||
} else {
|
||||
mdi->note = note_data->next;
|
||||
}
|
||||
note_data = note_data->next;
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
note_data->env++;
|
||||
|
||||
if (note_data->is_off == 1) {
|
||||
do_note_off_extra(note_data);
|
||||
}
|
||||
|
||||
if (note_data->env_level
|
||||
> note_data->sample->env_target[note_data->env]) {
|
||||
note_data->env_inc =
|
||||
-note_data->sample->env_rate[note_data->env];
|
||||
} else {
|
||||
note_data->env_inc =
|
||||
note_data->sample->env_rate[note_data->env];
|
||||
}
|
||||
note_data = note_data->next;
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* =========================
|
||||
* mix the channels together
|
||||
* =========================
|
||||
*/
|
||||
left_mix /= 1024;
|
||||
right_mix /= 1024;
|
||||
}
|
||||
|
||||
*buffer++ = left_mix;
|
||||
*buffer++ = right_mix;
|
||||
} while (--count);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
static int WM_GetOutput_Linear(midi * handle, char * buffer,
|
||||
unsigned long int size) {
|
||||
unsigned long int buffer_used = 0;
|
||||
unsigned long int i;
|
||||
struct _mdi *mdi = (struct _mdi *) handle;
|
||||
unsigned long int real_samples_to_mix = 0;
|
||||
unsigned long int data_pos;
|
||||
signed long int premix, left_mix, right_mix;
|
||||
signed long int vol_mul;
|
||||
struct _note *note_data = NULL;
|
||||
unsigned long int count;
|
||||
struct _event *event = mdi->current_event;
|
||||
signed long int *tmp_buffer;
|
||||
signed long int *out_buffer;
|
||||
int *tmp_buffer;
|
||||
int *out_buffer;
|
||||
int left_mix, right_mix;
|
||||
|
||||
_WM_Lock(&mdi->lock);
|
||||
|
||||
|
@ -3229,7 +3425,7 @@ static int WM_GetOutput_Linear(midi * handle, char * buffer,
|
|||
} else {
|
||||
mdi->mix_buffer_size = size / 2;
|
||||
}
|
||||
mdi->mix_buffer = (long*)realloc(mdi->mix_buffer, mdi->mix_buffer_size * sizeof(signed long int));
|
||||
mdi->mix_buffer = (int*)realloc(mdi->mix_buffer, mdi->mix_buffer_size * sizeof(signed int));
|
||||
}
|
||||
|
||||
tmp_buffer = mdi->mix_buffer;
|
||||
|
@ -3269,196 +3465,7 @@ static int WM_GetOutput_Linear(midi * handle, char * buffer,
|
|||
}
|
||||
|
||||
/* do mixing here */
|
||||
count = real_samples_to_mix;
|
||||
do {
|
||||
note_data = mdi->note;
|
||||
left_mix = right_mix = 0;
|
||||
if (__builtin_expect((note_data != NULL), 1)) {
|
||||
while (note_data) {
|
||||
/*
|
||||
* ===================
|
||||
* resample the sample
|
||||
* ===================
|
||||
*/
|
||||
data_pos = note_data->sample_pos >> FPBITS;
|
||||
vol_mul = ((note_data->vol_lvl
|
||||
* (note_data->env_level >> 12)) >> FPBITS);
|
||||
|
||||
premix = (note_data->sample->data[data_pos]
|
||||
+ ((note_data->sample->data[data_pos + 1]
|
||||
- note_data->sample->data[data_pos])
|
||||
* (signed long int) (note_data->sample_pos
|
||||
& FPMASK)>> FPBITS)) * vol_mul
|
||||
/ 1024;
|
||||
|
||||
left_mix += premix
|
||||
* mdi->channel[note_data->noteid >> 8].left_adjust;
|
||||
right_mix += premix
|
||||
* mdi->channel[note_data->noteid >> 8].right_adjust;
|
||||
|
||||
/*
|
||||
* ========================
|
||||
* sample position checking
|
||||
* ========================
|
||||
*/
|
||||
note_data->sample_pos += note_data->sample_inc;
|
||||
if (__builtin_expect(
|
||||
(note_data->sample_pos > note_data->sample->loop_end),
|
||||
0)) {
|
||||
if (note_data->modes & SAMPLE_LOOP) {
|
||||
note_data->sample_pos =
|
||||
note_data->sample->loop_start
|
||||
+ ((note_data->sample_pos
|
||||
- note_data->sample->loop_start)
|
||||
% note_data->sample->loop_size);
|
||||
} else if (__builtin_expect(
|
||||
(note_data->sample_pos
|
||||
>= note_data->sample->data_length),
|
||||
0)) {
|
||||
if (__builtin_expect((note_data->replay == NULL), 1)) {
|
||||
goto KILL_NOTE;
|
||||
}
|
||||
goto RESTART_NOTE;
|
||||
}
|
||||
}
|
||||
|
||||
if (__builtin_expect((note_data->env_inc == 0), 0)) {
|
||||
note_data = note_data->next;
|
||||
continue;
|
||||
}
|
||||
|
||||
note_data->env_level += note_data->env_inc;
|
||||
if (__builtin_expect((note_data->env_level > 4194304), 0)) {
|
||||
note_data->env_level =
|
||||
note_data->sample->env_target[note_data->env];
|
||||
}
|
||||
if (__builtin_expect(
|
||||
((note_data->env_inc < 0)
|
||||
&& (note_data->env_level
|
||||
> note_data->sample->env_target[note_data->env]))
|
||||
|| ((note_data->env_inc > 0)
|
||||
&& (note_data->env_level
|
||||
< note_data->sample->env_target[note_data->env])),
|
||||
1)) {
|
||||
note_data = note_data->next;
|
||||
continue;
|
||||
}
|
||||
|
||||
note_data->env_level =
|
||||
note_data->sample->env_target[note_data->env];
|
||||
switch (note_data->env) {
|
||||
case 0:
|
||||
#if 0
|
||||
if (!(note_data->modes & SAMPLE_ENVELOPE)) {
|
||||
note_data->env_inc = 0;
|
||||
note_data = note_data->next;
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
case 2:
|
||||
if (note_data->modes & SAMPLE_SUSTAIN) {
|
||||
note_data->env_inc = 0;
|
||||
note_data = note_data->next;
|
||||
continue;
|
||||
} else if (note_data->modes & SAMPLE_CLAMPED) {
|
||||
note_data->env = 5;
|
||||
if (note_data->env_level
|
||||
> note_data->sample->env_target[5]) {
|
||||
note_data->env_inc =
|
||||
-note_data->sample->env_rate[5];
|
||||
} else {
|
||||
note_data->env_inc =
|
||||
note_data->sample->env_rate[5];
|
||||
}
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
case 5:
|
||||
if (__builtin_expect((note_data->env_level == 0), 1)) {
|
||||
goto KILL_NOTE;
|
||||
}
|
||||
/* sample release */
|
||||
if (note_data->modes & SAMPLE_LOOP)
|
||||
note_data->modes ^= SAMPLE_LOOP;
|
||||
note_data->env_inc = 0;
|
||||
note_data = note_data->next;
|
||||
continue;
|
||||
case 6:
|
||||
if (__builtin_expect((note_data->replay != NULL), 1)) {
|
||||
RESTART_NOTE: note_data->active = 0;
|
||||
{
|
||||
struct _note *prev_note = NULL;
|
||||
struct _note *nte_array = mdi->note;
|
||||
|
||||
if (nte_array != note_data) {
|
||||
do {
|
||||
prev_note = nte_array;
|
||||
nte_array = nte_array->next;
|
||||
} while (nte_array != note_data);
|
||||
}
|
||||
if (prev_note) {
|
||||
prev_note->next = note_data->replay;
|
||||
} else {
|
||||
mdi->note = note_data->replay;
|
||||
}
|
||||
note_data->replay->next = note_data->next;
|
||||
note_data = note_data->replay;
|
||||
note_data->active = 1;
|
||||
}
|
||||
} else {
|
||||
KILL_NOTE: note_data->active = 0;
|
||||
{
|
||||
struct _note *prev_note = NULL;
|
||||
struct _note *nte_array = mdi->note;
|
||||
|
||||
if (nte_array != note_data) {
|
||||
do {
|
||||
prev_note = nte_array;
|
||||
nte_array = nte_array->next;
|
||||
} while ((nte_array != note_data)
|
||||
&& (nte_array));
|
||||
}
|
||||
if (prev_note) {
|
||||
prev_note->next = note_data->next;
|
||||
} else {
|
||||
mdi->note = note_data->next;
|
||||
}
|
||||
note_data = note_data->next;
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
note_data->env++;
|
||||
|
||||
if (note_data->is_off == 1) {
|
||||
do_note_off_extra(note_data);
|
||||
}
|
||||
|
||||
if (note_data->env_level
|
||||
> note_data->sample->env_target[note_data->env]) {
|
||||
note_data->env_inc =
|
||||
-note_data->sample->env_rate[note_data->env];
|
||||
} else {
|
||||
note_data->env_inc =
|
||||
note_data->sample->env_rate[note_data->env];
|
||||
}
|
||||
note_data = note_data->next;
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* =========================
|
||||
* mix the channels together
|
||||
* =========================
|
||||
*/
|
||||
left_mix /= 1024;
|
||||
right_mix /= 1024;
|
||||
}
|
||||
|
||||
*tmp_buffer++ = left_mix;
|
||||
*tmp_buffer++ = right_mix;
|
||||
} while (--count);
|
||||
tmp_buffer = WM_Mix_Linear(handle, tmp_buffer, real_samples_to_mix);
|
||||
|
||||
buffer_used += real_samples_to_mix * 4;
|
||||
size -= (real_samples_to_mix << 2);
|
||||
|
@ -3503,25 +3510,254 @@ static int WM_GetOutput_Linear(midi * handle, char * buffer,
|
|||
return buffer_used;
|
||||
}
|
||||
|
||||
static int *WM_Mix_Gauss(midi * handle, int * buffer, unsigned long int count)
|
||||
{
|
||||
struct _mdi *mdi = (struct _mdi *)handle;
|
||||
unsigned long int data_pos;
|
||||
signed int premix, left_mix, right_mix;
|
||||
signed int vol_mul;
|
||||
struct _note *note_data = NULL;
|
||||
signed short int *sptr;
|
||||
double y, xd;
|
||||
double *gptr, *gend;
|
||||
int left, right, temp_n;
|
||||
int ii, jj;
|
||||
|
||||
do {
|
||||
note_data = mdi->note;
|
||||
left_mix = right_mix = 0;
|
||||
if (__builtin_expect((note_data != NULL), 1)) {
|
||||
while (note_data) {
|
||||
/*
|
||||
* ===================
|
||||
* resample the sample
|
||||
* ===================
|
||||
*/
|
||||
data_pos = note_data->sample_pos >> FPBITS;
|
||||
vol_mul = ((note_data->vol_lvl
|
||||
* (note_data->env_level >> 12)) >> FPBITS);
|
||||
|
||||
/* check to see if we're near one of the ends */
|
||||
left = data_pos;
|
||||
right = (note_data->sample->data_length >> FPBITS) - left
|
||||
- 1;
|
||||
temp_n = (right << 1) - 1;
|
||||
if (temp_n <= 0)
|
||||
temp_n = 1;
|
||||
if (temp_n > (left << 1) + 1)
|
||||
temp_n = (left << 1) + 1;
|
||||
|
||||
/* use Newton if we can't fill the window */
|
||||
if (temp_n < gauss_n) {
|
||||
xd = note_data->sample_pos & FPMASK;
|
||||
xd /= (1L << FPBITS);
|
||||
xd += temp_n >> 1;
|
||||
y = 0;
|
||||
sptr = note_data->sample->data
|
||||
+ (note_data->sample_pos >> FPBITS)
|
||||
- (temp_n >> 1);
|
||||
for (ii = temp_n; ii;) {
|
||||
for (jj = 0; jj <= ii; jj++)
|
||||
y += sptr[jj] * newt_coeffs[ii][jj];
|
||||
y *= xd - --ii;
|
||||
}
|
||||
y += *sptr;
|
||||
} else { /* otherwise, use Gauss as usual */
|
||||
y = 0;
|
||||
gptr = &gauss_table[(note_data->sample_pos & FPMASK) *
|
||||
(gauss_n + 1)];
|
||||
gend = gptr + gauss_n;
|
||||
sptr = note_data->sample->data
|
||||
+ (note_data->sample_pos >> FPBITS)
|
||||
- (gauss_n >> 1);
|
||||
do {
|
||||
y += *(sptr++) * *(gptr++);
|
||||
} while (gptr <= gend);
|
||||
}
|
||||
|
||||
premix = (long) (y * vol_mul / 1024);
|
||||
|
||||
left_mix += premix
|
||||
* mdi->channel[note_data->noteid >> 8].left_adjust;
|
||||
right_mix += premix
|
||||
* mdi->channel[note_data->noteid >> 8].right_adjust;
|
||||
|
||||
/*
|
||||
* ========================
|
||||
* sample position checking
|
||||
* ========================
|
||||
*/
|
||||
note_data->sample_pos += note_data->sample_inc;
|
||||
if (__builtin_expect(
|
||||
(note_data->sample_pos > note_data->sample->loop_end),
|
||||
0)) {
|
||||
if (note_data->modes & SAMPLE_LOOP) {
|
||||
note_data->sample_pos =
|
||||
note_data->sample->loop_start
|
||||
+ ((note_data->sample_pos
|
||||
- note_data->sample->loop_start)
|
||||
% note_data->sample->loop_size);
|
||||
} else if (__builtin_expect(
|
||||
(note_data->sample_pos
|
||||
>= note_data->sample->data_length),
|
||||
0)) {
|
||||
if (__builtin_expect((note_data->replay == NULL), 1)) {
|
||||
goto KILL_NOTE;
|
||||
}
|
||||
goto RESTART_NOTE;
|
||||
}
|
||||
}
|
||||
|
||||
if (__builtin_expect((note_data->env_inc == 0), 0)) {
|
||||
note_data = note_data->next;
|
||||
continue;
|
||||
}
|
||||
|
||||
note_data->env_level += note_data->env_inc;
|
||||
if (__builtin_expect((note_data->env_level > 4194304), 0)) {
|
||||
note_data->env_level =
|
||||
note_data->sample->env_target[note_data->env];
|
||||
}
|
||||
if (__builtin_expect(
|
||||
((note_data->env_inc < 0)
|
||||
&& (note_data->env_level
|
||||
> note_data->sample->env_target[note_data->env]))
|
||||
|| ((note_data->env_inc > 0)
|
||||
&& (note_data->env_level
|
||||
< note_data->sample->env_target[note_data->env])),
|
||||
1)) {
|
||||
note_data = note_data->next;
|
||||
continue;
|
||||
}
|
||||
|
||||
note_data->env_level =
|
||||
note_data->sample->env_target[note_data->env];
|
||||
switch (note_data->env) {
|
||||
case 0:
|
||||
#if 0
|
||||
if (!(note_data->modes & SAMPLE_ENVELOPE)) {
|
||||
note_data->env_inc = 0;
|
||||
note_data = note_data->next;
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
case 2:
|
||||
if (note_data->modes & SAMPLE_SUSTAIN) {
|
||||
note_data->env_inc = 0;
|
||||
note_data = note_data->next;
|
||||
continue;
|
||||
} else if (note_data->modes & SAMPLE_CLAMPED) {
|
||||
note_data->env = 5;
|
||||
if (note_data->env_level
|
||||
> note_data->sample->env_target[5]) {
|
||||
note_data->env_inc =
|
||||
-note_data->sample->env_rate[5];
|
||||
} else {
|
||||
note_data->env_inc =
|
||||
note_data->sample->env_rate[5];
|
||||
}
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
case 5:
|
||||
if (__builtin_expect((note_data->env_level == 0), 1)) {
|
||||
goto KILL_NOTE;
|
||||
}
|
||||
/* sample release */
|
||||
if (note_data->modes & SAMPLE_LOOP)
|
||||
note_data->modes ^= SAMPLE_LOOP;
|
||||
note_data->env_inc = 0;
|
||||
note_data = note_data->next;
|
||||
continue;
|
||||
case 6:
|
||||
if (__builtin_expect((note_data->replay != NULL), 1)) {
|
||||
RESTART_NOTE: note_data->active = 0;
|
||||
{
|
||||
struct _note *prev_note = NULL;
|
||||
struct _note *nte_array = mdi->note;
|
||||
|
||||
if (nte_array != note_data) {
|
||||
do {
|
||||
prev_note = nte_array;
|
||||
nte_array = nte_array->next;
|
||||
} while (nte_array != note_data);
|
||||
}
|
||||
if (prev_note) {
|
||||
prev_note->next = note_data->replay;
|
||||
} else {
|
||||
mdi->note = note_data->replay;
|
||||
}
|
||||
note_data->replay->next = note_data->next;
|
||||
note_data = note_data->replay;
|
||||
note_data->active = 1;
|
||||
}
|
||||
} else {
|
||||
KILL_NOTE: note_data->active = 0;
|
||||
{
|
||||
struct _note *prev_note = NULL;
|
||||
struct _note *nte_array = mdi->note;
|
||||
|
||||
if (nte_array != note_data) {
|
||||
do {
|
||||
prev_note = nte_array;
|
||||
nte_array = nte_array->next;
|
||||
} while ((nte_array != note_data)
|
||||
&& (nte_array));
|
||||
}
|
||||
if (prev_note) {
|
||||
prev_note->next = note_data->next;
|
||||
} else {
|
||||
mdi->note = note_data->next;
|
||||
}
|
||||
note_data = note_data->next;
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
note_data->env++;
|
||||
|
||||
if (note_data->is_off == 1) {
|
||||
do_note_off_extra(note_data);
|
||||
}
|
||||
|
||||
if (note_data->env_level
|
||||
> note_data->sample->env_target[note_data->env]) {
|
||||
note_data->env_inc =
|
||||
-note_data->sample->env_rate[note_data->env];
|
||||
} else {
|
||||
note_data->env_inc =
|
||||
note_data->sample->env_rate[note_data->env];
|
||||
}
|
||||
note_data = note_data->next;
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* =========================
|
||||
* mix the channels together
|
||||
* =========================
|
||||
*/
|
||||
left_mix /= 1024;
|
||||
right_mix /= 1024;
|
||||
}
|
||||
|
||||
*buffer++ = left_mix;
|
||||
*buffer++ = right_mix;
|
||||
} while (--count);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
static int WM_GetOutput_Gauss(midi * handle, char * buffer,
|
||||
unsigned long int size) {
|
||||
unsigned long int buffer_used = 0;
|
||||
unsigned long int i;
|
||||
struct _mdi *mdi = (struct _mdi *) handle;
|
||||
unsigned long int real_samples_to_mix = 0;
|
||||
unsigned long int data_pos;
|
||||
signed long int premix, left_mix, right_mix;
|
||||
signed long int vol_mul;
|
||||
struct _note *note_data = NULL;
|
||||
unsigned long int count;
|
||||
signed short int *sptr;
|
||||
double y, xd;
|
||||
double *gptr, *gend;
|
||||
int left, right, temp_n;
|
||||
int ii, jj;
|
||||
struct _event *event = mdi->current_event;
|
||||
signed long int *tmp_buffer;
|
||||
signed long int *out_buffer;
|
||||
signed int *tmp_buffer;
|
||||
signed int *out_buffer;
|
||||
signed int left_mix, right_mix;
|
||||
|
||||
_WM_Lock(&mdi->lock);
|
||||
|
||||
|
@ -3533,7 +3769,7 @@ static int WM_GetOutput_Gauss(midi * handle, char * buffer,
|
|||
} else {
|
||||
mdi->mix_buffer_size = size / 2;
|
||||
}
|
||||
mdi->mix_buffer = (long*)realloc(mdi->mix_buffer, mdi->mix_buffer_size * sizeof(signed long int));
|
||||
mdi->mix_buffer = (int*)realloc(mdi->mix_buffer, mdi->mix_buffer_size * sizeof(signed int));
|
||||
}
|
||||
tmp_buffer = mdi->mix_buffer;
|
||||
memset(tmp_buffer, 0, ((size / 2) * sizeof(signed long int)));
|
||||
|
@ -3571,229 +3807,7 @@ static int WM_GetOutput_Gauss(midi * handle, char * buffer,
|
|||
}
|
||||
|
||||
/* do mixing here */
|
||||
count = real_samples_to_mix;
|
||||
do {
|
||||
note_data = mdi->note;
|
||||
left_mix = right_mix = 0;
|
||||
if (__builtin_expect((note_data != NULL), 1)) {
|
||||
while (note_data) {
|
||||
/*
|
||||
* ===================
|
||||
* resample the sample
|
||||
* ===================
|
||||
*/
|
||||
data_pos = note_data->sample_pos >> FPBITS;
|
||||
vol_mul = ((note_data->vol_lvl
|
||||
* (note_data->env_level >> 12)) >> FPBITS);
|
||||
|
||||
/* check to see if we're near one of the ends */
|
||||
left = data_pos;
|
||||
right = (note_data->sample->data_length >> FPBITS) - left
|
||||
- 1;
|
||||
temp_n = (right << 1) - 1;
|
||||
if (temp_n <= 0)
|
||||
temp_n = 1;
|
||||
if (temp_n > (left << 1) + 1)
|
||||
temp_n = (left << 1) + 1;
|
||||
|
||||
/* use Newton if we can't fill the window */
|
||||
if (temp_n < gauss_n) {
|
||||
xd = note_data->sample_pos & FPMASK;
|
||||
xd /= (1L << FPBITS);
|
||||
xd += temp_n >> 1;
|
||||
y = 0;
|
||||
sptr = note_data->sample->data
|
||||
+ (note_data->sample_pos >> FPBITS)
|
||||
- (temp_n >> 1);
|
||||
for (ii = temp_n; ii;) {
|
||||
for (jj = 0; jj <= ii; jj++)
|
||||
y += sptr[jj] * newt_coeffs[ii][jj];
|
||||
y *= xd - --ii;
|
||||
}
|
||||
y += *sptr;
|
||||
} else { /* otherwise, use Gauss as usual */
|
||||
y = 0;
|
||||
gptr = &gauss_table[(note_data->sample_pos & FPMASK) *
|
||||
(gauss_n + 1)];
|
||||
gend = gptr + gauss_n;
|
||||
sptr = note_data->sample->data
|
||||
+ (note_data->sample_pos >> FPBITS)
|
||||
- (gauss_n >> 1);
|
||||
do {
|
||||
y += *(sptr++) * *(gptr++);
|
||||
} while (gptr <= gend);
|
||||
}
|
||||
|
||||
premix = (long) (y * vol_mul / 1024);
|
||||
|
||||
left_mix += premix
|
||||
* mdi->channel[note_data->noteid >> 8].left_adjust;
|
||||
right_mix += premix
|
||||
* mdi->channel[note_data->noteid >> 8].right_adjust;
|
||||
|
||||
/*
|
||||
* ========================
|
||||
* sample position checking
|
||||
* ========================
|
||||
*/
|
||||
note_data->sample_pos += note_data->sample_inc;
|
||||
if (__builtin_expect(
|
||||
(note_data->sample_pos > note_data->sample->loop_end),
|
||||
0)) {
|
||||
if (note_data->modes & SAMPLE_LOOP) {
|
||||
note_data->sample_pos =
|
||||
note_data->sample->loop_start
|
||||
+ ((note_data->sample_pos
|
||||
- note_data->sample->loop_start)
|
||||
% note_data->sample->loop_size);
|
||||
} else if (__builtin_expect(
|
||||
(note_data->sample_pos
|
||||
>= note_data->sample->data_length),
|
||||
0)) {
|
||||
if (__builtin_expect((note_data->replay == NULL), 1)) {
|
||||
goto KILL_NOTE;
|
||||
}
|
||||
goto RESTART_NOTE;
|
||||
}
|
||||
}
|
||||
|
||||
if (__builtin_expect((note_data->env_inc == 0), 0)) {
|
||||
note_data = note_data->next;
|
||||
continue;
|
||||
}
|
||||
|
||||
note_data->env_level += note_data->env_inc;
|
||||
if (__builtin_expect((note_data->env_level > 4194304), 0)) {
|
||||
note_data->env_level =
|
||||
note_data->sample->env_target[note_data->env];
|
||||
}
|
||||
if (__builtin_expect(
|
||||
((note_data->env_inc < 0)
|
||||
&& (note_data->env_level
|
||||
> note_data->sample->env_target[note_data->env]))
|
||||
|| ((note_data->env_inc > 0)
|
||||
&& (note_data->env_level
|
||||
< note_data->sample->env_target[note_data->env])),
|
||||
1)) {
|
||||
note_data = note_data->next;
|
||||
continue;
|
||||
}
|
||||
|
||||
note_data->env_level =
|
||||
note_data->sample->env_target[note_data->env];
|
||||
switch (note_data->env) {
|
||||
case 0:
|
||||
#if 0
|
||||
if (!(note_data->modes & SAMPLE_ENVELOPE)) {
|
||||
note_data->env_inc = 0;
|
||||
note_data = note_data->next;
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
case 2:
|
||||
if (note_data->modes & SAMPLE_SUSTAIN) {
|
||||
note_data->env_inc = 0;
|
||||
note_data = note_data->next;
|
||||
continue;
|
||||
} else if (note_data->modes & SAMPLE_CLAMPED) {
|
||||
note_data->env = 5;
|
||||
if (note_data->env_level
|
||||
> note_data->sample->env_target[5]) {
|
||||
note_data->env_inc =
|
||||
-note_data->sample->env_rate[5];
|
||||
} else {
|
||||
note_data->env_inc =
|
||||
note_data->sample->env_rate[5];
|
||||
}
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
case 5:
|
||||
if (__builtin_expect((note_data->env_level == 0), 1)) {
|
||||
goto KILL_NOTE;
|
||||
}
|
||||
/* sample release */
|
||||
if (note_data->modes & SAMPLE_LOOP)
|
||||
note_data->modes ^= SAMPLE_LOOP;
|
||||
note_data->env_inc = 0;
|
||||
note_data = note_data->next;
|
||||
continue;
|
||||
case 6:
|
||||
if (__builtin_expect((note_data->replay != NULL), 1)) {
|
||||
RESTART_NOTE: note_data->active = 0;
|
||||
{
|
||||
struct _note *prev_note = NULL;
|
||||
struct _note *nte_array = mdi->note;
|
||||
|
||||
if (nte_array != note_data) {
|
||||
do {
|
||||
prev_note = nte_array;
|
||||
nte_array = nte_array->next;
|
||||
} while (nte_array != note_data);
|
||||
}
|
||||
if (prev_note) {
|
||||
prev_note->next = note_data->replay;
|
||||
} else {
|
||||
mdi->note = note_data->replay;
|
||||
}
|
||||
note_data->replay->next = note_data->next;
|
||||
note_data = note_data->replay;
|
||||
note_data->active = 1;
|
||||
}
|
||||
} else {
|
||||
KILL_NOTE: note_data->active = 0;
|
||||
{
|
||||
struct _note *prev_note = NULL;
|
||||
struct _note *nte_array = mdi->note;
|
||||
|
||||
if (nte_array != note_data) {
|
||||
do {
|
||||
prev_note = nte_array;
|
||||
nte_array = nte_array->next;
|
||||
} while ((nte_array != note_data)
|
||||
&& (nte_array));
|
||||
}
|
||||
if (prev_note) {
|
||||
prev_note->next = note_data->next;
|
||||
} else {
|
||||
mdi->note = note_data->next;
|
||||
}
|
||||
note_data = note_data->next;
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
note_data->env++;
|
||||
|
||||
if (note_data->is_off == 1) {
|
||||
do_note_off_extra(note_data);
|
||||
}
|
||||
|
||||
if (note_data->env_level
|
||||
> note_data->sample->env_target[note_data->env]) {
|
||||
note_data->env_inc =
|
||||
-note_data->sample->env_rate[note_data->env];
|
||||
} else {
|
||||
note_data->env_inc =
|
||||
note_data->sample->env_rate[note_data->env];
|
||||
}
|
||||
note_data = note_data->next;
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* =========================
|
||||
* mix the channels together
|
||||
* =========================
|
||||
*/
|
||||
left_mix /= 1024;
|
||||
right_mix /= 1024;
|
||||
}
|
||||
|
||||
*tmp_buffer++ = left_mix;
|
||||
*tmp_buffer++ = right_mix;
|
||||
} while (--count);
|
||||
tmp_buffer = WM_Mix_Gauss(handle, tmp_buffer, real_samples_to_mix);
|
||||
|
||||
buffer_used += real_samples_to_mix * 4;
|
||||
size -= (real_samples_to_mix << 2);
|
||||
|
|
Loading…
Reference in a new issue