Wavetable artifacts, noise

Status
Not open for further replies.

RABB17

Well-known member
Hello

In the process of converting single cycle waveforms to soundfonts for use with the wavetable object I have come across a problem:

When I create the custom soundfont it works on Windows in a variety of midi synths with no artifacting or noise, however, when I use the same soundfont in a a wavetable on the teensy there are very noticable artifacts. This doesn't happen with established soundfont packages I have ripped.

Main sketch below, followed by the 2 wavetables used

Code:
#include "0001_samples.h"
#include "0002_samples.h"

#include <Bounce.h>
#include <Audio.h>
#include <Wire.h>
#include <SPI.h>
#include <SD.h>
#include <SerialFlash.h>

//#define DEBUG_ALLOC

const int TOTAL_VOICES = 64;
const int TOTAL_MIXERS = 21;
const int SECONDARY_MIXERS = 4;

AudioControlSGTL5000 sgtl5000_1;
AudioSynthWavetable wavetable[TOTAL_VOICES];
AudioMixer4 mixer[TOTAL_MIXERS];
AudioOutputI2S i2s1;
AudioConnection patchCord[] = {
  {wavetable[0], 0, mixer[0], 0}, {wavetable[1], 0, mixer[0], 1}, {wavetable[2], 0, mixer[0],  2}, {wavetable[3], 0, mixer[0],  3}, {mixer[0], 0, mixer[TOTAL_MIXERS - 2], 0},
  {wavetable[4], 0, mixer[1], 0}, {wavetable[5], 0, mixer[1], 1}, {wavetable[6], 0, mixer[1],  2}, {wavetable[7], 0, mixer[1],  3}, {mixer[1], 0, mixer[TOTAL_MIXERS - 2], 1},
  {wavetable[8], 0, mixer[2], 0}, {wavetable[9], 0, mixer[2], 1}, {wavetable[10], 0, mixer[2],  2}, {wavetable[11], 0, mixer[2],  3}, {mixer[2], 0, mixer[TOTAL_MIXERS - 2], 2},
  {wavetable[12], 0, mixer[3], 0}, {wavetable[13], 0, mixer[3], 1}, {wavetable[14], 0, mixer[3],  2}, {wavetable[15], 0, mixer[3],  3}, {mixer[3], 0, mixer[TOTAL_MIXERS - 2], 3},
  {wavetable[16], 0, mixer[4], 0}, {wavetable[17], 0, mixer[4], 1}, {wavetable[18], 0, mixer[4],  2}, {wavetable[19], 0, mixer[4],  3}, {mixer[4], 0, mixer[TOTAL_MIXERS - 3], 0},
  {wavetable[20], 0, mixer[5], 0}, {wavetable[21], 0, mixer[5], 1}, {wavetable[22], 0, mixer[5],  2}, {wavetable[23], 0, mixer[5],  3}, {mixer[5], 0, mixer[TOTAL_MIXERS - 3], 1},
  {wavetable[24], 0, mixer[6], 0}, {wavetable[25], 0, mixer[6], 1}, {wavetable[26], 0, mixer[6],  2}, {wavetable[27], 0, mixer[6],  3}, {mixer[6], 0, mixer[TOTAL_MIXERS - 3], 2},
  {wavetable[28], 0, mixer[7], 0}, {wavetable[29], 0, mixer[7], 1}, {wavetable[30], 0, mixer[7],  2}, {wavetable[31], 0, mixer[7],  3}, {mixer[7], 0, mixer[TOTAL_MIXERS - 3], 3},
  {wavetable[32], 0, mixer[8], 0}, {wavetable[33], 0, mixer[8], 1}, {wavetable[34], 0, mixer[8],  2}, {wavetable[35], 0, mixer[8],  3}, {mixer[8], 0, mixer[TOTAL_MIXERS - 4], 0},
  {wavetable[36], 0, mixer[9], 0}, {wavetable[37], 0, mixer[9], 1}, {wavetable[38], 0, mixer[9],  2}, {wavetable[39], 0, mixer[9],  3}, {mixer[9], 0, mixer[TOTAL_MIXERS - 4], 1},
  {wavetable[40], 0, mixer[10], 0}, {wavetable[41], 0, mixer[10], 1}, {wavetable[42], 0, mixer[10], 2}, {wavetable[43], 0, mixer[10], 3}, {mixer[10], 0, mixer[TOTAL_MIXERS - 4], 2},
  {wavetable[44], 0, mixer[11], 0}, {wavetable[45], 0, mixer[11], 1}, {wavetable[46], 0, mixer[11], 2}, {wavetable[47], 0, mixer[11], 3}, {mixer[11], 0, mixer[TOTAL_MIXERS - 4], 3},
  {wavetable[48], 0, mixer[12], 0}, {wavetable[49], 0, mixer[12], 1}, {wavetable[50], 0, mixer[12], 2}, {wavetable[51], 0, mixer[12], 3}, {mixer[12], 0, mixer[TOTAL_MIXERS - 5], 0},
  {wavetable[52], 0, mixer[13], 0}, {wavetable[53], 0, mixer[13], 1}, {wavetable[54], 0, mixer[13], 2}, {wavetable[55], 0, mixer[13], 3}, {mixer[13], 0, mixer[TOTAL_MIXERS - 5], 1},
  {wavetable[56], 0, mixer[14], 0}, {wavetable[57], 0, mixer[14], 1}, {wavetable[58], 0, mixer[14], 2}, {wavetable[59], 0, mixer[14], 3}, {mixer[14], 0, mixer[TOTAL_MIXERS - 5], 2},
  {wavetable[60], 0, mixer[15], 0}, {wavetable[61], 0, mixer[15], 1}, {wavetable[62], 0, mixer[15], 2}, {wavetable[63], 0, mixer[15], 3}, {mixer[15], 0, mixer[TOTAL_MIXERS - 5], 3},
  {mixer[TOTAL_MIXERS - 2], 0, mixer[TOTAL_MIXERS - 1], 0},
  {mixer[TOTAL_MIXERS - 3], 0, mixer[TOTAL_MIXERS - 1], 1},
  {mixer[TOTAL_MIXERS - 4], 0, mixer[TOTAL_MIXERS - 1], 2},
  {mixer[TOTAL_MIXERS - 5], 0, mixer[TOTAL_MIXERS - 1], 3},
  {mixer[TOTAL_MIXERS - 1], 0, i2s1, 0},
  {mixer[TOTAL_MIXERS - 1], 0, i2s1, 1},
};

