<commit_before>/* FluidSynth - A Software Synthesizer
 *
 * Copyright (C) 2003  <NAME> and others.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public License
 * as published by the Free Software Foundation; either version 2.1 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free
 * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 * 02110-1301, USA
 */

#include "fluid_rvoice_mixer.h"
#include "fluid_rvoice.h"
#include "fluid_sys.h"
#include "fluid_rev.h"
#include "fluid_chorus.h"
#include "fluid_ladspa.h"
#include "fluid_synth.h"


// If less than x voices, the thread overhead is larger than the gain,
// so don't activate the thread(s).
#define VOICES_PER_THREAD 8

typedef struct _fluid_mixer_buffers_t fluid_mixer_buffers_t;

struct _fluid_mixer_buffers_t
{
    fluid_rvoice_mixer_t *mixer; /**< Owner of object */
#if ENABLE_MIXER_THREADS
    fluid_thread_t *thread;     /**< Thread object */
    fluid_atomic_int_t ready;   /**< Atomic: buffers are ready for mixing */
#endif

    fluid_rvoice_t **finished_voices; /* List of voices who have finished */
    int finished_voice_count;

    fluid_real_t *local_buf;

    int buf_count;
    int fx_buf_count;

    /** buffer to store the left part of a stereo channel to.
     * Specifically a two dimensional array, containing \c buf_count sample buffers
     * (i.e. for each synth.audio-groups), of which each contains
     * FLUID_BUFSIZE * FLUID_MIXER_MAX_BUFFERS_DEFAULT audio items (=samples)
     * @note Each sample buffer is aligned to the FLUID_DEFAULT_ALIGNMENT
     * boundary provided that this pointer points to an aligned buffer.
     * So make sure to access the sample buffer by first aligning this
     * pointer using fluid_align_ptr()
     */
    fluid_real_t *left_buf;

    /** dito, but for right part of a stereo channel */
    fluid_real_t *right_buf;

    /** buffer to store the left part of a stereo effects channel to.
     * Specifically a two dimensional array, containing \c fx_buf_count buffers
     * (i.e. for each synth.effects-channels), of which each buffer contains
     * FLUID_BUFSIZE * FLUID_MIXER_MAX_BUFFERS_DEFAULT audio items (=samples)
     */
    fluid_real_t *fx_left_buf;
    fluid_real_t *fx_right_buf;
};

typedef struct _fluid_mixer_fx_t fluid_mixer_fx_t;

struct _fluid_mixer_fx_t
{
    fluid_revmodel_t *reverb; /**< Reverb unit */
    fluid_chorus_t *chorus; /**< Chorus unit */
};

struct _fluid_rvoice_mixer_t
{
    fluid_mixer_fx_t *fx;

    fluid_mixer_buffers_t buffers; /**< Used by mixer only: own buffers */
    fluid_rvoice_eventhandler_t *eventhandler;

    fluid_rvoice_t **rvoices; /**< Read-only: Voices array, sorted so that all nulls are last */
    int polyphony; /**< Read-only: Length of voices array */
    int active_voices; /**< Read-only: Number of non-null voices */
    int current_blockcount;      /**< Read-only: how many blocks to process this time */
    int fx_units;
    int with_reverb;        /**< Should the synth use the built-in reverb unit? */
    int with_chorus;        /**< Should the synth use the built-in chorus unit? */
    int mix_fx_to_out;      /**< Should the effects be mixed in with the primary output? */

#ifdef LADSPA
    fluid_ladspa_fx_t *ladspa_fx; /**< Used by mixer only: Effects unit for LADSPA support. Never created or freed */
#endif

#if ENABLE_MIXER_THREADS
//  int sleeping_threads;        /**< Atomic: number of threads currently asleep */
//  int active_threads;          /**< Atomic: number of threads in the thread loop */
    fluid_atomic_int_t threads_should_terminate; /**< Atomic: Set to TRUE when threads should terminate */
    fluid_atomic_int_t current_rvoice;           /**< Atomic: for the threads to know next voice to  */
    fluid_cond_t *wakeup_threads; /**< Signalled when the threads should wake up */
    fluid_cond_mutex_t *wakeup_threads_m; /**< wakeup_threads mutex companion */
    fluid_cond_t *thread_ready; /**< Signalled from thread, when the thread has a buffer ready for mixing */
    fluid_cond_mutex_t *thread_ready_m; /**< thread_ready mutex companion */

