Skip to content

Commit 453dd5a

Browse files
committed
added cue IN/OUT for advanced loop control
1 parent f2caf31 commit 453dd5a

File tree

2 files changed

+56
-13
lines changed

2 files changed

+56
-13
lines changed

src/objects/sound/SoundfilePlayer.cpp

Lines changed: 54 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@
3737
//--------------------------------------------------------------
3838
SoundfilePlayer::SoundfilePlayer() : PatchObject("soundfile player"){
3939

40-
this->numInlets = 5;
40+
this->numInlets = 7;
4141
this->numOutlets = 3;
4242

4343
_inletParams[0] = new string(); // control
@@ -48,8 +48,12 @@ SoundfilePlayer::SoundfilePlayer() : PatchObject("soundfile player"){
4848
*(float *)&_inletParams[2] = 0.0f;
4949
_inletParams[3] = new float(); // volume
5050
*(float *)&_inletParams[3] = 0.0f;
51-
_inletParams[4] = new float(); // trigger
51+
_inletParams[4] = new float(); // cue IN
5252
*(float *)&_inletParams[4] = 0.0f;
53+
_inletParams[5] = new float(); // cue OUT
54+
*(float *)&_inletParams[5] = 0.0f;
55+
_inletParams[6] = new float(); // trigger
56+
*(float *)&_inletParams[6] = 0.0f;
5357

5458
_outletParams[0] = new ofSoundBuffer(); // signal
5559
_outletParams[1] = new vector<float>(); // audio buffer
@@ -95,6 +99,8 @@ void SoundfilePlayer::newObject(){
9599
this->addInlet(VP_LINK_NUMERIC,"playhead");
96100
this->addInlet(VP_LINK_NUMERIC,"speed");
97101
this->addInlet(VP_LINK_NUMERIC,"volume");
102+
this->addInlet(VP_LINK_NUMERIC,"cue in");
103+
this->addInlet(VP_LINK_NUMERIC,"cue out");
98104
this->addInlet(VP_LINK_NUMERIC,"bang");
99105

100106
this->addOutlet(VP_LINK_AUDIO,"audioFileSignal");
@@ -200,6 +206,16 @@ void SoundfilePlayer::updateObjectContent(map<int,shared_ptr<PatchObject>> &patc
200206
volume = ofClamp(*(float *)&_inletParams[3],0.0f,1.0f);
201207
}
202208

209+
// cue IN
210+
if(this->inletsConnected[4]){
211+
cueIN = static_cast<double>(ofClamp(*(float *)&_inletParams[4],0.0,cueOUT-2));
212+
}
213+
214+
// cue OUT
215+
if(this->inletsConnected[5]){
216+
cueOUT = static_cast<double>(ofClamp(*(float *)&_inletParams[5],cueIN+2, audiofile.length()-2));
217+
}
218+
203219
// outlet finish bang
204220
if(finishBang){
205221
*(float *)&_outletParams[2] = 1.0f;
@@ -268,17 +284,23 @@ void SoundfilePlayer::drawObjectNodeGui( ImGuiEx::NodeCanvas& _nodeCanvas ){
268284
// draw player state
269285
if(isPlaying){ // play
270286
_nodeCanvas.getNodeDrawList()->AddTriangleFilled(ImVec2(window_pos.x+window_size.x-(50*_nodeCanvas.GetCanvasScale()),window_pos.y+window_size.y-(40*_nodeCanvas.GetCanvasScale())), ImVec2(window_pos.x+window_size.x-(50*_nodeCanvas.GetCanvasScale()), window_pos.y+window_size.y-(20*_nodeCanvas.GetCanvasScale())), ImVec2(window_pos.x+window_size.x-(30*_nodeCanvas.GetCanvasScale()), window_pos.y+window_size.y-(30*_nodeCanvas.GetCanvasScale())), IM_COL32(255, 255, 255, 120));
271-
}else if(!isPlaying && playhead > 0.0){ // pause
287+
}else if(!isPlaying && playhead > cueIN){ // pause
272288
_nodeCanvas.getNodeDrawList()->AddRectFilled(ImVec2(window_pos.x+window_size.x-(50*_nodeCanvas.GetCanvasScale()),window_pos.y+window_size.y-(40*_nodeCanvas.GetCanvasScale())),ImVec2(window_pos.x+window_size.x-(42*_nodeCanvas.GetCanvasScale()),window_pos.y+window_size.y-(20*_nodeCanvas.GetCanvasScale())),IM_COL32(255, 255, 255, 120));
273289
_nodeCanvas.getNodeDrawList()->AddRectFilled(ImVec2(window_pos.x+window_size.x-(38*_nodeCanvas.GetCanvasScale()),window_pos.y+window_size.y-(40*_nodeCanvas.GetCanvasScale())),ImVec2(window_pos.x+window_size.x-(30*_nodeCanvas.GetCanvasScale()),window_pos.y+window_size.y-(20*_nodeCanvas.GetCanvasScale())),IM_COL32(255, 255, 255, 120));
274-
}else if(!isPlaying && playhead == 0.0){ // stop
290+
}else if(!isPlaying && playhead == cueIN){ // stop
275291
_nodeCanvas.getNodeDrawList()->AddRectFilled(ImVec2(window_pos.x+window_size.x-(50*_nodeCanvas.GetCanvasScale()),window_pos.y+window_size.y-(40*_nodeCanvas.GetCanvasScale())),ImVec2(window_pos.x+window_size.x-(30*_nodeCanvas.GetCanvasScale()),window_pos.y+window_size.y-(20*_nodeCanvas.GetCanvasScale())),IM_COL32(255, 255, 255, 120));
276292
}
277293

278294
// draw playhead
279295
float phx = ofMap( playhead, 0, audiofile.length()*0.98f, 1, (this->width*0.98f*_nodeCanvas.GetCanvasScale())-(31*this->scaleFactor) );
280296
_nodeCanvas.getNodeDrawList()->AddLine(ImVec2(ph_pos.x + phx, ph_pos.y),ImVec2(ph_pos.x + phx, window_size.y+ph_pos.y-(26*this->scaleFactor)),IM_COL32(255, 255, 255, 160), 2.0f);
281297

298+
// draw cues IN OUT
299+
float cinx = ofMap( cueIN, 0, audiofile.length()*0.98f, 1, (this->width*0.98f*_nodeCanvas.GetCanvasScale())-(31*this->scaleFactor) );
300+
_nodeCanvas.getNodeDrawList()->AddLine(ImVec2(ph_pos.x + cinx, ph_pos.y),ImVec2(ph_pos.x + cinx, window_size.y+ph_pos.y-(26*this->scaleFactor)),IM_COL32(255, 0, 0, 160), 2.0f);
301+
float coutx = ofMap( cueOUT, 0, audiofile.length()*0.98f, 1, (this->width*0.98f*_nodeCanvas.GetCanvasScale())-(31*this->scaleFactor) );
302+
_nodeCanvas.getNodeDrawList()->AddLine(ImVec2(ph_pos.x + coutx, ph_pos.y),ImVec2(ph_pos.x + coutx, window_size.y+ph_pos.y-(26*this->scaleFactor)),IM_COL32(255, 0, 0, 160), 2.0f);
303+
282304
}else if(loadingFile){
283305
ImGui::Text("LOADING FILE...");
284306
}else if(!isNewObject && !audiofile.loaded()){
@@ -327,14 +349,14 @@ void SoundfilePlayer::drawObjectNodeConfig(){
327349
ImGui::PushStyleColor(ImGuiCol_ButtonActive, VHS_BLUE_OVER);
328350
if(ImGui::Button(ICON_FA_PLAY,ImVec2(69*scaleFactor,26*scaleFactor))){
329351
isPlaying = true;
330-
playhead = 0.0;
352+
playhead = cueIN;
331353
audioWasPlaying = true;
332354
finishSemaphore = true;
333355
}
334356
ImGui::SameLine();
335357
if(ImGui::Button(ICON_FA_STOP,ImVec2(69*scaleFactor,26*scaleFactor))){
336358
isPlaying = false;
337-
playhead = 0.0;
359+
playhead = cueIN;
338360
audioWasPlaying = false;
339361
}
340362
ImGui::PopStyleColor(3);
@@ -356,6 +378,24 @@ void SoundfilePlayer::drawObjectNodeConfig(){
356378
ImGui::Spacing();
357379
ImGui::Checkbox("LOOP " ICON_FA_REDO,&loop);
358380

381+
ImGui::Spacing();
382+
float tempcueIN = cueIN;
383+
if(ImGui::SliderFloat("CUE IN",&tempcueIN,0.0, cueOUT-2)){
384+
cueIN = static_cast<double>(tempcueIN);
385+
if(playhead < cueIN){
386+
playhead = cueIN;
387+
}
388+
389+
}
390+
ImGui::Spacing();
391+
float tempcueOUT = cueOUT;
392+
if(ImGui::SliderFloat("CUE OUT",&tempcueOUT,cueIN+2, audiofile.length()-2)){
393+
cueOUT = static_cast<double>(tempcueOUT);
394+
if(playhead > cueOUT){
395+
playhead = cueOUT;
396+
}
397+
}
398+
359399
ImGuiEx::ObjectInfo(
360400
"Audiofile player, it can load .wav, .mp3, .ogg, and .flac files.",
361401
"https://mosaic.d3cod3.org/reference.php?r=soundfile-player", scaleFactor);
@@ -386,22 +426,21 @@ void SoundfilePlayer::audioOutObject(ofSoundBuffer &outputBuffer){
386426

387427
// trigger, this needs to run in audio thread
388428
if(this->inletsConnected[4]){
389-
if(ofClamp(*(float *)&_inletParams[4],0.0f,1.0f) == 1.0f && !isNextCycle){
429+
if(ofClamp(*(float *)&_inletParams[6],0.0f,1.0f) == 1.0f && !isNextCycle){
390430
isNextCycle = true;
391-
playhead = 0.0;
431+
playhead = cueIN;
392432
isPlaying = true;
393433
finishSemaphore = true;
394434
}else if(playhead > 6000){
395435
isNextCycle = false;
396436
}
397-
398437
}
399438

400439
if(isFileLoaded && audiofile.loaded() && isPlaying){
401440
for(size_t i = 0; i < monoBuffer.getNumFrames(); i++) {
402441
int n = static_cast<int>(floor(playhead));
403442

404-
if(n < static_cast<int>(audiofile.length()-1)){
443+
if(static_cast<unsigned long long>(n) < cueOUT-1){
405444
float fract = static_cast<float>(playhead - n);
406445
float isample = audiofile.sample(n, 0)*(1.0f-fract) + audiofile.sample(n+1, 0)*fract; // linear interpolation
407446
monoBuffer.getSample(i,0) = isample * volume;
@@ -419,9 +458,9 @@ void SoundfilePlayer::audioOutObject(ofSoundBuffer &outputBuffer){
419458
if(loop){
420459
// backword
421460
if(speed < 0.0){
422-
playhead = audiofile.length()-2;
461+
playhead = cueOUT;
423462
}else if(speed > 0.0){
424-
playhead = 0.0;
463+
playhead = cueIN;
425464
}
426465
}
427466
}
@@ -488,7 +527,9 @@ void SoundfilePlayer::loadAudioFile(string audiofilepath){
488527
monoBuffer.clear();
489528
monoBuffer = tmpBuffer;
490529

491-
playhead = 0.0;
530+
cueIN = 0.0;
531+
cueOUT = audiofile.length()-2;
532+
playhead = cueIN;
492533

493534
this->saveConfig(false);
494535

src/objects/sound/SoundfilePlayer.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,8 @@ class SoundfilePlayer : public PatchObject {
8282
pdsp::Scope scope;
8383
float *plot_data;
8484
double playhead;
85+
double cueIN;
86+
double cueOUT;
8587
double step;
8688
double sampleRate;
8789
int bufferSize;

0 commit comments

Comments
 (0)