Evil bug fixed in ALSA driver which was causing it to terminate even if

an ALSA write error was recovered successfully, now using inline roundf
replacement for dithering.
This commit is contained in:
Element Green 2007-01-14 17:48:51 +00:00
parent 932e87f1b7
commit b66e52e14d
7 changed files with 34 additions and 181 deletions

View file

@ -115,5 +115,5 @@ Rui Nuno Capela
Frieder Bürzele
Henri Manson
Mihail Zenkov
Paul Miller
Paul Millar
Nick Daly

View file

@ -1,3 +1,12 @@
2007-01-14 Josh Green <jgreen@users.sourceforge.net>
* src/fluid_alsa.c: Fixed evil bugs in ALSA driver where return value
of new fluid_alsa_handle_write_error() was not being checked correctly
causing successfully handled ALSA errors (underruns for example) to
terminate audio thread.
* src/fluid_synth.c: Using an inline roundi function to replace roundf
as per suggestion by Mihail Zenkov, 16 bit for dithering.
2006-12-10 Josh Green <jgreen@users.sourceforge.net>
Lots of documentation updates.
@ -13,7 +22,7 @@
* src/fluid_aufile.c: Now also doing 16 bit dithering.
* src/fluid_cmd.c: Removed use of old tokenizer instance.
* src/fluid_coreaudio.c: User defined callback function is now honored.
* src/fluid_defsfont.c: More leaks plugged (thanks to Paul Miller for
* src/fluid_defsfont.c: More leaks plugged (thanks to Paul Millar for
the patch), removed sfont_free_data() since sfont_close() should be
used instead (don't want to leak a file handle).
* src/fluid_midi_router.c: Took out uses of fflush() since sending a
@ -24,7 +33,7 @@
other improvements.
* src/fluid_synth.c (delete_fluid_synth): Turning off all voices so that
SoundFont data will be freed correctly (thanks to patch from
Paul Miller).
Paul Millar).
* src/fluid_sys.c (fluid_strtok): New function to replace old tokenizing
functions which required a token instance.
* src/fluidsynth.c: Warning message printed if a non option is not a

View file

@ -478,7 +478,7 @@ static void* fluid_alsa_audio_run_float(void* d)
if (n < 0) /* error occurred? */
{
if (!fluid_alsa_handle_write_error (dev->pcm, n))
if (fluid_alsa_handle_write_error (dev->pcm, n) != FLUID_OK)
goto error_recovery;
} else offset += n; /* no error occurred */
} /* while (offset < buffer_size) */
@ -498,7 +498,7 @@ static void* fluid_alsa_audio_run_float(void* d)
if (n < 0) /* error occurred? */
{
if (!fluid_alsa_handle_write_error (dev->pcm, n))
if (fluid_alsa_handle_write_error (dev->pcm, n) != FLUID_OK)
goto error_recovery;
} else offset += n; /* no error occurred */
} /* while (offset < buffer_size) */
@ -563,7 +563,7 @@ static void* fluid_alsa_audio_run_s16(void* d)
if (n < 0) /* error occurred? */
{
if (!fluid_alsa_handle_write_error (dev->pcm, n))
if (fluid_alsa_handle_write_error (dev->pcm, n) != FLUID_OK)
goto error_recovery;
} else offset += n; /* no error occurred */
} /* while (offset < buffer_size) */
@ -580,7 +580,7 @@ static void* fluid_alsa_audio_run_s16(void* d)
if (n < 0) /* error occurred? */
{
if (!fluid_alsa_handle_write_error (dev->pcm, n))
if (fluid_alsa_handle_write_error (dev->pcm, n) != FLUID_OK)
goto error_recovery;
} else offset += n; /* no error occurred */
} /* while (offset < buffer_size) */

View file

@ -95,4 +95,5 @@ HWND fluid_win32_get_window(void)
{
return fluid_wnd;
}
#endif
#endif // #ifdef WIN32

View file