AudioSynthWavetable::instrument_data customWavetables[] =
{ 0001, 0002};
Bounce buttons[] = { {0, 15}, {1, 15}, {2, 15}, };
const int TOTAL_BUTTONS = sizeof(buttons) / sizeof(Bounce);
static int CURRENT_INSTRUMENT = 00;

void guitarHeroMode();
void printVoices();
void setVolume() {
  sgtl5000_1.volume(0.8 * (analogRead(PIN_A2) - 1) / 1022.0);
}

struct voice_t {
  int wavetable_id;
  byte channel;
  byte note;
};
voice_t voices[TOTAL_VOICES];

IntervalTimer midiMapTimer;
IntervalTimer guitarHeroTimer;
IntervalTimer volumeTimer;

void setup() {
  Serial.begin(115200);

  pinMode(0, INPUT_PULLUP);
  pinMode(1, INPUT_PULLUP);
  pinMode(2, INPUT_PULLUP);

  AudioMemory(120);

  sgtl5000_1.enable();
  sgtl5000_1.volume(.77);
  sgtl5000_1.audioPostProcessorEnable();
  sgtl5000_1.autoVolumeControl(0, 0, 0, -18.0, .001, .002);

  for (int i = 0; i < TOTAL_VOICES; ++i) {
    wavetable[i].setInstrument(customWavetables[CURRENT_INSTRUMENT]);
    wavetable[i].amplitude(1);
    voices[i].wavetable_id = i;
    voices[i].channel = voices[i].note = 0xFF;
  }

  for (int i = 0; i < TOTAL_MIXERS - 1; ++i)
    for (int j = 0; j < 4; ++j)
      mixer[i].gain(j, 0.5);
  for (int i = 0; i < 4; ++i)
    mixer[TOTAL_MIXERS - 1].gain(i, i < SECONDARY_MIXERS ? 1.0 / SECONDARY_MIXERS : 0.0);

  usbMIDI.setHandleNoteOn(OnNoteOn);
  usbMIDI.setHandleNoteOff(OnNoteOff);
  usbMIDI.setHandleControlChange(OnControlChange);
  //volumeTimer.begin(setVolume, 100000);
  //guitarHeroTimer.begin(guitarHeroMode, 1000000 / 120);
  //midiMapTimer.begin(printVoices, 5000);

  delay(2000);
}

void loop() {
  usbMIDI.read();
  //for (int i = 0; i < TOTAL_BUTTONS; ++i) buttons[i].update();
  //if (buttons[0].fallingEdge()) AudioSynthWavetable::print_performance();
  //if (buttons[1].risingEdge()) {
  //  midiMapTimer.end();
  //  Serial.print('\n');
  //}
  //if (buttons[1].fallingEdge()) midiMapTimer.begin(printVoices, 5000);
  //if (buttons[2].risingEdge()) guitarHeroTimer.end();
  //if (buttons[2].fallingEdge())
  //  guitarHeroTimer.begin(guitarHeroMode, 1000000/60);
}

int allocateVoice(byte channel, byte note);
int findVoice(byte channel, byte note);
void freeVoices();

int used_voices = 0;
int stopped_voices = 0;
int evict_voice = 0;
int notes_played = 0;

