1
Fork 0

Added basic metronome. Fixed a bug. Scope works.

The metronome widget ticks when playing or recording.
The beats per measure affects the display of the
metronome. Better graphics would be nice here.

There was a bug in the song editor which failed to
place new blocks correctly when not using 4 beats per
measure. Fixed.

The monitor callback which updates the midi scope
now runs continuously. When not in playback mode,
the callback runs generally ten times a second. In
order to update widgets faster during playback it
automatically speeds up to 100 times per second and
returns to 10 after stopping.
This commit is contained in:
EvanR 2008-12-19 12:52:40 -06:00
parent a2b6c9662a
commit ef99964d0f
11 changed files with 164 additions and 18 deletions

View File

@ -10,4 +10,5 @@ trackmodule.cpp util.cpp midi.cpp uihelper.cpp \
saveload.cpp seq.h backend.h ui.h pianoroll.h \
trackselect.h eventedit.h timeline.h sampleview.h \
trackinfo.h arranger.h keyboard.h trackmodule.h \
util.h midi.h uihelper.h saveload.h
util.h midi.h uihelper.h saveload.h metronome.cpp \
metronome.h

View File

@ -217,7 +217,8 @@ int Arranger::handle(int event){
move_flag = 1;
}
if(new_drag){
new_right_t = quantize(xpix2tick(event_x())+q_tick);
//new_right_t = quantize(xpix2tick(event_x())) + quantize(q_tick);
new_right_t = quantize(xpix2tick(event_x()+tick2xpix(q_tick)));
if(new_right_t <= new_orig_t){
new_left_t = new_right_t - quantize(q_tick);
new_right_t = new_orig_t;
@ -492,8 +493,7 @@ int Arranger::xpix2tick(int xpix){
}
int Arranger::quantize(int tick){
int M = config.beats_per_measure;
return tick/(q_tick*M/4) * (q_tick*M/4);
return tick/q_tick * q_tick;
}

View File

@ -25,6 +25,8 @@
#include <inttypes.h>
#define TICKS_PER_BEAT 128
int init_backend();
int shutdown_backend();
int start_backend();

View File

@ -70,7 +70,7 @@ static int cur_tick;
static int last_tick;
static int bpm = 120;
static int new_bpm = 120;
static int tpb = 128;
static int tpb = TICKS_PER_BEAT;
static int sample_rate = 0;
static int frame_count = 0;

94
src/metronome.cpp Normal file
View File

@ -0,0 +1,94 @@
#include <stdio.h>
#include <math.h>
#include <fltk/Widget.h>
#include <fltk/events.h>
#include <fltk/draw.h>
#include "metronome.h"
using namespace fltk;
Metronome::Metronome(int x, int y, int w, int h, const char* label = 0) : fltk::Widget(x, y, w, h, label) {
N = 4;
n = 2;
last_beat = 0;
plus = 0;
r=255; g=0; b=0;
update(0);
}
int Metronome::handle(int event){
return 0;
}
void Metronome::draw(){
draw_box();
//setcolor(fltk::color(r,g,b));
//fillrect(2,2,w()-4,h()-4);
setcolor(fltk::WHITE);
int X = last_beat%N*(w()-4)/N+2;
int W = (w()-4)/N;
int H = h()-4;
fillrect(X,2,W,h()-4);
//int W2 = W/2;
//int H2 = H/2;
//setcolor(fltk::color(r,g,b));
//fillrect(X+W/2-W2/2,h()/2-H2/2,W2,H2);
//setcolor(fltk::BLACK);
//int C = (getascent()-getdescent())/2;
//drawtext(label(),X+W/2-getwidth(label())/2,h()/2+C);
}
//div N is the greatest divisor of N less than or equal to sqrt(N)
int div(int N){
int d = 0;
for(int i=1; i<=sqrt(N); i++){
if(N%i==0){
d=i;
}
}
if(d==1){
//prime
}
return d;
}
void Metronome::update(int tick){
int now_beat = tick/128;
if(now_beat != last_beat){
int step = last_beat - now_beat;
last_beat = now_beat;
char buf[16];
snprintf(buf,16,"%d",now_beat%N + plus);
copy_label(buf);
if(now_beat%N == 0){
r=255; g=0; b=0;
}
else if(now_beat%n == 0){
r=128; g=0; b=0;
}
else{
r=0; g=0; b=0;
}
redraw();
}
}
void Metronome::set_N(int zN){
N = zN;
n = div(zN);
}

19
src/metronome.h Normal file
View File

@ -0,0 +1,19 @@
class Metronome : public fltk::Widget {
int N, n;
int last_beat;
int plus;
unsigned char r,g,b;
public:
Metronome(int x, int y, int w, int h, const char* label);
int handle(int event);
void draw();
void update(int tick);
void set_N(int zN);
};

View File

@ -478,7 +478,10 @@ UI::UI() {
o->callback((fltk::Callback*)cb_record_button);
o->type(fltk::Button::TOGGLE);
}
metronome = new fltk::Widget(125, 5, 25, 25, "metr");
{Metronome* o = metronome = new Metronome(95, 5, 100, 25, "0");
o->color((fltk::Color)56);
o->labelcolor((fltk::Color)0xffffff00);
}
{fltk::Group* o = new fltk::Group(180, 0, 20, 35);
o->set_vertical();
fltk::Group::current()->resizable(o);
@ -920,5 +923,6 @@ track.");
qbutton0->image(fltk::SharedImage::get(ROOT_DATA_DIR"gfx/q0.gif"));
track_info->set_rec(0);
config_init();
start_monitor();
main_window->show();
}

View File

@ -231,8 +231,10 @@ ui->song_buttons->show();}
extra_code {o->type(fltk::Button::TOGGLE);}
}
{fltk::Widget} metronome {
label metr
xywh {125 5 25 25}
label 0
xywh {95 5 100 25} color 56 labelcolor 0xffffff00
extra_code {\#include <metronome.h>}
class Metronome
}
{fltk::Group} {} {
xywh {180 0 20 35} resizable
@ -757,7 +759,7 @@ savesmf(fltk::file_chooser("export file",NULL,get_last_dir()));}
}
}
{fltk::Window} scope_window {
label scope selected
label scope
xywh {647 310 425 280} hide resizable
} {
{fltk::TextDisplay} scope {
@ -785,6 +787,8 @@ qbutton128->image(fltk::SharedImage::get(ROOT_DATA_DIR"gfx/q128.gif"));
qbutton0->image(fltk::SharedImage::get(ROOT_DATA_DIR"gfx/q0.gif"));} {}
code {track_info->set_rec(0);} {}
code {config_init();} {}
code {start_monitor();} {selected
}
code {main_window->show();} {}
}
}

