Malfunction with Teensy 3.6 in an audio project

Status
Not open for further replies.

Sandro

Well-known member
Hi all,
I made a first and perfectly working prototype of an audio application, based on Teensy 3.6 (bought on June 2018) + Audio Adaptor + W25Q128JV flash memory:

IMG_20190826_211207.jpg

Ready to make again the same project with a more elegant and compact arrangement, I made a beautifull PCB and bought 2 pieces of Teensy 3.6 boards. But unfortunately, with both these new boards, I have problems of audio noise (clicks and pops)... I tried to use the same code, the same Audio board.. no way..

In order to do a fully simmetric test, I should remove 20 wires from the 20 pin pads on the bottom of the old and working Teensy board to make: before doing this, I'd like to know if anyone haas encountered a similar problem, and if there any known difference in performance (hopefully not!!!) among Teensy 3.6 over the years .

Thank you
 
We haven't changed anything about Teensy 3.6. Same PCB and same parts have been used on every one, since it was released in September 2016.

The audio shield was recently changed. Rev C adds a 100 ohm resistor in series with MCLK. But I can see in the photo you have the Rev B audio shield.
 
We haven't changed anything about Teensy 3.6. Same PCB and same parts have been used on every one, since it was released in September 2016.

The audio shield was recently changed. Rev C adds a 100 ohm resistor in series with MCLK. But I can see in the photo you have the Rev B audio shield.

Thank you Paul, good to read that Teensy 3.6 has not been changed!! I'll go deeper in my troubleshooting.
 
Hi all,
I did many tests these days, again using my full code and also simplified versions, but the result is always the same: only the old board works perfectly for my application. I did some search on this forum and found some posts talking about audio problems with 216MHz overclock, but the old Teensy 3.6 seems to be immune from this problems!

I did last test using a simplified version of my first working code published here:
https://forum.pjrc.com/threads/53213-Audio-Expander-for-Teensy?highlight=expander

For common utility, this was Audio_expander_serialflash_raw.h:
Code:
#ifndef Audio_expander_serialflash_raw_h_
#define Audio_expander_serialflash_raw_h_

#include "Arduino.h"
#include <AudioStream.h>
#include <SerialFlash.h>

class Audio_expander_serialflash_raw : public AudioStream
{
public:
	Audio_expander_serialflash_raw(void) : AudioStream(0, NULL) { begin(); }
	void begin(void);
	bool play(const char *filename, float speed_value, float velocity_value);
	void set_note(float speed_value, float velocity_value);
	void stop(void);
	bool isPlaying(void) { return playing; }
	uint32_t positionMillis(void);
	uint32_t lengthMillis(void);
	virtual void update(void);
	int time_lapse(void);
    void set_ADSR(float attack_time, float decay_time, float sustain_value, float release_time);
    void release_note(void);
    bool is_playing(void);
    void set_pitch_bend (float pitch_bend_value);

private:
	SerialFlashFile rawfile;
    volatile bool playing;
    uint32_t file_size;
	volatile uint32_t file_offset; // point the BYTE
    float file_sample_offset; // point the SAMPLE
    float base_file_sample_offset;
    int32_t j_adsr;
    int32_t samples_available;
    int8_t start_release;
    int8_t send_joint;
	int32_t J1, J2, J3, J4, DJ3_4; 	// indexes of samples
	int16_t last_value;  // values of samples
	float speed; // 0.5=half speed 1=original speed 2=double speed
	float velocity;	// 0 <= velocity <= 1.0
	int64_t t, t_0; // *t is the computational time, must be within 2902 microseconds (period of update() when 128 samples are required)
	float C1, C2, C3, gain, gain_0, sustain;    // coefficients for ADSR
	const float Alpha = 1.0/44100.0;
	float pitch_bend = 1.0;
	const int8_t min_speed = 0.01;
	const int8_t max_speed = 7.0;
};

#endif

and this was Audio_expander_serialflash_raw.cpp:
Code:
#include <Arduino.h>
#include "Audio_expander_serialflash_raw.h"
#include "spi_interrupt.h"

