Send note off messages

main
Michael Hayes 14 years ago
parent 662d0781d9
commit 5580ca8b3a

@ -124,7 +124,6 @@ static void display_task_init (void)
{
tinygl_init (DISPLAY_TASK_RATE);
tinygl_font_set (&font3x5_1);
tinygl_text_speed_set (MESSAGE_RATE);
tinygl_text_mode_set (TINYGL_TEXT_MODE_ROTATE_STEP);
display_note ();

@ -21,7 +21,7 @@
/* Define polling rates in Hz. */
#define TWEETER_TASK_RATE 20000
#define TUNE_TASK_RATE 100
#define TUNE_TASK_RATE 200
#define BUTTON_TASK_RATE 10

@ -69,6 +69,13 @@
<ABC]1DE]2FG> represents ABCDEABCFG where ]n denotes alternate
endings.
With 8 bits for the tempo (in bpm), the max tempo is 255 bpm.
This corresponds to 4.25 beats per second. If the minimum time
to release a note is 1 / 8 of a quarter note, then we need
to poll at a rate of at least 4.25 * 8 = 34 times per second.
This could be made a lot more flexible but the orginal
implementation had a tight memory constraint.
*/
enum {MMELODY_SCALE_SIZE = 12};
@ -79,17 +86,34 @@ mmelody_ticker_set (mmelody_t mmelody)
{
uint16_t speed;
/* Notes per four minutes. */
speed = mmelody->speed * mmelody->note_fraction;
TICKER_INIT (&mmelody->ticker, mmelody->poll_rate * 60 * 4 / speed);
mmelody->beat_duration = mmelody->poll_rate * 60 * 4 / speed;
}
static void
mmelody_note_play (mmelody_t mmelody, mmelody_note_t note)
mmelody_note_on (mmelody_t mmelody, mmelody_note_t note, uint8_t duration)
{
mmelody->play_callback (mmelody->play_callback_data, note,
mmelody->volume);
mmelody->note = note;
/* Determine ticks between sounding notes. */
mmelody->ticks2 = (mmelody->beat_duration + 8) / 16;
/* Determine ticks before turning the note off. */
mmelody->ticks1 = mmelody->beat_duration * duration - mmelody->ticks2;
}
static void
mmelody_note_off (mmelody_t mmelody)
{
mmelody->play_callback (mmelody->play_callback_data,
mmelody->note, 0);
mmelody->note = 0;
}
@ -125,11 +149,12 @@ mmelody_scan (mmelody_t mmelody, const char *str)
bool have_hash;
bool have_num;
mmelody_note_t note;
uint8_t duration = 1;
/* Play rest at end of melody. */
if (! *str)
{
mmelody_note_play (mmelody, 0);
mmelody_note_off (mmelody);
return str;
}
@ -195,7 +220,12 @@ mmelody_scan (mmelody_t mmelody, const char *str)
/* Play rest. */
case ' ':
mmelody_note_play (mmelody, 0);
while (*str == '/')
{
duration++;
str++;
}
mmelody_note_on (mmelody, 0, duration);
return str;
break;
@ -233,12 +263,16 @@ mmelody_scan (mmelody_t mmelody, const char *str)
/* Convert note to MIDI note number. */
note += (mmelody->octave + 1) * MMELODY_SCALE_SIZE;
mmelody_note_play (mmelody, note);
while (*str == '/')
{
duration++;
str++;
}
mmelody_note_on (mmelody, note, duration);
return str;
break;
/* Continue with previous note. */
case '/':
default:
return str;
break;
@ -258,7 +292,10 @@ mmelody_play (mmelody_t mmelody, const char *str)
/* Default to quarter notes. */
mmelody_note_fraction_set (mmelody, 4);
/* Stop what is currently sounding. */
mmelody_note_play (mmelody, 0);
mmelody_note_off (mmelody);
mmelody->ticks1 = 0;
mmelody->ticks2 = 1;
}
@ -266,6 +303,14 @@ mmelody_play (mmelody_t mmelody, const char *str)
void
mmelody_speed_set (mmelody_t mmelody, mmelody_speed_t speed)
{
/* The duration of a beat varies with the time signature:
2/2 : minum (half note)
4/4 : crotchet (quarter note)
6/8, 9/8, 12/8 : dotted crotchet (one and a half quarter notes)
Currently, there is no time signature support so we assume 4/4.
This means a beat is quarter note and a bar is four quarter notes.
*/
mmelody->speed = speed;
mmelody_ticker_set (mmelody);
}
@ -289,10 +334,23 @@ mmelody_active_p (mmelody_t mmelody)
void
mmelody_update (mmelody_t mmelody)
{
if (TICKER_UPDATE (&mmelody->ticker))
if (!mmelody->cur)
return;
if (mmelody->ticks1)
{
if (mmelody->cur)
mmelody->cur = mmelody_scan (mmelody, mmelody->cur);
mmelody->ticks1--;
if (!mmelody->ticks1)
mmelody_note_off (mmelody);
}
else
{
if (mmelody->ticks2)
{
mmelody->ticks2--;
if (!mmelody->ticks2)
mmelody->cur = mmelody_scan (mmelody, mmelody->cur);
}
}
}
@ -308,7 +366,10 @@ mmelody_init (mmelody_obj_t *mmelody,
mmelody->play_callback_data = play_callback_data;
mmelody->volume = 100;
mmelody->note_fraction = 1;
mmelody->note = 0;
mmelody->ticks1 = 0;
mmelody->ticks2 = 0;
mmelody_speed_set (mmelody, MMELODY_SPEED_DEFAULT);
mmelody_play (mmelody, 0);
return mmelody;
}