void OnPress(int key)
{
  Serial.print("key '");
  Serial.print((char)key);
  Serial.print("'  ");
  Serial.println(key);
  //Serial.print("key ");
  //Serial.print((char)keyboard1.getKey());
  //Serial.print("  ");
  //Serial.print((char)keyboard2.getKey());
  //Serial.println();
}

void OnControlChange(byte channel, byte control, byte value)
{
  Serial.print("Control Change, ch=");
  Serial.print(channel);
  Serial.print(", control=");
  Serial.print(control);
  Serial.print(", value=");
  Serial.print(value);
  Serial.println();

  switch (control) {
    case 70:
      CURRENT_INSTRUMENT = value;
      for (int i = 0; i < TOTAL_VOICES; ++i) {
        wavetable[i].setInstrument(customWavetables[CURRENT_INSTRUMENT]);
        wavetable[i].amplitude(1);
        voices[i].wavetable_id = i;
        voices[i].channel = voices[i].note = 0xFF;
      }
      break;
  }
}

void OnNoteOn(byte channel, byte note, byte velocity) {
  notes_played++;
#ifdef DEBUG_ALLOC
  //Serial.printf("**** NoteOn: channel==%hhu,note==%hhu ****\n", channel, note);
  printVoices();
#endif //DEBUG_ALLOC
  freeVoices();
  int wavetable_id = allocateVoice(channel, note);
  switch (channel) {
    case 1:
      wavetable[wavetable_id].setInstrument(customWavetables[CURRENT_INSTRUMENT]);
      break;
    /*
      case 2:
        wavetable[wavetable_id].setInstrument(Vibraphone0);
        break;
      case 3:
        wavetable[wavetable_id].setInstrument(MusicBox);
        break;
      case 4:
        wavetable[wavetable_id].setInstrument(AcouPiano3);
        break;
      case 5:
        wavetable[wavetable_id].setInstrument(SynthStrings1);
        break;
      case 6:
        wavetable[wavetable_id].setInstrument(Ocarina);
        break;
      case 7:
        wavetable[wavetable_id].setInstrument(Seashore);
        break;
      case 8:
        wavetable[wavetable_id].setInstrument(Recorder);
        break;
      case 9:
        wavetable[wavetable_id].setInstrument(SynthStrings1);
        break;
      case 10:
        wavetable[wavetable_id].setInstrument(ElectricPiano0);
        break;
      case 11:
        wavetable[wavetable_id].setInstrument(ElectricPiano0);
        break;
    */
    default:
      wavetable[wavetable_id].setInstrument(customWavetables[CURRENT_INSTRUMENT]);
      break;
  }
  wavetable[wavetable_id].playNote(note, velocity);
  //wavetable[wavetable_id+1].playNote(note, velocity);
#ifdef DEBUG_ALLOC
  printVoices();
#endif //DEBUG_ALLOC
}

void OnNoteOff(byte channel, byte note, byte velocity) {
#ifdef DEBUG_ALLOC
  //Serial.printf("\n**** NoteOff: channel==%hhu,note==%hhu ****", channel, note);
  printVoices();
#endif //DEBUG_ALLOC
  int wavetable_id = findVoice(channel, note);
  if (wavetable_id != TOTAL_VOICES)
    wavetable[wavetable_id].stop();
#ifdef DEBUG_ALLOC
  printVoices();
#endif //DEBUG_ALLOC
}

int allocateVoice(byte channel, byte note) {
  int i;
  int nonfree_voices = stopped_voices + used_voices;
  if (nonfree_voices < TOTAL_VOICES) {
    for (i = nonfree_voices; i < TOTAL_VOICES && voices[i].channel != channel; ++i);
    if (i < TOTAL_VOICES) {
      voice_t temp = voices[i];
      voices[i] = voices[nonfree_voices];
      voices[nonfree_voices] = temp;
    }
    i = nonfree_voices;
    used_voices++;
  }
  else {
    if (stopped_voices) {
      i = evict_voice % stopped_voices;
      voice_t temp = voices[i];
      stopped_voices--;
      voices[i] = voices[stopped_voices];
      voices[stopped_voices] = temp;
      used_voices++;
      i = stopped_voices;
    }
    else
      i = evict_voice;
  }

  voices[i].channel = channel;
  voices[i].note = note;

  evict_voice++;
  evict_voice %= TOTAL_VOICES;

  return voices[i].wavetable_id;
}

int findVoice(byte channel, byte note) {
  int i;
  //find match
  int nonfree_voices = stopped_voices + used_voices;
  for (i = stopped_voices; i < nonfree_voices && !(voices[i].channel == channel && voices[i].note == note); ++i);
  //return TOTAL_VOICES if no match
  if (i == (nonfree_voices)) return TOTAL_VOICES;

  voice_t temp = voices[i];
  voices[i] = voices[stopped_voices];
  voices[stopped_voices] = temp;
  --used_voices;

  return voices[stopped_voices++].wavetable_id;
}