void Audio_expander_serialflash_raw::begin(void)
{
    last_value = 0;
    playing = false;
    file_offset = 0;
    file_size = 0;
}

bool Audio_expander_serialflash_raw::play(const char *filename, float speed_value, float velocity_value)
{
    stop();
    AudioStartUsingSPI();
    rawfile = SerialFlash.open(filename);
    if (!rawfile)
    {
        AudioStopUsingSPI();
        return false;
    }
    // file_size = rawfile.size();
    speed = ((speed_value>=min_speed)? ((speed_value<=max_speed)? speed_value : max_speed) : min_speed); // set speed value within limits
    velocity = velocity_value;
    file_size = rawfile.size() - (rawfile.size()%256);
    send_joint = 1; //
    file_offset = 0; // punta il BYTE
    file_sample_offset = 0.0; // punta in SAMPLE
    samples_available = file_size/2;
    base_file_sample_offset = 0;
    rawfile.seek(file_offset);
    start_release = 0; // allows ADRS to start
    j_adsr=0;

    playing = true;
    return true;
}


void Audio_expander_serialflash_raw::stop(void)
{
    __disable_irq();
    if (playing)
    {
        playing = false;
        __enable_irq();
        rawfile.close();
        AudioStopUsingSPI();
    }
    else
    {
        __enable_irq();
    }
}


void Audio_expander_serialflash_raw::update(void)
{
    int i;
    int n;
    audio_block_t *block;
    int16_t samples_basket[AUDIO_BLOCK_SAMPLES*11]; // current vector of samples read from file
    int32_t LOW_sample, HIGH_sample;  // indexes of samples in RAW file
    int32_t L_sample, H_sample;  // indexes of samples in sample_basket
    int16_t samples_to_read;
    float index_delta;
    int16_t x_index_delta; 	// mantissa of virtual_file_offset
    float Cx;
    float speed_bend;
    float basket_offset;


    // only update if we're playing
    if (!playing)
        return;

    // allocate the audio blocks to transmit
    block = allocate();
    if (block == NULL)
        return;

    if (rawfile.available())
    {
        // this first ride generate a linear ramp which connects the last sample sent to 0, which is (MUST be) the value of the first sample of the .RAW file to be played
        t_0 = micros(); // start counting the computational time

        if (send_joint == 1)
        {
            Cx = last_value/129.0;
            for (i=0; i<AUDIO_BLOCK_SAMPLES; i++)
            {
                block->data[i] = last_value-(Cx*(i+1));
            }
            transmit(block);
            last_value = block->data[127];
            send_joint = 0;
        }

        // from this point samples are taken from the .RAW file
        else if (file_offset<file_size)
        {
            speed_bend = ((pitch_bend<1)? speed*pitch_bend : ((speed<(0.5*max_speed))? speed*pitch_bend : speed));
            LOW_sample = floor(base_file_sample_offset);
            HIGH_sample = ceil((speed_bend*(AUDIO_BLOCK_SAMPLES-1))+base_file_sample_offset);
            if (HIGH_sample>=samples_available)
            {
                stop();
            }

            samples_to_read = HIGH_sample-LOW_sample+1;
            file_offset=LOW_sample<<1;
            rawfile.seek(file_offset);
            n=rawfile.read(samples_basket, samples_to_read<<1);
            for (i=n/2; i < samples_to_read; i++)
            {
                samples_basket[i] = 0;
            }

            // calculating block->data[128] to be sent to the output Connection
            for (i = 0; i<AUDIO_BLOCK_SAMPLES; i++)
            {
                file_sample_offset=base_file_sample_offset+(i*speed_bend); // index of the needed sample, usually not-integer
                basket_offset=file_sample_offset-LOW_sample;
                L_sample = floor(basket_offset);// // index of the lower sample needed for calculation
                H_sample = ceil(basket_offset); // index of the upper sample needed for calculation
                index_delta = basket_offset-L_sample;
                x_index_delta = index_delta*1024.0;

                //ADSR envelope filter uses the specific index j_adsr to be independent from main_index
                if(start_release==0 && j_adsr<J1) // attack procedure
                {
                    gain = C1*j_adsr;
                }
                else if (start_release==0 && j_adsr<J2) // decay procedure
                {
                    gain = (C2*(j_adsr-J1))+ 1.0;
                }
                else if (start_release==1 && j_adsr<J4) // release procedure
                {
                    gain = (C3*(j_adsr-J3)) + gain_0;
                }
                else if (start_release==1 && j_adsr>=J4) // stop player!
                {
                    stop();
                }

                block->data[i] = gain*velocity*(samples_basket[L_sample] + ((x_index_delta*(samples_basket[H_sample]-samples_basket[L_sample]))>>10));
                j_adsr ++;
            }
            base_file_sample_offset = file_sample_offset+speed_bend;
            last_value = block->data[127];
            t = micros()-t_0; // calculating the computational time "t"
            transmit(block);
        }
        else
        {
            file_offset = 0;
            stop();
        }

    }
    else
    {
        rawfile.close();
        AudioStopUsingSPI();
        playing = false;
    }

    release(block);
}

