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

Thread: Malfunction with Teensy 3.6 in an audio project

  1. #1
    Member Sandro's Avatar
    Join Date
    Nov 2016
    Location
    Rimini - Italy
    Posts
    81

    Malfunction with Teensy 3.6 in an audio project

    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:

    Click image for larger version. 

Name:	IMG_20190826_211207.jpg 
Views:	10 
Size:	214.6 KB 
ID:	17334

    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

  2. #2
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    20,587
    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.

  3. #3
    Member Sandro's Avatar
    Join Date
    Nov 2016
    Location
    Rimini - Italy
    Posts
    81
    Quote Originally Posted by PaulStoffregen View Post
    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.

  4. #4
    Member Sandro's Avatar
    Join Date
    Nov 2016
    Location
    Rimini - Italy
    Posts
    81
    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...light=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.
    Click image for larger version. 

Name:	burst.PNG 
Views:	2 
Size:	14.2 KB 
ID:	17397

    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!

  5. #5
    Member Sandro's Avatar
    Join Date
    Nov 2016
    Location
    Rimini - Italy
    Posts
    81
    Hi all, I'm a bit desperate... cannot find any solution... should i post this issue into the Audio Projects section?
    Thanks

  6. #6
    Member Sandro's Avatar
    Join Date
    Nov 2016
    Location
    Rimini - Italy
    Posts
    81
    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=1K2...OZu_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

  7. #7
    Member Sandro's Avatar
    Join Date
    Nov 2016
    Location
    Rimini - Italy
    Posts
    81
    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 by Sandro; 09-05-2019 at 08:53 PM.

Posting Permissions

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