-
Notifications
You must be signed in to change notification settings - Fork 3
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
Change tempo to be in beats per minute #1
base: master
Are you sure you want to change the base?
Conversation
If you are changing the divisions you could get into a situation where the current step is out of bounds.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for contributing!
@@ -45,10 +45,10 @@ function setTempo(tempo) { | |||
|
|||
function setSequence(division, sequence) { | |||
if (typeof division !== 'number') throw new TypeError('Division must be a number'); | |||
if (!(sequence instanceof Array)) throw new TypeError('Sequence must be an array'); | |||
if (sequence && !(sequence instanceof Array)) throw new TypeError('Sequence must be an array'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
While you're here, let's change sequence instanceof Array
to Array.isArray(sequence)
.
@@ -20,9 +20,9 @@ function loop() { | |||
} | |||
|
|||
function advance() { | |||
if (this.step >= this.division) this.step = 0; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good catch, I think this makes more sense as well.
Though, I think this should be:
if (this.step >= this.sequence.length) this.step = 0;
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well, I am working under the assumption that the sequence can be empty because that's the way I have been using this. If we init it the way you describe below then it's different.
function calcTimeout(tempo, division) { | ||
return Math.floor((60 / tempo * division) * 10e8) + 'n'; | ||
function calcTimeout(tempo) { | ||
return Math.floor((60 / tempo) * 10e8) + 'n'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The way I had it initially, you could have multiple subdivisions per beat, i.e. you could say the tempo is 120
, and the division is 4
, and you would get 4 emits per beat. This is useful if you want eighth, sixteenth, half notes, etc.
This new way only emits once per beat. I guess you could change the tempo to get the effect of having subdivisions, but I would prefer to have subdivisions.
Thoughts?
@@ -49,11 +49,11 @@ function setSequence(division, sequence) { | |||
|
|||
this.division = division; | |||
this.sequence = sequence; | |||
this.timeout = calcTimeout(this.tempo, this.division) | |||
this.timeout = calcTimeout(this.tempo) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Semicolon.
@@ -66,7 +66,7 @@ function StepSequencer(tempo, division, sequence) { | |||
this.sequence = sequence || []; | |||
this.step = 0; | |||
this.timer = new NanoTimer(); | |||
this.timeout = calcTimeout(this.tempo, this.division) | |||
this.timeout = calcTimeout(this.tempo) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Semicolon.
|
||
this.division = division; | ||
this.sequence = sequence; | ||
this.sequence = sequence || []; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure, we could make the sequence optional. But maybe we should default to an Array that is the same length as the number of subdivisions (or maybe 16, typical step-sequencer length)
this.sequence = sequence || Array(divisions);
// or
this.sequence = sequence || Array(16);
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think I copied the initialization from the constructor.
Thanks for reviewing! There are two features mixed together on this branch now because I have been using my fork in my project and needed all these changes. I should have sent separate PRs from feature branches. Sorry about that. This could be split into the following, maybe you could comment on both.
To quote what you said about 1. already.
In my step sequencer I have 3 arguments: stepSequencer = new StepSequencer(tempo * stepsPerBeat, numberOfSteps) If I change one of those variables I do: stepSequencer.setTempo(tempo * stepsPerBeat)
stepSequencer.setSequence(numberOfSteps)
stepSequencer.removeAllListeners()
registerAllListeners() //loops through range numberOfSteps to register all the event handlers I found this way easier to reason about and I am still not sure I could do it if tempo was tied to divisions. |
Would you be happy to change the constructor to? StepSequencer(tempo, stepsPerBeat, numberOfSteps [, sequence]) Though I am not quite sure what to do about checking the size of the sequence array if we allow people to |
I fixed the semi-colons. Any thoughts on this? If I can't get this merged in some way I'll have to release a fork as I'd like to put my Launchpad step sequencer up on NPM. |
Hey @kasbah, I'll take a look at this when I get home from work. Hopefully we can get this merged in the next day or two. |
Looking at the constructor you posted earlier: StepSequencer(tempo, stepsPerBeat, numberOfSteps [, sequence]) I like this. I wrote this project while trying to create a little step sequencer for a Raspberry Pi/Teenage Engineering Pocket Operator thing. In the var sequence = [
true, false, false, false,
true, false, false, false,
true, false, false, false,
true, false, false, false
];
var sequencer = new StepSequencer(120, 4, 16, sequence);
// On you launchpad:
// [X] [ ] [ ] [ ] [X] [ ] [ ] [ ]
// [X] [ ] [ ] [ ] [X] [ ] [ ] [ ] Of course, you could keep the sequence outside of the Anyways, you can change the constructor as you suggested. There would need to be an |
Yes, that does make sense. In my application I prefer to keep the sequence We could make use of dynamic typing and make the last argument either On 30 September 2016 at 15:43, Brandon Freitag [email protected]
|
Ok, so if the last argument is a number, treat it as numberOfSteps, but if it is an array, treat it as sequence, deriving the number of steps from the length of the array. Sounds good to me! |
I am using this to make a nice step sequencer out of my old Novation Launchpad. Thanks very much!
To me it makes more sense to have the tempo be beats per minute and independant of the number of divisions, so I adapted it. What do you think?