#define B2M (uint32_t)((double)4294967296000.0 / AUDIO_SAMPLE_RATE_EXACT / 2.0) // 97352592

uint32_t Audio_expander_serialflash_raw::positionMillis(void)
{
    return ((uint64_t)file_offset * B2M)>>32;
}

uint32_t Audio_expander_serialflash_raw::lengthMillis(void)
{
    return ((uint64_t)file_size * B2M)>>32;
}

int Audio_expander_serialflash_raw::time_lapse(void) // reporting the computational time "t"
{
    return t;
}

void Audio_expander_serialflash_raw::set_ADSR(float attack_time, float decay_time, float sustain_value, float release_time) // ***** set ADSR parameters. Times are in seconds. 0 <= sustain_value <= 1.0
{
    attack_time = ((attack_time>0.05)? attack_time : 0);
    C1 = ((attack_time >0.05)? Alpha/attack_time : 0);
    decay_time = ((decay_time>0.05)? decay_time : 0.05);
    C2 = (sustain_value-1.0) * Alpha/decay_time;
    J1 = ((attack_time>0.05)? 1.0/C1: 0);
    J2 = (attack_time + decay_time)/Alpha;
    release_time = ((release_time>0.05)? release_time : 0.05);
    DJ3_4 = release_time/Alpha;
}

void Audio_expander_serialflash_raw::release_note(void)
{
    gain_0 = gain;
    J3 = (j_adsr/AUDIO_BLOCK_SAMPLES)*AUDIO_BLOCK_SAMPLES; // J3 = ride*AUDIO_BLOCK_SAMPLES;
    J4 = J3+DJ3_4;
    C3 = -gain_0/DJ3_4;
    start_release = 1;
}

bool Audio_expander_serialflash_raw::is_playing(void) // checking if the object is playing
{
    return playing;
}

void Audio_expander_serialflash_raw::set_pitch_bend (float pitch_bend_value) // 0.5= half speed, 1.0= no change 2.0=double speed
{
    pitch_bend = ((pitch_bend_value>=0.1)? ((pitch_bend_value<=2.0)? pitch_bend_value : 2.0) : 0.1) ; // set pitch value within limits
}

And this is a simple Arduino patch that works indipendently from any MIDI command:
Code:
/*
  TEST CODE
  Teensy MIDI Expander
  Board: Teensy 3.6 + Audio Adaptor Board + W25Q128FV flash memory chip
*/

#include <MIDI.h> // https://www.pjrc.com/teensy/td_libs_MIDI.html
#include <Audio.h>
#include <Wire.h>
#include <SPI.h>
#include <SerialFlash.h>
#include <Audio_expander_serialflash_raw.h>

#define voices 7