    int thread_count;            /**< Number of extra mixer threads for multi-core rendering */
    fluid_mixer_buffers_t *threads;    /**< Array of mixer threads (thread_count in length) */
#endif
};

#if ENABLE_MIXER_THREADS
static void delete_rvoice_mixer_threads(fluid_rvoice_mixer_t *mixer);
static int fluid_rvoice_mixer_set_threads(fluid_rvoice_mixer_t *mixer, int thread_count, int prio_level);
#endif

static FLUID_INLINE void
fluid_rvoice_mixer_process_fx(fluid_rvoice_mixer_t *mixer, int current_blockcount)
{
    const int fx_channels_per_unit = mixer->buffers.fx_buf_count / mixer->fx_units;
    int i, f;
    int dry_count = mixer->buffers.buf_count; /* dry buffers count */
    int dry_idx; /* dry buffer index */

    void (*reverb_process_func)(fluid_revmodel_t *rev, const fluid_real_t *in, fluid_real_t *left_out, fluid_real_t *right_out);
    void (*chorus_process_func)(fluid_chorus_t *chorus, const fluid_real_t *in, fluid_real_t *left_out, fluid_real_t *right_out);

    fluid_real_t *out_rev_l, *out_rev_r, *out_ch_l, *out_ch_r;

    // all dry unprocessed mono input is stored in the left channel
    fluid_real_t *in_rev = fluid_align_ptr(mixer->buffers.fx_left_buf, FLUID_DEFAULT_ALIGNMENT);
    fluid_real_t *in_ch = in_rev;

    fluid_profile_ref_var(prof_ref);


    if(mixer->mix_fx_to_out)
    {
        // mix effects to first stereo channel
        out_ch_l = out_rev_l = fluid_align_ptr(mixer->buffers.left_buf, FLUID_DEFAULT_ALIGNMENT);
        out_ch_r = out_rev_r = fluid_align_ptr(mixer->buffers.right_buf, FLUID_DEFAULT_ALIGNMENT);

        reverb_process_func = fluid_revmodel_processmix;
        chorus_process_func = fluid_chorus_processmix;<commit_msg>Fix possible uninitialized use of dry_idx variable<commit_after>/* FluidSynth - A Software Synthesizer
 *
 * Copyright (C) 2003  <NAME> and others.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public License
 * as published by the Free Software Foundation; either version 2.1 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free
 * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 * 02110-1301, USA
 */

#include "fluid_rvoice_mixer.h"
#include "fluid_rvoice.h"
#include "fluid_sys.h"
#include "fluid_rev.h"
#include "fluid_chorus.h"
#include "fluid_ladspa.h"
#include "fluid_synth.h"


// If less than x voices, the thread overhead is larger than the gain,
// so don't activate the thread(s).
#define VOICES_PER_THREAD 8

typedef struct _fluid_mixer_buffers_t fluid_mixer_buffers_t;

struct _fluid_mixer_buffers_t
{
    fluid_rvoice_mixer_t *mixer; /**< Owner of object */
#if ENABLE_MIXER_THREADS
    fluid_thread_t *thread;     /**< Thread object */
    fluid_atomic_int_t ready;   /**< Atomic: buffers are ready for mixing */
#endif

    fluid_rvoice_t **finished_voices; /* List of voices who have finished */
    int finished_voice_count;

    fluid_real_t *local_buf;

    int buf_count;
    int fx_buf_count;

    /** buffer to store the left part of a stereo channel to.
     * Specifically a two dimensional array, containing \c buf_count sample buffers
     * (i.e. for each synth.audio-groups), of which each contains
     * FLUID_BUFSIZE * FLUID_MIXER_MAX_BUFFERS_DEFAULT audio items (=samples)
     * @note Each sample buffer is aligned to the FLUID_DEFAULT_ALIGNMENT
     * boundary provided that this pointer points to an aligned buffer.
     * So make sure to access the sample buffer by first aligning this
     * pointer using fluid_align_ptr()
     */
    fluid_real_t *left_buf;

    /** dito, but for right part of a stereo channel */
    fluid_real_t *right_buf;

    /** buffer to store the left part of a stereo effects channel to.
     * Specifically a two dimensional array, containing \c fx_buf_count buffers
     * (i.e. for each synth.effects-channels), of which each buffer contains
     * FLUID_BUFSIZE * FLUID_MIXER_MAX_BUFFERS_DEFAULT audio items (=samples)
     */
    fluid_real_t *fx_left_buf;
    fluid_real_t *fx_right_buf;
};

typedef struct _fluid_mixer_fx_t fluid_mixer_fx_t;

struct _fluid_mixer_fx_t
{
    fluid_revmodel_t *reverb; /**< Reverb unit */
    fluid_chorus_t *chorus; /**< Chorus unit */
};

struct _fluid_rvoice_mixer_t
{
    fluid_mixer_fx_t *fx;

    fluid_mixer_buffers_t buffers; /**< Used by mixer only: own buffers */
    fluid_rvoice_eventhandler_t *eventhandler;

    fluid_rvoice_t **rvoices; /**< Read-only: Voices array, sorted so that all nulls are last */
    int polyphony; /**< Read-only: Length of voices array */
    int active_voices; /**< Read-only: Number of non-null voices */
    int current_blockcount;      /**< Read-only: how many blocks to process this time */
    int fx_units;
    int with_reverb;        /**< Should the synth use the built-in reverb unit? */
    int with_chorus;        /**< Should the synth use the built-in chorus unit? */
    int mix_fx_to_out;      /**< Should the effects be mixed in with the primary output? */

#ifdef LADSPA
    fluid_ladspa_fx_t *ladspa_fx; /**< Used by mixer only: Effects unit for LADSPA support. Never created or freed */
#endif

#if ENABLE_MIXER_THREADS
//  int sleeping_threads;        /**< Atomic: number of threads currently asleep */
//  int active_threads;          /**< Atomic: number of threads in the thread loop */
    fluid_atomic_int_t threads_should_terminate; /**< Atomic: Set to TRUE when threads should terminate */
    fluid_atomic_int_t current_rvoice;           /**< Atomic: for the threads to know next voice to  */
    fluid_cond_t *wakeup_threads; /**< Signalled when the threads should wake up */
    fluid_cond_mutex_t *wakeup_threads_m; /**< wakeup_threads mutex companion */
    fluid_cond_t *thread_ready; /**< Signalled from thread, when the thread has a buffer ready for mixing */
    fluid_cond_mutex_t *thread_ready_m; /**< thread_ready mutex companion */

    int thread_count;            /**< Number of extra mixer threads for multi-core rendering */
    fluid_mixer_buffers_t *threads;    /**< Array of mixer threads (thread_count in length) */
#endif
};

#if ENABLE_MIXER_THREADS
static void delete_rvoice_mixer_threads(fluid_rvoice_mixer_t *mixer);
static int fluid_rvoice_mixer_set_threads(fluid_rvoice_mixer_t *mixer, int thread_count, int prio_level);
#endif

static FLUID_INLINE void
fluid_rvoice_mixer_process_fx(fluid_rvoice_mixer_t *mixer, int current_blockcount)
{
    const int fx_channels_per_unit = mixer->buffers.fx_buf_count / mixer->fx_units;
    int i, f;
    int dry_count = mixer->buffers.buf_count; /* dry buffers count */
    int dry_idx = 0; /* dry buffer index */

    void (*reverb_process_func)(fluid_revmodel_t *rev, const fluid_real_t *in, fluid_real_t *left_out, fluid_real_t *right_out);
    void (*chorus_process_func)(fluid_chorus_t *chorus, const fluid_real_t *in, fluid_real_t *left_out, fluid_real_t *right_out);

    fluid_real_t *out_rev_l, *out_rev_r, *out_ch_l, *out_ch_r;

    // all dry unprocessed mono input is stored in the left channel
    fluid_real_t *in_rev = fluid_align_ptr(mixer->buffers.fx_left_buf, FLUID_DEFAULT_ALIGNMENT);
    fluid_real_t *in_ch = in_rev;

    fluid_profile_ref_var(prof_ref);


    if(mixer->mix_fx_to_out)
    {
        // mix effects to first stereo channel
        out_ch_l = out_rev_l = fluid_align_ptr(mixer->buffers.left_buf, FLUID_DEFAULT_ALIGNMENT);
        out_ch_r = out_rev_r = fluid_align_ptr(mixer->buffers.right_buf, FLUID_DEFAULT_ALIGNMENT);

        reverb_process_func = fluid_revmodel_processmix;
        chorus_process_func = fluid_chorus_processmix;
{'fraction_non_alphanumeric': 0.08333996656849478, 'fraction_numerical': 0.002945156411685107, 'mean_word_length': 3.8156381755461863, 'pattern_counts': {'":': 0, '<': 53, '<?xml version=': 0, '>': 19, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1761575', 'n_tokens_mistral': 4103, 'n_tokens_neox': 3959, 'n_words': 1282}