add sample and wavetable examples, parsers for both

This commit is contained in:
Jack Humbert
2019-06-05 00:47:31 -04:00
parent bfe468ef1d
commit f52faeb5d6
15 changed files with 6884 additions and 2348 deletions
+6 -4
View File
@@ -13,8 +13,8 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef AUDIO_H
#define AUDIO_H
#pragma once
#include <stdint.h>
#include <stdbool.h>
@@ -27,6 +27,9 @@
#include "voices.h"
#include "quantum.h"
#include <math.h>
#if defined(PROTOCOL_CHIBIOS)
#include "audio_arm.h"
#endif
// Largely untested PWM audio mode (doesn't sound as good)
// #define PWM_AUDIO
@@ -107,6 +110,5 @@ void play_notes(float (*np)[][2], uint16_t n_count, bool n_repeat);
#define PLAY_SONG(note_array) play_notes(&note_array, NOTE_ARRAY_SIZE((note_array)), false)
#define PLAY_LOOP(note_array) play_notes(&note_array, NOTE_ARRAY_SIZE((note_array)), true)
bool is_playing_note(void);
bool is_playing_notes(void);
#endif
+48 -143
View File
@@ -1,4 +1,4 @@
/* Copyright 2016 Jack Humbert
/* Copyright 2016-2019 Jack Humbert
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -26,75 +26,8 @@
// -----------------------------------------------------------------------------
/**
* Size of the dac_buffer arrays. All must be the same size.
*/
#define DAC_BUFFER_SIZE 256U
/**
* Highest value allowed by our 12bit DAC.
*/
#ifndef DAC_SAMPLE_MAX
#define DAC_SAMPLE_MAX 4095U
#endif
#define DAC_LOW_QUALITY
/**
* These presets allow you to quickly switch between quality/voice settings for
* the DAC. The sample rate and number of voices roughly has an inverse
* relationship - slightly higher sample rates may be possible.
*/
#ifdef DAC_VERY_LOW_QUALITY
#define DAC_SAMPLE_RATE 11025U
#define DAC_VOICES_MAX 8
#endif
#ifdef DAC_LOW_QUALITY
#define DAC_SAMPLE_RATE 22050U
#define DAC_VOICES_MAX 4
#endif
#ifdef DAC_HIGH_QUALITY
#define DAC_SAMPLE_RATE 44100U
#define DAC_VOICES_MAX 2
#endif
#ifdef DAC_VERY_HIGH_QUALITY
#define DAC_SAMPLE_RATE 88200U
#define DAC_VOICES_MAX 1
#endif
/**
* Effective bitrate of the DAC. 44.1khz is the standard for most audio - any
* lower will sacrifice perceptible audio quality. Any higher will limit the
* number of simultaneous voices. In most situations, a tenth (1/10) of the
* sample rate is where notes become unbearable.
*/
#ifndef DAC_SAMPLE_RATE
#define DAC_SAMPLE_RATE 44100U
#endif
/**
* The number of voices (in polyphony) that are supported. If too high a value
* is used here, the keyboard will freeze and glitch-out when that many voices
* are being played.
*/
#ifndef DAC_VOICES_MAX
#define DAC_VOICES_MAX 2
#endif
/**
* The default value of the DAC when not playing anything. Certain hardware
* setups may require a high (DAC_SAMPLE_MAX) or low (0) value here.
*/
#ifndef DAC_OFF_VALUE
#define DAC_OFF_VALUE DAC_SAMPLE_MAX / 2
#endif
int voices = 0;
float frequencies[8] = {0, 0, 0, 0, 0, 0, 0, 0};
int volumes[8] = {0, 0, 0, 0, 0, 0, 0, 0};
uint8_t dac_voices = 0;
float dac_frequencies[8] = { 0.0 };
bool playing_notes = false;
bool playing_note = false;
@@ -129,7 +62,7 @@ bool glissando = true;
#endif
float startup_song[][2] = STARTUP_SONG;
static const dacsample_t dac_buffer[DAC_BUFFER_SIZE] = {
static const dacsample_t dac_buffer_sine[DAC_BUFFER_SIZE] = {
// 256 values, max 4095
0x800,0x832,0x864,0x896,0x8c8,0x8fa,0x92c,0x95e,
0x98f,0x9c0,0x9f1,0xa22,0xa52,0xa82,0xab1,0xae0,
@@ -209,69 +142,40 @@ static const dacsample_t dac_buffer_square[DAC_BUFFER_SIZE] = {
static dacsample_t dac_buffer_empty[DAC_BUFFER_SIZE] = { DAC_OFF_VALUE };
#include "wavetable.h"
float dac_if[8] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0};
uint8_t dac_voice = 0;
uint8_t dac_voice_flipped = 0;
uint16_t dac_voice_counter = 0;
float dac_voice_count_flipped = 0;
static float dac_if[8] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0};
/**
* Generation of the sample being passed to the callback. Declared weak so users
* Generation of the waveform being passed to the callback. Declared weak so users
* can override it with their own waveforms/noises.
*/
__attribute__ ((weak))
uint16_t generate_sample(void) {
uint16_t sample = DAC_OFF_VALUE;
uint8_t working_voices = voices;
uint16_t dac_value_generate(void) {
uint16_t value = DAC_OFF_VALUE;
uint8_t working_voices = dac_voices;
if (working_voices > DAC_VOICES_MAX)
working_voices = DAC_VOICES_MAX;
if (working_voices > 0) {
uint16_t sample_sum = 0;
uint16_t value_avg = 0;
for (uint8_t i = 0; i < working_voices; i++) {
dac_if[i] = dac_if[i] + ((frequencies[i]*DAC_BUFFER_SIZE)/DAC_SAMPLE_RATE);
dac_if[i] = dac_if[i] + ((dac_frequencies[i] * DAC_BUFFER_SIZE) / DAC_SAMPLE_RATE);
// Needed because % doesn't work with floats
// 0.5 less than the size because we use round() later
while (dac_if[i] >= (DAC_BUFFER_SIZE))
dac_if[i] = dac_if[i] - DAC_BUFFER_SIZE;
(void)dac_buffer;
(void)dac_buffer_square;
(void)dac_buffer_triangle;
#define DAC_MORPH_SPEED 3000
#define DAC_SAMPLE_CUSTOM_LENGTH 64
#define DAC_MORPH_SPEED_COMPUTED (DAC_SAMPLE_RATE / DAC_SAMPLE_CUSTOM_LENGTH * DAC_MORPH_SPEED / 1000)
uint16_t dac_i = (uint16_t)dac_if[i];
// Wavetable generation/lookup
uint16_t dac_i = (uint16_t)dac_if[i];
// SINE
// sample_sum += dac_buffer[dac_i] / working_voices / 3;
value_avg += dac_buffer_sine[dac_i] / working_voices / 3;
// TRIANGLE
// sample_sum += dac_buffer_triangle[dac_i] / working_voices / 3;
// RISING TRIANGLE
// sample_sum += (uint16_t)round((dac_if[i] * DAC_SAMPLE_MAX) / DAC_BUFFER_SIZE / working_voices );
value_avg += dac_buffer_triangle[dac_i] / working_voices / 3;
// SQUARE
// sample_sum += ((dac_if[i] > (DAC_BUFFER_SIZE / 2)) ? DAC_SAMPLE_MAX / working_voices: 0);
// sample_sum += dac_buffer_square[dac_i] / working_voices / 3;
// sample_sum += dac_buffer_custom[dac_voice_flipped][dac_i] / working_voices / 2 * ((dac_voice >= 63) ? 6400 - dac_voice_counter : dac_voice_counter) / 6400;
// sample_sum += dac_buffer_custom[dac_voice_flipped + 1][dac_i] / working_voices / 2 * ((dac_voice >= 63) ? dac_voice_counter : 6400 - dac_voice_counter) / 6400;
sample_sum += dac_buffer_custom[dac_voice][dac_i] / working_voices / 2 * (DAC_MORPH_SPEED_COMPUTED - dac_voice_counter) / DAC_MORPH_SPEED_COMPUTED;
sample_sum += dac_buffer_custom[dac_voice + 1][dac_i] / working_voices / 2 * dac_voice_counter / DAC_MORPH_SPEED_COMPUTED;
}
sample = sample_sum;
dac_voice_counter++;
if (dac_voice_counter >= DAC_MORPH_SPEED_COMPUTED) {
dac_voice_counter = 0;
// dac_voice = (dac_voice + 1) % 125;
// dac_voice_flipped = ((dac_voice >= 63) ? (125 - dac_voice) : dac_voice);
dac_voice = (dac_voice + 1) % (DAC_SAMPLE_CUSTOM_LENGTH - 1);
value_avg += dac_buffer_square[dac_i] / working_voices / 3;
}
value = value_avg;
}
return sample;
return value;
}
/**
@@ -282,7 +186,7 @@ static void dac_end(DACDriver * dacp, dacsample_t * sample_p, size_t sample_coun
(void)dacp;
for (uint8_t s = 0; s < sample_count; s++) {
sample_p[s] = generate_sample();
sample_p[s] = dac_value_generate();
}
if (playing_notes) {
@@ -402,15 +306,13 @@ void stop_all_notes() {
if (!audio_initialized) {
audio_init();
}
voices = 0;
dac_voices = 0;
playing_notes = false;
playing_note = false;
for (uint8_t i = 0; i < 8; i++)
{
frequencies[i] = 0;
volumes[i] = 0;
for (uint8_t i = 0; i < 8; i++) {
dac_frequencies[i] = 0;
}
}
@@ -422,23 +324,20 @@ void stop_note(float freq) {
audio_init();
}
for (int i = 7; i >= 0; i--) {
if (frequencies[i] == freq) {
frequencies[i] = 0;
volumes[i] = 0;
if (dac_frequencies[i] == freq) {
dac_frequencies[i] = 0;
for (int j = i; (j < 7); j++) {
frequencies[j] = frequencies[j+1];
frequencies[j+1] = 0;
volumes[j] = volumes[j+1];
volumes[j+1] = 0;
dac_frequencies[j] = dac_frequencies[j+1];
dac_frequencies[j+1] = 0;
}
break;
}
}
voices--;
if (voices < 0) {
voices = 0;
dac_voices--;
if (dac_voices < 0) {
dac_voices = 0;
}
if (voices == 0) {
if (dac_voices == 0) {
playing_note = false;
}
}
@@ -472,25 +371,19 @@ void play_note(float freq, int vol) {
audio_init();
}
if (audio_config.enable && voices < 8) {
// Cancel notes if notes are playing
// if (playing_notes) {
// stop_all_notes();
// }
if (audio_config.enable && dac_voices < 8) {
playing_note = true;
if (freq > 0) {
envelope_index = 0;
frequencies[voices] = freq;
dac_if[voices] = 0.0f;
volumes[voices] = vol;
voices++;
dac_frequencies[dac_voices] = freq;
dac_voices++;
}
}
}
__attribute__ ((weak))
void dac_setup_note(void) {
dac_if[dac_voices] = 0.0f;
}
void play_notes(float (*np)[][2], uint16_t n_count, bool n_repeat) {
@@ -517,6 +410,10 @@ void play_notes(float (*np)[][2], uint16_t n_count, bool n_repeat) {
}
}
bool is_playing_note(void) {
return playing_note;
}
bool is_playing_notes(void) {
return playing_notes;
}
@@ -624,3 +521,11 @@ void increase_tempo(uint8_t tempo_change) {
note_tempo -= tempo_change;
}
}
uint8_t dac_number_of_voices(void) {
return dac_voices;
}
float dac_get_frequency(uint8_t index) {
return dac_frequencies[index];
}
+89
View File
@@ -0,0 +1,89 @@
/* Copyright 2019 Jack Humbert
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include "ch.h"
/**
* Size of the dac_buffer arrays. All must be the same size.
*/
#define DAC_BUFFER_SIZE 256U
/**
* Highest value allowed by our 12bit DAC.
*/
#ifndef DAC_SAMPLE_MAX
#define DAC_SAMPLE_MAX 4095U
#endif
// #define DAC_LOW_QUALITY
/**
* These presets allow you to quickly switch between quality/voice settings for
* the DAC. The sample rate and number of voices roughly has an inverse
* relationship - slightly higher sample rates may be possible.
*/
#ifdef DAC_VERY_LOW_QUALITY
#define DAC_SAMPLE_RATE 11025U
#define DAC_VOICES_MAX 8
#endif
#ifdef DAC_LOW_QUALITY
#define DAC_SAMPLE_RATE 22050U
#define DAC_VOICES_MAX 4
#endif
#ifdef DAC_HIGH_QUALITY
#define DAC_SAMPLE_RATE 44100U
#define DAC_VOICES_MAX 2
#endif
#ifdef DAC_VERY_HIGH_QUALITY
#define DAC_SAMPLE_RATE 88200U
#define DAC_VOICES_MAX 1
#endif
/**
* Effective bitrate of the DAC. 44.1khz is the standard for most audio - any
* lower will sacrifice perceptible audio quality. Any higher will limit the
* number of simultaneous voices. In most situations, a tenth (1/10) of the
* sample rate is where notes become unbearable.
*/
#ifndef DAC_SAMPLE_RATE
#define DAC_SAMPLE_RATE 44100U
#endif
/**
* The number of voices (in polyphony) that are supported. If too high a value
* is used here, the keyboard will freeze and glitch-out when that many voices
* are being played.
*/
#ifndef DAC_VOICES_MAX
#define DAC_VOICES_MAX 2
#endif
/**
* The default value of the DAC when not playing anything. Certain hardware
* setups may require a high (DAC_SAMPLE_MAX) or low (0) value here.
*/
#ifndef DAC_OFF_VALUE
#define DAC_OFF_VALUE DAC_SAMPLE_MAX / 2
#endif
uint8_t dac_number_of_voices(void);
float dac_get_frequency(uint8_t index);
uint16_t dac_value_generate(void);
void dac_setup_note(void);
File diff suppressed because it is too large Load Diff