Audio_expander_serialflash_raw  voice[voices];
AudioMixer4              mixer0;
AudioMixer4              mixer1;
AudioMixer4              mixer_out;

AudioOutputI2S           audio_out;
AudioConnection          patchCord1(voice[0], 0, mixer0, 0);
AudioConnection          patchCord2(voice[1], 0, mixer0, 1);
AudioConnection          patchCord3(voice[2], 0, mixer0, 2);
AudioConnection          patchCord4(voice[3], 0, mixer0, 3);

AudioConnection          patchCord5(voice[4], 0, mixer1, 0);
AudioConnection          patchCord6(voice[5], 0, mixer1, 1);
AudioConnection          patchCord7(voice[6], 0, mixer1, 2);

AudioConnection          patchCord8(mixer0, 0, mixer_out, 0);
AudioConnection          patchCord9(mixer1, 0, mixer_out, 1);

AudioConnection          patchCord10(mixer_out, 0, audio_out, 1);
AudioConnection          patchCord11(mixer_out, 0, audio_out, 0);
AudioControlSGTL5000     board;

int note_number;
float velocity;
float note_number_to_pitch[128];

unsigned long voice_timer[voices];
int key_played_by[voices];
float gain_0 = 0.25;
int base_note = 60;

void setup() {
  AudioMemory(10);

  // Audio shield
  board.enable();
  board.volume(1.0);

  // Mixer

  mixer0.gain(0, gain_0);
  mixer0.gain(1, gain_0);
  mixer0.gain(2, gain_0);
  mixer0.gain(3, gain_0);
  mixer1.gain(0, gain_0);
  mixer1.gain(1, gain_0);
  mixer1.gain(2, gain_0);
  mixer1.gain(3, gain_0);
  mixer_out.gain(0, gain_0/2.0);
  mixer_out.gain(1, gain_0/2.0);

  // set up SPI Teensy to SPI Flash
  SPI.setMOSI(7);
  SPI.setMISO(12);
  SPI.setSCK(14);
  SerialFlash.begin(6);
  delay(100);

  // set ADSR
  for (int i = 0; i < voices; i++) {
    voice[i].set_ADSR(0.2, 1, 1, 0.2);
    voice_timer[i] = 0;
  }

  // note numbert to pitch conversion
  for (int i = 0; i < 128; i++) {
    note_number_to_pitch[i] = pow(2.0, (i - 60.0) / 12.0);
  }
}

void loop()
{
  while (1)
  {
    play_note(base_note, 1.0);
    delay(100);
    play_note(base_note + 4, 1.0);
    delay(100);
    play_note(base_note + 7, 1.0);
    delay(100);
    play_note(base_note + 11, 1.0);
    delay(100);
    play_note(base_note + 12, 1.0);
    delay(100);
    play_note(base_note + 16, 1.0);
    delay(100);
    play_note(base_note + 19, 1.0);
    delay(5000);
  }
}

// play note
void play_note(int note_number, float velocity) {
  unsigned long minimum_time = voice_timer[0];
  int i;
  int ii = -1;

  for (i = 0; i < voices; i++) { // first test: if the same key is played we use the same voice
    if (key_played_by[i] == note_number) {
      ii = i;
      break;
    }
  }

  if (ii == -1) // second test choice: look for a voice not busy
  {
    for (i = 0; i < voices; i++)
    {
      if (voice[i].is_playing() == false) {
        ii = i;
        break;
      }
    }
  }

  if (ii == -1) // last test: choose the voice playing for the longest time
  {
    ii = 0;
    for (i = 0; i < voices; i++)
    {
      if (voice_timer[i] < minimum_time ) { // final test choice: look for the voice playing for the longest time
        minimum_time = voice_timer[i];
        ii = i;
      }
    }
  }
  key_played_by[ii] = note_number;
  voice[ii].play("0.RAW", note_number_to_pitch[note_number], velocity);
  voice_timer[ii] = millis();
}

// stop note
void release_voice(int note_number) {
  int i;
  for (i = 0; i < 4; i++) {
    if (key_played_by[i] == note_number) {
      voice[i].release_note();
      break;
    }
  }
}

