3 |
* LinuxSampler - modular, streaming capable sampler * |
* LinuxSampler - modular, streaming capable sampler * |
4 |
* * |
* * |
5 |
* Copyright (C) 2003, 2004 by Benno Senoner and Christian Schoenebeck * |
* Copyright (C) 2003, 2004 by Benno Senoner and Christian Schoenebeck * |
6 |
* Copyright (C) 2005, 2006 Christian Schoenebeck * |
* Copyright (C) 2005 - 2007 Christian Schoenebeck * |
7 |
* * |
* * |
8 |
* This program is free software; you can redistribute it and/or modify * |
* This program is free software; you can redistribute it and/or modify * |
9 |
* it under the terms of the GNU General Public License as published by * |
* it under the terms of the GNU General Public License as published by * |
24 |
#ifndef __LS_GIG_VOICE_H__ |
#ifndef __LS_GIG_VOICE_H__ |
25 |
#define __LS_GIG_VOICE_H__ |
#define __LS_GIG_VOICE_H__ |
26 |
|
|
27 |
#include "../../common/global.h" |
#include "../../common/global_private.h" |
28 |
|
|
29 |
#include <gig.h> |
#include <gig.h> |
30 |
|
|
31 |
#include "../../common/RTMath.h" |
#include "../../common/RTMath.h" |
32 |
#include "../../common/Pool.h" |
#include "../../common/Pool.h" |
33 |
#include "../../drivers/audio/AudioOutputDevice.h" |
#include "../../drivers/audio/AudioOutputDevice.h" |
|
#include "Engine.h" |
|
|
#include "EngineChannel.h" |
|
34 |
#include "Stream.h" |
#include "Stream.h" |
35 |
#include "DiskThread.h" |
#include "DiskThread.h" |
36 |
#include "EGADSR.h" |
#include "EGADSR.h" |
37 |
#include "EGDecay.h" |
#include "EGDecay.h" |
38 |
#include "Filter.h" |
#include "Filter.h" |
39 |
#include "../common/LFOBase.h" |
#include "../common/LFOBase.h" |
40 |
|
#include "../common/VoiceBase.h" |
41 |
#include "SynthesisParam.h" |
#include "SynthesisParam.h" |
42 |
#include "SmoothVolume.h" |
#include "SmoothVolume.h" |
43 |
|
|
64 |
#endif |
#endif |
65 |
|
|
66 |
namespace LinuxSampler { namespace gig { |
namespace LinuxSampler { namespace gig { |
|
|
|
67 |
class Engine; |
class Engine; |
68 |
|
class EngineChannel; |
69 |
|
|
70 |
/// Reflects a MIDI controller |
/// Reflects a MIDI controller |
71 |
struct midi_ctrl { |
struct midi_ctrl { |
94 |
* |
* |
95 |
* Renders a voice for the Gigasampler format. |
* Renders a voice for the Gigasampler format. |
96 |
*/ |
*/ |
97 |
class Voice { |
class Voice : public LinuxSampler::VoiceBase< ::gig::DimensionRegion> { |
98 |
public: |
public: |
|
// Types |
|
|
enum type_t { |
|
|
type_normal, |
|
|
type_release_trigger_required, ///< If the key of this voice will be released, it causes a release triggered voice to be spawned |
|
|
type_release_trigger ///< Release triggered voice which cannot be killed by releasing its key |
|
|
}; |
|
|
|
|
99 |
// Attributes |
// Attributes |
100 |
type_t Type; ///< Voice Type |
type_t Type; ///< Voice Type |
101 |
int MIDIKey; ///< MIDI key number of the key that triggered the voice |
int MIDIKey; ///< MIDI key number of the key that triggered the voice |
109 |
void Render(uint Samples); |
void Render(uint Samples); |
110 |
void Reset(); |
void Reset(); |
111 |
void SetOutput(AudioOutputDevice* pAudioOutputDevice); |
void SetOutput(AudioOutputDevice* pAudioOutputDevice); |
112 |
void SetEngine(Engine* pEngine); |
void SetEngine(LinuxSampler::Engine* pEngine); |
113 |
int Trigger(EngineChannel* pEngineChannel, Pool<Event>::Iterator& itNoteOnEvent, int PitchBend, ::gig::DimensionRegion* pDimRgn, type_t VoiceType, int iKeyGroup); |
int Trigger(EngineChannel* pEngineChannel, Pool<Event>::Iterator& itNoteOnEvent, int PitchBend, ::gig::DimensionRegion* pDimRgn, type_t VoiceType, int iKeyGroup); |
114 |
inline bool IsActive() { return PlaybackState; } |
inline bool IsActive() { return PlaybackState; } |
115 |
inline bool IsStealable() { return !itKillEvent && PlaybackState >= playback_state_ram; } |
inline bool IsStealable() { return !itKillEvent && PlaybackState >= playback_state_ram; } |
116 |
void UpdatePortamentoPos(Pool<Event>::Iterator& itNoteOffEvent); |
void UpdatePortamentoPos(Pool<Event>::Iterator& itNoteOffEvent); |
117 |
|
|
118 |
//private: |
virtual ::gig::DimensionRegion* GetRegion() { return pDimRgn; } |
|
// Types |
|
|
enum playback_state_t { |
|
|
playback_state_end = 0, |
|
|
playback_state_init = 1, |
|
|
playback_state_ram = 2, |
|
|
playback_state_disk = 3 |
|
|
}; |
|
119 |
|
|
120 |
|
//private: |
121 |
// Attributes |
// Attributes |
122 |
EngineChannel* pEngineChannel; |
EngineChannel* pEngineChannel; |
123 |
Engine* pEngine; ///< Pointer to the sampler engine, to be able to access the event lists. |
Engine* pEngine; ///< Pointer to the sampler engine, to be able to access the event lists. |
130 |
double Pos; ///< Current playback position in sample |
double Pos; ///< Current playback position in sample |
131 |
float PitchBase; ///< Basic pitch depth, stays the same for the whole life time of the voice |
float PitchBase; ///< Basic pitch depth, stays the same for the whole life time of the voice |
132 |
float PitchBend; ///< Current pitch value of the pitchbend wheel |
float PitchBend; ///< Current pitch value of the pitchbend wheel |
133 |
|
float PitchBendRange; ///< The pitch range of the pitchbend wheel, value is in cents / 8192 |
134 |
float CutoffBase; ///< Cutoff frequency before control change, EG and LFO are applied |
float CutoffBase; ///< Cutoff frequency before control change, EG and LFO are applied |
135 |
::gig::Sample* pSample; ///< Pointer to the sample to be played back |
::gig::Sample* pSample; ///< Pointer to the sample to be played back |
136 |
::gig::DimensionRegion* pDimRgn; ///< Pointer to the articulation information of current dimension region of this voice |
::gig::DimensionRegion* pDimRgn; ///< Pointer to the articulation information of current dimension region of this voice |
137 |
|
bool Orphan; ///< true if this voice is playing a sample from an instrument that is unloaded. When the voice dies, the sample (and dimension region) will be handed back to the instrument resource manager. |
138 |
playback_state_t PlaybackState; ///< When a sample will be triggered, it will be first played from RAM cache and after a couple of sample points it will switch to disk streaming and at the end of a disk stream we have to add null samples, so the interpolator can do it's work correctly |
playback_state_t PlaybackState; ///< When a sample will be triggered, it will be first played from RAM cache and after a couple of sample points it will switch to disk streaming and at the end of a disk stream we have to add null samples, so the interpolator can do it's work correctly |
139 |
bool DiskVoice; ///< If the sample is very short it completely fits into the RAM cache and doesn't need to be streamed from disk, in that case this flag is set to false |
bool DiskVoice; ///< If the sample is very short it completely fits into the RAM cache and doesn't need to be streamed from disk, in that case this flag is set to false |
140 |
Stream::reference_t DiskStreamRef; ///< Reference / link to the disk stream |
Stream::reference_t DiskStreamRef; ///< Reference / link to the disk stream |
168 |
static float CalculateFilterCutoffCoeff(); |
static float CalculateFilterCutoffCoeff(); |
169 |
|
|
170 |
// Methods |
// Methods |
171 |
void KillImmediately(); |
Stream::Handle KillImmediately(bool bRequestNotification = false); |
172 |
void ProcessEvents(uint Samples); |
void ProcessEvents(uint Samples); |
173 |
void Synthesize(uint Samples, sample_t* pSrc, uint Skip); |
void Synthesize(uint Samples, sample_t* pSrc, uint Skip); |
174 |
void processTransitionEvents(RTList<Event>::Iterator& itEvent, uint End); |
void processTransitionEvents(RTList<Event>::Iterator& itEvent, uint End); |