void freeVoices() {
  for (int i = 0; i < stopped_voices; i++)
    if (wavetable[voices[i].wavetable_id].isPlaying() == false) {
      voice_t temp = voices[i];
      --stopped_voices;
      voices[i] = voices[stopped_voices];
      int nonfree_voices = stopped_voices + used_voices;
      voices[stopped_voices] = voices[nonfree_voices];
      voices[nonfree_voices] = temp;
    }
}

void guitarHeroMode() { // now unicorn friendly
  const int RESET = 4;
  const int MIDI_NOTES = 128;
  static char line[MIDI_NOTES + 1] = { 0 };
  static int accumulated = 0;
  if (!accumulated) {
    for (int i = 0; i < MIDI_NOTES; ++i) line[i] = '-';
    ++accumulated;
  }
  for (int i = stopped_voices; i < used_voices + stopped_voices; ++i) line[voices[i].note] = '*';
  if (accumulated == RESET) {
    Serial.println(line);
    accumulated = 0;
  }
  else {
    ++accumulated;
  }
}

const char* note_map[] = {
  "C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"
};

void printVoices() {
  static int last_notes_played = notes_played;
  if (last_notes_played == notes_played)
    return;
  last_notes_played = notes_played;
  int usage = AudioProcessorUsage();
  Serial.printf("\nCPU:%03i voices:%02i CPU/Voice:%02i evict:%02i", usage, used_voices, usage / used_voices, evict_voice);
  for (int i = 0; i < used_voices; ++i)
    Serial.printf(" %02hhu %-2s", voices[i].channel, note_map[voices[i].note % 12]);

}
 
Last edited:
0001_samples.h
Code:
#pragma once
#include <Audio.h>
extern const AudioSynthWavetable::instrument_data 0001;

0001_samples.cpp

Code:
#include "0001_samples.h"

static const uint32_t sample_0_0001_0001[384] = {
0x068e00fb,0x12750c57,0x1f9818e1,0x2d772680,0x3ac3344b,0x44ad4082,0x50e2480f,0x5e1357e8,
0x699063f2,0x73696ec6,0x7a887759,0x7ea57cf5,0x7fff7fa6,0x7ef07fc0,0x7bd67d9d,0x772579a9,
0x71407455,0x6a476ddf,0x62b06691,0x5a395e93,0x50a05597,0x45994b4e,0x39073f82,0x2aff322f,
0x1bbd237e,0x0bbc13ca,0xfbb603ad,0xec75f3ef,0xded3e560,0xd3f9d8f1,0xcc09d0f1,0xc0f4c5d5,
0xb8b0bcad,0xb192b4f5,0xac12ae99,0xa85ea9ff,0xa653a726,0xa5d1a5e2,0xa6c4a61d,0xa911a7c2,
0xac8aaaaa,0xb102aea9,0xb64eb390,0xbc4db939,0xc2e0bf85,0xc9e9c658,0xd14bcd91,0xd8e5d513,
0xe09cdcbf,0xe84fe477,0xefe6ec1f,0xf747f39e,0xfe59fadb,0x050a01be,0x0b470837,0x10ff0e35,
0x162613a6,0x1aae187f,0x1e8e1cb4,0x21b32038,0x23ef22f7,0x25f52495,0x27ef270a,0x297c28bd,
0x2acb2a2e,0x2bc52b53,0x2c6e2c24,0x2cce2ca8,0x2ce92ce4,0x2cc62cdf,0x2c672c9e,0x2bd72c25,
0x2b1b2b7e,0x2a3c2ab0,0x293a29c0,0x281c28b0,0x26e02782,0x25862636,0x240f24cf,0x227a2348,
0x20c321a2,0x1ee91fdb,0x1ce91ded,0x1abf1bd9,0x186c199b,0x15ec1731,0x133f149b,0x106711d8,
0x0d640eea,0x0a3b0bd4,0x06f10899,0x03890540,0x000b01cc,0xfc7efe46,0xf8e9fab4,0xf551f71c,
0xf1bdf386,0xee38eff9,0xeac3ec7b,0xe766e912,0xe425e5c1,0xe104e291,0xde05df80,0xdb2ddc94,
0xd87ed9d1,0xd5fad737,0xd3a4d4c8,0xd180d28c,0xcf93d082,0xcde0ceb1,0xcc6fcd1f,0xcb44cbd0,
0xca66caca,0xc9dbca16,0xc9aac9b7,0xc9d5c9b4,0xca60ca0e,0xcb4ccaca,0xcc97cbe5,0xce3bcd5e,
0xd036cf2f,0xd27ed151,0xd50ad3bd,0xd7cdd666,0xdabbd93f,0xddc3dc3d,0xe0d6df4d,0xe3e4e25e,
0xe6dbe563,0xe9afe84a,0xec54eb08,0xeec4ed92,0xf100efe8,0xf316f20f,0xf527f41c,0xf7a0f650,
0xf8c6f828,0xf9f7f967,0xfae0fa74,0xfba6fb45,0xfc75fc0a,0xfd75fcee,0xfecbfe13,0x009bffa2,
0x031101bf,0x06460492,0x0a590832,0x0f620cbc,0x15911250,0x1e1d1984,0x25da2255,0x2bf0291f,
0x339b2e3b,0x3d5e3888,0x47944262,0x51fa4cd0,0x5b9656ee,0x63b15fdc,0x69d56707,0x6dc06c14,
0x6f636eda,0x6ee86f66,0x6ca56df9,0x69036af9,0x646866cf,0x5f2161d6,0x59615c4e,0x53325658,
0x4c874fef,0x453548f6,0x3d02413c,0x33b73882,0x29282e99,0x1d4c2363,0x104016e8,0x02560960,
0xf408fb33,0xe5ebece9,0xd8addf25,0xcd08d29c,0xc3f0c813,0xbddec168,0xb456b871,0xad7fb0cd,
0xa790aa65,0xa2f0a50f,0x9fd6a133,0x9e269ed3,0x9dc59dcd,0x9ea39e0c,0xa0a79f82,0xa3afa20e,
0xa78ba584,0xac1ba9bf,0xb13fae9c,0xb6e0b402,0xbce5b9d8,0xc33bc008,0xc9cbc67e,0xd083cd23,
0xd74fd3e8,0xde20dab8,0xe4e9e186,0xeb9ce847,0xf22deee9,0xf892f566,0xfec0fbb0,0x04af01bf,
0x0a56078d,0x0fb10d0e,0x14b7123f,0x1966171a,0x1dba1b9c,0x21b21fc1,0x254d238a,0x288c26f7,
0x2b722a0a,0x2e022cc4,0x30412f2b,0x32333144,0x33dd3311,0x35423497,0x366735dc,0x375036e3,
0x37fd37ad,0x3871383e,0x38aa3895,0x38a938b1,0x386b3892,0x37ec3834,0x372b3795,0x362436b0,
0x34d33585,0x3337340f,0x3151324d,0x2f203041,0x2ca62deb,0x29e82b4f,0x26ea2871,0x23b52557,
0x204d2206,0x1cbd1e89,0x19081ae6,0x15381723,0x11531348,0x0d5e0f5a,0x09600b61,0x055d075f,
0x015a035b,0xfd5cff5b,0xf965fb60,0xf57cf76f,0xf1a1f38b,0xedd6efb9,0xea22ebf9,0xe683e84f,
0xe2ffe4bd,0xdf97e147,0xdc52ddf0,0xd934dabd,0xd642d7b4,0xd383d4db,0xd102d23a,0xcec5cfda,
0xccd6cdc3,0xcb3bcbfc,0xc9fcca8f,0xc920c981,0xc8a7c8d7,0xc895c892,0xc8e5c8b0,0xc992c92f,
0xca94ca09,0xcbdecb31,0xcd62cc9a,0xcf0ece34,0xd0cdcfed,0xd28cd1ae,0xd42fd362,0xd59bd4ed,
0xd6a6d631,0xd698d6ee,0xd575d5ce,0xd550d56d,0xd4cad51e,0xd3d4d45a,0xd2a3d33f,0xd179d20a,
0xd090d0fa,0xd019d044,0xd040d016,0xd126d09a,0xd2dfd1e7,0xd577d40e,0xd8f5d719,0xdd5cdb0b,
0xe2bbdfec,0xe92ce5ce,0xf0eeecdc,0xfb45f5b4,0x00000000,0x00000000,0x00000000,0x00000000,
0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,
0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,
0x00000000,
};

