1 /*
2  * Author: Harry van Haaren 2013
3  *         harryhaaren@gmail.com
4  *
5  *  This program is free software: you can redistribute it and/or modify
6  *  it under the terms of the GNU General Public License as published by
7  *  the Free Software Foundation, either version 3 of the License, or
8  *  (at your option) any later version.
9  *
10  *  This program is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  *  GNU General Public License for more details.
14  *
15  *  You should have received a copy of the GNU General Public License
16  *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
17  */
18 
19 #ifndef LUPPP_LOOPER_CLIP_H
20 #define LUPPP_LOOPER_CLIP_H
21 
22 #include <stdio.h>
23 #include "state/stately.hxx"
24 #include "config.hxx"
25 #include "gridlogic.hxx"
26 
27 class AudioBuffer;
28 
29 /** LooperClip
30  * Represents each clip that a looper can playback. The core of the audio
31  * samples is stored in AudioBuffer objects which are dynamically resized. The
32  * base size of a AudioBuffer is 1 second's worth, after which larger buffers
33  * will be requested.
34  * The transition between AudioBuffer instances is seamless: when the clip is
35  * running out, the new one is requested. Upon its arrival the current data is
36  * copied, and the old buffer is returned for deallocation.
37  *
38  * This system allows for arbitrary length recordings, without huge
39  * pre-allocated buffers while it is still quite simple.
40  *
41  * Each clip has its properties like length and bars/beats, so the Looper knows
42  * to dynamically stretch / process the audio appropriately. Controllers and the
43  * UI are updated from this data.
44  *
45  * This class inherits from SaveAble to save its state.
46 **/
47 class LooperClip : public Stately
48 {
49 public:
50 	LooperClip(int track, int scene);
51 
52 	void init();
53 
54 	/// loads a sample: eg from disk, unloading current sample if necessary
55 	void load( AudioBuffer* ab );
56 
57 	/// audio functionality
58 	void getSample(long double playSpeed, float* L, float* R);
59 	void record(int count, float* L, float* R);
60 
61 	/// TimeObserver override
62 	void bar();
63 
64 	/// SaveAble overrides
65 	void save();
66 	void reset();
67 
68 	/// analyses current _playing _recording vars, returns the current State
69 	GridLogic::State getState();
70 	bool playing();
71 	bool getLoaded();
72 	bool getQueueStop();
73 	bool getQueuePlay();
74 	bool recording();
75 
76 	/// get buffer details
77 	int   getBeats();
78 	float getProgress();
79 	float getPlayhead();
80 	//Return the length of the complete buffer
81 	long  getBufferLenght();
82 	//Return the nr of samples holding actual audio. This is less then getBufferLength();
83 	long  getActualAudioLength();
84 	size_t audioBufferSize();
85 
getAudioBuffer()86 	AudioBuffer* getAudioBuffer()
87 	{
88 		return _buffer;
89 	}
90 
91 	/// set clip state
92 	void  queuePlay(bool=true);
93 	void  queueStop();
94 	void  queueRecord();
95 
96 	void  neutralize(); // removes all play || record states if on
97 	bool  somethingQueued(); // returns true if any state is queued
98 
99 	/// set buffer state
100 	void setBeats(int beats);
101 
102 	/// Luppp internal buffer resizing
103 	void newBufferInTransit(bool n);
104 	bool newBufferInTransit();
105 	unsigned long recordSpaceAvailable();
106 
107 	/** used to update the size of the buffer for this looperclip. The current
108 	 *  data is copied into the new buffer, then the smaller buffer is sent
109 	 *  for de-allocation.
110 	**/
111 	void setRequestedBuffer( AudioBuffer* ab );
112 
113 	/// used for saving the contents of this buffer to disk
114 	void recieveSaveBuffer( AudioBuffer* ab );
115 
116 	///reset the play head to zero. Does nothing when recording
117 	void setPlayHead(float ph);
118 
119 #ifdef BUILD_TESTS
120 	// used only in test cases
121 	void setState( bool load, bool play, bool rec, bool qPlay, bool qStop, bool qRec );
122 #endif
123 
124 private:
125 	int track, scene;
126 
127 	/** Luppp needs more than the current state of the clip to accuratly handle
128 	 *  it. The current state of the grid is kept up-to-date by GridLogic
129 	 *  abstracting detail away, sending GridLogic::State to Controllers.
130 	**/
131 	bool _loaded;
132 	bool _playing;
133 	bool _recording;
134 
135 	bool _queuePlay;
136 	bool _queueStop;
137 	bool _queueRecord;
138 
139 	bool _newBufferInTransit;
140 
141 	long double _playhead;
142 	float _recordhead;
143 
144 	unsigned int _barsPlayed;
145 	AudioBuffer* _buffer;
146 };
147 
148 #endif // LUPPP_LOOPER_CLIP_H
149 
150