@ -1,123 +0,0 @@
/* FluidSynth - A Software Synthesizer
*
* Copyright (C) 2003 Peter Hanappe and others.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public License
* as published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
* 02111-1307, USA
*/
#include "fluid_strtok.h"
#include "fluidsynth_priv.h"
/*
* new_fluid_strtok
*/
fluid_strtok_t* new_fluid_strtok(char* s, char* d)
{
fluid_strtok_t* st;
st = FLUID_NEW(fluid_strtok_t);
if (st == NULL) {
FLUID_LOG(FLUID_ERR, "Out of memory");
return NULL;
}
/* Careful! the strings are not copied for speed */
st->string = s;
st->delimiters = d;
st->offset = 0;
st->len = (s == NULL)? 0 : strlen(s);
return st;
}
int delete_fluid_strtok(fluid_strtok_t* st)
{
if (st == NULL) {
FLUID_LOG(FLUID_ERR, "Null pointer");
return 0;
}
free(st);
return 0;
}
int fluid_strtok_set(fluid_strtok_t* st, char* s, char* d)
{
/* Careful! the strings are not copied for speed */
st->string = s;
st->delimiters = d;
st->offset = 0;
st->len = (s == NULL)? 0 : strlen(s);
return 0;
}
char* fluid_strtok_next_token(fluid_strtok_t* st)
{
int start = st->offset;
int end;
if ((st == NULL) || (st->string == NULL) || (st->delimiters == NULL)) {
FLUID_LOG(FLUID_ERR, "Null pointer");
return NULL;
}
if (start >= st->len) {
return NULL;
}
while (fluid_strtok_char_index(st->string[start], st->delimiters) >= 0) {
if (start == st->len) {
return NULL;
}
start++;
}
end = start + 1;
while (fluid_strtok_char_index(st->string[end], st->delimiters) < 0) {
if (end == st->len) {
break;
}
end++;
}
st->string[end] = 0;
st->offset = end + 1;
return &st->string[start];
}
int fluid_strtok_has_more(fluid_strtok_t* st)
{
int cur = st->offset;
if ((st == NULL) || (st->string == NULL) || (st->delimiters == NULL)) {
FLUID_LOG(FLUID_ERR, "Null pointer");
return -1;
}
while (cur < st->len) {
if (fluid_strtok_char_index(st->string[cur], st->delimiters) < 0) {
return -1;
}
cur++;
}
return 0;
}
int fluid_strtok_char_index(char c, char* s)
{
int i;
if (s == NULL) {
FLUID_LOG(FLUID_ERR, "Null pointer");
return -1;
}
for (i = 0; s[i] != 0; i++) {
if (s[i] == c) {
return i;
}
}
return -1;
}

View file

@ -1,44 +0,0 @@
/* FluidSynth - A Software Synthesizer
*
* Copyright (C) 2003 Peter Hanappe and others.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public License
* as published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
* 02111-1307, USA
*/
#ifndef _FLUID_STRTOK_H
#define _FLUID_STRTOK_H
#include "fluidsynth_priv.h"
/** string tokenizer */
typedef struct {
char* string;
char* delimiters;
int offset;
int len;
} fluid_strtok_t;
fluid_strtok_t* new_fluid_strtok(char* s, char* d);
int delete_fluid_strtok(fluid_strtok_t* st);
int fluid_strtok_set(fluid_strtok_t* st, char* s, char* d);
char* fluid_strtok_next_token(fluid_strtok_t* st);
int fluid_strtok_has_more(fluid_strtok_t* st);
int fluid_strtok_char_index(char c, char* s);
#endif /* _FLUID_STRTOK_H */

View file

@ -1722,6 +1722,16 @@ static void init_dither(void)
}
}
/* A portable replacement for roundf(), seems it may actually be faster too! */
static inline int
roundi (float x)
{
if (x >= 0.0f)
return (int)(x+0.5f);
else
return (int)(x-0.5f);
}
/*
* fluid_synth_write_s16
*/
@ -1740,6 +1750,7 @@ fluid_synth_write_s16(fluid_synth_t* synth, int len,
fluid_real_t right_sample;
double time = fluid_utime();
int di = synth->dither_index;
double prof_ref_on_block;
/* make sure we're playing */
if (synth->state != FLUID_SYNTH_PLAYING) {
@ -1752,8 +1763,7 @@ fluid_synth_write_s16(fluid_synth_t* synth, int len,
/* fill up the buffers as needed */
if (cur == FLUID_BUFSIZE) {
double prof_ref_on_block = fluid_profile_ref();
prof_ref_on_block = fluid_profile_ref();
fluid_synth_one_block(synth, 0);
cur = 0;
@ -1761,8 +1771,8 @@ fluid_synth_write_s16(fluid_synth_t* synth, int len,
fluid_profile(FLUID_PROF_ONE_BLOCK, prof_ref_on_block);
}
left_sample = left_in[cur] * 32767.0f + rand_table[0][di];
right_sample = right_in[cur] * 32767.0f + rand_table[1][di];
left_sample = roundi (left_in[cur] * 32766.0f + rand_table[0][di]);
right_sample = roundi (right_in[cur] * 32766.0f + rand_table[1][di]);
di++;
if (di >= DITHER_SIZE) di = 0;
@ -1815,8 +1825,8 @@ fluid_synth_dither_s16(fluid_synth_t* synth, int len, float* lin, float* rin,
for (i = 0, j = loff, k = roff; i < len; i++, j += lincr, k += rincr) {
left_sample = lin[i] * 32767.0f + rand_table[0][di];
right_sample = rin[i] * 32767.0f + rand_table[1][di];
left_sample = roundi (lin[i] * 32766.0f + rand_table[0][di]);
right_sample = roundi (rin[i] * 32766.0f + rand_table[1][di]);
di++;
if (di >= DITHER_SIZE) di = 0;