static const AudioSynthWavetable::sample_data 0001_samples[1] = {
	{
		(int16_t*)sample_0_0001_0001, // sample
		true, // LOOP
		10, // LENGTH_BITS
		(1 << (32 - 10)) * WAVETABLE_CENTS_SHIFT(0) * 44100.0 / WAVETABLE_NOTE_TO_FREQUENCY(38) / AUDIO_SAMPLE_RATE_EXACT + 0.5, // PER_HERTZ_PHASE_INCREMENT
		((uint32_t)600 - 1) << (32 - 10), // MAX_PHASE
		((uint32_t)600 - 1) << (32 - 10), // LOOP_PHASE_END
		(((uint32_t)600 - 1) << (32 - 10)) - (((uint32_t)0 - 1) << (32 - 10)), // LOOP_PHASE_LENGTH
		uint16_t(UINT16_MAX * WAVETABLE_DECIBEL_SHIFT(0)), // INITIAL_ATTENUATION_SCALAR
		uint32_t(0.00 * AudioSynthWavetable::SAMPLES_PER_MSEC / AudioSynthWavetable::ENVELOPE_PERIOD + 0.5), // DELAY_COUNT
		uint32_t(1.00 * AudioSynthWavetable::SAMPLES_PER_MSEC / AudioSynthWavetable::ENVELOPE_PERIOD + 0.5), // ATTACK_COUNT
		uint32_t(0.00 * AudioSynthWavetable::SAMPLES_PER_MSEC / AudioSynthWavetable::ENVELOPE_PERIOD + 0.5), // HOLD_COUNT
		uint32_t(1.00 * AudioSynthWavetable::SAMPLES_PER_MSEC / AudioSynthWavetable::ENVELOPE_PERIOD + 0.5), // DECAY_COUNT
		uint32_t(1.00 * AudioSynthWavetable::SAMPLES_PER_MSEC / AudioSynthWavetable::ENVELOPE_PERIOD + 0.5), // RELEASE_COUNT
		int32_t((1.0 - WAVETABLE_DECIBEL_SHIFT(0.0)) * AudioSynthWavetable::UNITY_GAIN), // SUSTAIN_MULT
		uint32_t(0.00 * AudioSynthWavetable::SAMPLES_PER_MSEC / (2 * AudioSynthWavetable::LFO_PERIOD)), // VIBRATO_DELAY
		uint32_t(8.2 * AudioSynthWavetable::LFO_PERIOD * (UINT32_MAX / AUDIO_SAMPLE_RATE_EXACT)), // VIBRATO_INCREMENT
		(WAVETABLE_CENTS_SHIFT(0) - 1.0) * 4, // VIBRATO_PITCH_COEFFICIENT_INITIAL
		(1.0 - WAVETABLE_CENTS_SHIFT(0)) * 4, // VIBRATO_COEFFICIENT_SECONDARY
		uint32_t(0.00 * AudioSynthWavetable::SAMPLES_PER_MSEC / (2 * AudioSynthWavetable::LFO_PERIOD)), // MODULATION_DELAY
		uint32_t(8.2 * AudioSynthWavetable::LFO_PERIOD * (UINT32_MAX / AUDIO_SAMPLE_RATE_EXACT)), // MODULATION_INCREMENT
		(WAVETABLE_CENTS_SHIFT(0) - 1.0) * 4, // MODULATION_PITCH_COEFFICIENT_INITIAL
		(1.0 - WAVETABLE_CENTS_SHIFT(0)) * 4, // MODULATION_PITCH_COEFFICIENT_SECOND
		int32_t(UINT16_MAX * (WAVETABLE_DECIBEL_SHIFT(0) - 1.0)) * 4, // MODULATION_AMPLITUDE_INITIAL_GAIN
		int32_t(UINT16_MAX * (1.0 - WAVETABLE_DECIBEL_SHIFT(0))) * 4, // MODULATION_AMPLITUDE_FINAL_GAIN
	},
};

static const uint8_t 0001_ranges[] = {127, };

const AudioSynthWavetable::instrument_data 0001 = {1, 0001_ranges, 0001_samples };
 
0002_samples.h
Code:
#pragma once
#include <Audio.h>
extern const AudioSynthWavetable::instrument_data 0002;

0002_samples.cpp

Code:
#include "0002_samples.h"