0.RAW in my case is a bell tolling, I belive it is not foundamental to share this.
This patch, if uploaded on different Tensy 3.6 board, works this way:

Old Tensy 3.6 (bought June 2018 and installed (soldered) in my prototype) + Audio shield + flash memory
clock 180MHz = sound deeply distorted: clock is not sufficient due to to the number of contemporary voices (well known behave, overcame with overclock!)
clock 192MHz = same
clock 216MHz = sound perfect (not verified with instruments, but no spikes, no high frequency hiss)
clock 240MHz = sound perfect (not verified with instruments, but no spikes, no high frequency hiss)

New Tensy 3.6 (bought August 2019, free air) + the same Audio shield + flash memory
clock 180MHz = sound deeply distorted: clock is not sufficient due to to the number of contemporary voices
clock 192MHz = same
clock 216MHz = sound distorted: deep and random pitch flattering (documented is some posts I've noticed)
clock 240MHz = unacceptable behave: sound good, but with high frequency hiss and (not frequent) deep burst like this.
burst.PNG

Hopefully Teensy 4 will overcome this problem... but still I guess: it's true that "the older the better"? Well, good for me that I'm not so young ;)!

Last info: I'm using Arduino IDE 1.8.8.

Thank you!
 
Hi all, I'm a bit desperate... cannot find any solution... should i post this issue into the Audio Projects section?
Thanks
 
Hi all,
if someone would be so kind to check on his Teensy 3.6 what happens... I wrote some more simple code. All files, included 0.RAW, can also be downloaded here:
https://drive.google.com/open?id=1K2q6i1N-lMv_r8aFOWOZu_qKxZZWYSa2

Library needs to be imported, and 0.RAW file has to be copied on flash memory.

This is Audio_expander_serialflash_raw.h:
Code:
#ifndef Audio_expander_serialflash_raw_h_
#define Audio_expander_serialflash_raw_h_

#include "Arduino.h"
#include <AudioStream.h>
#include <SerialFlash.h>

class Audio_expander_serialflash_raw : public AudioStream
{
public:
	Audio_expander_serialflash_raw(void) : AudioStream(0, NULL) { begin(); }
	void begin(void);
	bool play(const char *filename, float speed_value, float velocity_value);
	void set_note(float speed_value, float velocity_value);
	void stop(void);
	bool isPlaying(void) {return playing;}
	virtual void update(void);
	int time_lapse(void);
    void release_note(void);
    bool is_playing(void);

private:
	SerialFlashFile rawfile;
    volatile bool playing;
    uint32_t file_size;
	volatile uint32_t file_offset; // point the BYTE
    float file_sample_offset; // point the SAMPLE
    float base_file_sample_offset;
    int32_t samples_available;
	int16_t last_value;  // values of samples
	bool send_joint;
	float speed; // 0.5=half speed 1=original speed 2=double speed
	float velocity;	// 0 <= velocity <= 1.0
	int64_t t, t_0; // *t is the computational time, must be within 2902 microseconds (period of update() when 128 samples are required)
	// const float Alpha = 1.0/44100.0;
	const int8_t min_speed = 0.01;
	const int8_t max_speed = 7.0;
};

#endif

this is Audio_expander_serialflash_raw.cpp:
Code:
#include <Arduino.h>
#include "Audio_expander_serialflash_raw.h"
#include "spi_interrupt.h"
#include <Wire.h>

void Audio_expander_serialflash_raw::begin(void)
{
    last_value = 0;
    playing = false;
    file_offset = 0;
    file_size = 0;
}

