Forum Rule: Always post complete source code & details to reproduce any issue!
Results 1 to 2 of 2

Thread: Problems converting Aud.lib wavetable synth example from FLASh based samples to RAM

  1. #1
    Senior Member bmillier's Avatar
    Join Date
    Apr 2016
    Location
    Halifax, N.S. Canada
    Posts
    156

    Problems converting Aud.lib wavetable synth example from FLASh based samples to RAM

    Hi: I'm not having much luck converting the audio library wavetable synth example which stores the sample data entirely in FLASH (i.e. compiled with the program thru .cpp and .h include files for the sample data) into something that stores the sample data in SRAM (loaded in from an SD card). I have succeeded in partically converting it over so that the large waveform data files are now stored in SRAM, but am unable to convert the FLASH-based arrays that store the voice parameter data for each of the ranges on the keyboard.
    In the example, these voice parameter arrays were stored in FLASH as follows:

    Code:
    static const AudioSynthWavetable::sample_data AcousticBass_samples[3] = {
    	{
    		(int16_t*)sample_0_Flute_100kbyte_FluteD4, // sample
    		true, // LOOP
    		14, // LENGTH_BITS
    		(1 << (32 - 14)) * WAVETABLE_CENTS_SHIFT(0) * 37248.0 / WAVETABLE_NOTE_TO_FREQUENCY(63) / AUDIO_SAMPLE_RATE_EXACT + 0.5, // PER_HERTZ_PHASE_INCREMENT
    		((uint32_t)15713 - 1) << (32 - 14), // MAX_PHASE
    		((uint32_t)15712 - 1) << (32 - 14), // LOOP_PHASE_END
    		(((uint32_t)15712 - 1) << (32 - 14)) - (((uint32_t)9379 - 1) << (32 - 14)), // LOOP_PHASE_LENGTH
    		uint16_t(UINT16_MAX * WAVETABLE_DECIBEL_SHIFT(0)), // INI
       and so on for 3 complete tables of voice parameters , 1 per each keyboard range

    I can load in the waveform arrays from an SD card and place them sequentially into a big RAM array uint32_t SAMPLE_BUFFER[50000]. Then I can change the above to
    Code:
    AudioSynthWavetable::sample_data AcousticBass_samples[3] = {
    	{
    		 (int16_t*)  &SAMPLE_BUFFER[0],
    		 true, // LOOP
    		14, // LENGTH_BITS
    		(1 << (32 - 14)) * CENTS_SHIFT(-1) * 22050.0 / NOTE(64) / AUDIO_SAMPLE_RATE_EXACT + 0.5, // PER_HERTZ_PHASE_INCREMENT
    		((uint32_t)10502 - 1) << (32 - 14), // MAX_PHASE
    		((uint32_t)10446 - 1) << (32 - 14), // LOOP_PHASE_END
    		(((uint32_t)10446 - 1) << (32 - 14)) - (((uint32_t)10179 - 1) << (32 - 14)), // LOOP_PHASE_LENGTH
    		uint16_t(UINT16_MAX * DECIBEL_SHIFT(0)), // INITIAL_ATTENUATION_SCALAR
    		uint32_t(0.00 * SAMPLES_PER_MSEC / ENVELOPE_PERIOD + 0.5), // DELAY_COUNT
    		uint32_t(6.00 * SAMPLES_PER_MSEC / ENVELOPE_PERIOD + 0.5), // ATTACK_COUNT
    This works fine- I'm still using the FLASH-based voice parameter files, but now pointing the 1st parameter, the waveform data pointer into my SAMPLE_BUFFER SRAM array.

    Things fall apart when I try to move the FLASH-based voice parameters into SRAM. First I set up a structure for these parameters, matching what is defined in the synth_wavetable.h file:

    AudioSynthWavetable::sample_data* sd0[3];

    I then fill sd0[0] (and [1] etc) it up with exactly the same parameter values as were in the FLASH-based array (i.e from the #included AcousticBass.cpp file) as follows
    sd0[0]->LOOP = true; ss0[0]-> LENGTH_BITS = 14; etc.
    I load these from an SD card file, and I've checked that the values all match those in the FLASH array.
    The example program informed the wavetable routine of the pointers to the various arrays as follows:

    Code:
     AudioSynthWavetable::instrument_data AcousticBass = { 3, AcousticBass_ranges, AcousticBass_samples };
    which I change to
    Code:
     AudioSynthWavetable::instrument_data AcousticBass = { 2, AcousticBass_ranges, sd0[0]};
    I reduce the keyboard ranges from the original 3 down to 2, as I am only loading 2 of the 3 ranges on the SD card (too much extra code needed until I figure out what actually works) While testing, I only play notes in the first 2 ranges to allow for this.

    The program compiles OK this way. When I play notes on the keyboard, everything works fine with the FLASH-based version of the example, even after I modify the program to load the actual waveform data into SRAM, and change the pointers to that SAMPLE_BUFFER array.
    However when I change the program to use the second of the two lines shown just above (voice parameter arrays now in SRAM at sd0[0], sd0[1], the program will run, the serial monitor will indicate which note I am playing ( + CPU utilization), but no sounds are produced. Also, the CPU utilization will show 0, whereas it will show 1 or 2% when everything is working properly, with the FLASH-Based voice parameter data.
    I've tried everything I know- I'm not an expert in transferring variables in a structure, to a class. Most of the other code variations I've tried won't compile properly- complaining that I am not matching the parameter types needed for this line (although the following does compile properly- just doesn't produce sound)
    Code:
    AudioSynthWavetable::instrument_data AcousticBass = { 2, AcousticBass_ranges, sd0[0]};
    The complete listing is as follows (rather messy as I've tried many things along the way).

    Any ideas?? Thanks

    Code:
    /*   This works using the waveform sample data brought in by the SD card
    but  still using the Flash based program parameter files
    */
    
    
    #include <SPI.h>
    #include <SD.h>
    #include <Audio.h>
    #include <MIDI.h>
    
    
    // Use these with the Teensy Audio Shield
    #define SDCARD_CS_PIN    10
    #define SDCARD_MOSI_PIN  7
    #define SDCARD_SCK_PIN   14
    
    //#define DEBUG_ALLOC
    const int TOTAL_VOICES = 48;
    const int TOTAL_MIXERS = 17;
    const int SECONDARY_MIXERS = 1;
    
    
    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 },
    	{ 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 },
    };
    
    MIDI_CREATE_INSTANCE(HardwareSerial, Serial1, MIDI);
    
    File myFile;
    
    #define CENTS_SHIFT(C) (pow(2.0, (C)/1200.0))
    #define NOTE_TO_FREQUENCY(N) (440.0 * pow(2.0, ((N) - 69) / 12.0))
    #define NOTE(N) (440.0 * pow(2.0, ((N) - 69) / 12.0))
    #define DECIBEL_SHIFT(dB) (pow(10.0, (dB)/20.0))
    
    const int32_t UNITY_GAIN = INT32_MAX;
    const int32_t LFO_SMOOTHNESS = 3;
    const float LFO_PERIOD = (AUDIO_BLOCK_SAMPLES / (1 << (LFO_SMOOTHNESS - 1)));
    static  float SAMPLES_PER_MSEC = (AUDIO_SAMPLE_RATE_EXACT / 1000.0);
    static const int32_t ENVELOPE_PERIOD = 8;
    int used_voices = 0;
    int stopped_voices = 0;
    int evict_voice = 0;
    int notes_played = 0;
    
    
    int noteAlloc[TOTAL_VOICES];
    
    
    char buffer[100];
    String tmpString;
    String paramString;
    int totalSampleLength = 0;
    int numRanges;
    uint8_t ranges[10];
    int sIndex;
    int fIndex;
    int rangeIndex;
    String paramString2;
    
    
    AudioSynthWavetable::sample_data* sd0[3];
    
    // The 3rd range is loaded into the following array- I have not yet converted that code to place it into the sd0[3] array, since its too much trouble until I get the first ranges working
    uint32_t* pointer3;
    bool LOOP3;
    int INDEX_BITS3;
    float PER_HERTZ_PHASE_INCREMENT3;
    uint32_t MAX_PHASE3;
    uint32_t LOOP_PHASE_END3;
    uint32_t LOOP_PHASE_LENGTH3;
    uint16_t INITIAL_ATTENUATION_SCALAR3;
    // VOLUME ENVELOPE VALUES
    uint32_t DELAY_COUNT3;
    uint32_t ATTACK_COUNT3;
    uint32_t HOLD_COUNT3;
    uint32_t DECAY_COUNT3;
    uint32_t RELEASE_COUNT3;
    int32_t SUSTAIN_MULT3;
    // VIBRATO VALUES
    uint32_t VIBRATO_DELAY3;
    uint32_t VIBRATO_INCREMENT3;
    float VIBRATO_PITCH_COEFFICIENT_INITIAL3;
    float VIBRATO_PITCH_COEFFICIENT_SECOND3;
    // MODULATION VALUES
    uint32_t MODULATION_DELAY3;
    uint32_t MODULATION_INCREMENT3;
    float MODULATION_PITCH_COEFFICIENT_INITIAL3;
    float MODULATION_PITCH_COEFFICIENT_SECOND3;
    int32_t MODULATION_AMPLITUDE_INITIAL_GAIN3;
    int32_t MODULATION_AMPLITUDE_SECOND_GAIN3;
    
    
    
    uint32_t SAMPLE_BUFFER[50000];
    
    int cents_offset;
    float sample_rate;
    int sample_note;
    
    
    AudioSynthWavetable::sample_data AcousticBass_samples[3] = {
    	{
    		 (int16_t*)  &SAMPLE_BUFFER[0],
    		 true, // LOOP
    		14, // LENGTH_BITS
    		(1 << (32 - 14)) * CENTS_SHIFT(-1) * 22050.0 / NOTE(64) / AUDIO_SAMPLE_RATE_EXACT + 0.5, // PER_HERTZ_PHASE_INCREMENT
    		((uint32_t)10502 - 1) << (32 - 14), // MAX_PHASE
    		((uint32_t)10446 - 1) << (32 - 14), // LOOP_PHASE_END
    		(((uint32_t)10446 - 1) << (32 - 14)) - (((uint32_t)10179 - 1) << (32 - 14)), // LOOP_PHASE_LENGTH
    		uint16_t(UINT16_MAX * DECIBEL_SHIFT(0)), // INITIAL_ATTENUATION_SCALAR
    		uint32_t(0.00 * SAMPLES_PER_MSEC / ENVELOPE_PERIOD + 0.5), // DELAY_COUNT
    		uint32_t(6.00 * SAMPLES_PER_MSEC / ENVELOPE_PERIOD + 0.5), // ATTACK_COUNT
    		uint32_t(350.10 * SAMPLES_PER_MSEC / ENVELOPE_PERIOD + 0.5), // HOLD_COUNT
    		uint32_t(5136.67 * SAMPLES_PER_MSEC / ENVELOPE_PERIOD + 0.5), // DECAY_COUNT
    		uint32_t(1100.00 * SAMPLES_PER_MSEC / ENVELOPE_PERIOD + 0.5), // RELEASE_COUNT
    		int32_t((1.0 - DECIBEL_SHIFT(-96.0)) * UNITY_GAIN), // SUSTAIN_MULT
    		uint32_t(0.00 * SAMPLES_PER_MSEC / (2 * LFO_PERIOD)), // VIBRATO_DELAY
    		uint32_t(8.2 * LFO_PERIOD * (UINT32_MAX / AUDIO_SAMPLE_RATE_EXACT)), // VIBRATO_INCREMENT
    		(CENTS_SHIFT(0) - 1.0) * 4, // VIBRATO_PITCH_COEFFICIENT_INITIAL
    		(1.0 - CENTS_SHIFT(0)) * 4, // VIBRATO_COEFFICIENT_SECONDARY
    		uint32_t(0.00 * SAMPLES_PER_MSEC / (2 * LFO_PERIOD)), // MODULATION_DELAY
    		uint32_t(8.2 * LFO_PERIOD * (UINT32_MAX / AUDIO_SAMPLE_RATE_EXACT)), // MODULATION_INCREMENT
    		(CENTS_SHIFT(0) - 1.0) * 4, // MODULATION_PITCH_COEFFICIENT_INITIAL
    		(1.0 - CENTS_SHIFT(0)) * 4, // MODULATION_PITCH_COEFFICIENT_SECOND
    		int32_t(UINT16_MAX * (DECIBEL_SHIFT(0) - 1.0)) * 4, // MODULATION_AMPLITUDE_INITIAL_GAIN
    		int32_t(UINT16_MAX * (1.0 - DECIBEL_SHIFT(0))) * 4, // MODULATION_AMPLITUDE_FINAL_GAIN
    	},
    	{
    		//SAMPLE_BUFFER[5282],
    		(int16_t*)&SAMPLE_BUFFER[5282],
    		true, // LOOP
    		13, // LENGTH_BITS
    		(1 << (32 - 13)) * CENTS_SHIFT(25) * 28000.0 / NOTE(76) / AUDIO_SAMPLE_RATE_EXACT + 0.5, // PER_HERTZ_PHASE_INCREMENT
    		((uint32_t)5880 - 1) << (32 - 13), // MAX_PHASE
    		((uint32_t)5837 - 1) << (32 - 13), // LOOP_PHASE_END
    		(((uint32_t)5837 - 1) << (32 - 13)) - (((uint32_t)5751 - 1) << (32 - 13)), // LOOP_PHASE_LENGTH
    		uint16_t(UINT16_MAX * DECIBEL_SHIFT(-3.0)), // INITIAL_ATTENUATION_SCALAR
    		uint32_t(0.00 * SAMPLES_PER_MSEC / ENVELOPE_PERIOD + 0.5), // DELAY_COUNT
    		uint32_t(1.00 * SAMPLES_PER_MSEC / ENVELOPE_PERIOD + 0.5), // ATTACK_COUNT
    		uint32_t(300.06 * SAMPLES_PER_MSEC / ENVELOPE_PERIOD + 0.5), // HOLD_COUNT
    		uint32_t(5136.67 * SAMPLES_PER_MSEC / ENVELOPE_PERIOD + 0.5), // DECAY_COUNT
    		uint32_t(1100.00 * SAMPLES_PER_MSEC / ENVELOPE_PERIOD + 0.5), // RELEASE_COUNT
    		int32_t((1.0 - DECIBEL_SHIFT(-96.0)) * UNITY_GAIN), // SUSTAIN_MULT
    		uint32_t(0.00 * SAMPLES_PER_MSEC / (2 * LFO_PERIOD)), // VIBRATO_DELAY
    		uint32_t(8.2 * LFO_PERIOD * (UINT32_MAX / AUDIO_SAMPLE_RATE_EXACT)), // VIBRATO_INCREMENT
    		(CENTS_SHIFT(0) - 1.0) * 4, // VIBRATO_PITCH_COEFFICIENT_INITIAL
    		(1.0 - CENTS_SHIFT(0)) * 4, // VIBRATO_COEFFICIENT_SECONDARY
    		uint32_t(0.00 * SAMPLES_PER_MSEC / (2 * LFO_PERIOD)), // MODULATION_DELAY
    		uint32_t(8.2 * LFO_PERIOD * (UINT32_MAX / AUDIO_SAMPLE_RATE_EXACT)), // MODULATION_INCREMENT
    		(CENTS_SHIFT(0) - 1.0) * 4, // MODULATION_PITCH_COEFFICIENT_INITIAL
    		(1.0 - CENTS_SHIFT(0)) * 4, // MODULATION_PITCH_COEFFICIENT_SECOND
    		int32_t(UINT16_MAX * (DECIBEL_SHIFT(0) - 1.0)) * 4, // MODULATION_AMPLITUDE_INITIAL_GAIN
    		int32_t(UINT16_MAX * (1.0 - DECIBEL_SHIFT(0))) * 4, // MODULATION_AMPLITUDE_FINAL_GAIN
    	},
    	{
    		(int16_t*) &SAMPLE_BUFFER[8223], // sample
    		true, // LOOP
    		12, // LENGTH_BITS
    		(1 << (32 - 12)) * CENTS_SHIFT(18) * 28000.0 / NOTE(92) / AUDIO_SAMPLE_RATE_EXACT + 0.5, // PER_HERTZ_PHASE_INCREMENT
    		((uint32_t)2152 - 1) << (32 - 12), // MAX_PHASE
    		((uint32_t)2142 - 1) << (32 - 12), // LOOP_PHASE_END
    		(((uint32_t)2142 - 1) << (32 - 12)) - (((uint32_t)2108 - 1) << (32 - 12)), // LOOP_PHASE_LENGTH
    		uint16_t(UINT16_MAX * DECIBEL_SHIFT(0)), // INITIAL_ATTENUATION_SCALAR
    		uint32_t(0.00 * SAMPLES_PER_MSEC / ENVELOPE_PERIOD + 0.5), // DELAY_COUNT
    		uint32_t(1.00 * SAMPLES_PER_MSEC / ENVELOPE_PERIOD + 0.5), // ATTACK_COUNT
    		uint32_t(250.00 * SAMPLES_PER_MSEC / ENVELOPE_PERIOD + 0.5), // HOLD_COUNT
    		uint32_t(5136.67 * SAMPLES_PER_MSEC / ENVELOPE_PERIOD + 0.5), // DECAY_COUNT
    		uint32_t(1100.00 * SAMPLES_PER_MSEC / ENVELOPE_PERIOD + 0.5), // RELEASE_COUNT
    		int32_t((1.0 - DECIBEL_SHIFT(-96.0)) * UNITY_GAIN), // SUSTAIN_MULT
    		uint32_t(0.00 * SAMPLES_PER_MSEC / (2 * LFO_PERIOD)), // VIBRATO_DELAY
    		uint32_t(8.2 * LFO_PERIOD * (UINT32_MAX / AUDIO_SAMPLE_RATE_EXACT)), // VIBRATO_INCREMENT
    		(CENTS_SHIFT(0) - 1.0) * 4, // VIBRATO_PITCH_COEFFICIENT_INITIAL
    		(1.0 - CENTS_SHIFT(0)) * 4, // VIBRATO_COEFFICIENT_SECONDARY
    		uint32_t(0.00 * SAMPLES_PER_MSEC / (2 * LFO_PERIOD)), // MODULATION_DELAY
    		uint32_t(8.2 * LFO_PERIOD * (UINT32_MAX / AUDIO_SAMPLE_RATE_EXACT)), // MODULATION_INCREMENT
    		(CENTS_SHIFT(0) - 1.0) * 4, // MODULATION_PITCH_COEFFICIENT_INITIAL
    		(1.0 - CENTS_SHIFT(0)) * 4, // MODULATION_PITCH_COEFFICIENT_SECOND
    		int32_t(UINT16_MAX * (DECIBEL_SHIFT(0) - 1.0)) * 4, // MODULATION_AMPLITUDE_INITIAL_GAIN
    		int32_t(UINT16_MAX * (1.0 - DECIBEL_SHIFT(0))) * 4, // MODULATION_AMPLITUDE_FINAL_GAIN
    	},
    };
    
    
    //uint8_t AcousticBass_ranges[] = { 47, 60, 127, };
    uint8_t AcousticBass_ranges[10];  // loaded constants at start of setup()
    
    //The following line works
    // AudioSynthWavetable::instrument_data AcousticBass = { 3, AcousticBass_ranges, AcousticBass_samples };
    
    // This one doesn't produce any sound, but program doesn't crash
     AudioSynthWavetable::instrument_data AcousticBass = { 2, AcousticBass_ranges, sd0[0]};
    
    
    void setup() {
    	AcousticBass_ranges[0] = 70;
    	AcousticBass_ranges[1] = 90;	
    	AcousticBass_ranges[2] = 127;
    	Serial.begin(115200);
    	MIDI.begin(MIDI_CHANNEL_OMNI);
    	MIDI.setHandleNoteOn(handleNoteOn);
    	MIDI.setHandleNoteOff(handleNoteOff);
    	AudioMemory(120);
    	sgtl5000_1.enable();
    	sgtl5000_1.volume(0.8);
    	for (int i = 0; i < TOTAL_VOICES; i++) {
    		noteAlloc[i] = 0;
    	}
    	for (int i = 0; i < TOTAL_MIXERS - 3; i++) {
    		for (int j = 0; j < 4; j++) {
    			mixer[i].gain(j, 0.50);
    		}
    	}
    	for (int j = 0; j < 4; j++) {
    		mixer[TOTAL_MIXERS - 4].gain(j, 0.5);
    		mixer[TOTAL_MIXERS - 3].gain(j, 0.5);
    		mixer[TOTAL_MIXERS - 2].gain(j, 0.5);
    	}
    	mixer[TOTAL_MIXERS - 1].gain(0, 1);
    	mixer[TOTAL_MIXERS - 1].gain(1, 1);
    
    
    	for (int i = 0; i < TOTAL_VOICES; i++) {
    		wavetable[i].setInstrument(AcousticBass);  
    		wavetable[i].amplitude(1);
    	}
    	bool playing = false;
    
    
    	if (!(SD.begin(SDCARD_CS_PIN))) {
    		// stop here, but print a message repetitively
    		while (1) {
    			Serial.println("Unable to access the card");
    			delay(1000);
    		}
    	}
    
    	myFile = SD.open("sample1.cpp");
    	if (myFile) {
    		Serial.println("cpp file opened");
    		int i = 0;
    		while (myFile.available()) {
    			myFile.readBytesUntil(',', buffer, 50);
    			uint32_t value = strtoul(buffer, 0, 16);
    			SAMPLE_BUFFER[i] = value;
    			i++;
    			// Serial.print(SAMPLE_BUFFER[i-1]);
    			// Serial.write(" ");
    		}
    		// close the file:
    		myFile.close();
    		totalSampleLength = i - 1;
    		Serial.println();
    		Serial.print("num samples");
    		Serial.println(totalSampleLength);
    
    	}
    
    	myFile = SD.open("sample1.h");
    	if (myFile) {
    		rangeIndex = 0;
    		Serial.println("h file opened");
    		int i = 0;
    		int l;
    		l = myFile.readBytesUntil('\n', buffer, 50);
    		buffer[l] = 0;
    		String paramString1(buffer);
    		//	   Serial.println(paramString1);
    		int index = paramString1.indexOf("[", 0);
    		index++;
    		for (i = 0; i < 10; i++) {
    			buffer[i] = 0;
    		}
    		for (i = 0; i < 3; i++) {
    			char t = paramString1.charAt(index + i);
    			if (t == ']') {
    				buffer[i] = 0;
    			}
    			else {
    				buffer[i] = t;
    			}
    		}
    		String tmpString(buffer);
    		numRanges = tmpString.toInt();
    		Serial.println(numRanges);
    
    		// get key values for each range from following line
    
    		l = myFile.readBytesUntil('\n', buffer, 50);
    		String paramString2(buffer);
    		Serial.println(paramString2);
    		sIndex = paramString2.indexOf("=", 0);
    		sIndex++;
    		fIndex = paramString2.indexOf(",", 0);
    		String tmpString2 = paramString2.substring(sIndex, fIndex);
    		ranges[0] = tmpString2.toInt();
    		Serial.println(ranges[0]);
    
    		for (int i = 1; i < numRanges; i++) {
    			sIndex = fIndex + 1;
    			fIndex = paramString2.indexOf(",", sIndex);
    			String tmpString3 = paramString2.substring(sIndex, fIndex);
    			ranges[i] = tmpString3.toInt();
    			Serial.println(ranges[i]);
    		}
    		l = myFile.readBytesUntil('\n', buffer, 50);   // region name
    		Serial.println(buffer);
    
    		// for (rangeIndex = 0; rangeIndex < numRanges; rangeIndex++) {
    		// ***************************************************************
    
    		l = myFile.readBytesUntil('\n', buffer, 50);   // get loop true/false
    		String paramString3(buffer);
    		sIndex = paramString3.indexOf("true", 0);
    		if (sIndex >=0) {
    			sd0[0]->LOOP = true;
    			Serial.println("true");
    		}
    		else {
    			sd0[0]->LOOP = false;
    			Serial.println("false");
    		}
    		l = myFile.readBytesUntil('\n', buffer, 50);   // get INDEX_BITS
    		String paramString4(buffer);
    		sd0[0]->INDEX_BITS = paramString4.toInt();
    		Serial.println(sd0[0]->INDEX_BITS);
    		l = myFile.readBytesUntil('\n', buffer, 50);   // get cents_offset
    		String paramString5(buffer);
    		cents_offset = paramString5.toInt();
    		Serial.println(cents_offset);
    		l = myFile.readBytesUntil('\n', buffer, 50);   // get sample_rate
    		String paramString6(buffer);
    		sample_rate = paramString6.toFloat();
    		Serial.println(sample_rate);
    		l = myFile.readBytesUntil('\n', buffer, 50);   // get sample_note
    		String paramString7(buffer);
    		sample_note = paramString7.toFloat();
    		Serial.println(sample_note);
    		// calculate PER_HERTZ_PHASE_INCREMENT
    		sd0[0]->PER_HERTZ_PHASE_INCREMENT = (1 << (32 - sd0[0]->INDEX_BITS)) * CENTS_SHIFT(cents_offset) * sample_rate / NOTE(sample_note) / AUDIO_SAMPLE_RATE_EXACT + 0.5;
    		Serial.println(sd0[0]->PER_HERTZ_PHASE_INCREMENT);
    		l = myFile.readBytesUntil('\n', buffer, 50);   // get MAX_PHASE
    		String paramString8(buffer);
    		int temp1 = paramString8.toInt();
    		Serial.println(temp1);
    		sd0[0]->MAX_PHASE = ((uint32_t)temp1 - 1) << (32 - sd0[0]->INDEX_BITS);
    		Serial.println(sd0[0]->MAX_PHASE);
    		l = myFile.readBytesUntil('\n', buffer, 50);   // get LOOP_PHASE_END
    		String paramString9(buffer);
    		temp1 = paramString9.toInt();
    		Serial.println(temp1);
    		sd0[0]->LOOP_PHASE_END = ((uint32_t)temp1 - 1) << (32 - sd0[0]->INDEX_BITS);
    		Serial.println(sd0[0]->LOOP_PHASE_END);
    		l = myFile.readBytesUntil('\n', buffer, 50);   // get LOOP_PHASE_LENGTH
    		String paramString10(buffer);
    		temp1 = paramString10.toInt();
    		Serial.println(temp1);
    		sd0[0]->LOOP_PHASE_LENGTH = ((uint32_t)temp1 - 1) << (32 - sd0[0]->INDEX_BITS);
    		Serial.println(sd0[0]->LOOP_PHASE_LENGTH);
    		l = myFile.readBytesUntil('\n', buffer, 50);   // get INITIAL_ATTENUATION_SCALAR
    		String paramString11(buffer);
    		temp1 = paramString11.toInt();
    		sd0[0]->INITIAL_ATTENUATION_SCALAR = (uint16_t) UINT16_MAX * DECIBEL_SHIFT(temp1);
    		Serial.println(sd0[0]->INITIAL_ATTENUATION_SCALAR);
    		l = myFile.readBytesUntil('\n', buffer, 50);   // get DELAY_COUNT
    		String paramString12(buffer);
    		temp1 = paramString12.toFloat();
    		sd0[0]->DELAY_COUNT = uint32_t(temp1 * SAMPLES_PER_MSEC / ENVELOPE_PERIOD + 0.5);
    		Serial.println(sd0[0]->DELAY_COUNT);
    		l = myFile.readBytesUntil('\n', buffer, 50);   // get ATTACK_COUNT
    		String paramString13(buffer);
    		temp1 = paramString13.toFloat();
    		sd0[0]->ATTACK_COUNT = uint32_t(temp1 * SAMPLES_PER_MSEC / ENVELOPE_PERIOD + 0.5);
    		Serial.println(sd0[0]->ATTACK_COUNT);
    		l = myFile.readBytesUntil('\n', buffer, 50);   // get HOLD_COUNT
    		String paramString14(buffer);
    		temp1 = paramString14.toFloat();
    		sd0[0]->HOLD_COUNT = uint32_t(temp1 * SAMPLES_PER_MSEC / ENVELOPE_PERIOD + 0.5);
    		Serial.println(sd0[0]->HOLD_COUNT);
    		l = myFile.readBytesUntil('\n', buffer, 50);   // get DECAY_COUNT
    		String paramString15(buffer);
    		temp1 = paramString15.toFloat();
    		sd0[0]->DECAY_COUNT = uint32_t(temp1 * SAMPLES_PER_MSEC / ENVELOPE_PERIOD + 0.5);
    		Serial.println(sd0[0]->DECAY_COUNT);
    		l = myFile.readBytesUntil('\n', buffer, 50);   // get RELEASE_COUNT
    		String paramString16(buffer);
    		temp1 = paramString16.toFloat();
    		sd0[0]->RELEASE_COUNT = uint32_t(temp1 * SAMPLES_PER_MSEC / ENVELOPE_PERIOD + 0.5);
    		Serial.println(sd0[0]->RELEASE_COUNT);
    		l = myFile.readBytesUntil('\n', buffer, 50);   // get SUSTAIN_MULT
    		String paramString17(buffer);
    		temp1 = paramString17.toFloat();
    		sd0[0]->SUSTAIN_MULT = int32_t((1.0 - DECIBEL_SHIFT(temp1)) * UNITY_GAIN);
    		Serial.println(sd0[0]->SUSTAIN_MULT);
    		l = myFile.readBytesUntil('\n', buffer, 50);   // get VIBRATO_DELAY
    		String paramString18(buffer);
    		temp1 = paramString18.toFloat();
    		sd0[0]->VIBRATO_DELAY = uint32_t(temp1 * SAMPLES_PER_MSEC / (2 * LFO_PERIOD));
    		Serial.println(sd0[0]->VIBRATO_DELAY);
    		l = myFile.readBytesUntil('\n', buffer, 50);   // get VIBRATO_INCREMENT
    		String paramString19(buffer);
    		temp1 = paramString19.toFloat();
    		sd0[0]->VIBRATO_INCREMENT = uint32_t(temp1 * LFO_PERIOD * (UINT32_MAX / AUDIO_SAMPLE_RATE_EXACT));
    		Serial.println(sd0[0]->VIBRATO_INCREMENT);
    		l = myFile.readBytesUntil('\n', buffer, 50);   // get VIBRATO_PITCH_COEFICIENT_INITIAL
    		String paramString20(buffer);
    		temp1 = paramString20.toFloat();
    		sd0[0]->VIBRATO_PITCH_COEFFICIENT_INITIAL = (CENTS_SHIFT(temp1) - 1.0) * 4;
    		Serial.println(sd0[0]->VIBRATO_PITCH_COEFFICIENT_INITIAL);
    		l = myFile.readBytesUntil('\n', buffer, 50);   // get VIBRATO_PITCH_COEFICIENT_SECOND
    		String paramString21(buffer);
    		temp1 = paramString21.toFloat();
    		sd0[0]->VIBRATO_PITCH_COEFFICIENT_SECOND = (1.0 - CENTS_SHIFT(temp1)) * 4;
    		Serial.println(sd0[0]->VIBRATO_PITCH_COEFFICIENT_SECOND);
    		l = myFile.readBytesUntil('\n', buffer, 50);   // get MODULATION_DELAY
    		String paramString22(buffer);
    		temp1 = paramString22.toFloat();
    		sd0[0]->MODULATION_DELAY = uint32_t(temp1 * SAMPLES_PER_MSEC / (2 * LFO_PERIOD)),
    		Serial.println(sd0[0]->MODULATION_DELAY);
    		l = myFile.readBytesUntil('\n', buffer, 50);   // get MODULATION_INCREMENT
    		String paramString23(buffer);
    		temp1 = paramString23.toFloat();
    		sd0[0]->MODULATION_INCREMENT = uint32_t(temp1 * LFO_PERIOD * (UINT32_MAX / AUDIO_SAMPLE_RATE_EXACT));
    		Serial.println(sd0[0]->MODULATION_INCREMENT);
    		l = myFile.readBytesUntil('\n', buffer, 50);   // get MODULATION_PITCH_COEFFICIENT_INITIAL
    		String paramString24(buffer);
    		temp1 = paramString24.toInt();
    		sd0[0]->MODULATION_PITCH_COEFFICIENT_INITIAL = (CENTS_SHIFT(temp1) - 1.0) * 4;
    		Serial.println(sd0[0]->MODULATION_PITCH_COEFFICIENT_INITIAL);
    		l = myFile.readBytesUntil('\n', buffer, 50);   // get MODULATION_PITCH_COEFFICIENT_SECOND
    		String paramString25(buffer);
    		temp1 = paramString25.toInt();
    		sd0[0]->MODULATION_PITCH_COEFFICIENT_SECOND = (1.0 - CENTS_SHIFT(temp1)) * 4;
    		Serial.println(sd0[0]->MODULATION_PITCH_COEFFICIENT_SECOND);
    		l = myFile.readBytesUntil('\n', buffer, 50);   // get MODULATION_AMPLITUDE_INITIAL_GAIN
    		String paramString26(buffer);
    		temp1 = paramString26.toInt();
    		sd0[0]->MODULATION_AMPLITUDE_INITIAL_GAIN = (int32_t) (UINT16_MAX * (DECIBEL_SHIFT(temp1) - 1.0)) * 4;
    		Serial.println(sd0[0]->MODULATION_AMPLITUDE_INITIAL_GAIN);
    		l = myFile.readBytesUntil('\n', buffer, 50);   // get MODULATION_AMPLITUDE_SECOND_GAIN
    		String paramString27(buffer);
    		temp1 = paramString27.toInt();
    		sd0[0]->MODULATION_AMPLITUDE_SECOND_GAIN = (int32_t) (UINT16_MAX * (1.0 - DECIBEL_SHIFT(temp1))) * 4;
    		Serial.println(sd0[0]->MODULATION_AMPLITUDE_SECOND_GAIN);
    		l = myFile.readBytesUntil('\n', buffer, 50);   // get closing parenthesis
    		Serial.println(buffer);
    		l = myFile.readBytesUntil('\n', buffer, 50);   // get opening parenthesis (except in last record
    		Serial.println(buffer);
    		l = myFile.readBytesUntil('\n', buffer, 50);   // get region name (except in last record is sample size list
    		Serial.println(buffer);
    
    	
    			// second range
    
    
    		l = myFile.readBytesUntil('\n', buffer, 50);   // get loop true/false
    		String paramString28(buffer);
    		sIndex = paramString28.indexOf("true", 0);
    		if (sIndex >= 0) {
    			sd0[1]->LOOP = true;
    			Serial.println("true");
    		}
    		else {
    			sd0[1]->LOOP = false;
    			Serial.println("false");
    		}
    		l = myFile.readBytesUntil('\n', buffer, 50);   // get INDEX_BITS
    		String paramString29(buffer);
    		sd0[1]->INDEX_BITS = paramString29.toInt();
    		Serial.println(sd0[1]->INDEX_BITS);
    		l = myFile.readBytesUntil('\n', buffer, 50);   // get cents_offset
    		String paramString30(buffer);
    		cents_offset = paramString30.toInt();
    		Serial.println(cents_offset);
    		l = myFile.readBytesUntil('\n', buffer, 50);   // get sample_rate
    		String paramString31(buffer);
    		sample_rate = paramString31.toFloat();
    		Serial.println(sample_rate);
    		l = myFile.readBytesUntil('\n', buffer, 50);   // get sample_note
    		String paramString32(buffer);
    		sample_note = paramString32.toFloat();
    		Serial.println(sample_note);
    		// calculate PER_HERTZ_PHASE_INCREMENT
    		sd0[1]->PER_HERTZ_PHASE_INCREMENT = (1 << (32 - sd0[1]->INDEX_BITS)) * CENTS_SHIFT(cents_offset) * sample_rate / NOTE(sample_note) / AUDIO_SAMPLE_RATE_EXACT + 0.5;
    		Serial.println(sd0[1]->PER_HERTZ_PHASE_INCREMENT);
    		l = myFile.readBytesUntil('\n', buffer, 50);   // get MAX_PHASE
    		String paramString33(buffer);
    		temp1 = paramString33.toInt();
    		Serial.println(temp1);
    		sd0[1]->MAX_PHASE = ((uint32_t)temp1 - 1) << (32 - sd0[1]->INDEX_BITS);
    		Serial.println(sd0[1]->MAX_PHASE);
    		l = myFile.readBytesUntil('\n', buffer, 50);   // get LOOP_PHASE_END
    		String paramString34(buffer);
    		temp1 = paramString34.toInt();
    		Serial.println(temp1);
    		sd0[1]->LOOP_PHASE_END = ((uint32_t)temp1 - 1) << (32 - sd0[1]->INDEX_BITS);
    		Serial.println(sd0[1]->LOOP_PHASE_END);
    		l = myFile.readBytesUntil('\n', buffer, 50);   // get LOOP_PHASE_LENGTH
    		String paramString35(buffer);
    		temp1 = paramString35.toInt();
    		Serial.println(temp1);
    		sd0[1]->LOOP_PHASE_LENGTH = ((uint32_t)temp1 - 1) << (32 - sd0[1]->INDEX_BITS);
    		Serial.println(sd0[1]->LOOP_PHASE_LENGTH);
    		l = myFile.readBytesUntil('\n', buffer, 50);   // get INITIAL_ATTENUATION_SCALAR
    		String paramString36(buffer);
    		temp1 = paramString36.toInt();
    		sd0[1]->INITIAL_ATTENUATION_SCALAR = (uint16_t)UINT16_MAX * DECIBEL_SHIFT(temp1);
    		Serial.println(sd0[1]->INITIAL_ATTENUATION_SCALAR);
    		l = myFile.readBytesUntil('\n', buffer, 50);   // get DELAY_COUNT
    		String paramString37(buffer);
    		temp1 = paramString37.toFloat();
    		sd0[1]->DELAY_COUNT = uint32_t(temp1 * SAMPLES_PER_MSEC / ENVELOPE_PERIOD + 0.5);
    		Serial.println(sd0[1]->DELAY_COUNT);
    		l = myFile.readBytesUntil('\n', buffer, 50);   // get ATTACK_COUNT
    		String paramString38(buffer);
    		temp1 = paramString38.toFloat();
    		sd0[1]->ATTACK_COUNT = uint32_t(temp1 * SAMPLES_PER_MSEC / ENVELOPE_PERIOD + 0.5);
    		Serial.println(sd0[1]->ATTACK_COUNT);
    		l = myFile.readBytesUntil('\n', buffer, 50);   // get HOLD_COUNT
    		String paramString39(buffer);
    		temp1 = paramString39.toFloat();
    		sd0[1]->HOLD_COUNT = uint32_t(temp1 * SAMPLES_PER_MSEC / ENVELOPE_PERIOD + 0.5);
    		Serial.println(sd0[1]->HOLD_COUNT);
    		l = myFile.readBytesUntil('\n', buffer, 50);   // get DECAY_COUNT
    		String paramString40(buffer);
    		temp1 = paramString40.toFloat();
    		sd0[1]->DECAY_COUNT = uint32_t(temp1 * SAMPLES_PER_MSEC / ENVELOPE_PERIOD + 0.5);
    		Serial.println(sd0[1]->DECAY_COUNT);
    		l = myFile.readBytesUntil('\n', buffer, 50);   // get RELEASE_COUNT
    		String paramString41(buffer);
    		temp1 = paramString41.toFloat();
    		sd0[1]->RELEASE_COUNT = uint32_t(temp1 * SAMPLES_PER_MSEC / ENVELOPE_PERIOD + 0.5);
    		Serial.println(sd0[1]->RELEASE_COUNT);
    		l = myFile.readBytesUntil('\n', buffer, 50);   // get SUSTAIN_MULT
    		String paramString42(buffer);
    		temp1 = paramString42.toFloat();
    		sd0[1]->SUSTAIN_MULT = int32_t((1.0 - DECIBEL_SHIFT(temp1)) * UNITY_GAIN);
    		Serial.println(sd0[1]->SUSTAIN_MULT);
    		l = myFile.readBytesUntil('\n', buffer, 50);   // get VIBRATO_DELAY
    		String paramString43(buffer);
    		temp1 = paramString43.toFloat();
    		sd0[1]->VIBRATO_DELAY = uint32_t(temp1 * SAMPLES_PER_MSEC / (2 * LFO_PERIOD));
    		Serial.println(sd0[1]->VIBRATO_DELAY);
    		l = myFile.readBytesUntil('\n', buffer, 50);   // get VIBRATO_INCREMENT
    		String paramString44(buffer);
    		temp1 = paramString44.toFloat();
    		sd0[1]->VIBRATO_INCREMENT = uint32_t(temp1 * LFO_PERIOD * (UINT32_MAX / AUDIO_SAMPLE_RATE_EXACT));
    		Serial.println(sd0[1]->VIBRATO_INCREMENT);
    		l = myFile.readBytesUntil('\n', buffer, 50);   // get VIBRATO_PITCH_COEFICIENT_INITIAL
    		String paramString45(buffer);
    		temp1 = paramString45.toFloat();
    		sd0[1]->VIBRATO_PITCH_COEFFICIENT_INITIAL = (CENTS_SHIFT(temp1) - 1.0) * 4;
    		Serial.println(sd0[1]->VIBRATO_PITCH_COEFFICIENT_INITIAL);
    		l = myFile.readBytesUntil('\n', buffer, 50);   // get VIBRATO_PITCH_COEFICIENT_SECOND
    		String paramString46(buffer);
    		temp1 = paramString46.toFloat();
    		sd0[1]->VIBRATO_PITCH_COEFFICIENT_SECOND = (1.0 - CENTS_SHIFT(temp1)) * 4;
    		Serial.println(sd0[1]->VIBRATO_PITCH_COEFFICIENT_SECOND);
    		l = myFile.readBytesUntil('\n', buffer, 50);   // get MODULATION_DELAY
    		String paramString47(buffer);
    		temp1 = paramString47.toFloat();
    		sd0[1]->MODULATION_DELAY = uint32_t(temp1 * SAMPLES_PER_MSEC / (2 * LFO_PERIOD)),
    			Serial.println(sd0[1]->MODULATION_DELAY);
    		l = myFile.readBytesUntil('\n', buffer, 50);   // get MODULATION_INCREMENT
    		String paramString48(buffer);
    		temp1 = paramString48.toFloat();
    		sd0[1]->MODULATION_INCREMENT = uint32_t(temp1 * LFO_PERIOD * (UINT32_MAX / AUDIO_SAMPLE_RATE_EXACT));
    		Serial.println(sd0[1]->MODULATION_INCREMENT);
    		l = myFile.readBytesUntil('\n', buffer, 50);   // get MODULATION_PITCH_COEFFICIENT_INITIAL
    		String paramString49(buffer);
    		temp1 = paramString49.toInt();
    		sd0[1]->MODULATION_PITCH_COEFFICIENT_INITIAL = (CENTS_SHIFT(temp1) - 1.0) * 4;
    		Serial.println(sd0[1]->MODULATION_PITCH_COEFFICIENT_INITIAL);
    		l = myFile.readBytesUntil('\n', buffer, 50);   // get MODULATION_PITCH_COEFFICIENT_SECOND
    		String paramString50(buffer);
    		temp1 = paramString50.toInt();
    		sd0[1]->MODULATION_PITCH_COEFFICIENT_SECOND = (1.0 - CENTS_SHIFT(temp1)) * 4;
    		Serial.println(sd0[1]->MODULATION_PITCH_COEFFICIENT_SECOND);
    		l = myFile.readBytesUntil('\n', buffer, 50);   // get MODULATION_AMPLITUDE_INITIAL_GAIN
    		String paramString51(buffer);
    		temp1 = paramString51.toInt();
    		sd0[1]->MODULATION_AMPLITUDE_INITIAL_GAIN = (int32_t)(UINT16_MAX * (DECIBEL_SHIFT(temp1) - 1.0)) * 4;
    		Serial.println(sd0[1]->MODULATION_AMPLITUDE_INITIAL_GAIN);
    		l = myFile.readBytesUntil('\n', buffer, 50);   // get MODULATION_AMPLITUDE_SECOND_GAIN
    		String paramString52(buffer);
    		temp1 = paramString52.toInt();
    		sd0[1]->MODULATION_AMPLITUDE_SECOND_GAIN = (int32_t)(UINT16_MAX * (1.0 - DECIBEL_SHIFT(temp1))) * 4;
    		Serial.println(sd0[1]->MODULATION_AMPLITUDE_SECOND_GAIN);
    		l = myFile.readBytesUntil('\n', buffer, 50);   // get closing parenthesis
    		Serial.println(buffer);
    		l = myFile.readBytesUntil('\n', buffer, 50);   // get opening parenthesis (except in last record
    		Serial.println(buffer);
    		l = myFile.readBytesUntil('\n', buffer, 50);   // get region name (except in last record is sample size list
    		Serial.println(buffer);
    		
    		// Third range
    
    		l = myFile.readBytesUntil('\n', buffer, 50);   // get loop true/false
    		String paramString53(buffer);
    		sIndex = paramString53.indexOf("true", 0);
    		if (sIndex >= 0) {
    			LOOP3 = true;
    			Serial.println("true");
    		}
    		else {
    			LOOP3 = false;
    			Serial.println("false");
    		}
    		l = myFile.readBytesUntil('\n', buffer, 50);   // get INDEX_BITS
    		String paramString54(buffer);
    		INDEX_BITS3 = paramString54.toInt();
    		Serial.println(INDEX_BITS3);
    		l = myFile.readBytesUntil('\n', buffer, 50);   // get cents_offset
    		String paramString55(buffer);
    		cents_offset = paramString55.toInt();
    		Serial.println(cents_offset);
    		l = myFile.readBytesUntil('\n', buffer, 50);   // get sample_rate
    		String paramString56(buffer);
    		sample_rate = paramString56.toFloat();
    		Serial.println(sample_rate);
    		l = myFile.readBytesUntil('\n', buffer, 50);   // get sample_note
    		String paramString57(buffer);
    		sample_note = paramString57.toFloat();
    		Serial.println(sample_note);
    		// calculate PER_HERTZ_PHASE_INCREMENT
    		PER_HERTZ_PHASE_INCREMENT3 = (1 << (32 - INDEX_BITS3)) * (pow(2.0, (cents_offset) / 1200.0)) * sample_rate / (440.0 * pow(2.0, ((sample_note)-69) / 12.0)) / AUDIO_SAMPLE_RATE_EXACT + 0.5;
    		Serial.println(PER_HERTZ_PHASE_INCREMENT3);
    		l = myFile.readBytesUntil('\n', buffer, 50);   // get MAX_PHASE
    		String paramString58(buffer);
    		temp1 = paramString58.toInt();
    		Serial.println(temp1);
    		MAX_PHASE3 = ((uint32_t)temp1 - 1) << (32 - INDEX_BITS3);
    		Serial.println(MAX_PHASE3);
    		l = myFile.readBytesUntil('\n', buffer, 50);   // get LOOP_PHASE_END
    		String paramString59(buffer);
    		temp1 = paramString59.toInt();
    		Serial.println(temp1);
    		LOOP_PHASE_END3 = ((uint32_t)temp1 - 1) << (32 - INDEX_BITS3);
    		Serial.println(LOOP_PHASE_END3);
    		l = myFile.readBytesUntil('\n', buffer, 50);   // get LOOP_PHASE_LENGTH
    		String paramString60(buffer);
    		temp1 = paramString60.toInt();
    		Serial.println(temp1);
    		LOOP_PHASE_LENGTH3 = ((uint32_t)temp1 - 1) << (32 - INDEX_BITS3);
    		Serial.println(LOOP_PHASE_LENGTH3);
    		l = myFile.readBytesUntil('\n', buffer, 50);   // get INITIAL_ATTENUATION_SCALAR
    		String paramString61(buffer);
    		temp1 = paramString61.toInt();
    		INITIAL_ATTENUATION_SCALAR3 = uint16_t(UINT16_MAX * pow(10.0, (temp1) / 20.0));
    		Serial.println(INITIAL_ATTENUATION_SCALAR3);
    		l = myFile.readBytesUntil('\n', buffer, 50);   // get DELAY_COUNT
    		String paramString62(buffer);
    		temp1 = paramString62.toFloat();
    		DELAY_COUNT3 = uint32_t(temp1 * SAMPLES_PER_MSEC / ENVELOPE_PERIOD + 0.5);
    		Serial.println(DELAY_COUNT3);
    		l = myFile.readBytesUntil('\n', buffer, 50);   // get ATTACK_COUNT
    		String paramString63(buffer);
    		temp1 = paramString63.toFloat();
    		ATTACK_COUNT3 = uint32_t(temp1 * SAMPLES_PER_MSEC / ENVELOPE_PERIOD + 0.5);
    		Serial.println(ATTACK_COUNT3);
    		l = myFile.readBytesUntil('\n', buffer, 50);   // get HOLD_COUNT
    		String paramString64(buffer);
    		temp1 = paramString64.toFloat();
    		HOLD_COUNT3 = uint32_t(temp1 * SAMPLES_PER_MSEC / ENVELOPE_PERIOD + 0.5);
    		Serial.println(HOLD_COUNT3);
    		l = myFile.readBytesUntil('\n', buffer, 50);   // get DECAY_COUNT
    		String paramString65(buffer);
    		temp1 = paramString65.toFloat();
    		DECAY_COUNT3 = uint32_t(temp1 * SAMPLES_PER_MSEC / ENVELOPE_PERIOD + 0.5);
    		Serial.println(DECAY_COUNT3);
    		l = myFile.readBytesUntil('\n', buffer, 50);   // get RELEASE_COUNT
    		String paramString66(buffer);
    		temp1 = paramString66.toFloat();
    		RELEASE_COUNT3 = uint32_t(temp1 * SAMPLES_PER_MSEC / ENVELOPE_PERIOD + 0.5);
    		Serial.println(RELEASE_COUNT3);
    		l = myFile.readBytesUntil('\n', buffer, 50);   // get SUSTAIN_MULT
    		String paramString67(buffer);
    		temp1 = paramString67.toFloat();
    		SUSTAIN_MULT3 = int32_t((1.0 - (pow(10.0, (temp1) / 20.0))) * UNITY_GAIN);
    		Serial.println(SUSTAIN_MULT3);
    		l = myFile.readBytesUntil('\n', buffer, 50);   // get VIBRATO_DELAY
    		String paramString68(buffer);
    		temp1 = paramString68.toFloat();
    		VIBRATO_DELAY3 = uint32_t(temp1 * SAMPLES_PER_MSEC / (2 * LFO_PERIOD));
    		Serial.println(VIBRATO_DELAY3);
    		l = myFile.readBytesUntil('\n', buffer, 50);   // get VIBRATO_INCREMENT
    		String paramString69(buffer);
    		temp1 = paramString69.toFloat();
    		VIBRATO_INCREMENT3 = uint32_t(temp1 * LFO_PERIOD * (UINT32_MAX / AUDIO_SAMPLE_RATE_EXACT));
    		Serial.println(VIBRATO_INCREMENT3);
    		l = myFile.readBytesUntil('\n', buffer, 50);   // get VIBRATO_PITCH_COEFICIENT_INITIAL
    		String paramString70(buffer);
    		temp1 = paramString70.toFloat();
    		VIBRATO_PITCH_COEFFICIENT_INITIAL3 = (CENTS_SHIFT(temp1) - 1.0) * 4;
    		Serial.println(VIBRATO_PITCH_COEFFICIENT_INITIAL3);
    		l = myFile.readBytesUntil('\n', buffer, 50);   // get VIBRATO_PITCH_COEFICIENT_SECOND
    		String paramString71(buffer);
    		temp1 = paramString71.toFloat();
    		VIBRATO_PITCH_COEFFICIENT_SECOND3 = (1.0 - CENTS_SHIFT(temp1)) * 4;
    		Serial.println(VIBRATO_PITCH_COEFFICIENT_SECOND3);
    		l = myFile.readBytesUntil('\n', buffer, 50);   // get MODULATION_DELAY
    		String paramString72(buffer);
    		temp1 = paramString72.toFloat();
    		MODULATION_DELAY3 = uint32_t(temp1 * SAMPLES_PER_MSEC / (2 * LFO_PERIOD)),
    			Serial.println(MODULATION_DELAY3);
    		l = myFile.readBytesUntil('\n', buffer, 50);   // get MODULATION_INCREMENT
    		String paramString73(buffer);
    		temp1 = paramString73.toFloat();
    		MODULATION_INCREMENT3 = uint32_t(temp1 * LFO_PERIOD * (UINT32_MAX / AUDIO_SAMPLE_RATE_EXACT));
    		Serial.println(MODULATION_INCREMENT3);
    		l = myFile.readBytesUntil('\n', buffer, 50);   // get MODULATION_PITCH_COEFFICIENT_INITIAL
    		String paramString74(buffer);
    		temp1 = paramString74.toInt();
    		MODULATION_PITCH_COEFFICIENT_INITIAL3 = ((pow(2.0, (temp1) / 1200.0)) - 1.0) * 4;
    		Serial.println(MODULATION_PITCH_COEFFICIENT_INITIAL3);
    		l = myFile.readBytesUntil('\n', buffer, 50);   // get MODULATION_PITCH_COEFFICIENT_SECOND
    		String paramString75(buffer);
    		temp1 = paramString75.toInt();
    		MODULATION_PITCH_COEFFICIENT_SECOND3 = (1.0 - (pow(2.0, (temp1) / 1200.0))) * 4;
    		Serial.println(MODULATION_PITCH_COEFFICIENT_SECOND3);
    		l = myFile.readBytesUntil('\n', buffer, 50);   // get MODULATION_AMPLITUDE_INITIAL_GAIN
    		String paramString76(buffer);
    		temp1 = paramString76.toInt();
    		MODULATION_AMPLITUDE_INITIAL_GAIN3 = int32_t(UINT16_MAX * ((pow(10.0, (temp1) / 20.0)) - 1.0)) * 4;
    		Serial.println(MODULATION_AMPLITUDE_INITIAL_GAIN3);
    		l = myFile.readBytesUntil('\n', buffer, 50);   // get MODULATION_AMPLITUDE_SECOND_GAIN
    		String paramString77(buffer);
    		temp1 = paramString77.toInt();
    		MODULATION_AMPLITUDE_SECOND_GAIN3 = int32_t(UINT16_MAX * (1.0 - (pow(10.0, (temp1) / 20.0)))) * 4;
    		Serial.println(MODULATION_AMPLITUDE_SECOND_GAIN3);
    		l = myFile.readBytesUntil('\n', buffer, 50);   // get closing parenthesis
    		Serial.println(buffer);
    		l = myFile.readBytesUntil('\n', buffer, 50);   // get opening parenthesis (except in last record
    		Serial.println(buffer);
    		l = myFile.readBytesUntil('\n', buffer, 50);   // get region name (except in last record is sample size list
    		Serial.println(buffer);
    
    
    		String paramString78(buffer);    // get length of first region of waveform samples- used as pointer to next region
    		sIndex = paramString78.indexOf("[", 0);
    		sIndex++;
    		fIndex = paramString78.indexOf("]", 0);
    		String tmpString3 = paramString78.substring(sIndex, fIndex);
    		uint16_t temp2 = tmpString3.toInt();
    
    		l = myFile.readBytesUntil('\n', buffer, 50);  // ignore blank line
    		l = myFile.readBytesUntil('\n', buffer, 50);   // get length of second region of waveform samples- used as pointer to next region
    		String paramString79(buffer);
    		sIndex = paramString79.indexOf("[", 0);
    		sIndex++;
    		fIndex = paramString79.indexOf("]", 0);
    		String tmpString4 = paramString79.substring(sIndex, fIndex);
    		uint16_t temp3 = tmpString4.toInt();
    		Serial.print("pointer3=");
    		sd0[0]->sample = (int16_t*) &SAMPLE_BUFFER[0]; // also tried without & 
    		sd0[1]->sample = (int16_t*)&SAMPLE_BUFFER[5282];
    		myFile.close();
    	}
    }
     
    
    void loop() {
    	MIDI.read();
    	freeVoices();
    // Serial.println("in loop");
     
    }
    
    int allocateVoice(byte channel, byte note) {
    	for (int i = 1; i < TOTAL_VOICES; i++) {
    		if (noteAlloc[i] == 0) {
    			noteAlloc[i] = note;
    			return i;
    			break;
    		}
    	}
    	return -1;
    }
    void freeVoices() {
    	for (int i = 0; i < TOTAL_VOICES; i++)
    		if (wavetable[i].isPlaying() == false && noteAlloc[i] == -1) {
    			noteAlloc[i] = 0;
    		}
    }
    
    int findVoice(byte channel, byte note) {
    	for (int i = 1; i < TOTAL_VOICES; i++) {
    		if (noteAlloc[i] == note) {
    			noteAlloc[i] = -1;
    			return i;
    			break;
    		}
    		}
    	return -1;
    	}
    
    void handleNoteOn(byte channel, byte note, byte velocity) {
    	notes_played++;
    #ifdef DEBUG_ALLOC
    	Serial.printf("\n**** NoteOn: channel==%hhu,note==%hhu ****", channel, note);
    	//printVoices();
    #endif //DEBUG_ALLOC
    	Serial.print("note= ");
    	Serial.println(note);
    	int wavetable_id = allocateVoice(channel, note);
    	Serial.println(wavetable_id);
    	wavetable[wavetable_id].playNote(note, velocity);
    	int usage = AudioProcessorUsage();
    	Serial.print("CPU= ");
    	Serial.println(usage);
    #ifdef DEBUG_ALLOC
    	//printVoices();
    #endif //DEBUG_ALLOC
    }
    
    void handleNoteOff(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 != -1)
    		wavetable[wavetable_id].stop();
    #ifdef DEBUG_ALLOC
    	//printVoices();
    #endif //DEBUG_ALLOC
    }

  2. #2
    Senior Member bmillier's Avatar
    Join Date
    Apr 2016
    Location
    Halifax, N.S. Canada
    Posts
    156
    I forgot to mention that I am using the Teensy 4.0

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •