summaryrefslogtreecommitdiff
path: root/libs/fluidsynth/src/fluid_voice.h
blob: fb0b28239f3a7c74fb83b8b0087c8b586a7d838f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
/* 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 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
 */


#ifndef _FLUID_VOICE_H
#define _FLUID_VOICE_H

#include "fluid_phase.h"
#include "fluid_gen.h"
#include "fluid_mod.h"
#include "fluid_iir_filter.h"
#include "fluid_adsr_env.h"
#include "fluid_lfo.h"
#include "fluid_rvoice.h"
#include "fluid_rvoice_event.h"
#include "fluid_sys.h"

#define NO_CHANNEL             0xff

typedef struct _fluid_overflow_prio_t fluid_overflow_prio_t;

struct _fluid_overflow_prio_t
{
    float percussion; /**< Is this voice on the drum channel? Then add this score */
    float released; /**< Is this voice in release stage? Then add this score (usually negative) */
    float sustained; /**< Is this voice sustained? Then add this score (usually negative) */
    float volume; /**< Multiply current (or future) volume (a value between 0 and 1) */
    float age; /**< This score will be divided by the number of seconds the voice has lasted */
    float important; /**< This score will be added to all important channels */
    char *important_channels; /**< "important" flags indexed by MIDI channel number */
    int num_important_channels; /**< Number of elements in the important_channels array */
};

enum fluid_voice_status
{
    FLUID_VOICE_CLEAN,
    FLUID_VOICE_ON,
    FLUID_VOICE_SUSTAINED,         /* Sustained by Sustain pedal */
    FLUID_VOICE_HELD_BY_SOSTENUTO, /* Sustained by Sostenuto pedal */
    FLUID_VOICE_OFF
};


/*
 * fluid_voice_t
 */
struct _fluid_voice_t
{
    unsigned int id;                /* the id is incremented for every new noteon.
					   it's used for noteoff's  */
    unsigned char status;
    unsigned char chan;             /* the channel number, quick access for channel messages */
    unsigned char key;              /* the key of the noteon event, quick access for noteoff */
    unsigned char vel;              /* the velocity of the noteon event */
    fluid_channel_t *channel;
    fluid_rvoice_eventhandler_t *eventhandler;
    fluid_zone_range_t *zone_range;  /* instrument zone range*/
    fluid_sample_t *sample;         /* Pointer to sample (dupe in rvoice) */

    unsigned int start_time;
    int mod_count;
    fluid_mod_t mod[FLUID_NUM_MOD];
    fluid_gen_t gen[GEN_LAST];

    /* basic parameters */
    fluid_real_t output_rate;        /* the sample rate of the synthesizer (dupe in rvoice) */

    /* basic parameters */
    fluid_real_t pitch;              /* the pitch in midicents (dupe in rvoice) */
    fluid_real_t attenuation;        /* the attenuation in centibels (dupe in rvoice) */
    fluid_real_t root_pitch;

    /* master gain (dupe in rvoice) */
    fluid_real_t synth_gain;

    /* pan */
    fluid_real_t pan;

    /* balance */
    fluid_real_t balance;

    /* reverb */
    fluid_real_t reverb_send;

    /* chorus */
    fluid_real_t chorus_send;

    /* rvoice control */
    fluid_rvoice_t *rvoice;
    fluid_rvoice_t *overflow_rvoice; /* Used temporarily and only in overflow situations */
    char can_access_rvoice; /* False if rvoice is being rendered in separate thread */
    char can_access_overflow_rvoice; /* False if overflow_rvoice is being rendered in separate thread */
    char has_noteoff; /* Flag set when noteoff has been sent */

#ifdef WITH_PROFILING
    /* for debugging */
    double ref;
#endif
};


fluid_voice_t *new_fluid_voice(fluid_rvoice_eventhandler_t *handler, fluid_real_t output_rate);
void delete_fluid_voice(fluid_voice_t *voice);

void fluid_voice_start(fluid_voice_t *voice);
void  fluid_voice_calculate_gen_pitch(fluid_voice_t *voice);

int fluid_voice_init(fluid_voice_t *voice, fluid_sample_t *sample,
                     fluid_zone_range_t *inst_zone_range,
                     fluid_channel_t *channel, int key, int vel,
                     unsigned int id, unsigned int time, fluid_real_t gain);

int fluid_voice_modulate(fluid_voice_t *voice, int cc, int ctrl);
int fluid_voice_modulate_all(fluid_voice_t *voice);

/** Set the NRPN value of a generator. */
int fluid_voice_set_param(fluid_voice_t *voice, int gen, fluid_real_t value, int abs);


/** Set the gain. */
int fluid_voice_set_gain(fluid_voice_t *voice, fluid_real_t gain);

void fluid_voice_set_output_rate(fluid_voice_t *voice, fluid_real_t value);


/** Update all the synthesis parameters, which depend on generator
    'gen'. This is only necessary after changing a generator of an
    already operating voice.  Most applications will not need this
    function.*/
void fluid_voice_update_param(fluid_voice_t *voice, int gen);

/** legato modes */
/* force in the attack section for legato mode multi_retrigger: 1 */
void fluid_voice_update_multi_retrigger_attack(fluid_voice_t *voice, int tokey, int vel);
/* Update portamento parameter */
void fluid_voice_update_portamento(fluid_voice_t *voice, int fromkey, int tokey);


void fluid_voice_release(fluid_voice_t *voice);
void fluid_voice_noteoff(fluid_voice_t *voice);
void fluid_voice_off(fluid_voice_t *voice);
void fluid_voice_stop(fluid_voice_t *voice);
void fluid_voice_add_mod_local(fluid_voice_t *voice, fluid_mod_t *mod, int mode, int check_limit_count);
void fluid_voice_overflow_rvoice_finished(fluid_voice_t *voice);

int fluid_voice_kill_excl(fluid_voice_t *voice);
float fluid_voice_get_overflow_prio(fluid_voice_t *voice,
                                    fluid_overflow_prio_t *score,
                                    unsigned int cur_time);

#define OVERFLOW_PRIO_CANNOT_KILL 999999.

/**
 * Locks the rvoice for rendering, so it can't be modified directly
 */
static FLUID_INLINE void
fluid_voice_lock_rvoice(fluid_voice_t *voice)
{
    voice->can_access_rvoice = 0;
}

/**
 * Unlocks the rvoice for rendering, so it can be modified directly
 */
static FLUID_INLINE void
fluid_voice_unlock_rvoice(fluid_voice_t *voice)
{
    voice->can_access_rvoice = 1;
}

#define _AVAILABLE(voice)  ((voice)->can_access_rvoice && \
 (((voice)->status == FLUID_VOICE_CLEAN) || ((voice)->status == FLUID_VOICE_OFF)))
//#define _RELEASED(voice)  ((voice)->chan == NO_CHANNEL)
#define _SAMPLEMODE(voice) ((int)(voice)->gen[GEN_SAMPLEMODE].val)


fluid_real_t fluid_voice_gen_value(const fluid_voice_t *voice, int num);
void fluid_voice_set_custom_filter(fluid_voice_t *voice, enum fluid_iir_filter_type type, enum fluid_iir_filter_flags flags);


#endif /* _FLUID_VOICE_H */