Send note off messages

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

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

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

@ -69,6 +69,13 @@
<ABC]1DE]2FG> represents ABCDEABCFG where ]n denotes alternate <ABC]1DE]2FG> represents ABCDEABCFG where ]n denotes alternate
endings. 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}; enum {MMELODY_SCALE_SIZE = 12};
@ -79,17 +86,34 @@ mmelody_ticker_set (mmelody_t mmelody)
{ {
uint16_t speed; uint16_t speed;
/* Notes per four minutes. */
speed = mmelody->speed * mmelody->note_fraction; 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 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->play_callback (mmelody->play_callback_data, note,
mmelody->volume); 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_hash;
bool have_num; bool have_num;
mmelody_note_t note; mmelody_note_t note;
uint8_t duration = 1;
/* Play rest at end of melody. */ /* Play rest at end of melody. */
if (! *str) if (! *str)
{ {
mmelody_note_play (mmelody, 0); mmelody_note_off (mmelody);
return str; return str;
} }
@ -195,7 +220,12 @@ mmelody_scan (mmelody_t mmelody, const char *str)
/* Play rest. */ /* Play rest. */
case ' ': case ' ':
mmelody_note_play (mmelody, 0); while (*str == '/')
{
duration++;
str++;
}
mmelody_note_on (mmelody, 0, duration);
return str; return str;
break; break;
@ -233,12 +263,16 @@ mmelody_scan (mmelody_t mmelody, const char *str)
/* Convert note to MIDI note number. */ /* Convert note to MIDI note number. */
note += (mmelody->octave + 1) * MMELODY_SCALE_SIZE; note += (mmelody->octave + 1) * MMELODY_SCALE_SIZE;
mmelody_note_play (mmelody, note); while (*str == '/')
{
duration++;
str++;
}
mmelody_note_on (mmelody, note, duration);
return str; return str;
break; break;
/* Continue with previous note. */
case '/':
default: default:
return str; return str;
break; break;
@ -258,7 +292,10 @@ mmelody_play (mmelody_t mmelody, const char *str)
/* Default to quarter notes. */ /* Default to quarter notes. */
mmelody_note_fraction_set (mmelody, 4); mmelody_note_fraction_set (mmelody, 4);
/* Stop what is currently sounding. */ /* 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 void
mmelody_speed_set (mmelody_t mmelody, mmelody_speed_t speed) 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->speed = speed;
mmelody_ticker_set (mmelody); mmelody_ticker_set (mmelody);
} }
@ -289,10 +334,23 @@ mmelody_active_p (mmelody_t mmelody)
void void
mmelody_update (mmelody_t mmelody) mmelody_update (mmelody_t mmelody)
{ {
if (TICKER_UPDATE (&mmelody->ticker)) if (!mmelody->cur)
return;
if (mmelody->ticks1)
{ {
if (mmelody->cur) mmelody->ticks1--;
mmelody->cur = mmelody_scan (mmelody, mmelody->cur); 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->play_callback_data = play_callback_data;
mmelody->volume = 100; mmelody->volume = 100;
mmelody->note_fraction = 1; mmelody->note_fraction = 1;
mmelody->note = 0;
mmelody->ticks1 = 0;
mmelody->ticks2 = 0;
mmelody_speed_set (mmelody, MMELODY_SPEED_DEFAULT); mmelody_speed_set (mmelody, MMELODY_SPEED_DEFAULT);
mmelody_play (mmelody, 0);
return mmelody; return mmelody;
} }

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

@ -7,8 +7,6 @@
#include "tweeter.h" #include "tweeter.h"
#define TWEETER_HOLDOFF_TIME 50e-3
enum {TWEETER_SCALE_SIZE = 12}; enum {TWEETER_SCALE_SIZE = 12};
@ -19,12 +17,6 @@ tweeter_note_set (tweeter_t tweeter,
{ {
tweeter->note_period = period; tweeter->note_period = period;
tweeter->note_duty = duty; 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 index;
uint8_t octave; uint8_t octave;
if (note == 0) if (note == 0 || velocity == 0)
{ {
/* Play a rest. */ /* Stop playing. */
tweeter_note_set (tweeter, 0, 0); tweeter_note_set (tweeter, 0, 0);
return; return;
} }
@ -70,12 +62,6 @@ tweeter_note_play (tweeter_t tweeter, tweeter_note_t note, uint8_t velocity)
bool bool
tweeter_update (tweeter_t tweeter) tweeter_update (tweeter_t tweeter)
{ {
if (tweeter->note_holdoff)
{
tweeter->note_holdoff--;
return 0;
}
if (++tweeter->note_clock >= tweeter->note_period) if (++tweeter->note_clock >= tweeter->note_period)
tweeter->note_clock = 0; tweeter->note_clock = 0;

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

Loading…
Cancel
Save