GigPlayer.h 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371
  1. /*
  2. * GigPlayer.h - a GIG player using libgig (based on Sf2 player plugin)
  3. *
  4. * Copyright (c) 2008 Paul Giblock <drfaygo/at/gmail/dot/com>
  5. * Copyright (c) 2009-2014 Tobias Doerffel <tobydox/at/users.sourceforge.net>
  6. *
  7. * This file is part of LMMS - https://lmms.io
  8. *
  9. * This program is free software; you can redistribute it and/or
  10. * modify it under the terms of the GNU General Public
  11. * License as published by the Free Software Foundation; either
  12. * version 2 of the License, or (at your option) any later version.
  13. *
  14. * This program is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  17. * General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU General Public
  20. * License along with this program (see COPYING); if not, write to the
  21. * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  22. * Boston, MA 02110-1301 USA.
  23. *
  24. */
  25. #ifndef GIG_PLAYER_H
  26. #define GIG_PLAYER_H
  27. #include <QList>
  28. #include <QMutex>
  29. #include <QMutexLocker>
  30. #include <samplerate.h>
  31. #include "Instrument.h"
  32. #include "PixmapButton.h"
  33. #include "InstrumentView.h"
  34. #include "Knob.h"
  35. #include "LcdSpinBox.h"
  36. #include "LedCheckbox.h"
  37. #include "MemoryManager.h"
  38. #include "gig.h"
  39. class GigInstrumentView;
  40. class NotePlayHandle;
  41. class PatchesDialog;
  42. class QLabel;
  43. struct GIGPluginData
  44. {
  45. int midiNote;
  46. } ;
  47. // Load a GIG file using libgig
  48. class GigInstance
  49. {
  50. public:
  51. GigInstance( QString filename ) :
  52. riff( filename.toUtf8().constData() ),
  53. gig( &riff )
  54. {}
  55. private:
  56. RIFF::File riff;
  57. public:
  58. gig::File gig;
  59. } ;
  60. // Stores options for the notes, e.g. velocity and release time
  61. struct Dimension
  62. {
  63. Dimension() :
  64. release( false )
  65. {
  66. for( int i = 0; i < 8; ++i )
  67. {
  68. DimValues[i] = 0;
  69. }
  70. }
  71. uint DimValues[8];
  72. bool release;
  73. } ;
  74. // Takes information from the GIG file for a certain note and provides the
  75. // amplitude (0-1) to multiply the signal by (internally incrementing the
  76. // position in the envelope when asking for the amplitude).
  77. class ADSR
  78. {
  79. // From the file
  80. float preattack; // initial amplitude (0-1)
  81. float attack; // 0-60s
  82. float decay1; // 0-60s
  83. float decay2; // 0-60s
  84. bool infiniteSustain; // i.e., no decay2
  85. float sustain; // sustain amplitude (0-1)
  86. float release; // 0-60s
  87. // Used to calculate current amplitude
  88. float amplitude;
  89. bool isAttack;
  90. bool isRelease;
  91. bool isDone;
  92. f_cnt_t attackPosition;
  93. f_cnt_t attackLength;
  94. f_cnt_t decayLength;
  95. f_cnt_t releasePosition;
  96. f_cnt_t releaseLength;
  97. public:
  98. ADSR();
  99. ADSR( gig::DimensionRegion * region, int sampleRate );
  100. void keyup(); // We will begin releasing starting now
  101. bool done(); // Is this sample done playing?
  102. float value(); // What's the current amplitude
  103. void inc( f_cnt_t num ); // Increment internal positions by num
  104. } ;
  105. // The sample from the GIG file with our current position in both the sample
  106. // and the envelope
  107. class GigSample
  108. {
  109. public:
  110. GigSample( gig::Sample * pSample, gig::DimensionRegion * pDimRegion,
  111. float attenuation, int interpolation, float desiredFreq );
  112. ~GigSample();
  113. // Needed when initially creating in QList
  114. GigSample( const GigSample& g );
  115. GigSample& operator=( const GigSample& g );
  116. // Needed since libsamplerate stores data internally between calls
  117. void updateSampleRate();
  118. bool convertSampleRate( sampleFrame & oldBuf, sampleFrame & newBuf,
  119. f_cnt_t oldSize, f_cnt_t newSize, float freq_factor, f_cnt_t& used );
  120. gig::Sample * sample;
  121. gig::DimensionRegion * region;
  122. float attenuation;
  123. ADSR adsr;
  124. // The position in sample
  125. f_cnt_t pos;
  126. // Whether to change the pitch of the samples, e.g. if there's only one
  127. // sample per octave and you want that sample pitch shifted for the rest of
  128. // the notes in the octave, this will be true
  129. bool pitchtrack;
  130. // Used to convert sample rates
  131. int interpolation;
  132. SRC_STATE * srcState;
  133. // Used changing the pitch of the note if desired
  134. float sampleFreq;
  135. float freqFactor;
  136. } ;
  137. // What portion of a note are we in?
  138. enum GigState
  139. {
  140. // We just pressed the key
  141. KeyDown,
  142. // The note is currently playing
  143. PlayingKeyDown,
  144. // We just released the key
  145. KeyUp,
  146. // The note is being released, e.g. a release sample is playing
  147. PlayingKeyUp,
  148. // The note is done playing, you can delete this note now
  149. Completed
  150. } ;
  151. // Corresponds to a certain midi note pressed, but may contain multiple samples
  152. class GigNote
  153. {
  154. public:
  155. int midiNote;
  156. int velocity;
  157. bool release; // Whether to trigger a release sample on key up
  158. bool isRelease; // Whether this is a release sample, changes when we delete it
  159. GigState state;
  160. float frequency;
  161. QList<GigSample> samples;
  162. // Used to determine which note should be released on key up
  163. //
  164. // Note: if accessing the data, be careful not to access it after the key
  165. // has been released since that's when it is deleted
  166. GIGPluginData * handle;
  167. GigNote( int midiNote, int velocity, float frequency, GIGPluginData * handle )
  168. : midiNote( midiNote ), velocity( velocity ),
  169. release( false ), isRelease( false ), state( KeyDown ),
  170. frequency( frequency ), handle( handle )
  171. {
  172. }
  173. } ;
  174. class GigInstrument : public Instrument
  175. {
  176. Q_OBJECT
  177. MM_OPERATORS
  178. mapPropertyFromModel( int, getBank, setBank, m_bankNum );
  179. mapPropertyFromModel( int, getPatch, setPatch, m_patchNum );
  180. public:
  181. GigInstrument( InstrumentTrack * _instrument_track );
  182. virtual ~GigInstrument();
  183. virtual void play( sampleFrame * _working_buffer );
  184. virtual void playNote( NotePlayHandle * _n,
  185. sampleFrame * _working_buffer );
  186. virtual void deleteNotePluginData( NotePlayHandle * _n );
  187. virtual void saveSettings( QDomDocument & _doc, QDomElement & _parent );
  188. virtual void loadSettings( const QDomElement & _this );
  189. virtual void loadFile( const QString & _file );
  190. virtual AutomatableModel * childModel( const QString & _modelName );
  191. virtual QString nodeName() const;
  192. virtual f_cnt_t desiredReleaseFrames() const
  193. {
  194. return 0;
  195. }
  196. virtual Flags flags() const
  197. {
  198. return IsSingleStreamed|IsNotBendable;
  199. }
  200. virtual PluginView * instantiateView( QWidget * _parent );
  201. QString getCurrentPatchName();
  202. void setParameter( const QString & _param, const QString & _value );
  203. public slots:
  204. void openFile( const QString & _gigFile, bool updateTrackName = true );
  205. void updatePatch();
  206. void updateSampleRate();
  207. private:
  208. // The GIG file and instrument we're using
  209. GigInstance * m_instance;
  210. gig::Instrument * m_instrument;
  211. // Part of the UI
  212. QString m_filename;
  213. LcdSpinBoxModel m_bankNum;
  214. LcdSpinBoxModel m_patchNum;
  215. FloatModel m_gain;
  216. // Locking for the data
  217. QMutex m_synthMutex;
  218. QMutex m_notesMutex;
  219. // Used for resampling
  220. int m_interpolation;
  221. // List of all the currently playing notes
  222. QList<GigNote> m_notes;
  223. // Used when determining which samples to use
  224. uint32_t m_RandomSeed;
  225. float m_currentKeyDimension;
  226. private:
  227. // Delete the current GIG instance if one is open
  228. void freeInstance();
  229. // Open the instrument in the currently-open GIG file
  230. void getInstrument();
  231. // Create "dimension" to select desired samples from GIG file based on
  232. // parameters such as velocity
  233. Dimension getDimensions( gig::Region * pRegion, int velocity, bool release );
  234. // Load sample data from the Gig file, looping the sample where needed
  235. void loadSample( GigSample& sample, sampleFrame* sampleData, f_cnt_t samples );
  236. f_cnt_t getLoopedIndex( f_cnt_t index, f_cnt_t startf, f_cnt_t endf ) const;
  237. f_cnt_t getPingPongIndex( f_cnt_t index, f_cnt_t startf, f_cnt_t endf ) const;
  238. // Add the desired samples to the note, either normal samples or release
  239. // samples
  240. void addSamples( GigNote & gignote, bool wantReleaseSample );
  241. friend class GigInstrumentView;
  242. signals:
  243. void fileLoading();
  244. void fileChanged();
  245. void patchChanged();
  246. } ;
  247. class GigInstrumentView : public InstrumentViewFixedSize
  248. {
  249. Q_OBJECT
  250. public:
  251. GigInstrumentView( Instrument * _instrument,
  252. QWidget * _parent );
  253. virtual ~GigInstrumentView();
  254. private:
  255. virtual void modelChanged();
  256. PixmapButton * m_fileDialogButton;
  257. PixmapButton * m_patchDialogButton;
  258. LcdSpinBox * m_bankNumLcd;
  259. LcdSpinBox * m_patchNumLcd;
  260. QLabel * m_filenameLabel;
  261. QLabel * m_patchLabel;
  262. Knob * m_gainKnob;
  263. static PatchesDialog * s_patchDialog;
  264. protected slots:
  265. void invalidateFile();
  266. void showFileDialog();
  267. void showPatchDialog();
  268. void updateFilename();
  269. void updatePatchName();
  270. } ;
  271. #endif