Glissando working again

This commit is contained in:
Neale Pickett 2020-11-26 18:49:09 -07:00
parent d31398ed63
commit 8e39c5118f
5 changed files with 71 additions and 73 deletions

View File

@ -19,21 +19,21 @@ void doPlay(bool forceDisplayUpdate) {
display.display();
}
if (pipe.silent) {
if (pipe.Silent) {
Chanter.NoteOff();
} else {
// Calculate pitch, and glissando pitch
float pitch = tuning.GetPitch(pipe.note);
float glissandoPitch = tuning.GetPitch(pipe.glissandoNote);
float pitch = tuning.GetPitch(pipe.CurrentNote);
float glissandoPitch = tuning.GetPitch(pipe.GlissandoNote);
// Bend pitch if fewer than 3 half steps away
if (abs(pipe.glissandoNote - pipe.note) < 3) {
if (abs(pipe.GlissandoNote - pipe.CurrentNote) < 3) {
float diff = glissandoPitch - pitch;
pitch += diff * pipe.glissandoOpenness;
pitch = glissandoPitch - (diff * pipe.GlissandoPressure);
}
// Apply a low shelf filter if this is the alternate fingering
if (pipe.altFingering) {
if (pipe.AltFingering) {
biquad1.setLowShelf(0, 2000, 0.2, 1);
} else {
biquad1.setHighShelf(0, 1000, 1.0, 1);
@ -47,17 +47,16 @@ void doPlay(bool forceDisplayUpdate) {
}
}
if (pipe.note != last_note) {
if (pipe.CurrentNote != last_note) {
updateDisplay = true;
}
diag("%d %f", pipe.keys, pipe.glissandoOpenness);
#if 0
if (updateDisplay) {
// Look up the note name
const char *note_name = NoteName(pipe.note);
if (pipe.silent) {
note_name = "--";
const char *noteName = NoteName(pipe.CurrentNote);
if (pipe.Silent) {
noteName = "--";
updateDisplay = true;
}
@ -65,10 +64,10 @@ void doPlay(bool forceDisplayUpdate) {
display.setFont(&FreeSans9pt7b);
display.setCursor(0, 16);
display.print(note_name);
display.print(noteName);
display.display();
last_note = pipe.note;
last_note = pipe.CurrentNote;
}
#endif
}

View File

@ -36,7 +36,10 @@ void setupVolume() {
break;
case ADJUST_UP:
case ADJUST_DOWN:
volume[i] += float(volAdjust)*0.02;
{
float vol = volume[i] + float(volAdjust)*0.02;
volume[i] = min(max(vol, 1.0), 0.0);
}
break;
default:
break;
@ -143,6 +146,9 @@ void setupInfo() {
display.print("FC-1");
display.setCursor(0, 24);
display.print(buildDate);
display.setCursor(0, 0);
display.print("M:");
display.print(AudioMemoryUsageMax());
}
/** doSetup performs "setup mode" behavior for the pipe.

View File

@ -8,7 +8,7 @@
#define GLISSANDO_STEPS (OPENVAL - CLOSEDVAL)
Pipe::Pipe() {
keysLast = 0;
KeysLast = 0;
}
bool Pipe::Init() {
@ -17,8 +17,8 @@ bool Pipe::Init() {
return false;
}
// Proximity sensor
if (paj7620Init()) {
// Knee sensor
if (!kneeSensor.begin()) {
return false;
}
@ -33,70 +33,72 @@ bool Pipe::Init() {
void Pipe::Update() {
uint8_t glissandoKeys = 0;
keysLast = keys;
keys = 0;
KeysLast = Keys;
Keys = 0;
// Read the bag state, if there's a bag.
// if there isn't a bag, don't try, or this library will crash the program.
if (bag_enabled) {
bag = bagSensor.isPressed();
Bag = bagSensor.isPressed();
} else {
bag = false;
Bag = false;
}
// 0x6c is actually 8 bytes, but all 8 are always the same...
paj7620ReadReg(0x6c, 1, &kneeClosedness);
KneeClosedness = 255 - kneeSensor.readRange();
for (int i = 0; i < NUM_KEYS; ++i) {
uint16_t val = max(capSensor.filteredData(i), CLOSEDVAL);
keyOpen[i] = ((val - CLOSEDVAL) / float(GLISSANDO_STEPS));
uint16_t sensorReading = capSensor.filteredData(i);
uint16_t val = OPENVAL - min(max(sensorReading, CLOSEDVAL), OPENVAL);
KeyPressure[i] = val / float(GLISSANDO_STEPS);
// keys = all keys which are at least touched
// glissandoKeys = all keys which are fully closed
// The glissando operation computes the difference.
if (keyOpen[i] < 1.0) {
glissandoOpenness = max(glissandoOpenness, keyOpen[i]);
bitSet(keys, i);
if (KeyPressure[i] > 0.0) {
bitSet(Keys, i);
}
if (keyOpen[i] == 0.0) {
if (KeyPressure[i] == 1.0) {
bitSet(glissandoKeys, i);
}
}
// Compute glissando amount
glissandoOpenness = 0.0;
GlissandoPressure = 1.0;
for (int i = 0; i < 8; ++i) {
glissandoOpenness = max(glissandoOpenness, keyOpen[i]);
if (KeyPressure[i] > 0) {
GlissandoPressure = min(GlissandoPressure, KeyPressure[i]);
}
}
// Look up notes in the big table
struct Fingering f = FingeredNote(keys);
struct Fingering f = FingeredNote(Keys);
struct Fingering gf = FingeredNote(glissandoKeys);
note = f.note;
glissandoNote = gf.note;
CurrentNote = f.note;
GlissandoNote = gf.note;
// Was the high bit set? That indicates "alternate fingering", which sounds different.
altFingering = f.alt;
AltFingering = f.alt;
// If the bag is squished, jump up an octave
// But only if the left thumb is down!
if (bag && (keys & bit(7))) {
note += NOTE_OCTAVE;
glissandoNote += NOTE_OCTAVE;
if (Bag && (Keys & bit(7))) {
CurrentNote += NOTE_OCTAVE;
GlissandoNote += NOTE_OCTAVE;
}
// All keys closed + knee = no sound
silent = ((kneeClosedness > 240) && (keys == 0xff));
Silent = ((KneeClosedness > 240) && (Keys == 0xff));
}
bool Pipe::Pressed(uint8_t key) {
return bitRead(keys, key);
return bitRead(Keys, key);
}
bool Pipe::JustPressed(uint8_t key) {
if (bitRead(keys, key)) {
return !bitRead(keysLast, key);
if (bitRead(Keys, key)) {
return !bitRead(KeysLast, key);
}
return false;
}

27
pipe.h
View File

@ -1,12 +1,12 @@
#pragma once
#include <Adafruit_MPR121.h>
#include <Adafruit_VL6180X.h>
#include <SparkFun_Qwiic_Button.h>
#include <paj7620.h>
#include <stdint.h>
#include "tuning.h"
#define NUM_KEYS 8
#define NUM_KEYS 12
enum Adjust {
ADJUST_DOWN = -1,
@ -18,31 +18,31 @@ enum Adjust {
class Pipe {
public:
// kneeClosedness indicates how "closed" the knee sensor is. 0 = wide open.
uint8_t kneeClosedness;
uint8_t KneeClosedness;
// keys are which keys are being pressed.
uint16_t keys;
uint16_t keysLast;
float keyOpen[NUM_KEYS];
uint16_t Keys;
uint16_t KeysLast;
float KeyPressure[NUM_KEYS];
// note holds the note being played, according to the fingering chart.
Note note;
Note CurrentNote;
// glissandoNote is the note that would be played if partially open keys were fully open.
Note glissandoNote;
Note GlissandoNote;
// glissandoOpenness is how "open" the holes are in the direction of the glissandoNote.
float glissandoOpenness;
// glissandoPressure is how "closed" the holes are in the direction away from the glissandoNote.
float GlissandoPressure;
// silent is true if all keys and the knee are closed.
bool silent;
bool Silent;
// bag is true if the bag is being squished.
bool bag;
bool Bag;
// altFingering is true if the "alternate fingering" is being played.
// This should sound different than the standard fingering.
bool altFingering;
bool AltFingering;
Pipe();
@ -70,6 +70,7 @@ class Pipe {
private:
Adafruit_MPR121 capSensor;
Adafruit_VL6180X kneeSensor;
QwiicButton bagSensor;
bool bag_enabled;
unsigned long nextRepeat[NUM_KEYS];

View File

@ -1,10 +1,7 @@
#include <Adafruit_GFX.h>
#include <Adafruit_MPR121.h>
#include <Adafruit_SSD1306.h>
#include <Audio.h>
#include <Fonts/FreeSans9pt7b.h>
#include <Wire.h>
#include <paj7620.h>
#include <stdio.h>
#include "patches.h"
@ -26,7 +23,7 @@ Adafruit_SSD1306 display(128, 32, &Wire, -1);
// Settings
uint8_t patch[4] = {0};
float volume[4] = {0};
float volume[5] = {0.75, 0.75, 0.75, 0.75, 0.3};
// Pipes
#define NUM_DRONES 3
@ -132,13 +129,6 @@ void diag(const char *fmt, ...) {
#include "main-setup.h"
void setup() {
// Initialize settings
// XXX: Read these from persistent storage later
for (int i = 0; i < 4; i++) {
patch[i] = 0;
volume[i] = 0.75;
}
// PREPARE TO BLINK
pinMode(LED_BUILTIN, OUTPUT);
digitalWrite(LED_BUILTIN, true);
@ -160,16 +150,16 @@ void setup() {
diag("Pipe...");
while (!pipe.Init()) {
diag("No pipe. Is it connected?");
diag("Pipe connected?");
blink(false);
}
diag("Audio...");
AudioMemory(20);
AudioMemory(120);
AudioProcessorUsageMaxReset();
AudioMemoryUsageMaxReset();
sgtl5000.enable();
sgtl5000.volume(0.3);
sgtl5000.volume(volume[4]);
diag("Synth...");
loadPatch(0);
@ -188,7 +178,7 @@ void setup() {
for (int i = 0; i < NUM_DRONES; ++i) {
mixDrones.gain(i, 1);
}
biquad1.setBandpass(0, PITCH_CONCERT_A4, 1.0);
biquad1.setNotch(0, PITCH_CONCERT_A4, 0.001);
diag("Drones...");
playDrones();
@ -231,12 +221,12 @@ void loop() {
// If we're infinitely (for the sensor) off the knee,
// we might be in setup mode.
if (pipe.kneeClosedness == 0) {
if (pipe.KneeClosedness == 0) {
// We only enter into setup mode if no keys are pressed.
// This hopefully avoids accidentally entering setup while playing.
// Like say you're playing a jaunty tune and suddenly there's an earthquake.
// You ought to be able to finish the tune off before your pipe goes into setup mode.
if (upSetting || (pipe.keys == 0)) {
if (upSetting || (pipe.Keys == 0)) {
doSetup();
upSetting = true;
return;