View File

@ -18,7 +18,7 @@
#include "trackselect.h"
#include "sampleview.h"
#include "keyboard.h"
#include <fltk/Widget.h>
#include <metronome.h>
#include "saveload.h"
#include <fltk/TabGroup.h>
#include <fltk/ValueInput.h>
@ -75,7 +75,7 @@ private:
inline void cb_record_button_i(fltk::Button*, void*);
static void cb_record_button(fltk::Button*, void*);
public:
fltk::Widget *metronome;
Metronome *metronome;
fltk::Group *pattern_buttons;
fltk::Button *qbutton4;
private:

View File

@ -23,6 +23,8 @@
#include <stdlib.h>
#include <vector>
#include <math.h>
#include <fltk/run.h>
#include "seq.h"
@ -54,13 +56,18 @@ void config_init(){
config.robmode = 0;
}
void playing_timeout_cb(void* v){
if(!is_backend_playing()){
return;
}
//if(!is_backend_playing()){
// return;
//}
int pos = get_play_position();
ui->song_timeline->update(pos);
ui->pattern_timeline->update(pos);
ui->metronome->update(pos);
if(config.follow){
ui->arranger->update(pos);
ui->piano_roll->update(pos);
@ -72,7 +79,7 @@ void playing_timeout_cb(void* v){
int type;
int val1;
int val2;
track* t = tracks[get_rec_track()];
Command* c;
seqpat* s;
@ -239,14 +246,25 @@ void playing_timeout_cb(void* v){
}
}
fltk::repeat_timeout(0.01, playing_timeout_cb, NULL);
if(is_backend_playing()){
fltk::repeat_timeout(0.01, playing_timeout_cb, NULL);
}
else{
fltk::repeat_timeout(0.1, playing_timeout_cb, NULL);
}
}
void start_monitor(){
printf("started\n");
fltk::add_timeout(0.1, playing_timeout_cb, NULL);
}
void press_play(){
if(!is_backend_playing()){
start_backend();
ui->play_button->label("@||");
fltk::add_timeout(0.01, playing_timeout_cb, NULL);
//fltk::add_timeout(0.01, playing_timeout_cb, NULL);
}
else{
pause_backend();
@ -277,6 +295,8 @@ void press_stop(){
ui->play_button->label("@>");
ui->play_button->redraw();
ui->metronome->update(0);
}
@ -358,8 +378,10 @@ void set_quant(int q){
void set_beats_per_measure(int n){
config.beats_per_measure = n;
ui->metronome->set_N(n);
ui->piano_roll->redraw();
ui->arranger->redraw();
ui->arranger->q_tick = n*TICKS_PER_BEAT;
ui->song_timeline->redraw();
ui->pattern_timeline->redraw();
}

View File

@ -40,7 +40,7 @@ struct conf{
};
void config_init();
void start_monitor();
void press_stop();
void press_panic();