Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Let sample tracks play from any song position #3133

Merged
merged 15 commits into from Jan 5, 2017
Merged

Conversation

@BaraMGB
Copy link
Contributor

@BaraMGB BaraMGB commented Nov 26, 2016

Okay, let's test this. I hope I found a solution that works for all.

@Umcaruje
Copy link
Member

@Umcaruje Umcaruje commented Nov 26, 2016

So I did some testing:
screenshot from 2016-11-26 12 45 53

It works really nice when I jump the playhead around and there's low CPU usage

Bugs:

  • When resizing the windows the CPU usage goes really high
  • CPU usage also goes high when you have a lot of sample tracks and you zoom in or out
  • When scrolling and resizing windows there are very noticeable clicks in the audio
  • The sync breaks when the playhead mode is set to anything other than to go back to the beginning after stopping (screenshot from 2016-11-26 12 49 15 screenshot from 2016-11-26 12 49 06)
  • It seems that when you actually resize the sample track so it's bigger than it's normal size, the part with no sample plays random parts of previous samples, or even stuff I previewed beforehand. I'll try to make a video later today.

Loading

@Umcaruje
Copy link
Member

@Umcaruje Umcaruje commented Nov 26, 2016

Here's a video of the weird behaviour: https://youtu.be/Hh9at-DF7hI

Loading

@BaraMGB
Copy link
Contributor Author

@BaraMGB BaraMGB commented Nov 29, 2016

Click noises on resize and scrolling Song Editor should be fixed now.

Loading

@softrabbit
Copy link
Member

@softrabbit softrabbit commented Nov 29, 2016

How well does this cope with time signature and/or tempo automation?

Loading

@BaraMGB
Copy link
Contributor Author

@BaraMGB BaraMGB commented Nov 29, 2016

How well does this cope with time signature and/or tempo automation?

Sorry, thats not implemented yet. Please let's do the things step by step.

Loading

@BaraMGB
Copy link
Contributor Author

@BaraMGB BaraMGB commented Dec 11, 2016

@Umcaruje the fourth point should be fixed now. You can now looping, change songposition per mouse and per left/right key. mute and unmute the track, solo and unsolo an other track, stop pause playing and all that stuff. It will be synced perfectly ( I hope 😄 )

Loading

@zonkmachine
Copy link
Member

@zonkmachine zonkmachine commented Dec 11, 2016

Bloody amazing!

Loading

@tresf
Copy link
Member

@tresf tresf commented Dec 15, 2016

@BaraMGB I'm still getting some pretty bad artifacts if the sample is extended past its length... (white noise, clicks)

untitled

Loading

@BaraMGB
Copy link
Contributor Author

@BaraMGB BaraMGB commented Dec 15, 2016

My plan is to limit the TCO length to sample length. I think this is the simplest way to avoid this.

Loading

@BaraMGB
Copy link
Contributor Author

@BaraMGB BaraMGB commented Dec 15, 2016

@tresf okay, I guess I fixed it. Can you test this again?

Loading

@tresf
Copy link
Member

@tresf tresf commented Dec 16, 2016

artifacts if the sample is extended past its length

[fixed] Can you test this again?

Confirmed, the artifacts are gone.

Loading

@Umcaruje
Copy link
Member

@Umcaruje Umcaruje commented Dec 16, 2016

Do any artifacts occur when you add an empty tco, without any sample loaded?

Loading

@tresf
Copy link
Member

@tresf tresf commented Dec 16, 2016

Do any artifacts occur when you add an empty tco, without any sample loaded?

None.

screen shot 2016-12-16 at 12 46 30 pm

Loading

@Umcaruje
Copy link
Member

@Umcaruje Umcaruje commented Dec 16, 2016

Awesome 👍

Loading

@tresf
Copy link
Member

@tresf tresf commented Dec 16, 2016

@Umcaruje @BaraMGB @softrabbit I think this is ready to merge. I understand time signature will break this however we have many bugs today with time signature and seeking ahead. I want this in 1.2.0-RC2 so that we get solid usage and feedback on it.

Loading

@Umcaruje
Copy link
Member

@Umcaruje Umcaruje commented Dec 16, 2016

The drawing sequence needs to be simplified so it won't produce such high cpu usage on redraws, though I guess that could be an issue for a seperate PR. I'm going to do some more thorough testing now.

Loading

@Umcaruje
Copy link
Member

@Umcaruje Umcaruje commented Dec 16, 2016

Ok so I found a problem: when you change the time signature to something other than 4/4 visually the sample view breaks. The track seems to sync up properly to the new time signature, but it's off from the drawn waveform. And on 3/4 time signature when you add a blank element it looks like this:
image
And it should be 1 measure long as usual

Loading

@BaraMGB
Copy link
Contributor Author

@BaraMGB BaraMGB commented Dec 17, 2016