@ -7,7 +7,6 @@
#define MMELODY_H
#include "system.h"
#include "ticker.h"
typedef uint8_t mmelody_speed_t;
typedef uint8_t mmelody_scale_t;
@ -21,7 +20,9 @@ enum {MMELODY_SPEED_DEFAULT = 200};
typedef struct
{
ticker_t ticker;
uint16_t beat_duration;
uint16_t ticks1;
uint16_t ticks2;
/* Pointer to current position in string. */
const char *cur;
/* Pointer to start of string. */
@ -29,6 +30,8 @@ typedef struct
const char *loop_start;
int8_t loop_count;
uint8_t note_fraction;
uint8_t note;
/* Tempo in beats per minute. */
mmelody_speed_t speed;
mmelody_volume_t volume;
uint8_t octave;

@ -7,8 +7,6 @@
#include "tweeter.h"
#define TWEETER_HOLDOFF_TIME 50e-3
enum {TWEETER_SCALE_SIZE = 12};
@ -19,12 +17,6 @@ tweeter_note_set (tweeter_t tweeter,
{
tweeter->note_period = period;
tweeter->note_duty = duty;
/* To distinguish between two quarter notes and a half note of the
same pitch we have a short hold off period at the start of each
note. */
tweeter->note_holdoff = tweeter->poll_rate
/ (uint16_t)(1 / TWEETER_HOLDOFF_TIME);
}
@ -40,9 +32,9 @@ tweeter_note_play (tweeter_t tweeter, tweeter_note_t note, uint8_t velocity)
uint8_t index;
uint8_t octave;
if (note == 0)
if (note == 0 || velocity == 0)
{
/* Play a rest. */
/* Stop playing. */
tweeter_note_set (tweeter, 0, 0);
return;
}
@ -70,12 +62,6 @@ tweeter_note_play (tweeter_t tweeter, tweeter_note_t note, uint8_t velocity)
bool
tweeter_update (tweeter_t tweeter)
{
if (tweeter->note_holdoff)
{
tweeter->note_holdoff--;
return 0;
}
if (++tweeter->note_clock >= tweeter->note_period)
tweeter->note_clock = 0;

@ -54,7 +54,6 @@ typedef struct
uint8_t note_clock;
uint8_t note_period;
uint8_t note_duty;
uint16_t note_holdoff;
uint16_t poll_rate;
tweeter_scale_t *scale_table;
} tweeter_private_t;

Loading…
Cancel
Save