Forum Rule: Always post complete source code & details to reproduce any issue!
Page 5 of 6 FirstFirst ... 3 4 5 6 LastLast
Results 101 to 125 of 140

Thread: Limits of delay effect in audio library

  1. #101
    Junior Member
    Join Date
    Dec 2017
    Location
    Oregon, USA
    Posts
    7
    Wanted to let folks know that I was able to successfully get 6ea CY15B104Qs on Franks memory board and can now delay/loop >35 seconds of audio! There were hurdles:
    * To solder the (wide) chips to the board I bent the leads under and soldered carefully. A scary proposition with these expensive parts. But done in the right order and checking work under a microscope, it can (does) work.
    * I updated the lib for another type to allow for this config. That's archived here:https://github.com/SensoriumEmbedded/Audio

    I was thinking about adding Franks CS architecture and SRAMs (with wide footprints) to this project: https://oshpark.com/shared_projects/yTlhWecX
    I'll certainly post here if I do. Thank you all for your wonderful efforts! -Travis

  2. #102
    AH I just came across this. Perfect for my idea.
    When flying, the ATC can be very busy and loud over the headset. This will allow me to record 9seconds live, and be able to click a button for playback if I missed any communication.

  3. #103
    I am curious if the Teensy 4.1 PSRAM can be used with the Audio Board and Frank Boesings Memory Board4 for more delay.

  4. #104
    Senior Member
    Join Date
    Apr 2014
    Location
    -
    Posts
    9,735
    I think it can - needs some lines added to the code.
    I can have a look in the next days.

  5. #105
    If you get the chance to I would appreciate it.
    Thanks
    Last edited by merlins_ghost; 05-23-2020 at 03:30 PM.

  6. #106
    Senior Member ETMoody3's Avatar
    Join Date
    Mar 2014
    Location
    New Ulm, Mn
    Posts
    181
    Quote Originally Posted by Frank B View Post
    I think it can - needs some lines added to the code.
    I can have a look in the next days.
    Bump!

    I'd like to see this happen as well.

  7. #107
    I'm also curious about adding ram for longer delay with the audio library and a teensy 4.1. Can I use both the extra ram on the 4.1 and the audio board at the same time? thanks!

  8. #108
    I made a memory board and am not able to get it to work. I am using it in conjunction with the multichannel tdm board. The code loads without any problems. When I replace my extended delays with typical delay, then the delay works, but when I use the extended delay, there is no delayed signal in the output. Also btw, I am using 6 23LC1024 chips on the board and as far as I can tell all my solders look clean and the board is oriented correctly. The board is mounted on top of my teensy 3.6. Any help solving this issue would be much appreciated.

    Code:
    #include <Audio.h>
    #include <Wire.h>
    #include <SPI.h>
    #include <SD.h>
    #include <SerialFlash.h>
    
    //#include <WireKinetis.h>
    //#include <i2c_t3.h>  //this is for teensy when using i2C ports other than the otiginal default ports
    
    
    unsigned char frequencyH = 0;
    unsigned char frequencyL = 0;
    unsigned int frequencyB;
    double frequency,  StationFreq, Station;
    unsigned char byt1, byt2, byt3, byt4, byt5,StationFlag;
    unsigned short StationSect1, StationSect2;
    float ProgStation[10];
    int StationTotal;
    
    
    
    
    // GUItool: begin automatically generated code
    AudioInputTDM            tdm1;           //xy=180.20000076293945,443.60001373291016
    AudioEffectDelay         delay1;         //xy=367.00000381469727,451.00000762939453
    AudioEffectDelayExternal delayExt2(AUDIO_MEMORY_23LC1024);;      //xy=371.00000762939453,597.9999847412109
    
    AudioMixer4              mixer1;         //xy=663.200023651123,437.6001091003418
    AudioAmplifier           amp1;           //xy=775.200023651123,359.6000123023987
    AudioOutputTDM           tdm2;           //xy=946.2000122070312,417.6000061035156
    AudioConnection          patchCord1(tdm1, 0, mixer1, 0);
    AudioConnection          patchCord2(tdm1, 4, delay1, 0);
    AudioConnection          patchCord3(tdm1, 8, delayExt2, 0);
    AudioConnection          patchCord4(delay1, 0, mixer1, 1);
    AudioConnection          patchCord5(delayExt2, 0, mixer1, 2);
    AudioConnection          patchCord6(mixer1, amp1);
    AudioConnection          patchCord7(amp1, 0, tdm2, 0);
    AudioConnection          patchCord8(amp1, 0, tdm2, 2);
    AudioControlCS42448      cs42448_1;      //xy=187,681.9999828338623
    // GUItool: end automatically generated code
    
    
    
    
    
    void setup() {
    Wire1.setSDA(38);
    Wire1.setSCL(37);
    Wire1.begin(0x60);
    Serial.begin(9600);
    
    cs42448_1.enable();
    cs42448_1.volume(50);
    AudioMemory(800);
    delay1.delay(0, 500);
    delayExt2.delay(0, 1000);
    amp1.gain(3.0);
    
    setFrequency(99.9, 0);
    }
    
    void loop() {
      // put your main code here, to run repeatedly:
    
      setFrequency(99.9, 0);
      delay(500);
      setFrequency(85.5, 1);
      delay(2000);
      setFrequency(92.9, 0);
      delay(500);
      setFrequency(85.5, 1);
      delay(2000);
      setFrequency(99.1, 0);
      delay(500);
      setFrequency(85.5, 1);
      delay(2000);
    }
    
    void setFrequency(float frequency, int Mute){
      //int sensorValue = digitalRead(2);
      frequencyB = 4 * (frequency * 1000000 + 225000) / 32768;  //  # Frequency distribution for two bytes (according to the data sheet)
      frequencyH = frequencyB >> 8;   //  #int (freq14bit / 256)  shifts to the right 8 places, aka adds 8 0's to the front,  essentially gets rid of second byte 
      if (Mute == 1){
        frequencyH = frequencyH | 0x80;
       Serial.print("Mute on: ");
       Serial.println(Mute);
      };  // adds ability to turn on and off mute
      frequencyL = frequencyB & 0XFF;  //essentially the & 0XFF is just taking off the first byte maybe should not be needed?
      Wire1.beginTransmission(0x60);
      Wire1.write(frequencyH);   //  (MUTE bit; Frequency H)  // MUTE is 0x80 and search true is 0x40
      Wire1.write(frequencyL); // (frequency L)
      Wire1.write(0xB0);  //  # 3.bajt (SUD; SSL1, SSL2; HLSI, MS, MR, ML; SWP1)
      Wire1.write(0x10);  //  (SWP2; STBY, BL; XTAL; smut; HCC, SNC, SI)
      Wire1.write((byte)0x00);  // # (PLREFF; DTC; 0; 0; 0; 0; 0; 0)
      Wire1.endTransmission();
    }
    here are a few pictures of the hardware
    Attached Thumbnails Attached Thumbnails Click image for larger version. 