static const uint32_t sample_0_0002_0002[384] = {
0x04d6001c,0x10a70a87,0x1d841707,0x2a87240b,0x372730eb,0x43033d32,0x4ddc4893,0x578852d9,
0x5ff75be9,0x672363b5,0x6d156a43,0x71db6f9c,0x758673d2,0x782b76f8,0x79d8791f,0x7a9a7a55,
0x7a777aa4,0x79717a0f,0x77877899,0x74b4763a,0x70f572f1,0x6c4e6ebe,0x66cc69a8,0x607863ba,
0x595d5d02,0x5191558c,0x492b4d6f,0x405144ca,0x372d3bc4,0x2dee328d,0x24cf2957,0x1c04205b,
0x13c417cf,0x0c450fea,0x05c408e2,0x00a302fa,0xfc97fece,0xf7f8fa48,0xf38cf5b6,0xef9bf181,
0xec45edda,0xe99deadb,0xe7ace88e,0xe672e6f9,0xe5e7e618,0xe5fde5e0,0xe6a3e640,0xe7c4e724,
0xe952e87f,0xeb3dea3d,0xed70ec4f,0xefdceea1,0xf26bf120,0xf507f3b8,0xf79cf653,0xfa13f8dd,
0xfc59fb3d,0xfe57fd63,0xffe7ff32,0x01320080,0x029a01e8,0x03e10344,0x04f10471,0x05bf0561,
0x0647060d,0x06880670,0x0684068f,0x063f0669,0x05ba0603,0x04ff0564,0x0415048e,0x03080391,
0x01e70278,0x00c80155,0xffd80043,0xfec3ff56,0xfd88fe27,0xfc46fce7,0xfb12fba9,0xf9fafa81,
0xf90ff97f,0xf85ff8af,0xf7eef81e,0xf7c5f7d2,0xf7e5f7cc,0xf851f811,0xf90df8a5,0xfa18f987,
0xfb6cfab9,0xfd00fc2f,0xfebafddb,0x004fff95,0x02600142,0x050503a4,0x08180681,0x0b8409c4,
0x0f330d54,0x130f111c,0x16ff1506,0x1ae918f6,0x1eb41cd3,0x22442084,0x258323ef,0x285926fc,
0x2ab32997,0x2c7e2bab,0x2dad2d2a,0x2e352e06,0x2e0f2e38,0x2d3a2dba,0x2bbb2c8f,0x299e2abf,
0x26e72855,0x239b2554,0x1fc021bf,0x1b611da0,0x168d1904,0x11611400,0x0c010eb4,0x06a3094d,
0x01a9040f,0xfd89ffbd,0xf81efaf1,0xf208f522,0xeb9beed9,0xe517e85a,0xdeabe1db,0xd882db8b,
0xd2c4d593,0xcd8fd016,0xc901cb31,0xc52cc6fe,0xc226c38e,0xbff8c0f3,0xbeacbf35,0xbe46be5c,
0xbec7be6a,0xc02cbf5e,0xc26ac132,0xc56fc3d3,0xc92ec737,0xcda2cb52,0xd2c1d01d,0xd878d58a,
0xdeb5db88,0xe554e1fa,0xec2be8bb,0xf306ef9d,0xf994f65d,0xff45fc9a,0x04460177,0x0aa6075f,
0x11790e08,0x186514f1,0x1f2c1bd1,0x25982270,0x2b8528a1,0x30d02e40,0x35603331,0x3925375d,
0x3c0d3ab5,0x3e153d2e,0x3f373ec3,0x3f723f71,0x3ecd3f3b,0x3d503e29,0x3b0a3c45,0x380f39a1,
0x34703653,0x303a3267,0x2b7b2dea,0x264628ef,0x20b02385,0x1ad91dcc,0x14e217df,0x0ef211e6,
0x093e0c0e,0x0400068b,0xffdf01b1,0xfbadfded,0xf6d3f948,0xf1dff458,0xed0cef6e,0xe886eabe,
0xe46ce66a,0xe0d6e290,0xddd7df43,0xdb79dc93,0xd9c4da89,0xd8b9d929,0xd855d873,0xd893d860,
0xd967d8eb,0xdac2da05,0xdc92db9c,0xdec3dd9e,0xe147dffb,0xe40de2a2,0xe707e585,0xea22e892,
0xed4debb8,0xf074eee2,0xf384f201,0xf66cf4fe,0xf91bf7cc,0xfb80fa57,0xfd8ffc92,0xff36fe71,
0x0057ffd9,0x017600e7,0x027601fb,0x033d02e1,0x03c6038a,0x040e03f3,0x04130419,0x03da03fe,
0x036303a5,0x02b80314,0x01e40252,0x00f80170,0x00120081,0xff2affad,0xfdfbfe98,0xfcadfd56,
0xfb51fbff,0xf9fbfaa5,0xf8bcf957,0xf7a1f829,0xf6bdf728,0xf616f661,0xf5b9f5df,0xf5a9f5a8,
0xf5e6f5bd,0xf675f623,0xf755f6da,0xf889f7e5,0xfa0bf941,0xfbd0fae6,0xfdc2fcc5,0xffaffec0,
0x01920080,0x043002d0,0x074005ac,0x0aa608ea,0x0e450c70,0x12041022,0x15c313e4,0x1967179b,
0x1cd21b26,0x1fe71e69,0x228b2149,0x24a523ab,0x26202577,0x26e8269a,0x26f32706,0x263f26b1,
0x24ce259e,0x229c23cd,0x1fa42139,0x1be21ddb,0x175a19b5,0x122014d3,0x0c590f4b,0x06470953,
0x0095034c,0xfafefe30,0xf358f758,0xea88ef0e,0xe0ebe5cd,0xd6d2dbea,0xcc89d1af,0xc253c767,
0xb871bd55,0xaf17b3af,0xa66daaaa,0x9e93a264,0x979c9afb,0x91919478,0x8c738ee5,0x88408a3d,
0x84f2867e,0x827e839c,0x80e18195,0x80158061,0x80208001,0x810b807a,0x82e381d8,0x85bc842e,
0x89a6878e,0x8eb08c07,0x94ea91a5,0x9c6f9882,0xa54ba0b1,0xaf83aa3d,0xbafeb51a,0xc789c125,
0xd4d1ce1b,0xe261db99,0xef9be916,0xfb8bf5d4,0x00000000,0x00000000,0x00000000,0x00000000,
0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,
0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,
0x00000000,0x00000000,
};