bool Audio_expander_serialflash_raw::play(const char *filename, float speed_value, float velocity_value)
{
    stop();
    AudioStartUsingSPI();
    rawfile = SerialFlash.open(filename);
    if (!rawfile)
    {
        AudioStopUsingSPI();
        return false;
    }

    speed = ((speed_value>=min_speed)? ((speed_value<=max_speed)? speed_value : max_speed) : min_speed); // set speed value within limits
    velocity = velocity_value;
    file_size = rawfile.size() - (rawfile.size()%256);
    file_offset = 0; // BYTE pointer
    send_joint = 1; //
    file_sample_offset = 0.0; // SAMPLE pointer
    samples_available = file_size/2;
    base_file_sample_offset = 0;
    rawfile.seek(file_offset);
    playing = true;
    return true;
}


void Audio_expander_serialflash_raw::stop(void)
{
    __disable_irq();
    if (playing)
    {
        playing = false;
        __enable_irq();
        rawfile.close();
        AudioStopUsingSPI();
    }
    else
    {
        __enable_irq();
    }
}


void Audio_expander_serialflash_raw::update(void)
{
    int i;
    int n;
    audio_block_t *block;
    int16_t samples_basket[AUDIO_BLOCK_SAMPLES*11]; // current vector of samples read from file
    int32_t LOW_sample, HIGH_sample;  // indexes of samples in RAW file
    int32_t L_sample, H_sample;  // indexes of samples in sample_basket
    int16_t samples_to_read;
    float index_delta;
    int16_t x_index_delta; 	// mantissa of virtual_file_offset
    float Cx;
    float basket_offset;


    // only update if we're playing
    if (!playing)
        return;

    // allocate the audio blocks to transmit
    block = allocate();
    if (block == NULL)
        return;

    if (rawfile.available())
    {
        t_0 = micros(); // computational time

                if (send_joint == 1)
        {
            Cx = last_value/129.0;
            for (i=0; i<AUDIO_BLOCK_SAMPLES; i++)
            {
                block->data[i] = last_value-(Cx*(i+1));
            }
            transmit(block);
            last_value = block->data[127];
            send_joint = 0;
        }


        if (file_offset<file_size)
        {
            LOW_sample = floor(base_file_sample_offset);
            HIGH_sample = ceil((speed*(AUDIO_BLOCK_SAMPLES-1))+base_file_sample_offset);
            if (HIGH_sample>=samples_available)
                stop();
            samples_to_read = HIGH_sample-LOW_sample+1;
            file_offset=LOW_sample<<1;
            rawfile.seek(file_offset);
            n=rawfile.read(samples_basket, samples_to_read<<1);
            for (i=n/2; i < samples_to_read; i++)
                samples_basket[i] = 0;

            // calculating block->data[128] to be sent to the output Connection
            for (i = 0; i<AUDIO_BLOCK_SAMPLES; i++)
            {
                file_sample_offset=base_file_sample_offset+(i*speed); // index of the needed sample, usually not-integer
                basket_offset=file_sample_offset-LOW_sample;
                L_sample = floor(basket_offset);// // index of the lower sample needed for calculation
                H_sample = ceil(basket_offset); // index of the upper sample needed for calculation
                index_delta = basket_offset-L_sample;
                x_index_delta = index_delta*1024.0;
                block->data[i] = velocity*(samples_basket[L_sample] + ((x_index_delta*(samples_basket[H_sample]-samples_basket[L_sample]))>>10));
            }
            base_file_sample_offset = file_sample_offset + speed;
            last_value = block->data[127];
            t = micros()-t_0; // calculating the computational time "t"
            transmit(block);
        }
        else
        {
            file_offset = 0;
            stop();
        }

    }
    else
    {
        rawfile.close();
        AudioStopUsingSPI();
        playing = false;
    }
    release(block);
}

#define B2M (uint32_t)((double)4294967296000.0 / AUDIO_SAMPLE_RATE_EXACT / 2.0) // 97352592

int Audio_expander_serialflash_raw::time_lapse(void) // reporting the computational time "t"
{
    return t;
}

bool Audio_expander_serialflash_raw::is_playing(void) // checking if the object is playing
{
    return playing;
}

