Author |
Message |
capicoso
Joined: Nov 19, 2012 Posts: 128 Location: Argentina
|
Posted: Mon Jun 10, 2013 10:58 pm Post subject:
Programming midi sequencer |
|
|
Hello. I'm trying to build a midi sequencer. I'm using the midi library. The sequencer would be similar to analogs on pot for tempo, 8 switches for gates, 8 pots for note for each step, and i want to add other 8 pots to control the lenght of the steps. in two manners:
the easy one, done already. When the step is short, it'll play and jump without silence. Basically it just shorts the overall step duration.
The hard one im having trouble with is, i want to control the duration of the note, but the i don't want the step to change. So this would change the duration of the note on and at the same time, the duration of the silence or note off, so if the whole step is 2seg, when the note is at half, it's 1sec of note on and other sec of note off... i don't know if i'm clear...
With delay() it works. But i don't want to use delay().
I'm trying with millis()
i thought something like this would work
Code: | unsigned long oldTime=0, period1=10000, period2=2000;
void setup() {
pinMode(4, OUTPUT);
}
void loop() {
if(millis() - oldTime < period1) {
digitalWrite(4, HIGH);
}
else if(millis() - oldTime < period1 + period2) {
digitalWrite(4, LOW);
}
else {
oldTime = millis();
}
} |
where digitalwrite would be noteon and noteoff. But no. When i send it to a synth, it plays once, and then GATE is always on.
thanks
edit: Well, i wanted to do this like the mfos vari clock. And now i realised that the vari clock works the same as i got it now. It doesn't include silences, it gives more interesting results to be honest. So i'll leave it like this... i'd be nice to have both options though. Silence is necessary ...
Sometimes i tend to over complicate everything.. Last edited by capicoso on Wed Jul 31, 2013 4:37 pm; edited 1 time in total |
|
Back to top
|
|
|
capicoso
Joined: Nov 19, 2012 Posts: 128 Location: Argentina
|
Posted: Tue Jun 11, 2013 1:46 am Post subject:
|
|
|
Hmm. Well now it's working fine but not as i expected. I can vary the space between each note, one pot for one note. Thing is the note out is a pulse. If i put a release of about 350-500ms on my adsr it works fine, very good actually, but at if note lenght is shorted than the release, then it'll sound like one... if they're different notes it doesn't matter too much though... but i'm so frustrated that i couldn't make it work like i wanted
thing is that millis() works fine for leds, they're going HIGH every loop. But for notes out it's no good... The only "perfect" solution would be the use of delays, but i want to store sequences in rom, so maybe i push the button in the delay time and it won't store. And i also want to contro visuals parallel to the sequencer |
|
Back to top
|
|
|
Cynosure
Site Admin
Joined: Dec 11, 2010 Posts: 966 Location: Toronto, Ontario - Canada
Audio files: 82
|
Posted: Tue Jun 11, 2013 8:54 am Post subject:
|
|
|
A better way would be to set up two timers to trigger interrupts and start them at the same time.
The duration of the first timer (timer1) will vary according to the tempo pot and will be the duration of the step.
The duration of the second timer will be the reading of the note duration pot subtracted from the duration of timer1.
You will also need to ensure that the reading from the note duration pot can never exceed the value of the tempo pot. _________________ JacobWatters.com |
|
Back to top
|
|
|
capicoso
Joined: Nov 19, 2012 Posts: 128 Location: Argentina
|
Posted: Tue Jun 11, 2013 10:27 am Post subject:
|
|
|
Cynosure wrote: | A better way would be to set up two timers to trigger interrupts and start them at the same time. |
Is there an example of this? Interrupts are related to millis or delay? Or is a totally different thing?
Cynosure wrote: |
The duration of the second timer will be the reading of the note duration pot subtracted from the duration of timer1.
You will also need to ensure that the reading from the note duration pot can never exceed the value of the tempo pot.
. |
Yes i thought it like that...
but just using millis() the problem is that for example, when 500ms have passed, it'll send a note on, but just a pulse, and inmediatly a note off...
I'll read on interrupts if it's the solution, although it seems very complicated...
This is what i should read? http://playground.arduino.cc/Code/Interrupts |
|
Back to top
|
|
|
elmegil
Joined: Mar 20, 2012 Posts: 2177 Location: Chicago
Audio files: 16
|
Posted: Tue Jun 11, 2013 12:20 pm Post subject:
|
|
|
If you're doing anything at ALL complex with an Arduino you need to use interrupts, because otherwise you can only do as much as you can fit in your shortest time slice. In other words, if I'm running a beat fast at say 180BPM (3Hz), I have no more than 1/3 of a second each cycle to do EVERYTHING I have to get done. Now, if I'm not doing very much, that's not hard. But if I'm processing various inputs (like the adjustment pots) and sending MIDI, and doing calculations, it adds up pretty fast.
Here are a couple of tutorials on Interrupts I've bookmarked for my own use, hopefully they will be helpful for you as well. They aren't specifically music applications, but the concepts are the same.
http://letsmakerobots.com/node/28278
http://blog.makezine.com/2012/01/25/how-to-arduino-interrupts/
Good luck! |
|
Back to top
|
|
|
capicoso
Joined: Nov 19, 2012 Posts: 128 Location: Argentina
|
|
Back to top
|
|
|
capicoso
Joined: Nov 19, 2012 Posts: 128 Location: Argentina
|
Posted: Tue Jun 11, 2013 6:11 pm Post subject:
|
|
|
Hey, i made a big progress thanks to you guys.
I have a few doubts though, but here's what i got:
i used one timer, with attachInterrupt, RISING.
Used this
Code: | if(currentMillis - previousMillis > (ledState ? valorpote : valorpote2)) {
// save the last time you blinked the LED
previousMillis = currentMillis;
ledState = !ledState;
MIDI.sendNoteOff(50, 0, 1);
// set the LED with the ledState of the variable:
digitalWrite(4, ledState);
} |
it controls the speed of output 4, that is connected to pin 2, like a clock, is this right?
So when it's high it calls
Code: | void parpadeo()
{
//valorpote2= analogRead(pote2)/8;
MIDI.sendNoteOn(50, 127, 1);
} |
and i added a led on a pwm output controlled by the same pot, just to see if i can do other things countinously when the interrupt happens. And it works so i guess it's ok
I'm using one step now. I'll add others now and try to use a 4051 to multiplex inputs. Will check that later.
thanks again |
|
Back to top
|
|
|
cappy2112
Joined: Dec 24, 2004 Posts: 2465 Location: San Jose, California
Audio files: 2
G2 patch files: 1
|
Posted: Wed Jun 12, 2013 9:14 pm Post subject:
Re: Programming midi sequencer Subject description: need a little help... |
|
|
capicoso wrote: | Hello. I'm trying to build a midi sequencer. I'm using the midi library.
I'm trying with millis()
|
You have to be careful with libraries.
They may be disabling interrupts without you knowing it.
Check the documentation as well as the source code.
Keep in mind it's possible (and often preferable) to program the Arduino
without using the Arduino functions. Enabling/disabling interrupts & Timers can also be done by using register notation that is documented in AVRLib, instead of using the convenience functions in the Arduino library.
Timers & Serial I/O require that interrupts are enabled.
I'm pretty sure that there is some interaction between millis() and one of the Timers too.
digitalWrite() is very slow. You can also write to each of the three I/O ports (A,B,C) by writing directly to the port control registers. This is much faster, but I don't think this alone will fix your problem.
http://www.arduino.cc/en/Reference/PortManipulation
(This may come in handy for other projects) _________________ Free Tibet. Release the Panchen Lama from prison. Let the Dalai Lama return to his home. |
|
Back to top
|
|
|
cappy2112
Joined: Dec 24, 2004 Posts: 2465 Location: San Jose, California
Audio files: 2
G2 patch files: 1
|
Posted: Wed Jun 12, 2013 9:19 pm Post subject:
|
|
|
capicoso wrote: | Hey, i made a big progress thanks to you guys.
I have a few doubts though, but here's what i got:
i used one timer, with attachInterrupt, RISING.
Used this
Code: | if(currentMillis - previousMillis > (ledState ? valorpote : valorpote2)) {
// save the last time you blinked the LED
previousMillis = currentMillis;
ledState = !ledState;
MIDI.sendNoteOff(50, 0, 1);
// set the LED with the ledState of the variable:
digitalWrite(4, ledState);
} |
it controls the speed of output 4, that is connected to pin 2, like a clock, is this right?
So when it's high it calls
Code: | void parpadeo()
{
//valorpote2= analogRead(pote2)/8;
MIDI.sendNoteOn(50, 127, 1);
} |
and i added a led on a pwm output controlled by the same pot, just to see if i can do other things countinously when the interrupt happens. And it works so i guess it's ok
I'm using one step now. I'll add others now and try to use a 4051 to multiplex inputs. Will check that later.
thanks again |
Quote: | just to see if i can do other things countinously when the interrupt happens |
Would you post your ISR?
You can't spend too much time in the ISR or else loop() will get sluggish _________________ Free Tibet. Release the Panchen Lama from prison. Let the Dalai Lama return to his home. |
|
Back to top
|
|
|
capicoso
Joined: Nov 19, 2012 Posts: 128 Location: Argentina
|
Posted: Thu Jun 13, 2013 12:54 am Post subject:
|
|
|
cappy2112 wrote: | capicoso wrote: | Hey, i made a big progress thanks to you guys.
I have a few doubts though, but here's what i got:
i used one timer, with attachInterrupt, RISING.
Used this
Code: | if(currentMillis - previousMillis > (ledState ? valorpote : valorpote2)) {
// save the last time you blinked the LED
previousMillis = currentMillis;
ledState = !ledState;
MIDI.sendNoteOff(50, 0, 1);
// set the LED with the ledState of the variable:
digitalWrite(4, ledState);
} |
it controls the speed of output 4, that is connected to pin 2, like a clock, is this right?
So when it's high it calls
Code: | void parpadeo()
{
//valorpote2= analogRead(pote2)/8;
MIDI.sendNoteOn(50, 127, 1);
} |
and i added a led on a pwm output controlled by the same pot, just to see if i can do other things countinously when the interrupt happens. And it works so i guess it's ok
I'm using one step now. I'll add others now and try to use a 4051 to multiplex inputs. Will check that later.
thanks again |
Quote: | just to see if i can do other things countinously when the interrupt happens |
Would you post your ISR?
You can't spend too much time in the ISR or else loop() will get sluggish |
actually i just did this
Code: |
void setup()
{
Serial.begin(31250);
attachInterrupt(0, parpadeo, RISING);
}
void parpadeo()
{
MIDI.sendNoteOn(50,127, 1);
}
|
i tried to put a ledstate HIGH on parpadeo() and it was a very fast pulse. I suppose it's alright then? |
|
Back to top
|
|
|
cappy2112
Joined: Dec 24, 2004 Posts: 2465 Location: San Jose, California
Audio files: 2
G2 patch files: 1
|
Posted: Thu Jun 13, 2013 9:45 am Post subject:
|
|
|
actually i just did this
Code: |
void setup()
{
Serial.begin(31250);
attachInterrupt(0, parpadeo, RISING);
}
void parpadeo()
{
MIDI.sendNoteOn(50,127, 1);
}
|
i tried to put a ledstate HIGH on parpadeo() and it was a very fast pulse. I suppose it's alright then?[/quote]
Sorry- I didn't catch that it was your ISR.
If you want the LED to be on longer, without using delay, try to fire off a timer from within the ISR so that after 100ms (or period of your choosing)
the timer ISR will turn the LED off. _________________ Free Tibet. Release the Panchen Lama from prison. Let the Dalai Lama return to his home. |
|
Back to top
|
|
|
capicoso
Joined: Nov 19, 2012 Posts: 128 Location: Argentina
|
Posted: Thu Jun 13, 2013 10:08 am Post subject:
|
|
|
cappy2112 wrote: | actually i just did this
Code: |
void setup()
{
Serial.begin(31250);
attachInterrupt(0, parpadeo, RISING);
}
void parpadeo()
{
MIDI.sendNoteOn(50,127, 1);
}
|
i tried to put a ledstate HIGH on parpadeo() and it was a very fast pulse. I suppose it's alright then? |
Sorry- I didn't catch that it was your ISR.
If you want the LED to be on longer, without using delay, try to fire off a timer from within the ISR so that after 100ms (or period of your choosing)
the timer ISR will turn the LED off.[/quote]
It's working as expected i think. The LED for each note stays as long as the duration of the note on. The note on is just a pulse, so the note on is "held" until note off is activated, depending on the millis() part. |
|
Back to top
|
|
|
cappy2112
Joined: Dec 24, 2004 Posts: 2465 Location: San Jose, California
Audio files: 2
G2 patch files: 1
|
Posted: Thu Jun 13, 2013 10:34 am Post subject:
|
|
|
Quote: |
i tried to put a ledstate HIGH on parpadeo() and it was a very fast pulse. I suppose it's alright then? |
Here's an idea-but it's probably not good to do in the ISR
Code: | void parpadeo()
{
MIDI.sendNoteOn(50,127, 1);
digitalWrite(); // LED on
tone(pin, frequency, duration); // forces a delay using Timer0.
// Use an empty pin,
digitalWrite(); // LED off
} |
_________________ Free Tibet. Release the Panchen Lama from prison. Let the Dalai Lama return to his home. |
|
Back to top
|
|
|
MusicMan11712
Joined: Aug 08, 2009 Posts: 1082 Location: Out scouting . . .
|
Posted: Fri Jun 14, 2013 3:10 pm Post subject:
|
|
|
[This post was quoted in its entirety below.] Last edited by MusicMan11712 on Mon Nov 21, 2016 11:01 am; edited 1 time in total |
|
Back to top
|
|
|
capicoso
Joined: Nov 19, 2012 Posts: 128 Location: Argentina
|
Posted: Fri Jun 14, 2013 8:15 pm Post subject:
|
|
|
MusicMan11712 wrote: | I think its been almost a year since I did arduino stuff (maybe not that long), but I experimented with a timer interrupt using the timer library. (I forget the exact name.) It worked. I was able to push really high timer interrupt rates. But I had to keep the guts of what was done (midi processing) down; either that or cut down on the rapidity of the interrupts.
One thing I found: while echoing data to the console was good for writing the code (seeing the data as it flew by), the serial write routines really had a major impact on what could be done in between interrupts.
Another option is the hairless midi/usb/serial program--if it will meet the needs of your program/programming, though that too seemed to take away time that could be used for processing data.
My next step was to test hardware interrupts, but I never was able to make the time to work on that. If you can do it with hardware timers, that might be the best way to go.
Oh, and yes, at one point I did have my own internal delay routine--not sure its in the last set of sketches I was working on.
Looking forward to seeing more of your progress and getting back into it myself.
Thanks for sharing.
Steve |
I consider myself a newb on programming, but i spend hours trying to find a solution, even if it not the "perfect" one.
Were you doing a sequencer or...?
My idea was to control note on duration and note off. I managed to do it, yesterday, with 4051 multiplexers and all. But i couldn't make the leds follow each step. I spent more than 10 hours trying but no luck with the leds, so i'll stick with just adjusting the note on duration. It's for a university project, so i don't have too much time...
Sometimes i do things that i don't know the name of. Maybe my english is not good enough to understand everything. But external interrupts is what am i doing? Sending HIGH and LOW info to input 2? controlled by 4 output...
Right now my code is unreadable. I'll skip the note off part, and try to make it work with the rest, 8 steps x 3 pots, duration, note on, velocity. And then try to write and read rom. Although the steps won't be editable that way, because it would read the actual position of the analog pots... maybe if i used digitals... But it's good for live. Anything is better than the computer anyways...
When i'm done i'll share my newb code, commented and all, along with my Processing code for visuals and PD code for audio.
I'm sure someone of you have a solution to my leds problem... but i may implement everything in V2...
Thanks for the interest! |
|
Back to top
|
|
|
capicoso
Joined: Nov 19, 2012 Posts: 128 Location: Argentina
|
Posted: Tue Jun 25, 2013 11:41 pm Post subject:
|
|
|
Made some progress!
Right now i have 8 steps, with 8 pots for each note, and 8 for step duration cuantized in 1/32, 1/16, 1/8, 1/4, 1/2, 1, 2, 3, 4. Using 2 4051 and 595 for leds. HAve to add a 4067 i have somewhere for 8 pots for velo and others for some CC |
|
Back to top
|
|
|
cappy2112
Joined: Dec 24, 2004 Posts: 2465 Location: San Jose, California
Audio files: 2
G2 patch files: 1
|
Posted: Wed Jun 26, 2013 6:10 am Post subject:
|
|
|
capicoso wrote: | Made some progress!
Right now i have 8 steps, with 8 pots for each note, and 8 for step duration cuantized in 1/32, 1/16, 1/8, 1/4, 1/2, 1, 2, 3, 4. Using 2 4051 and 595 for leds. HAve to add a 4067 i have somewhere for 8 pots for velo and others for some CC |
Did you get the LED/timer thing working ok? _________________ Free Tibet. Release the Panchen Lama from prison. Let the Dalai Lama return to his home. |
|
Back to top
|
|
|
capicoso
Joined: Nov 19, 2012 Posts: 128 Location: Argentina
|
Posted: Wed Jun 26, 2013 9:13 am Post subject:
|
|
|
cappy2112 wrote: | capicoso wrote: | Made some progress!
Right now i have 8 steps, with 8 pots for each note, and 8 for step duration cuantized in 1/32, 1/16, 1/8, 1/4, 1/2, 1, 2, 3, 4. Using 2 4051 and 595 for leds. HAve to add a 4067 i have somewhere for 8 pots for velo and others for some CC |
Did you get the LED/timer thing working ok? |
yes |
|
Back to top
|
|
|
capicoso
Joined: Nov 19, 2012 Posts: 128 Location: Argentina
|
Posted: Wed Jun 26, 2013 6:44 pm Post subject:
|
|
|
Here's a vid
It's finished. Now i have just 2 weeks to put it on a veroboard and a box...and drill and drill... Then ver2 may come, with midi clock, midi in for arpeggiator and tap tempo.
video:
http://youtu.be/_FVu_tGh04U
Sorry for the blur and movement, bit hard to do everything with the sames hands, and even harder if the cam is all manual and a f1.4 lens
I need a suggestion. Vel pots at 0 are note off. Do you think it is neccesary to add switches for note off? OR with the pot is enough? And now it goes from 1/16 to 4, maybe they're too many values? Less better? And how big should be the range of the notes? Now it goes from 24-96
thanks for the helpp |
|
Back to top
|
|
|
capicoso
Joined: Nov 19, 2012 Posts: 128 Location: Argentina
|
Posted: Thu Jul 11, 2013 9:25 pm Post subject:
|
|
|
Hey, i finished the first version. It has many things to fix yet, but it was enough for my teacher.
I'll post the code now and maybe someone can help me? The big problem is that the sequence gets out of sync, without other instruments it can't be noticed. But if i put for example, the bpm at 120bpm, and listen to a metronome, they get out of sync. I think it's because of how i used the timers and interrupts, i didn't have the time to make it very good, i'll keep reading on it. The only thing that i'm unclear of is: with timer1 library
Code: | #include "TimerOne.h"
void setup()
{
pinMode(10, OUTPUT);
Timer1.initialize(500000); // initialize timer1, and set a 1/2 second period
Timer1.pwm(9, 512); // setup pwm on pin 9, 50% duty cycle
Timer1.attachInterrupt(callback); // attaches callback() as a timer overflow interrupt
} |
can i put Timer1.initialize(); in the loop? So the timer will be dynamic, acting as a tempo?
The other problem is that sometimes the midi note sends a semitone higher or lower, this is because of the potentiometers fluctuation, i suppose i'll fix this with a delta variable...
And somethings to add will be midi clock, change patterns...
i attached the arduino code plus processing codei wrote for visuals if interested... they respond to the OSC protocol
Description: |
|
Download |
Filename: |
arduino_seq_code.tar.gz |
Filesize: |
5.21 KB |
Downloaded: |
297 Time(s) |
Last edited by capicoso on Fri Jul 12, 2013 9:42 am; edited 1 time in total |
|
Back to top
|
|
|
blue hell
Site Admin
Joined: Apr 03, 2004 Posts: 24079 Location: The Netherlands, Enschede
Audio files: 278
G2 patch files: 320
|
Posted: Fri Jul 12, 2013 2:34 am Post subject:
|
|
|
capicoso wrote: | but it was enough for my teacher. |
Congratulations with that.
Quote: | The big problem is that the sequence gets out of sync |
Your code is fine probably, but no matter how good you make clocks they will always get out of sync ...
Code: |
tick tock tick tock tick tock
tick tock tick tock tick
tick tock tick tock tick
|
Only thing you can do is that you sync them to each other by making one the master and have that one send sync signals to all the others.
Code: |
tick tock tick tock tick tock
| | | | | | sync
v v v v v v signals
tick tock tick tock tick tock
| | | | | | sync
V v v v v v signals
tick tock tick tock tick tock
|
There are several methods in use to sync instruments to each other, most common currently would be MIDI clock - you could probably use OSC as well. It depends a bit on the exact devices you want to sync, a simple pulse may do the trick too. _________________ Jan
also .. could someone please turn down the thermostat a bit.
|
|
Back to top
|
|
|
capicoso
Joined: Nov 19, 2012 Posts: 128 Location: Argentina
|
Posted: Fri Jul 12, 2013 10:07 am Post subject:
|
|
|
Blue Hell wrote: | capicoso wrote: | but it was enough for my teacher. |
Congratulations with that.
Quote: | The big problem is that the sequence gets out of sync |
Your code is fine probably, but no matter how good you make clocks they will always get out of sync ...
Code: |
tick tock tick tock tick tock
tick tock tick tock tick
tick tock tick tock tick
|
Only thing you can do is that you sync them to each other by making one the master and have that one send sync signals to all the others.
Code: |
tick tock tick tock tick tock
| | | | | | sync
v v v v v v signals
tick tock tick tock tick tock
| | | | | | sync
V v v v v v signals
tick tock tick tock tick tock
|
There are several methods in use to sync instruments to each other, most common currently would be MIDI clock - you could probably use OSC as well. It depends a bit on the exact devices you want to sync, a simple pulse may do the trick too. |
Well that's a relief, because i want to implement midi clock.
What i wonder is, if there's a way of building a midi clock device myself? And put it inside the sequencer...
here's a vid of the actual state
http://youtu.be/lmYM1167Icg
thanks |
|
Back to top
|
|
|
MusicMan11712
Joined: Aug 08, 2009 Posts: 1082 Location: Out scouting . . .
|
Posted: Fri Jul 12, 2013 10:36 am Post subject:
|
|
|
Last year I was playing around with a timer-based interrupt to generate midi clock. I used the TimerOne library and played around with different settings to see how fast I could make the interrupts without it interfering with the code (and vice versa).
I used serial writes to the console/monitor to output counter loops. However, serial writes seemed to use up a lot of unnecessary time.
I won't be able to dig out my code for a couple of days, but as I recall, I had the interrupt count the number of interrupts and then send out midi timing bytes based on the bpm values.
I seem to recall when I was last working on it, I was experimenting with using different TimerOne parameters/functions.
Sorry this is not very specific. I will look to see if the code is anything worth sharing here
Steve |
|
Back to top
|
|
|
blue hell
Site Admin
Joined: Apr 03, 2004 Posts: 24079 Location: The Netherlands, Enschede
Audio files: 278
G2 patch files: 320
|
Posted: Fri Jul 12, 2013 11:22 am Post subject:
|
|
|
it (indeed) is not a very good idea to send out serial bytes from a timer interrpt ... as you might have to wait before the UART is able to send. You'd want to use a queue to store bytes in, and thn have the UART interrpt read from that to do the actual sending.
Anyway, capicoso, do you want to send a MIDI clock or do you want to receive it? _________________ Jan
also .. could someone please turn down the thermostat a bit.
|
|
Back to top
|
|
|
capicoso
Joined: Nov 19, 2012 Posts: 128 Location: Argentina
|
Posted: Fri Jul 12, 2013 11:27 am Post subject:
|
|
|
I'd like to receive midi clock |
|
Back to top
|
|
|
|