static const AudioSynthWavetable::sample_data 0002_samples[1] = {
	{
		(int16_t*)sample_0_0002_0002, // sample
		true, // LOOP
		10, // LENGTH_BITS
		(1 << (32 - 10)) * WAVETABLE_CENTS_SHIFT(0) * 44100.0 / WAVETABLE_NOTE_TO_FREQUENCY(38) / AUDIO_SAMPLE_RATE_EXACT + 0.5, // PER_HERTZ_PHASE_INCREMENT
		((uint32_t)600 - 1) << (32 - 10), // MAX_PHASE
		((uint32_t)600 - 1) << (32 - 10), // LOOP_PHASE_END
		(((uint32_t)600 - 1) << (32 - 10)) - (((uint32_t)0 - 1) << (32 - 10)), // LOOP_PHASE_LENGTH
		uint16_t(UINT16_MAX * WAVETABLE_DECIBEL_SHIFT(0)), // INITIAL_ATTENUATION_SCALAR
		uint32_t(0.00 * AudioSynthWavetable::SAMPLES_PER_MSEC / AudioSynthWavetable::ENVELOPE_PERIOD + 0.5), // DELAY_COUNT
		uint32_t(1.00 * AudioSynthWavetable::SAMPLES_PER_MSEC / AudioSynthWavetable::ENVELOPE_PERIOD + 0.5), // ATTACK_COUNT
		uint32_t(0.00 * AudioSynthWavetable::SAMPLES_PER_MSEC / AudioSynthWavetable::ENVELOPE_PERIOD + 0.5), // HOLD_COUNT
		uint32_t(1.00 * AudioSynthWavetable::SAMPLES_PER_MSEC / AudioSynthWavetable::ENVELOPE_PERIOD + 0.5), // DECAY_COUNT
		uint32_t(1.00 * AudioSynthWavetable::SAMPLES_PER_MSEC / AudioSynthWavetable::ENVELOPE_PERIOD + 0.5), // RELEASE_COUNT
		int32_t((1.0 - WAVETABLE_DECIBEL_SHIFT(0.0)) * AudioSynthWavetable::UNITY_GAIN), // SUSTAIN_MULT
		uint32_t(0.00 * AudioSynthWavetable::SAMPLES_PER_MSEC / (2 * AudioSynthWavetable::LFO_PERIOD)), // VIBRATO_DELAY
		uint32_t(8.2 * AudioSynthWavetable::LFO_PERIOD * (UINT32_MAX / AUDIO_SAMPLE_RATE_EXACT)), // VIBRATO_INCREMENT
		(WAVETABLE_CENTS_SHIFT(0) - 1.0) * 4, // VIBRATO_PITCH_COEFFICIENT_INITIAL
		(1.0 - WAVETABLE_CENTS_SHIFT(0)) * 4, // VIBRATO_COEFFICIENT_SECONDARY
		uint32_t(0.00 * AudioSynthWavetable::SAMPLES_PER_MSEC / (2 * AudioSynthWavetable::LFO_PERIOD)), // MODULATION_DELAY
		uint32_t(8.2 * AudioSynthWavetable::LFO_PERIOD * (UINT32_MAX / AUDIO_SAMPLE_RATE_EXACT)), // MODULATION_INCREMENT
		(WAVETABLE_CENTS_SHIFT(0) - 1.0) * 4, // MODULATION_PITCH_COEFFICIENT_INITIAL
		(1.0 - WAVETABLE_CENTS_SHIFT(0)) * 4, // MODULATION_PITCH_COEFFICIENT_SECOND
		int32_t(UINT16_MAX * (WAVETABLE_DECIBEL_SHIFT(0) - 1.0)) * 4, // MODULATION_AMPLITUDE_INITIAL_GAIN
		int32_t(UINT16_MAX * (1.0 - WAVETABLE_DECIBEL_SHIFT(0))) * 4, // MODULATION_AMPLITUDE_FINAL_GAIN
	},
};

static const uint8_t 0002_ranges[] = {127, };

const AudioSynthWavetable::instrument_data 0002 = {1, 0002_ranges, 0002_samples };
 
If anyone would like the sf2 for comparison I can add that to the drive as well. It's very odd. I have turned the gains down to account for any saturation/clipping but it persists. The sf2 plays cleanly across 3 diff computers and 2 HW samplers. Sounds like utter garbage on the teensy.

Here is a picture of the waveform a0001, it's sampled at exactly 256 samples, with the root note at 172.265625 Hz. I have tried 128, 256, 512, 1024, 2048 samples adjusting the root note accordingly to no avail. The sample is from a well known collection of single cycles sampled at D2 + 2 cents, eg 600 samples. This sample size produced odd aliasing and the same noise problem so I switched to the multiples of 128. The sf2 produced from each of these sample sizes worked correctly on PC, but not the Teensy. However, the Teensy plays SF2 from known packs cleanly. I have tried smoothing the samples and "cleaning" for looping, these parameters have no effect.

waveform.jpg
 
Last edited:
Status
Not open for further replies.
Back
Top