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 #include "looperclip.hxx"
20 
21 #include <stdio.h>
22 #include "config.hxx"
23 #include "jack.hxx"
24 #include "event.hxx"
25 #include "eventhandler.hxx"
26 #include "audiobuffer.hxx"
27 
28 #include "controllerupdater.hxx"
29 #include "timemanager.hxx"
30 #include <math.h>
31 
32 
33 extern Jack* jack;
34 
LooperClip(int t,int s)35 LooperClip::LooperClip(int t, int s) :
36 	Stately(),
37 	track(t),
38 	scene(s)
39 {
40 	_buffer = new AudioBuffer();
41 	_buffer->nonRtResize( 4410 );
42 	init();
43 }
44 
init()45 void LooperClip::init()
46 {
47 	_loaded     = false;
48 	_playing    = false;
49 	_recording  = false;
50 
51 	_queuePlay  = false;
52 	_queueStop  = false;
53 	_queueRecord= false;
54 
55 	if ( _buffer ) {
56 		_buffer->init();
57 	}
58 	_newBufferInTransit = false;
59 
60 	_playhead   = 0;
61 	_recordhead = 0;
62 
63 	_barsPlayed = 0;
64 
65 }
66 
save()67 void LooperClip::save()
68 {
69 	// ensure the buffer exists, and is saveable (not recording)
70 	if ( _loaded && !_recording && !_queueRecord ) {
71 		char buffer [50];
72 		sprintf (buffer, "LC::save() track %i, scene %i", track,scene);
73 		EventGuiPrint e( buffer );
74 		writeToGuiRingbuffer( &e );
75 
76 		int frames = _buffer->getAudioFrames();
77 		EventRequestSaveBuffer e2( track, scene, frames );
78 		writeToGuiRingbuffer( &e2 );
79 	} else {
80 		// notify of "success" of save if there *is* no state to save
81 		Stately::success();
82 	}
83 }
84 
reset()85 void LooperClip::reset()
86 {
87 	// TODO make the LooperClip reset to initial state
88 	if ( _loaded ) {
89 		char buffer [50];
90 		sprintf (buffer, "LC::reset() track %i, scene %i", track,scene);
91 		EventGuiPrint e( buffer );
92 		writeToGuiRingbuffer( &e );
93 
94 		// set "progress" to zero as there's no clip anymore
95 		jack->getControllerUpdater()->setTrackSceneProgress(track, scene, 0 );
96 	} else {
97 		//SaveAble::done();
98 	}
99 
100 	init();
101 }
102 
103 /// loads a sample: eg from disk, unloading current sample if necessary
load(AudioBuffer * ab)104 void LooperClip::load( AudioBuffer* ab )
105 {
106 	_loaded = true;
107 	_recording = false;
108 	_playing    = false;
109 
110 	_queuePlay  = false;
111 	_queueStop  = false;
112 	_queueRecord= false;
113 
114 	if ( _buffer ) {
115 		EventDeallocateBuffer e( _buffer );
116 		writeToGuiRingbuffer( &e );
117 	}
118 
119 	_buffer = ab;
120 
121 	_playhead = 0;
122 	_barsPlayed = 0;
123 	jack->getControllerUpdater()->setTrackSceneProgress(track, scene, 0);
124 
125 	// set the endpoint to the buffer's size
126 	_recordhead = _buffer->getSize();
127 
128 #ifdef DEBUG_BUFFER
129 	char buffer [50];
130 	sprintf (buffer, "LC::load() t %i, s %i, aF %i",track, scene, int(_buffer->getAudioFrames()) );
131 	EventGuiPrint e( buffer );
132 	writeToGuiRingbuffer( &e );
133 #endif
134 }
135 
setRequestedBuffer(AudioBuffer * ab)136 void LooperClip::setRequestedBuffer( AudioBuffer* ab )
137 {
138 	if ( _buffer ) {
139 		size_t size = _buffer->getSize();
140 		memcpy( &ab->getDataL().at(0), &_buffer->getDataL().at(0), sizeof(float)*size);
141 		memcpy( &ab->getDataR().at(0), &_buffer->getDataR().at(0), sizeof(float)*size);
142 
143 		ab->setID   ( _buffer->getID()    );
144 		ab->setBeats( _buffer->getBeats() );
145 
146 		EventDeallocateBuffer e( _buffer );
147 		writeToGuiRingbuffer( &e );
148 	}
149 
150 	_buffer = ab;
151 
152 	_newBufferInTransit = false;
153 }
154 
155 
156 
recieveSaveBuffer(AudioBuffer * saveBuffer)157 void LooperClip::recieveSaveBuffer( AudioBuffer* saveBuffer )
158 {
159 	if ( saveBuffer->getSize() >= _buffer->getDataL().at(0) ||
160 	     saveBuffer->getSize() >= _buffer->getDataR().at(0) ) {
161 		// copy current contents into save buffer,
162 		// getData() contains L and R buffer, so twice the size is needed
163 		size_t framesBySize = _buffer->getAudioFrames();
164 		memcpy( &saveBuffer->getDataL().at(0), &_buffer->getDataL().at(0), sizeof(float)*framesBySize);
165 		memcpy( &saveBuffer->getDataR().at(0), &_buffer->getDataR().at(0), sizeof(float)*framesBySize);
166 
167 		saveBuffer->setID   ( _buffer->getID()    );
168 		saveBuffer->setBeats( _buffer->getBeats() );
169 		saveBuffer->setAudioFrames( _buffer->getAudioFrames() );
170 
171 		EventStateSaveBuffer e ( track, scene, saveBuffer );
172 		writeToGuiRingbuffer( &e );
173 
174 		Stately::success();
175 	} else {
176 		char buffer [50];
177 		sprintf (buffer, "LC:: %i, %i: can't save, buf too small",track, scene );
178 		EventGuiPrint e( buffer );
179 		writeToGuiRingbuffer( &e );
180 		Stately::error("");
181 	}
182 }
183 
setPlayHead(float ph)184 void LooperClip::setPlayHead(float ph)
185 {
186 	if(!_recording&&_playing) {
187 		_playhead = ph;
188 		jack->getControllerUpdater()->setTrackSceneProgress(track, scene, getProgress() );
189 	}
190 }
191 
192 
193 
record(int count,float * L,float * R)194 void LooperClip::record(int count, float* L, float* R)
195 {
196 	// write "count" samples into current buffer.
197 	if ( _buffer ) {
198 		size_t size = _buffer->getSize();
199 
200 		for(int i = 0; i < count; i++) {
201 			if ( _recordhead < size ) {
202 				_buffer->getDataL().at( _recordhead ) = *L++;
203 				_buffer->getDataR().at( _recordhead ) = *R++;
204 				_recordhead++;
205 			} else {
206 				// break: this is *BAD*, audio data is lost but the buffer isn't here
207 				// yet to hold new audio data so there's no option. This has not been
208 				// encountered in actual usage, only during the development process.
209 				char buffer [50];
210 				sprintf (buffer, "LooperClip t %i, s %i, Error: out of mem!",track, scene );
211 				EventGuiPrint e( buffer );
212 				writeToGuiRingbuffer( &e );
213 #ifdef BUILD_TESTS
214 				LUPPP_WARN("%s","buffer has no space");
215 #endif
216 
217 				break;
218 			}
219 		}
220 	}
221 
222 	_loaded = true;
223 }
224 
recordSpaceAvailable()225 unsigned long LooperClip::recordSpaceAvailable()
226 {
227 	if ( _buffer )
228 		// getData() contains L and R buffer, so it is twice the size
229 		return _buffer->getSize() - _recordhead;
230 
231 	return 0;
232 }
233 
audioBufferSize()234 size_t LooperClip::audioBufferSize()
235 {
236 	if ( _buffer ) {
237 		return _buffer->getSize();
238 	}
239 	return 0;
240 }
241 
setBeats(int beats)242 void LooperClip::setBeats(int beats)
243 {
244 	if ( _buffer ) {
245 		_buffer->setBeats( beats );
246 	}
247 }
248 
getBeats()249 int LooperClip::getBeats()
250 {
251 	if ( _buffer )
252 		return _buffer->getBeats();
253 
254 	return 0;
255 }
256 
getBufferLenght()257 long LooperClip::getBufferLenght()
258 {
259 	return _recordhead;
260 }
261 
getActualAudioLength()262 long LooperClip::getActualAudioLength()
263 {
264 	char cbuffer [50];
265 //    sprintf (cbuffer, "LooperClip recordhead %f,audioFrames %d \n",_recordhead,(int)_buffer->getAudioFrames());
266 //    EventGuiPrint e( cbuffer );
267 //    writeToGuiRingbuffer( &e );
268 //    printf(cbuffer);
269 	return _buffer->getAudioFrames();
270 }
271 
bar()272 void LooperClip::bar()
273 {
274 	bool change = false;
275 	GridLogic::State s = GridLogic::STATE_EMPTY;
276 
277 	// first update the buffer, as time has passed
278 	if ( _recording ) {
279 		// FIXME: assumes 4 beats in a bar
280 		_buffer->setBeats( _buffer->getBeats() + 4 );
281 		_buffer->setAudioFrames( jack->getTimeManager()->getFpb() * _buffer->getBeats() );
282 	}
283 
284 	if ( _playing ) {
285 		_barsPlayed++;
286 	}
287 
288 	if ( _playing && _barsPlayed >= getBeats() / 4) {
289 #ifdef DEBUG_TIME
290 			cout << "reset: " << _playhead << " - " << _barsPlayed << "\n";
291 #endif
292 		_barsPlayed = 0;
293 		_playhead = 0;
294 	}
295 
296 	if ( _playhead >= _recordhead ) {
297 		_playhead = 0.f;
298 		_barsPlayed = 0;
299 	}
300 
301 	if ( _queuePlay && _loaded ) {
302 		//LUPPP_NOTE("QPLay + loaded" );
303 		_playing = true;
304 		s = GridLogic::STATE_PLAYING;
305 		_recording = false;
306 		_queuePlay = false;
307 		change = true;
308 
309 		_playhead = 0;
310 		_barsPlayed = 0;
311 	}
312 	else if (_queueStop && _loaded)
313 	{
314 		_playing   = false;
315 		s = GridLogic::STATE_STOPPED;
316 		_recording = false;
317 		_queueStop = false;
318 		change = true;
319 		// set "progress" to zero, as we're stopped!
320 		jack->getControllerUpdater()->setTrackSceneProgress(track, scene, 0 );
321 	} else if ( _queueRecord ) {
322 		_recording   = true;
323 		s = GridLogic::STATE_RECORDING;
324 		_playing     = false;
325 		_queueRecord = false;
326 		change = true;
327 
328 		if ( _buffer ) {
329 			_buffer->setBeats( 0 );
330 		}
331 
332 		_recordhead = 0;
333 	} else if ( _queuePlay ) {
334 		// clip was queued, but there's nothing loaded
335 		_queuePlay = false;
336 		change = true;
337 	}
338 
339 	if ( change ) {
340 		jack->getControllerUpdater()->setSceneState(track, scene, s );
341 	}
342 }
343 
neutralize()344 void LooperClip::neutralize()
345 {
346 	_queuePlay = false;
347 	_queueRecord = false;
348 	_queueStop = false;
349 }
350 
somethingQueued()351 bool LooperClip::somethingQueued()
352 {
353 	if ( _queuePlay || _queueStop || _queueRecord ) {
354 		return true;
355 	}
356 	return false;
357 }
358 
queuePlay(bool qP)359 void LooperClip::queuePlay(bool qP)
360 {
361 	_queuePlay   = true;
362 	_queueStop   = false;
363 	_queueRecord = false;
364 }
365 
queueStop()366 void LooperClip::queueStop()
367 {
368 	// comment
369 	if ( _loaded ) {
370 		_queueStop   = true;
371 		_queuePlay   = false;
372 	}
373 }
374 
queueRecord()375 void LooperClip::queueRecord()
376 {
377 	_queueRecord = true;
378 	_queuePlay   = false;
379 	_queueStop   = false;
380 }
381 
getState()382 GridLogic::State LooperClip::getState()
383 {
384 	GridLogic::State s = GridLogic::STATE_EMPTY;
385 
386 	if ( _loaded       )
387 		s = GridLogic::STATE_STOPPED;
388 	if ( _playing      )
389 		s = GridLogic::STATE_PLAYING;
390 	if ( _recording    )
391 		s = GridLogic::STATE_RECORDING;
392 	if ( _queuePlay    )
393 		s = GridLogic::STATE_PLAY_QUEUED;
394 	if ( _queueStop    )
395 		s = GridLogic::STATE_STOP_QUEUED;
396 	if ( _queueRecord  )
397 		s = GridLogic::STATE_RECORD_QUEUED;
398 
399 	return s;
400 }
401 
playing()402 bool LooperClip::playing()
403 {
404 	return _playing;
405 }
406 
getQueueStop()407 bool LooperClip::getQueueStop()
408 {
409 	return _queueStop;
410 }
411 
getQueuePlay()412 bool LooperClip::getQueuePlay()
413 {
414 	return _queuePlay;
415 }
416 
getLoaded()417 bool LooperClip::getLoaded()
418 {
419 	return _loaded;
420 }
421 
recording()422 bool LooperClip::recording()
423 {
424 	return _recording;
425 }
426 
newBufferInTransit(bool n)427 void LooperClip::newBufferInTransit(bool n)
428 {
429 	_newBufferInTransit = n;
430 }
431 
newBufferInTransit()432 bool LooperClip::newBufferInTransit()
433 {
434 	return _newBufferInTransit;
435 }
436 
getSample(long double playSpeed,float * L,float * R)437 void LooperClip::getSample(long double playSpeed, float* L, float* R)
438 {
439 	if ( _buffer && (_buffer->getSize() > 0)) {
440 		if ( _playhead >= _recordhead ||
441 		     _playhead >= _buffer->getSize() ||
442 		     _playhead < 0  ) {
443 			_playhead = 0;
444 			_barsPlayed = 0;
445 
446 			EventGuiPrint e( "LooperClip resetting _playhead" );
447 			//writeToGuiRingbuffer( &e );
448 		}
449 
450 		std::vector<float>& vL = _buffer->getDataL();
451 		std::vector<float>& vR = _buffer->getDataR();
452 		*L = vL[_playhead+0.5];
453 		*R = vR[_playhead+0.5];
454 		_playhead += playSpeed;
455 	} else {
456 		*L = 0.f;
457 		*R = 0.f;
458 	}
459 }
460 
getProgress()461 float LooperClip::getProgress()
462 {
463 	if ( _buffer && _playing ) {
464 		float p = float(_playhead) / _recordhead;
465 		//printf("LooperClip progress %f\n", p );
466 		return p;
467 	}
468 	return 0.f;
469 }
470 
getPlayhead()471 float LooperClip::getPlayhead()
472 {
473 	return _playhead;
474 }
475 
476 #ifdef BUILD_TESTS
setState(bool load,bool play,bool rec,bool qPlay,bool qStop,bool qRec)477 void LooperClip::setState( bool load, bool play, bool rec, bool qPlay, bool qStop, bool qRec )
478 {
479 	_loaded       = load;
480 	_playing      = play;
481 	_recording    = rec;
482 
483 	_queuePlay    = qPlay;
484 	_queueStop    = qStop;
485 	_queueRecord  = qRec;
486 }
487 #endif
488