Skip to content

Commit

Permalink
Merge pull request #38 from marchingband/mute-group
Browse files Browse the repository at this point in the history
Mute group, midi CC's
  • Loading branch information
marchingband authored Feb 28, 2022
2 parents 8f81e28 + cdc7395 commit 15d0aa2
Show file tree
Hide file tree
Showing 8 changed files with 357 additions and 248 deletions.
8 changes: 8 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ If you have Thames : WVR in a Pedal, go here : https://github.com/marchingband/w
* [playing sounds](#playing-sounds)
* sound settings
* * [understanding priority](#understanding-priority)
* * [understanding exclusive group](#understanding-exclusive-group)
* * [understanding playback mode](#understanding-playback-mode)
* * [understanding response curve](#understanding-response-curve)
* * [understanding retrigger mode](#understanding-retrigger-mode)
* * [understanding note off](#understanding-note-off)
Expand Down Expand Up @@ -88,6 +90,12 @@ Congradulations! You now have the most up-to-date firmware loaded onto your WVR
# understanding priority
WVR can playback up to 18 stereo sounds at once. It mixes all the sounds into a stereo output. If you play very fast, or play dense chords, or have very long sounds, it's possible to ask the WVR to play back more then 18 sounds. When this happens, WVR runs an algorithm to figure out what to do. It will try to find an old, or an unimportant sound, stop playing that sound, and play the newly triggered sound instead. You can help it make this decision by giving some sounds higher **priority**. A lower priority sound will never stop a higher priority sound, only equal or lower priority. In the case where all 18 voices are busy playing high priority sounds, and a lower priority sound is triggered, WVR will not play the sound.

# understanding exclusive group
**Exclusive Group** allows you to tell WVR that only one member out of a group of notes can be playing at one time. If you want your open hihat sample to stop when a closed hihat sample starts, or if you want one bass note to stop when another starts, you can achieve this by setting the **exclusive group** value of all the notes in that group to the same number ie. add them all to the same exclusive group. These groups work across voices and channels. When a note-on is received on a memeber of an exclusive group, any other note in that group that is playing will be immidiately stopped. As with all the note settings, you can select multiple notes using shift-click or command-click, and change the exclusive group for all selected notes.

# understanding playback mode
A *one-shot* sample will play once and stop. A *loop* sample will loop precisely, so trim the sample carefully to avoid pops. It will continue until it receives a note-off and then immidiately stop. An *ASR-loop* sample will start at the beginning of the sample, play until loop-end, then loop between loop-start and loop-end until it receives a note off, at which time it will play from its current position, past the loop-end, to the end of the sample. Choose the loop-start and loop-end carefully to avoid pops. The numbers you enter into loop-start and loop-end are expressed in *samples*. These are channel samples, and WVR converts all samples to stereo, so in your DAW, when measuring and calculating these points, you may need to half or double the number, depending on if your original sample is stereo or mono, and depending on how your DAW measures sample positions. The points are shown in the waveform view as golden vertical lines, but only the first time you load a sample. When you return to modify these points after a sync, the waveform is no longer loaded, so these points wont be displayed.

# understanding response curve
Every MIDI note has a velocity (or volume) attached to it. This is a value from 0 to 127. Imagine a graph with these 127 velocities on the y axis, and the playback volume that each actually triggers on the x axis. If this is a streight line, we have a **linear** response curve. Many people find other curves to be more human, or more musical. The default response curve for WVR is the **Square Root** algorithm, but you can also choose **linear** or **logarithmic**.

Expand Down
4 changes: 2 additions & 2 deletions src/bundle.h

Large diffs are not rendered by default.

14 changes: 12 additions & 2 deletions src/file_system.c
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,8 @@

// july 10 / 2021
// char waver_tag[METADATA_TAG_LENGTH] = "wvr_magic_13"; // v1.x.x
char waver_tag[METADATA_TAG_LENGTH] = "wvr_magic_14"; // v2.x.x
// char waver_tag[METADATA_TAG_LENGTH] = "wvr_magic_14"; // v2.x.x
char waver_tag[METADATA_TAG_LENGTH] = "wvr_magic_15"; // v3.x.x
static const char* TAG = "file_system";

// declare prototypes from emmc.c
Expand Down Expand Up @@ -240,6 +241,7 @@ void init_wav_lut(void){
wav_lut[i][j].retrigger_mode = RETRIGGER;
wav_lut[i][j].response_curve = RESPONSE_SQUARE_ROOT;
wav_lut[i][j].priority = 0;
wav_lut[i][j].mute_group = 0;
wav_lut[i][j].loop_start = 0;
wav_lut[i][j].loop_end = 0;
}
Expand All @@ -258,8 +260,10 @@ void init_wav_lut(void){
voice[j].retrigger_mode = RETRIGGER;
voice[j].response_curve = RESPONSE_SQUARE_ROOT;
voice[j].priority = 0;
voice[j].mute_group = 0;
voice[j].loop_start = 0;
voice[j].loop_end = 0;
voice[j].RFU = 0;
memcpy(voice[j].name, blank, 1);
}
ESP_ERROR_CHECK(emmc_write(
Expand Down Expand Up @@ -400,6 +404,7 @@ void read_wav_lut_from_disk(void)
wav_lut[i][j].note_off_meaning = voice[j].note_off_meaning;
wav_lut[i][j].response_curve = voice[j].response_curve;
wav_lut[i][j].priority = voice[j].priority;
wav_lut[i][j].mute_group = voice[j].mute_group;
wav_lut[i][j].loop_start = voice[j].loop_start;
wav_lut[i][j].loop_end = voice[j].loop_end;
}
Expand Down Expand Up @@ -505,6 +510,7 @@ struct wav_lu_t get_file_t_from_lookup_table(uint8_t voice, uint8_t note, uint8_
wav.note_off_meaning = wav_lut[voice][note].note_off_meaning;
wav.response_curve = wav_lut[voice][note].response_curve;
wav.priority = wav_lut[voice][note].priority;
wav.mute_group = wav_lut[voice][note].mute_group;
wav.loop_start = wav_lut[voice][note].loop_start;
wav.loop_end = wav_lut[voice][note].loop_end;
return wav;
Expand Down Expand Up @@ -853,10 +859,12 @@ cJSON* add_voice_json(uint8_t voice_num)
if(ret==NULL){log_e("failed to make json responseCurve");continue;}
ret = cJSON_AddNumberToObject(note, "priority", voice[j].priority);
if(ret==NULL){log_e("failed to make json priority");continue;}
ret = cJSON_AddNumberToObject(note, "muteGroup", voice[j].mute_group);
if(ret==NULL){log_e("failed to make json muteGroup");continue;}
ret = cJSON_AddNumberToObject(note, "loopStart", voice[j].loop_start);
if(ret==NULL){log_e("failed to make json loppStart");continue;}
ret = cJSON_AddNumberToObject(note, "loopEnd", voice[j].loop_end);
if(ret==NULL){log_e("failed to make json priority");continue;}
if(ret==NULL){log_e("failed to make json loop_end");continue;}
if(voice[j].isRack > -1){
// its a rack
// log_i("rack %d",voice[j].isRack);
Expand Down Expand Up @@ -1116,6 +1124,7 @@ void updateSingleVoiceConfig(char *json, int num_voice){
voice_data[num_note].note_off_meaning = cJSON_GetObjectItemCaseSensitive(note, "noteOff")->valueint;
voice_data[num_note].response_curve = cJSON_GetObjectItemCaseSensitive(note, "responseCurve")->valueint;
voice_data[num_note].priority = cJSON_GetObjectItemCaseSensitive(note, "priority")->valueint;
voice_data[num_note].mute_group = cJSON_GetObjectItemCaseSensitive(note, "muteGroup")->valueint;
voice_data[num_note].loop_start = cJSON_GetObjectItemCaseSensitive(note, "loopStart")->valueint;
voice_data[num_note].loop_end = cJSON_GetObjectItemCaseSensitive(note, "loopEnd")->valueint;
// is a rack, and not a new rack (would be -2)
Expand Down Expand Up @@ -1161,6 +1170,7 @@ void updateSingleVoiceConfig(char *json, int num_voice){
voice_data[num_note].note_off_meaning = HALT;
voice_data[num_note].response_curve = RESPONSE_SQUARE_ROOT;
voice_data[num_note].priority = 0;
voice_data[num_note].mute_group = 0;
voice_data[num_note].loop_start = 0;
voice_data[num_note].loop_end = 0;
char *blank = "";
Expand Down
8 changes: 8 additions & 0 deletions src/file_system.h
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,11 @@ struct metadata_t {
uint8_t midi_channel; // 0 is omni
};

struct vol_t {
uint8_t left;
uint8_t right;
};

struct wav_lu_t {
size_t length;
size_t start_block;
Expand All @@ -115,6 +120,7 @@ struct wav_lu_t {
enum note_off_meaning note_off_meaning;
enum response_curve response_curve;
uint8_t priority; // 0 to 15
uint8_t mute_group;
uint8_t empty;
size_t loop_start;
size_t loop_end;
Expand All @@ -130,9 +136,11 @@ struct wav_file_t {
enum note_off_meaning note_off_meaning;
enum response_curve response_curve;
uint8_t priority; // 0 to 15
uint8_t mute_group; // 0 to 15
uint8_t empty;
size_t loop_start;
size_t loop_end;
int RFU;
};

struct firmware_t {
Expand Down
Loading

0 comments on commit 15d0aa2

Please sign in to comment.