this is Arduino code:
Code:
#include <MIDI.h> // https://www.pjrc.com/teensy/td_libs_MIDI.html
#include <Audio.h>
#include <Wire.h>
#include <SPI.h>
#include <SerialFlash.h>
#include <Audio_expander_serialflash_raw.h>

#define voices 7

Audio_expander_serialflash_raw  voice[voices];
AudioMixer4              mixer0;
AudioMixer4              mixer1;
AudioMixer4              mixer_out;

AudioOutputI2S           audio_out;
AudioConnection          patchCord1(voice[0], 0, mixer0, 0);
AudioConnection          patchCord2(voice[1], 0, mixer0, 1);
AudioConnection          patchCord3(voice[2], 0, mixer0, 2);
AudioConnection          patchCord4(voice[3], 0, mixer0, 3);
AudioConnection          patchCord5(voice[4], 0, mixer1, 0);
AudioConnection          patchCord6(voice[5], 0, mixer1, 1);
AudioConnection          patchCord7(voice[6], 0, mixer1, 2);

AudioConnection          patchCord8(mixer0, 0, mixer_out, 0);
AudioConnection          patchCord9(mixer1, 0, mixer_out, 1);

AudioConnection          patchCord10(mixer_out, 0, audio_out, 1);
AudioConnection          patchCord11(mixer_out, 0, audio_out, 0);
AudioControlSGTL5000     board;

int base_note = 60;
float velocity = 1.0;
float note_number_to_pitch[128];
float gain_0 = 0.25;
int lapse = 500;

void setup() {
  AudioMemory(10);

  // Audio shield
  board.enable();
  board.volume(1.0);

  // Mixers
  mixer0.gain(0, gain_0);
  mixer0.gain(1, gain_0);
  mixer0.gain(2, gain_0);
  mixer0.gain(3, gain_0);
  mixer1.gain(0, gain_0);
  mixer1.gain(1, gain_0);
  mixer1.gain(2, gain_0);
  mixer1.gain(3, gain_0);
  mixer_out.gain(0, gain_0/2.0);
  mixer_out.gain(1, gain_0/2.0);

  // set up SPI Teensy to SPI Flash
  SPI.setMOSI(7);
  SPI.setMISO(12);
  SPI.setSCK(14);
  SerialFlash.begin(6);
  delay(100);

  // note numbert to pitch conversion
  for (int i = 0; i < 128; i++) {
    note_number_to_pitch[i] = pow(2.0, (i - 60.0) / 12.0);
  }
}

void loop()
{
  while (1)
  {
    voice[0].play("0.RAW", note_number_to_pitch[base_note], velocity);
    delay(lapse);
    voice[1].play("0.RAW", note_number_to_pitch[base_note+4], velocity);
    delay(lapse);
    voice[2].play("0.RAW", note_number_to_pitch[base_note+7], velocity);
    delay(lapse);
    voice[3].play("0.RAW", note_number_to_pitch[base_note+11], velocity);
    delay(lapse);
    voice[4].play("0.RAW", note_number_to_pitch[base_note+12], velocity);
    delay(lapse);
    voice[5].play("0.RAW", note_number_to_pitch[base_note+17], velocity);
    delay(lapse);
    voice[6].play("0.RAW", note_number_to_pitch[base_note+12], velocity);
    delay(3*lapse);
  }

Thanks in advance
 
I had not tried with simple applications yet; if I upload the example "WavFilePlayer" and play it on my Teensy 3.6 boards, this is the result:

Old Tensy 3.6 (bought June 2018 and installed (soldered) in my prototype) + Audio shield + SD
clock 180MHz/ 192MHz / 216MHz / 240MHz = sound perfect

New Tensy 3.6 (bought August 2019, free air) + Audio shield + same SD
clock 180MHz = sound perfect
clock 192MHz = sound perfect but week clicks
clock 216MHz = sound distorted: deep and random pitch flattering
clock 240MHz = sound good, with high frequency hiss and week clicks

Whishing sombody would do on his Teensy 3.6 this simple check..

Thank you
 
Last edited:
Status
Not open for further replies.
Back
Top