Name:	20210309_220641.jpg 
Views:	51 
Size:	146.1 KB 
ID:	24005   Click image for larger version. 

Name:	20210309_220554.jpg 
Views:	47 
Size:	138.4 KB 
ID:	24006  

    Click image for larger version. 

Name:	20210309_220603.jpg 
Views:	47 
Size:	128.0 KB 
ID:	24007  

  9. #109
    I figured out the issue. My issue was a hardware issue, after soldering up a new memoryboard4 I was able to make it work.

  10. #110
    Junior Member robz's Avatar
    Join Date
    Jul 2020
    Location
    Virginia, USA
    Posts
    5
    I was playing around with the 23LC1024, and found the PSRAM 8MB chip to be drop in compatible, with just a few tweaks to AudioEffectDelayExternal, mainly just changing the amount of ram to 8388608 (allowing 95108ms, 95 seconds) of delay. That's like having 10.6 memoryboard4's at your disposal, or or 16x 4-mbit fram chips. All for the cost of one inexpensive chip and a soic to dip adapter.

    I'm thinking of adding a second chip as well for delays of 190 seconds.

    I'll post the code tweaks this evening. I am using a Teensy 4.1 and also modified the SPI pins to get AudioEffectDelayExternal working for me.

    So excited about this simple change, especially with fram so expensive.

  11. #111
    Junior Member robz's Avatar
    Join Date
    Jul 2020
    Location
    Virginia, USA
    Posts
    5
    Here are the tweaks I ended up making to effect_delay_ext.h and effect_delay_ext.cpp. I added an audio memory type AUDIO_MEMORY_PSRAM_8MB and the the supporting code for that:

    $ diff ./arduino/arduino-1.8.15/effect_delay_ext.h ./arduino/arduino-1.8.15/hardware/teensy/avr/libraries/Audio/effect_delay_ext.h
    37c37,38
    < AUDIO_MEMORY_UNDEFINED = 3
    ---
    > AUDIO_MEMORY_PSRAM_8MB = 3, // 8192k x 8 PS-RAM
    > AUDIO_MEMORY_UNDEFINED = 4

    and

    $ diff ./arduino/arduino-1.8.15/effect_delay_ext.cpp ./arduino/arduino-1.8.15/hardware/teensy/avr/libraries/Audio/effect_delay_ext.cpp
    43,47c43,52
    < #define SPIRAM_MOSI_PIN 7
    < #define SPIRAM_MISO_PIN 12
    < #define SPIRAM_SCK_PIN 14
    <
    < #define SPIRAM_CS_PIN 6
    ---
    > //#define SPIRAM_MOSI_PIN 7
    > //#define SPIRAM_MISO_PIN 12
    > //#define SPIRAM_SCK_PIN 14
    >
    > //#define SPIRAM_CS_PIN 6
    >
    > #define SPIRAM_MOSI_PIN 11 //-----------------
    > #define SPIRAM_MISO_PIN 12 // for Teensy 4.1
    > #define SPIRAM_SCK_PIN 13 //
    > #define SPIRAM_CS_PIN 36 //-----------------
    130c135,136
    <
    ---
    > SPI.setCS(SPIRAM_CS_PIN); // added for Teensy 4.1
    >
    157a164,172
    > } else if (type == AUDIO_MEMORY_PSRAM_8MB) {
    > #ifdef INTERNAL_TEST
    > memsize = 8000;
    > #else
    > memsize = (2^23); // 8388608 bytes
    > #endif
    > pinMode(SPIRAM_CS_PIN, OUTPUT);
    > digitalWriteFast(SPIRAM_CS_PIN, HIGH);
    >
    187c202,204
    < memory_type == AUDIO_MEMORY_CY15B104) {
    ---
    > memory_type == AUDIO_MEMORY_CY15B104 ||
    > memory_type == AUDIO_MEMORY_PSRAM_8MB)
    > {
    232c249,250
    < if (memory_type == AUDIO_MEMORY_23LC1024) {
    ---
    > if (memory_type == AUDIO_MEMORY_23LC1024 ||
    > memory_type == AUDIO_MEMORY_PSRAM_8MB ) {

  12. #112
    Junior Member robz's Avatar
    Join Date
    Jul 2020
    Location
    Virginia, USA
    Posts
    5
    Example:

    Code:
    #include <Audio.h>
    #include <Wire.h>
    #include <SPI.h>
    #include <SD.h>
    #include <SerialFlash.h>
    
    // GUItool: begin automatically generated code
    AudioInputI2S2           i2s2_1;         //xy=123.75,368.75
    AudioAmplifier           preamp;         //xy=279.75,482.7500057220459
    AudioEffectDelayExternal delay1(AUDIO_MEMORY_PSRAM_8MB,95108);         //xy=505.75,458.75
    //AudioEffectDelay         delay1;         //xy=505.75,458.75
    AudioMixer4              mixer1;         //xy=860.75,411.75
    AudioAmplifier           amp1;           //xy=1021.75,417.75
    AudioOutputSPDIF3        spdif3_1;       //xy=1225.75,536.75
    AudioConnection          patchCord1(i2s2_1, 0, preamp, 0);
    AudioConnection          patchCord2(preamp, delay1);
    AudioConnection          patchCord3(delay1, 0, mixer1, 0);
    AudioConnection          patchCord4(delay1, 1, mixer1, 1);
    AudioConnection          patchCord5(delay1, 2, mixer1, 2);
    AudioConnection          patchCord6(delay1, 3, mixer1, 3);
    AudioConnection          patchCord7(mixer1, amp1);
    AudioConnection          patchCord8(amp1, 0, spdif3_1, 0);
    AudioConnection          patchCord9(amp1, 0, spdif3_1, 1);
    // GUItool: end automatically generated code
    
    void setup() {
      AudioMemory(100);
      preamp.gain(1.8F);
      mixer1.gain(0,0.5F);
      mixer1.gain(1,0.5F);
      delay1.delay( 0, 95000 );
      delay1.delay( 1, 100 );
      delay1.delay( 2, 0 );
      amp1.gain(2.2F);
    }
    void loop() {
      // put your main code here, to run repeatedly:
      delay(1000);
    }
    I'm thinking of adding optional SPI parameters to the object so that multiple instances could be created using different SPI ports or CS pins that refer to different 8MB chips.

    Also, I'm fairly confident that Frank's Memoryboard could hold 6 x 8MB (48MB or 9.5 minutes of delay), but I don't need that that much delay loop yet, so holding off on that thought for now.

    Here's the board with SOIC adapter. I also turned up the SPI speed to 90000000 without ill effect, so external delay object initializes much faster.

    You can see the SPDIF3 output via LED (the yellow and green wires going off the top of board) and the MEMS microphones I'm using on AudioInputI2s2

    Click image for larger version. 

Name:	psram AudioEffectDelayExternal.jpg 
Views:	75 
Size:	105.5 KB 
ID:	25567

  13. #113
    Senior Member
    Join Date
    Oct 2016
    Posts
    211
    Quote Originally Posted by robz View Post
    I was playing around with the 23LC1024, and found the PSRAM 8MB chip to be drop in compatible, with just a few tweaks to AudioEffectDelayExternal, mainly just changing the amount of ram to 8388608 (allowing 95108ms, 95 seconds) of delay. That's like having 10.6 memoryboard4's at your disposal, or or 16x 4-mbit fram chips. All for the cost of one inexpensive chip and a soic to dip adapter.
    what's the part nr. of this kind of PSRAM? I'm very interested.. the F-RAM is very expensive..

  14. #114
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    27,694
    The main PSRAM part number is APS6404L-3SQR.

    Several other parts are the exact same chip with different marking. Details on the PSRAM page.

    https://www.pjrc.com/store/psram.html

  15. #115
    Member
    Join Date
    Jan 2020
    Location
    Finland
    Posts
    40
    Quote Originally Posted by robz View Post
    Example:

    Code:
    #include <Audio.h>
    #include <Wire.h>
    #include <SPI.h>
    #include <SD.h>
    #include <SerialFlash.h>
    
    // GUItool: begin automatically generated code
    AudioInputI2S2           i2s2_1;         //xy=123.75,368.75
    AudioAmplifier           preamp;         //xy=279.75,482.7500057220459
    AudioEffectDelayExternal delay1(AUDIO_MEMORY_PSRAM_8MB,95108);         //xy=505.75,458.75
    //AudioEffectDelay         delay1;         //xy=505.75,458.75
    AudioMixer4              mixer1;         //xy=860.75,411.75
    AudioAmplifier           amp1;           //xy=1021.75,417.75
    AudioOutputSPDIF3        spdif3_1;       //xy=1225.75,536.75
    AudioConnection          patchCord1(i2s2_1, 0, preamp, 0);
    AudioConnection          patchCord2(preamp, delay1);
    AudioConnection          patchCord3(delay1, 0, mixer1, 0);
    AudioConnection          patchCord4(delay1, 1, mixer1, 1);
    AudioConnection          patchCord5(delay1, 2, mixer1, 2);
    AudioConnection          patchCord6(delay1, 3, mixer1, 3);
    AudioConnection          patchCord7(mixer1, amp1);
    AudioConnection          patchCord8(amp1, 0, spdif3_1, 0);
    AudioConnection          patchCord9(amp1, 0, spdif3_1, 1);
    // GUItool: end automatically generated code
    
    void setup() {
      AudioMemory(100);
      preamp.gain(1.8F);
      mixer1.gain(0,0.5F);
      mixer1.gain(1,0.5F);
      delay1.delay( 0, 95000 );
      delay1.delay( 1, 100 );
      delay1.delay( 2, 0 );
      amp1.gain(2.2F);
    }
    void loop() {
      // put your main code here, to run repeatedly:
      delay(1000);
    }
    I'm thinking of adding optional SPI parameters to the object so that multiple instances could be created using different SPI ports or CS pins that refer to different 8MB chips.

    Also, I'm fairly confident that Frank's Memoryboard could hold 6 x 8MB (48MB or 9.5 minutes of delay), but I don't need that that much delay loop yet, so holding off on that thought for now.

    Here's the board with SOIC adapter. I also turned up the SPI speed to 90000000 without ill effect, so external delay object initializes much faster.

    You can see the SPDIF3 output via LED (the yellow and green wires going off the top of board) and the MEMS microphones I'm using on AudioInputI2s2

    Click image for larger version. 

Name:	psram AudioEffectDelayExternal.jpg 
Views:	75 
Size:	105.5 KB 
ID:	25567
    Hi Robz!

    Did you ever end up trying the Frank's memory board with 6x PSRAM chips? I'm interested in trying this out myself but would like to double check before ordering anything.

    Another more broad question, not particularly to you Robz. Of course if you can help, it's very welcome.
    What is the maximum number of PSRAM chips that can be connected to the Teensy 4.0 or 4.1 without the additional chips of the memory board?

    Best,
    Miro

  16. #116
    Senior Member h4yn0nnym0u5e's Avatar
    Join Date
    Apr 2021
    Location
    Cambridgeshire, UK
    Posts
    632
    Quote Originally Posted by robz View Post
    I was playing around with the 23LC1024, and found the PSRAM 8MB chip to be drop in compatible, with just a few tweaks to AudioEffectDelayExternal, mainly just changing the amount of ram to 8388608 (allowing 95108ms, 95 seconds) of delay.
    Can I point out that you need to change the memory amount to 4194304, as the AudioEffectDelayExternal code works in samples, not bytes.

  17. #117
    Senior Member
    Join Date
    May 2018
    Posts
    162
    Hi robz,

    thanks for testing this and creating a patch. I tried to integrate this into an additional library, but have some problems getting the whole thing to run. Unfortunately the whole thing seems to crash. The test program for the RAM works though. So I hope you have an idea what is going wrong?

    Before posting my code, these are small changes I made:
    - I renamed the class to AudioEffectDelayExternal8 and the enum type to AudioEffectDelayMemoryType8_t to be able to use the library next to the original library.
    - I extended the array static uint32_t allocated[4]; to four (and initialized it with zeroes), because of the four different memory types used.
    - Last, I reduced the memsize for initialization to 2^22 (see post above): memsize = (2^22); // 2^23 = 8388608 bytes, but 2^22 = 4194304 samples!

    Here is my library code and my test program:
    effect_delay_ext8.h:
    Code:
    #ifndef effect_delay_ext8_h_
    #define effect_delay_ext8_h_
    #include "Arduino.h"
    #include "AudioStream.h"
    #include "spi_interrupt.h"
    
    enum AudioEffectDelayMemoryType8_t {
            AUDIO_MEMORY8_23LC1024 = 0,     // 128k x 8 S-RAM
            AUDIO_MEMORY8_MEMORYBOARD = 1,
            AUDIO_MEMORY8_CY15B104 = 2,     // 512k x 8 F-RAM
            AUDIO_MEMORY8_PSRAM_8MB = 3,    // 8192k x 8 PS-RAM 
            AUDIO_MEMORY8_UNDEFINED = 4
    };
    
    class AudioEffectDelayExternal8 : public AudioStream
    {
    public:
            AudioEffectDelayExternal8() : AudioStream(1, inputQueueArray) {
                    initialize(AUDIO_MEMORY8_23LC1024, 65536);
            }
            AudioEffectDelayExternal8(AudioEffectDelayMemoryType8_t type, float milliseconds=1e6)
              : AudioStream(1, inputQueueArray) {
                    uint32_t n = (milliseconds*(AUDIO_SAMPLE_RATE_EXACT/1000.0f))+0.5f;
                    initialize(type, n);
            }
    
            void delay(uint8_t channel, float milliseconds) {
                    if (channel >= 8 || memory_type >= AUDIO_MEMORY8_UNDEFINED) return;
                    if (milliseconds < 0.0f) milliseconds = 0.0f;
                    uint32_t n = (milliseconds*(AUDIO_SAMPLE_RATE_EXACT/1000.0f))+0.5f;
                    n += AUDIO_BLOCK_SAMPLES;
                    if (n > memory_length - AUDIO_BLOCK_SAMPLES)
                            n = memory_length - AUDIO_BLOCK_SAMPLES;
                    delay_length[channel] = n;
                    uint8_t mask = activemask;
                    if (activemask == 0) AudioStartUsingSPI();
                    activemask = mask | (1<<channel);
            }
            void disable(uint8_t channel) {
                    if (channel >= 8) return;
                    uint8_t mask = activemask & ~(1<<channel);
                    activemask = mask;
                    if (mask == 0) AudioStopUsingSPI();
            }
            virtual void update(void);
    private:
            void initialize(AudioEffectDelayMemoryType8_t type, uint32_t samples);
            void read(uint32_t address, uint32_t count, int16_t *data);
            void write(uint32_t address, uint32_t count, const int16_t *data);
            void zero(uint32_t address, uint32_t count) {
                    write(address, count, NULL);
            }
            uint32_t memory_begin;    // the first address in the memory we're using
            uint32_t memory_length;   // the amount of memory we're using
            uint32_t head_offset;     // head index (incoming) data into external memory
            uint32_t delay_length[8]; // # of sample delay for each channel (128 = no delay)
            uint8_t  activemask;      // which output channels are active
            uint8_t  memory_type;     // 0=23LC1024, 1=Frank's Memoryboard, 3=CY15B104 ,4=APS6404L-3SQR
            static uint32_t allocated[4];
            audio_block_t *inputQueueArray[1];
    };
    
    #endif
    effect_delay_ext8.cpp
    Code:
    #include <Arduino.h>
    #include "effect_delay_ext8.h"
    
    //#define INTERNAL_TEST
    
    // While 20 MHz (Teensy actually uses 16 MHz in most cases) and even 24 MHz
    // have worked well in testing at room temperature with 3.3V power, to fully
    // meet all the worst case timing specs, the SPI clock low time would need
    // to be 40ns (12.5 MHz clock) for the single chip case and 51ns (9.8 MHz
    // clock) for the 6-chip memoryboard with 74LCX126 buffers.
    //
    // Timing analysis and info is here:
    // https://forum.pjrc.com/threads/29276-Limits-of-delay-effect-in-audio-library?p=97506&viewfull=1#post97506
    #define SPISETTING SPISettings(20000000, MSBFIRST, SPI_MODE0)
    
    // Use these with the audio adaptor board  (should be adjustable by the user...)
    //#define SPIRAM_MOSI_PIN 7
    //#define SPIRAM_MISO_PIN 12
    //#define SPIRAM_SCK_PIN 14
    
    //#define SPIRAM_CS_PIN 6
    
    #define SPIRAM_MOSI_PIN 11 //-----------------
    #define SPIRAM_MISO_PIN 12 // for Teensy 4.1
    #define SPIRAM_SCK_PIN 13 //
    #define SPIRAM_CS_PIN 36 //-----------------
                             //
    #define MEMBOARD_CS0_PIN 2
    #define MEMBOARD_CS1_PIN 3
    #define MEMBOARD_CS2_PIN 4
    
    uint32_t AudioEffectDelayExternal8::allocated[4] = {0, 0, 0, 0};
    
    void AudioEffectDelayExternal8::update(void)
    {
            audio_block_t *block;
            uint32_t n, channel, read_offset;
    
            // grab incoming data and put it into the memory
            block = receiveReadOnly();
            if (memory_type >= AUDIO_MEMORY8_UNDEFINED) {
                    // ignore input and do nothing if undefined memory type
                    release(block);
                    return;
            }
            if (block) {
                    if (head_offset + AUDIO_BLOCK_SAMPLES <= memory_length) {
                            // a single write is enough
                            write(head_offset, AUDIO_BLOCK_SAMPLES, block->data);
                            head_offset += AUDIO_BLOCK_SAMPLES;
                    } else {
                            // write wraps across end-of-memory
                            n = memory_length - head_offset;
                            write(head_offset, n, block->data);
                            head_offset = AUDIO_BLOCK_SAMPLES - n;
                            write(0, head_offset, block->data + n);
                    }
                    release(block);
            } else {
                    // if no input, store zeros, so later playback will
                    // not be random garbage previously stored in memory
                    if (head_offset + AUDIO_BLOCK_SAMPLES <= memory_length) {
                            zero(head_offset, AUDIO_BLOCK_SAMPLES);
                            head_offset += AUDIO_BLOCK_SAMPLES;
                    } else {
                            n = memory_length - head_offset;
                            zero(head_offset, n);
                            head_offset = AUDIO_BLOCK_SAMPLES - n;
                            zero(0, head_offset);
                    }
            }
    
            // transmit the delayed outputs
            for (channel = 0; channel < 8; channel++) {
                    if (!(activemask & (1<<channel))) continue;
                    block = allocate();
                    if (!block) continue;
                    // compute the delayed location where we read
                    if (delay_length[channel] <= head_offset) {
                            read_offset = head_offset - delay_length[channel];
                    } else {
                            read_offset = memory_length + head_offset - delay_length[channel];
                    }
                    if (read_offset + AUDIO_BLOCK_SAMPLES <= memory_length) {
                            // a single read will do it
                            read(read_offset, AUDIO_BLOCK_SAMPLES, block->data);
                    } else {
                            // read wraps across end-of-memory
                            n = memory_length - read_offset;
                            read(read_offset, n, block->data);
                            read(0, AUDIO_BLOCK_SAMPLES - n, block->data + n);
                    }
                    transmit(block, channel);
                    release(block);
            }
    }
    
    void AudioEffectDelayExternal8::initialize(AudioEffectDelayMemoryType8_t type, uint32_t samples)
    {
            uint32_t memsize, avail;
    
            activemask = 0;
            head_offset = 0;
            memory_type = type;
    
            SPI.setMOSI(SPIRAM_MOSI_PIN);
            SPI.setMISO(SPIRAM_MISO_PIN);
            SPI.setSCK(SPIRAM_SCK_PIN);
            SPI.setCS(SPIRAM_CS_PIN); // added for Teensy 4.1
    
            SPI.begin();
    
            if (type == AUDIO_MEMORY8_23LC1024) {
    #ifdef INTERNAL_TEST
                    memsize = 8000;
    #else
                    memsize = 65536;
    #endif
                    pinMode(SPIRAM_CS_PIN, OUTPUT);
                    digitalWriteFast(SPIRAM_CS_PIN, HIGH);
            } else if (type == AUDIO_MEMORY8_MEMORYBOARD) {
                    memsize = 393216;
                    pinMode(MEMBOARD_CS0_PIN, OUTPUT);
                    pinMode(MEMBOARD_CS1_PIN, OUTPUT);
                    pinMode(MEMBOARD_CS2_PIN, OUTPUT);
                    digitalWriteFast(MEMBOARD_CS0_PIN, LOW);
                    digitalWriteFast(MEMBOARD_CS1_PIN, LOW);
                    digitalWriteFast(MEMBOARD_CS2_PIN, LOW);
            } else if (type == AUDIO_MEMORY8_CY15B104) {
    #ifdef INTERNAL_TEST
                    memsize = 8000;
    #else
                    memsize = 262144;
    #endif
                    pinMode(SPIRAM_CS_PIN, OUTPUT);
                    digitalWriteFast(SPIRAM_CS_PIN, HIGH);
            } else if (type == AUDIO_MEMORY8_PSRAM_8MB) {
                    #ifdef INTERNAL_TEST
                    memsize = 8000;
                    #else
                    memsize = (2^22); // 2^23 = 8388608 bytes
                    #endif
                    pinMode(SPIRAM_CS_PIN, OUTPUT);
                    digitalWriteFast(SPIRAM_CS_PIN, HIGH);
            } else {
                    return;
            }
            avail = memsize - allocated[type];
            if (avail < AUDIO_BLOCK_SAMPLES*2+1) {
                    memory_type = AUDIO_MEMORY8_UNDEFINED;
                    return;
            }
            if (samples > avail) samples = avail;
            memory_begin = allocated[type];
            allocated[type] += samples;
            memory_length = samples;
    
            zero(0, memory_length);
    }
    
    
    #ifdef INTERNAL_TEST
    static int16_t testmem[8000]; // testing only
    #endif
    
    void AudioEffectDelayExternal8::read(uint32_t offset, uint32_t count, int16_t *data)
    {
            uint32_t addr = memory_begin + offset;
    
    #ifdef INTERNAL_TEST
            while (count) { *data++ = testmem[addr++]; count--; } // testing only
    #else
            if (memory_type == AUDIO_MEMORY8_23LC1024 || 
                    memory_type == AUDIO_MEMORY8_CY15B104 ||
                    memory_type == AUDIO_MEMORY8_PSRAM_8MB)
            {
                    addr *= 2;
                    SPI.beginTransaction(SPISETTING);
                    digitalWriteFast(SPIRAM_CS_PIN, LOW);
                    SPI.transfer16((0x03 << 8) | (addr >> 16));
                    SPI.transfer16(addr & 0xFFFF);
                    while (count) {
                            *data++ = (int16_t)(SPI.transfer16(0));
                            count--;
                    }
                    digitalWriteFast(SPIRAM_CS_PIN, HIGH);
                    SPI.endTransaction();
            } else if (memory_type == AUDIO_MEMORY8_MEMORYBOARD) {
                    SPI.beginTransaction(SPISETTING);
                    while (count) {
                            uint32_t chip = (addr >> 16) + 1;
                            digitalWriteFast(MEMBOARD_CS0_PIN, chip & 1);
                            digitalWriteFast(MEMBOARD_CS1_PIN, chip & 2);
                            digitalWriteFast(MEMBOARD_CS2_PIN, chip & 4);
                            uint32_t chipaddr = (addr & 0xFFFF) << 1;
                            SPI.transfer16((0x03 << 8) | (chipaddr >> 16));
                            SPI.transfer16(chipaddr & 0xFFFF);
                            uint32_t num = 0x10000 - (addr & 0xFFFF);
                            if (num > count) num = count;
                            count -= num;
                            addr += num;
                            do {
                                    *data++ = (int16_t)(SPI.transfer16(0));
                            } while (--num > 0);
                    }
                    digitalWriteFast(MEMBOARD_CS0_PIN, LOW);
                    digitalWriteFast(MEMBOARD_CS1_PIN, LOW);
                    digitalWriteFast(MEMBOARD_CS2_PIN, LOW);
                    SPI.endTransaction();
            }
    #endif
    }
    
    void AudioEffectDelayExternal8::write(uint32_t offset, uint32_t count, const int16_t *data)
    {
            uint32_t addr = memory_begin + offset;
    
    #ifdef INTERNAL_TEST
            while (count) { testmem[addr++] = *data++; count--; } // testing only
    #else
            if (memory_type == AUDIO_MEMORY8_23LC1024 ||
                    memory_type == AUDIO_MEMORY8_PSRAM_8MB ) {
                    addr *= 2;
                    SPI.beginTransaction(SPISETTING);
                    digitalWriteFast(SPIRAM_CS_PIN, LOW);
                    SPI.transfer16((0x02 << 8) | (addr >> 16));
                    SPI.transfer16(addr & 0xFFFF);
                    while (count) {
                            int16_t w = 0;
                            if (data) w = *data++;
                            SPI.transfer16(w);
                            count--;
                    }
                    digitalWriteFast(SPIRAM_CS_PIN, HIGH);
                    SPI.endTransaction();
            } else if (memory_type == AUDIO_MEMORY8_CY15B104) {
                    addr *= 2;
    
                    SPI.beginTransaction(SPISETTING);
                    digitalWriteFast(SPIRAM_CS_PIN, LOW);
                    SPI.transfer(0x06); //write-enable before every write
                    digitalWriteFast(SPIRAM_CS_PIN, HIGH);
                    asm volatile ("NOP\n NOP\n NOP\n NOP\n NOP\n NOP\n");
                    digitalWriteFast(SPIRAM_CS_PIN, LOW);
                    SPI.transfer16((0x02 << 8) | (addr >> 16));
                    SPI.transfer16(addr & 0xFFFF);
                    while (count) {
                            int16_t w = 0;
                            if (data) w = *data++;
                            SPI.transfer16(w);
                            count--;
                    }
                    digitalWriteFast(SPIRAM_CS_PIN, HIGH);
                    SPI.endTransaction();
            } else if (memory_type == AUDIO_MEMORY8_MEMORYBOARD) {
                    SPI.beginTransaction(SPISETTING);
                    while (count) {
                            uint32_t chip = (addr >> 16) + 1;
                            digitalWriteFast(MEMBOARD_CS0_PIN, chip & 1);
                            digitalWriteFast(MEMBOARD_CS1_PIN, chip & 2);
                            digitalWriteFast(MEMBOARD_CS2_PIN, chip & 4);
                            uint32_t chipaddr = (addr & 0xFFFF) << 1;
                            SPI.transfer16((0x02 << 8) | (chipaddr >> 16));
                            SPI.transfer16(chipaddr & 0xFFFF);
                            uint32_t num = 0x10000 - (addr & 0xFFFF);
                            if (num > count) num = count;
                            count -= num;
                            addr += num;
                            do {
                                    int16_t w = 0;
                                    if (data) w = *data++;
                                    SPI.transfer16(w);
                            } while (--num > 0);
                    }
                    digitalWriteFast(MEMBOARD_CS0_PIN, LOW);
                    digitalWriteFast(MEMBOARD_CS1_PIN, LOW);
                    digitalWriteFast(MEMBOARD_CS2_PIN, LOW);
                    SPI.endTransaction();
            }
    #endif
    }
    ... and the test program:
    Code:
    #include <Audio.h>
    #include <Wire.h>
    #include <SPI.h>
    #include <effect_delay_ext8.h>
    
    // GUItool: begin automatically generated code
    AudioSynthWaveformSine   sine1;          //xy=382,432
    AudioAmplifier           amp1;           //xy=606,441
    AudioEffectDelayExternal8 delayExt1(AUDIO_MEMORY_PSRAM_8MB,95108);      //xy=770,321
    AudioMixer4              mixer1;         //xy=983,386
    AudioOutputI2S           i2s1;           //xy=1131,343
    AudioConnection          patchCord1(sine1, amp1);
    AudioConnection          patchCord2(amp1, delayExt1);
    AudioConnection          patchCord3(amp1, 0, mixer1, 1);
    AudioConnection          patchCord4(delayExt1, 0, mixer1, 0);
    AudioConnection          patchCord5(mixer1, 0, i2s1, 0);
    AudioConnection          patchCord6(mixer1, 0, i2s1, 1);
    AudioControlSGTL5000     sgtl5000;     //xy=943,541
    // GUItool: end automatically generated code
    
    
    void setup() {
      AudioMemory(100);
    
      sgtl5000.enable();
      sgtl5000.lineOutLevel(29);
      sgtl5000.dacVolumeRamp();
      sgtl5000.dacVolume(1.0);
      sgtl5000.unmuteHeadphone();
      sgtl5000.unmuteLineout();
      sgtl5000.volume(0.8,0.8); // Headphone volume
      sgtl5000.audioProcessorDisable();
      sgtl5000.autoVolumeDisable();
      sgtl5000.surroundSoundDisable();
      sgtl5000.enhanceBassDisable();
      delayExt1.delay(0,100);
      sine1.amplitude(1.0);
      sine1.frequency(440);
      sine1.phase(0.0);
      mixer1.gain(0,0.5);
      mixer1.gain(1,1.0);
      amp1.gain(1.0);
    }
    
    void loop() {
      amp1.gain(1.0);
      delay(200);
      amp1.gain(0.0);
      delay(2000);
    }
    The first problem I am getting: error: 'AUDIO_MEMORY_PSRAM_8MB' was not declared in this scop, so I replaced it with "3" for 8MB memory. But my test program does not work - even serial messages are not shown. Do you have an idea what is going wrong?

    TIA, Holger

  18. #118
    Senior Member h4yn0nnym0u5e's Avatar
    Join Date
    Apr 2021
    Location
    Cambridgeshire, UK
    Posts
    632
    Quote Originally Posted by C0d3man View Post

    The first problem I am getting: error: 'AUDIO_MEMORY_PSRAM_8MB' was not declared in this scop, so I replaced it with "3" for 8MB memory.
    This part is fairly easy: AUDIO_MEMORY_PSRAM_8MB isn't declared, because you called it AUDIO_MEMORY8_PSRAM_8MB.
    But my test program does not work - even serial messages are not shown. Do you have an idea what is going wrong?
    Not sure why serial messages aren't showing up, but ... it sounds as if you've added PSRAM to the Teensy 4.1 to give it some EXTMEM, and generated an edited AudioEffectDelayExternal8 which expects the PSRAM to be on the audio adaptor, which it isn't!

    I have a pull request in which nearly got merged but didn't because of a conflict (that I've fixed, but I think we have to wait for Paul's stack to pop a few levels before he re-addresses this). This lets you use PSRAM on the audio adaptor or as EXTMEM (or indeed both) for your delay memory; you could give that a try. There isn't an example, but I did update the info pane in the Design Tool.

  19. #119
    Senior Member
    Join Date
    May 2018
    Posts
    162

    Quote Originally Posted by h4yn0nnym0u5e View Post
    This part is fairly easy: AUDIO_MEMORY_PSRAM_8MB isn't declared, because you called it AUDIO_MEMORY8_PSRAM_8MB.
    Argh! Ok, I see the problem...

    Quote Originally Posted by h4yn0nnym0u5e View Post
    Not sure why serial messages aren't showing up, but ... it sounds as if you've added PSRAM to the Teensy 4.1 to give it some EXTMEM, and generated an edited AudioEffectDelayExternal8 which expects the PSRAM to be on the audio adaptor, which it isn't!
    Ok, thanks for the hint! I totally forgot that the memory may also be soldered on the audio board. Yes, my memory is on the T_4.1 itself.

    Quote Originally Posted by h4yn0nnym0u5e View Post
    I have a pull request in which nearly got merged but didn't because of a conflict (that I've fixed, but I think we have to wait for Paul's stack to pop a few levels before he re-addresses this). This lets you use PSRAM on the audio adaptor or as EXTMEM (or indeed both) for your delay memory; you could give that a try. There isn't an example, but I did update the info pane in the Design Tool.
    Wow, you have written a complete memory management for EXTMEM - that's nice! I hope your PR will be merged soon!

    Thanks for your help! I will try my version again with fixed pin numbers and come back with the result soon!

    Regards, Holger

  20. #120
    Senior Member
    Join Date
    May 2018
    Posts
    162
    I found this interesting Excel sheet in a forum thread: https://forum.pjrc.com/attachment.ph...3&d=1593888859.

    I found MISO(54)/MOSI(50) and SCK(49), but CS is missing. Perhaps CS is 52? Does anyone know if this makes sense?

  21. #121
    Senior Member h4yn0nnym0u5e's Avatar
    Join Date
    Apr 2021
    Location
    Cambridgeshire, UK
    Posts
    632
    Quote Originally Posted by C0d3man View Post
    I found this interesting Excel sheet in a forum thread: https://forum.pjrc.com/attachment.ph...3&d=1593888859.

    I found MISO(54)/MOSI(50) and SCK(49), but CS is missing. Perhaps CS is 52? Does anyone know if this makes sense?
    If I'm reading it right CS on the "back memory chips" is either 48 or 51 (the little grey cells, M. Poirot)

    Quote Originally Posted by C0d3man View Post
    Ok, thanks for the hint! I totally forgot that the memory may also be soldered on the audio board. Yes, my memory is on the T_4.1 itself.

    Wow, you have written a complete memory management for EXTMEM - that's nice! I hope your PR will be merged soon!

    Thanks for your help! I will try my version again with fixed pin numbers and come back with the result soon!

    Regards, Holger
    I can't take credit for the EXTMEM heap management, that's already part of Teensyduino; not much documentation, though - the Teensy 4.1 page is about it as far as I can tell. I did hack together the on-audio-adaptor memory "management" (because I wanted it ready for dynamic audio objects), though I'll freely confess it's a bit crude and could be improved on.

  22. #122
    Senior Member
    Join Date
    May 2018
    Posts
    162
    Quote Originally Posted by h4yn0nnym0u5e View Post
    If I'm reading it right CS on the "back memory chips" is either 48 or 51 (the little grey cells, M. Poirot)
    Ahhh, yep - but does not work either

    I tried to get the crash report:
    Code:
    11:02:05.534 -> Latest crash report:
    11:02:05.534 -> CrashReport:
    11:02:05.534 ->   A problem occurred at (system time) 11:1:58
    11:02:05.534 ->   Code was executing from address 0xE478
    11:02:05.534 ->   CFSR: 82
    11:02:05.534 -> 	(DACCVIOL) Data Access Violation
    11:02:05.534 -> 	(MMARVALID) Accessed Address: 0x2 (nullptr)
    11:02:05.534 -> 	  Check code at 0xE478 - very likely a bug!
    
    addr2line -e AudioDelay8M.ino.elf 0xE478
    ...../.arduino15/packages/teensy/hardware/avr/1.57.2/cores/teensy4/AudioStream.cpp:128
    ... which points to
    Code:
    AudioStream::release()
    At this point I can't get any further with my current knowledge... let's see if I can find the error. At least it will take a while until I have understood the whole. Maybe I will manage to test your PR somehow - maybe I will get further with it.

    Regards, Holger

  23. #123
    Senior Member
    Join Date
    May 2018
    Posts
    162
    Quote Originally Posted by h4yn0nnym0u5e View Post
    I have a pull request in which nearly got merged
    I just tried the PR, but unfortunately it does not work. I put a 200ms sine signal into the delay and get nothing (except the original signal). With AudioEffectDelay() everything works... re is the code I used:
    Code:
    #include <Arduino.h>
    #include <Audio.h>
    #include <Wire.h>
    #include <SPI.h>
    
    // GUItool: begin automatically generated code
    AudioSynthWaveformSine sine1;                                     //xy=382,432
    AudioAmplifier amp1;                                              //xy=606,441
    AudioEffectDelayExternal delayExt1(AUDIO_MEMORY_PSRAM64, 2000);  //xy=770,321
    AudioMixer4 mixer1;                                               //xy=983,386
    AudioOutputI2S i2s1;                                              //xy=1131,343
    AudioConnection patchCord1(sine1, amp1);
    AudioConnection patchCord2(amp1, delayExt1);
    AudioConnection patchCord3(amp1, 0, mixer1, 1);
    AudioConnection patchCord4(delayExt1, 0, mixer1, 0);
    AudioConnection patchCord5(mixer1, 0, i2s1, 0);
    AudioConnection patchCord6(mixer1, 0, i2s1, 1);
    AudioControlSGTL5000 sgtl5000;  //xy=943,541
    // GUItool: end automatically generated code
    
    
    void setup() {
      Serial.begin(230400);
      delay(50);
      Serial.println("<setup begin>");
    
      AudioMemory(200);
    
      sgtl5000.enable();
      sgtl5000.lineOutLevel(29);
      sgtl5000.dacVolumeRamp();
      sgtl5000.dacVolume(1.0);
      sgtl5000.unmuteHeadphone();
      sgtl5000.unmuteLineout();
      sgtl5000.volume(0.8, 0.8);  // Headphone volume
      sgtl5000.audioProcessorDisable();
      sgtl5000.autoVolumeDisable();
      sgtl5000.surroundSoundDisable();
      sgtl5000.enhanceBassDisable();
      delayExt1.delay(0, 333);
      sine1.amplitude(1.0);
      sine1.frequency(440);
      sine1.phase(0.0);
      mixer1.gain(0, 0.5);
      mixer1.gain(1, 1.0);
      amp1.gain(0.0);
    
      Serial.println("<setup end>");
    }
    
    void loop() {
      Serial.print("<SINE ON>");
      amp1.gain(1.0);
      delay(200);
      amp1.gain(0.0);
      Serial.println("<SINE OFF>");
      delay(2000);
    }
    Doe you have an idea?

  24. #124
    Senior Member h4yn0nnym0u5e's Avatar
    Join Date
    Apr 2021
    Location
    Cambridgeshire, UK
    Posts
    632
    Quote Originally Posted by C0d3man View Post
    I just tried the PR, but unfortunately it does not work. I put a 200ms sine signal into the delay and get nothing (except the original signal). With AudioEffectDelay() everything works... re is the code I used:
    Code:
    #include <Arduino.h>
    #include <Audio.h>
    #include <Wire.h>
    #include <SPI.h>
    
    // GUItool: begin automatically generated code
    AudioSynthWaveformSine sine1;                                     //xy=382,432
    AudioAmplifier amp1;                                              //xy=606,441
    AudioEffectDelayExternal delayExt1(AUDIO_MEMORY_PSRAM64, 2000);  //xy=770,321
    AudioMixer4 mixer1;                                               //xy=983,386
    AudioOutputI2S i2s1;                                              //xy=1131,343
    AudioConnection patchCord1(sine1, amp1);
    AudioConnection patchCord2(amp1, delayExt1);
    AudioConnection patchCord3(amp1, 0, mixer1, 1);
    AudioConnection patchCord4(delayExt1, 0, mixer1, 0);
    AudioConnection patchCord5(mixer1, 0, i2s1, 0);
    AudioConnection patchCord6(mixer1, 0, i2s1, 1);
    AudioControlSGTL5000 sgtl5000;  //xy=943,541
    // GUItool: end automatically generated code
    
    
    void setup() {
      Serial.begin(230400);
      delay(50);
      Serial.println("<setup begin>");
    
      AudioMemory(200);
    
      sgtl5000.enable();
      sgtl5000.lineOutLevel(29);
      sgtl5000.dacVolumeRamp();
      sgtl5000.dacVolume(1.0);
      sgtl5000.unmuteHeadphone();
      sgtl5000.unmuteLineout();
      sgtl5000.volume(0.8, 0.8);  // Headphone volume
      sgtl5000.audioProcessorDisable();
      sgtl5000.autoVolumeDisable();
      sgtl5000.surroundSoundDisable();
      sgtl5000.enhanceBassDisable();
      delayExt1.delay(0, 333);
      sine1.amplitude(1.0);
      sine1.frequency(440);
      sine1.phase(0.0);
      mixer1.gain(0, 0.5);
      mixer1.gain(1, 1.0);
      amp1.gain(0.0);
    
      Serial.println("<setup end>");
    }
    
    void loop() {
      Serial.print("<SINE ON>");
      amp1.gain(1.0);
      delay(200);
      amp1.gain(0.0);
      Serial.println("<SINE OFF>");
      delay(2000);
    }
    Doe you have an idea?
    It looks as if you've requested to use delay memory fitted to the audio adaptor, but previously you said you put it on the Teensy 4.1 as EXTMEM - try changing that statement to AudioEffectDelayExternal delayExt1(AUDIO_MEMORY_EXTMEM, 2000);

    The various options are listed in AudioEffectDelayMemoryType_t in extmem.h, but not very well-commented. The first 4 use SPI memory on the adaptor; don't use the next one; then the others are in heap and EXTMEM.

  25. #125
    Senior Member
    Join Date
    May 2018
    Posts
    162
    Quote Originally Posted by h4yn0nnym0u5e View Post
    It looks as if you've requested to use delay memory fitted to the audio adaptor, but previously you said you put it on the Teensy 4.1 as EXTMEM - try changing that statement to AudioEffectDelayExternal delayExt1(AUDIO_MEMORY_EXTMEM, 2000);

    The various options are listed in AudioEffectDelayMemoryType_t in extmem.h, but not very well-commented. The first 4 use SPI memory on the adaptor; don't use the next one; then the others are in heap and EXTMEM.
    Yep - sorry for my misunderstanding! Now it works like a charme!!!

    Many thanks for this - MicroDexed now supports loooooooong delays and some more memory for variables is available. I created a library which can be added to the local library folder and which does not overlap with the Teensy library (until the PR is finally recorded): https://codeberg.org/dcoredump/Micro...ect_delay_ext8

Posting Permissions

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