Oh boy, that time signature stuff drives me crazy. I hope my thoughts about that and the resulting calculations are correct. Please test this out. @tresf @Umcaruje

Loading

@tresf
Copy link
Member

@tresf tresf commented Dec 17, 2016

👍

screen shot 2016-12-17 at 11 22 41 am

Loading

@zonkmachine
Copy link
Member

@zonkmachine zonkmachine commented Dec 17, 2016

Works mighty well. Is it screaming hard to have this work in the Beat/Bassline Sample Track too?

Loading

{
if( sTco->isPlaying() == false )
{
f_cnt_t sampleStart = ( _start * framesPerTick ) - ( sTco->startPosition() * framesPerTick );
Copy link
Contributor

@zapashcanon zapashcanon Dec 17, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

f_cnt_t sampleStart = framesPerTick * ( _start - sTco->startPosition() );

Loading

if( sTco->isPlaying() == false )
{
f_cnt_t sampleStart = ( _start * framesPerTick ) - ( sTco->startPosition() * framesPerTick );
f_cnt_t tcoFrameLength = ( sTco->endPosition() * framesPerTick ) - ( sTco->startPosition() * framesPerTick );
Copy link
Contributor

@zapashcanon zapashcanon Dec 17, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

f_cnt_t tcoFrameLength = framesPerTick * ( sTco->endPosition() - sTco->startPosition() );

Loading

@@ -394,10 +454,12 @@ void SampleTCOView::paintEvent( QPaintEvent * pe )
/ (float) m_tco->length().getTact() :
pixelsPerTact();

float nom = Engine::getSong()->getTimeSigModel().getNumerator();
float den = Engine::getSong()->getTimeSigModel().getDenominator();
float ticksPerTact = DefaultTicksPerTact * ( nom / den );
Copy link
Contributor

@zapashcanon zapashcanon Dec 17, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

float ticksPerTact = DefaultTicksPerTact * nom / den;

Loading

@zonkmachine
Copy link
Member

@zonkmachine zonkmachine commented Dec 17, 2016

clicktrack

clicktrack.zip Edit: re-uploaded with correct samples...

OK. I made a test project with two different length click tracks and they sync perfectly. However, every now and then the samples will cut out after the first click on one and sometimes both sides. I haven't seen this on export.

Loading

@zonkmachine
Copy link
Member

@zonkmachine zonkmachine commented Jan 1, 2017

https://github.com/LMMS/lmms/blob/master/src/core/Song.cpp#L262:L274

I thought there was cases in the code where we go one tick ahead (when we're playing) but I can't find any examples of it.

Loading

@zonkmachine
Copy link
Member

@zonkmachine zonkmachine commented Jan 1, 2017

if the loop goes back to start the first tick is not played

Also, the glitchy tick on loop back, is that the first tick of the next bar before a loop? So the whole audio track is one tick off... but instrument tracks isn't?

Loading

f_cnt_t sampleStart = ( _start * framesPerTick ) - ( sTco->startPosition() * framesPerTick );
f_cnt_t tcoFrameLength = ( sTco->endPosition() * framesPerTick ) - ( sTco->startPosition() * framesPerTick );
f_cnt_t sampleStart = framesPerTick * ( _start - sTco->startPosition() );
f_cnt_t tcoFrameLength = framesPerTick * ( sTco->endPosition() - sTco->startPosition() );
f_cnt_t sampleBufferLength = sTco->sampleBuffer()->frames();
//if the Tco smaller than the sample length we play only until Tco end
//else we play the sample to the end but nothing more
f_cnt_t samplePlayLength = tcoFrameLength > sampleBufferLength ? sampleBufferLength : tcoFrameLength;
//we only play within the sampleBuffer limits
if( sampleStart < sTco->sampleBuffer()->frames() )
Copy link
Contributor

@zapashcanon zapashcanon Jan 1, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if( sampleStart < sampleBufferLength )

Loading

Copy link
Contributor Author

@BaraMGB BaraMGB Jan 2, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you, sometimes I'm a little bit blind. ;)

Loading

@BaraMGB
Copy link
Contributor Author

@BaraMGB BaraMGB commented Jan 2, 2017

@zonkmachine the next problem is, this seems to be a timing issue. On my big computer (i7) the loop seems perfect. So on different computers it appears different.

edit: there's something fishy, but I don't see it. 😩

Loading

@BaraMGB
Copy link
Contributor Author

@BaraMGB BaraMGB commented Jan 5, 2017

@zonkmachine : perhaps this is a stupid idea:
https://github.com/BaraMGB/lmms/blob/sampletrack/src/core/Song.cpp#L341-L344
Here the loopback position emits the signal one tick earlier. Your clicktrack seem okay now. But may be the sampletrack is cut off at the end now ( one tick ) I can't hear and test it. For me it sounds okay.

Loading

if( m_playPos[m_playMode] == tl->loopEnd() - 1 )
{
emit updateSampleTracks();
}
if( m_playPos[m_playMode] >= tl->loopEnd() )
{
m_playPos[m_playMode].setTicks( tl->loopBegin().getTicks() );

m_elapsedMilliSeconds =
( ( tl->loopBegin().getTicks() ) * 60 * 1000 / 48 ) /
Copy link
Contributor

@zapashcanon zapashcanon Jan 5, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

m_elapsedMilliSeconds = tl->loopBegin().getTicks() * 1250 / getTempo();

Loading

Copy link
Contributor

@zapashcanon zapashcanon Jan 5, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And the same thing on lines 269, 326, 409, 574 and 643.

Loading

Copy link
Member

@zonkmachine zonkmachine Jan 5, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No. This will make it harder to deduce where 1250 came from in the first place. The compiler does operations on real numbers for us.

Loading

Copy link
Contributor Author

@BaraMGB BaraMGB Jan 5, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't want to change code I don't have to touch. I want to have this PR as clean as possible. We can make an extra PR with code cleaning stuff.

Loading

if( m_playPos[m_playMode] == tl->loopEnd() - 1 )
{
emit updateSampleTracks();
}
if( m_playPos[m_playMode] >= tl->loopEnd() )
Copy link
Contributor

@zapashcanon zapashcanon Jan 5, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

else if( m_playPos[m_playMode] >= tl->loopEnd() )

Loading

Copy link
Contributor

@zapashcanon zapashcanon Jan 5, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would also switch them, as the second one is likely to be true more often.

Loading

Copy link
Contributor Author

@BaraMGB BaraMGB Jan 5, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a great idea. I've changed this.

Loading

Copy link
Member

@zonkmachine zonkmachine Jan 5, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you should just try and move the whole loop one tick earlier. (in if( checkLoop ) )

if( m_playPos[m_playMode] >= tl->loopEnd() )
{
     m_playPos[m_playMode].setTicks( tl->loopBegin().getTicks() );

to something like (pseudocodeish...):

if( m_playPos[m_playMode] >= tl->loopEnd().getTicks() - 1 )
{
     m_playPos[m_playMode].setTicks( tl->loopBegin().getTicks() - 1 );

Loading

@@ -298,7 +311,7 @@ void SampleTCOView::updateSample()
// sample-tco contains
ToolTip::add( this, ( m_tco->m_sampleBuffer->audioFile() != "" ) ?
m_tco->m_sampleBuffer->audioFile() :
tr( "double-click to select sample" ) );
tr( "double-click to select sample" ) );
Copy link
Member

@Umcaruje Umcaruje Jan 5, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

2 spaces added on accident

Loading

@Umcaruje
Copy link
Member

@Umcaruje Umcaruje commented Jan 5, 2017

Ok so we went over this PR on Discord and both @BaraMGB and @zonkmachine agree on a merge. I'm going to merge this once Travis is done buidling, and we can make an RC2 🎉

There are a few quirks in the GUI drawing and also one minor bug when looping, and that can be adressed later.

Loading

@Umcaruje Umcaruje changed the title lets Sampletrack play from any song position Let sample tracks play from any song position Jan 5, 2017
@Umcaruje Umcaruje merged commit 43a77a0 into LMMS:master Jan 5, 2017
1 check was pending
Loading
liushuyu added a commit to senseab/lmms that referenced this issue Jan 10, 2017
* play sampletracks from any song position

* take care of TCO length

* TCOs shouldn't be updated when SE window is resized

* take care of zooming level

* takes care on all song position changes and mute/solo tracks now

* playes the sample only within the buffer limits

* takes care of time signature changes

* some minor code improvements (zapashcanon)

* loopback one tick earlier

* minor code changes

* get rid off clicks by resize and scrolling song editor

* removes playhandle by remove TCO

* minor bugs on manipulating TCOs in Song Editor

* update on add sample by playing

* white spaces 1
@zonkmachine
Copy link
Member

@zonkmachine zonkmachine commented Jan 17, 2017

@zonkmachine : perhaps this is a stupid idea:
https://github.com/BaraMGB/lmms/blob/sampletrack/src/core/Song.cpp#L341-L344
Here the loopback position emits the signal one tick earlier. Your clicktrack seem okay now. But may be the sampletrack is cut off at the end now ( one tick ) I can't hear and test it. For me it sounds okay.

The glitches are still there but not as prominent. I'm looking into it.

Loading

@zonkmachine
Copy link
Member

@zonkmachine zonkmachine commented Jan 24, 2017

So on different computers it appears different.

Apparently libsndfile corrected some buffer overflow error in 1.0.26 and I'm on 1.0.25 so this could be related.

Loading

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Linked issues

Successfully merging this pull request may close these issues.

None yet

6 participants