Forum Rule: Always post complete source code & details to reproduce any issue!
Page 1 of 4 1 2 3 ... LastLast
Results 1 to 25 of 78

Thread: Discussion about a simple way to change the sample-rate

Hybrid View

  1. #1
    Senior Member+ Frank B's Avatar
    Join Date
    Apr 2014
    Location
    Germany NRW
    Posts
    5,679

    Discussion about a simple way to change the sample-rate

    Hi,

    i guess, there is a - more or less - simple way to change the samplerate of the audiolibrary at runtime.
    For example, if you use the I2S-Output, i think, it would be sufficient to patch the "timing"-registers (multipliers/dividers) to archive 48KHz.
    - without any changes to the library code -

    Of course, this has several unwanted side-effects, and some things will NOT work.
    But which ?

    For example,
    - the sine-object will work, but with a wrong frequeny. The would be easy to "repair" (call frequency(freq*0.85))
    - mixers will work

    So, which parts will work, which not ? Where are problems ?

    Edit: My reason to ask:
    I re-activated an old project, my webradio, and some stations are using 48KHz. Therey are not usable, at the moment.
    A "hack" like this would allow to play them - without having to patch audio-library sourcecode.
    Last edited by Frank B; 10-27-2016 at 10:26 PM.

  2. #2
    Senior Member
    Join Date
    Jul 2014
    Posts
    2,365
    Quote Originally Posted by Frank B View Post
    Hi,

    i guess, there is a - more or less - simple way to change the samplerate of the audiolibrary at runtime.
    For example, if you use the I2S-Output, i think, it would be sufficient to patch the "timing"-registers (multipliers/dividers) to archive 48KHz.
    Yes, that is the way to do it.
    Consequences:
    I only see: different sampling-> different block duration -> different frequency.
    So all instances that internally use 44.1 kHz must be converted to 48 kHz, as you suggested.

  3. #3
    Member
    Join Date
    Oct 2016
    Location
    Colchester, Essex, UK
    Posts
    55
    Not sure I understand the question, but I think you're asking what will happen if you play audio at a different rate than it was orignially sampled at?
    E.g. audio recorded at 44.1kHz played out at 48kHz.
    If the audio is recorded and you have it all in local storage somewhere, chances are it will work, but you will hear it at a slightly higher pitch (or lower if the other way around).
    If the audio is being streamed live, you might hear audio breaks as you run out of data (clocking it out faster than clocking it in) or you will have to handle buffer overruns (clocking it in faster than clocking out) in your software which will probably sound like short skips in the audio (when you dump a chunk of data).

  4. #4
    Senior Member+ Frank B's Avatar
    Join Date
    Apr 2014
    Location
    Germany NRW
    Posts
    5,679
    Quote Originally Posted by mundungus View Post
    Not sure I understand the question, but I think you're asking what will happen if you play audio at a different rate than it was orignially sampled at?
    No.
    I want to know the side-effects of changing the sample-freq at runtime - and if there are workarounds for the different objects.
    And *which* parts make problems.
    Because i want to be able to switch to 48KHz or other freqs and runtime.
    (An other way would be to create a "up/down" sampler that re-samples anything to 44.1KHz - but this is more work and less quality)

    But *without* changing anything in the core- or audiolibrary.

    Ok, I guess, I have to read all the sourcecode..
    Last edited by Frank B; 10-28-2016 at 12:52 PM.

  5. #5
    Senior Member+ Frank B's Avatar
    Join Date
    Apr 2014
    Location
    Germany NRW
    Posts
    5,679
    ...if someone wants to try it:

    Code:
    void setI2SFreq(int freq) {
      typedef struct {
        uint8_t mult;
        uint16_t div;
      } tmclk;
    
      const int numfreqs = 14;
      const int samplefreqs[numfreqs] = { 8000, 11025, 16000, 22050, 32000, 44100, 44117.64706 , 48000, 88200, 44117.64706 * 2, 96000, 176400, 44117.64706 * 4, 192000};
    
    #if (F_PLL==16000000)
      const tmclk clkArr[numfreqs] = {{16, 125}, {148, 839}, {32, 125}, {145, 411}, {64, 125}, {151, 214}, {12, 17}, {96, 125}, {151, 107}, {24, 17}, {192, 125}, {127, 45}, {48, 17}, {255, 83} };
    #elif (F_PLL==72000000)
      const tmclk clkArr[numfreqs] = {{32, 1125}, {49, 1250}, {64, 1125}, {49, 625}, {128, 1125}, {98, 625}, {8, 51}, {64, 375}, {196, 625}, {16, 51}, {128, 375}, {249, 397}, {32, 51}, {185, 271} };
    #elif (F_PLL==96000000)
      const tmclk clkArr[numfreqs] = {{8, 375}, {73, 2483}, {16, 375}, {147, 2500}, {32, 375}, {147, 1250}, {2, 17}, {16, 125}, {147, 625}, {4, 17}, {32, 125}, {151, 321}, {8, 17}, {64, 125} };
    #elif (F_PLL==120000000)
      const tmclk clkArr[numfreqs] = {{32, 1875}, {89, 3784}, {64, 1875}, {147, 3125}, {128, 1875}, {205, 2179}, {8, 85}, {64, 625}, {89, 473}, {16, 85}, {128, 625}, {178, 473}, {32, 85}, {145, 354} };
    #elif (F_PLL==144000000)
      const tmclk clkArr[numfreqs] = {{16, 1125}, {49, 2500}, {32, 1125}, {49, 1250}, {64, 1125}, {49, 625}, {4, 51}, {32, 375}, {98, 625}, {8, 51}, {64, 375}, {196, 625}, {16, 51}, {128, 375} };
    #elif (F_PLL==180000000)
      const tmclk clkArr[numfreqs] = {{46, 4043}, {49, 3125}, {73, 3208}, {98, 3125}, {183, 4021}, {196, 3125}, {16, 255}, {128, 1875}, {107, 853}, {32, 255}, {219, 1604}, {214, 853}, {64, 255}, {219, 802} };
    #elif (F_PLL==192000000)
      const tmclk clkArr[numfreqs] = {{4, 375}, {37, 2517}, {8, 375}, {73, 2483}, {16, 375}, {147, 2500}, {1, 17}, {8, 125}, {147, 1250}, {2, 17}, {16, 125}, {147, 625}, {4, 17}, {32, 125} };
    #elif (F_PLL==216000000)
      const tmclk clkArr[numfreqs] = {{32, 3375}, {49, 3750}, {64, 3375}, {49, 1875}, {128, 3375}, {98, 1875}, {8, 153}, {64, 1125}, {196, 1875}, {16, 153}, {128, 1125}, {226, 1081}, {32, 153}, {147, 646} };
    #elif (F_PLL==240000000)
      const tmclk clkArr[numfreqs] = {{16, 1875}, {29, 2466}, {32, 1875}, {89, 3784}, {64, 1875}, {147, 3125}, {4, 85}, {32, 625}, {205, 2179}, {8, 85}, {64, 625}, {89, 473}, {16, 85}, {128, 625} };
    #endif
    
      for (int f = 0; f < numfreqs; f++) {
        if ( freq == samplefreqs[f] ) {
          while (I2S0_MCR & I2S_MCR_DUF) ;
          I2S0_MDR = I2S_MDR_FRACT((clkArr[f].mult - 1)) | I2S_MDR_DIVIDE((clkArr[f].div - 1));
          return;
        }
      }
    }
    (Tested with PT8211 only)
    Last edited by Frank B; 10-31-2016 at 10:33 AM.

  6. #6
    Senior Member
    Join Date
    Nov 2012
    Posts
    1,166
    OOooooohh Frank,
    If you can get the SGTL5000 running at 11025kHz and/or 8kHz sampling rate, life would be so much easier for some things I'd like to play with - assuming that the audio library doesn't require major tweaks to accomodate this.

    Pete

  7. #7
    Senior Member+ Frank B's Avatar
    Join Date
    Apr 2014
    Location
    Germany NRW
    Posts
    5,679
    Quote Originally Posted by el_supremo View Post
    OOooooohh Frank,
    If you can get the SGTL5000 running at 11025kHz and/or 8kHz sampling rate, life would be so much easier for some things I'd like to play with - assuming that the audio library doesn't require major tweaks to accomodate this.

    Pete
    Can you try the code above ? Maybe it works ?
    setI2SFreq(11025);

    I don't know if the SGTL accepts that, and i did not look at the datasheet, but it is worth a try

  8. #8
    Senior Member
    Join Date
    Nov 2012
    Posts
    1,166
    Hi Frank,
    Just tried the code in a sketch which routes microphone input straight to output on T3.6 at 180MHz. At 8000 and 11025, neither of them work but it works at 44100.
    This is calling your function immediately after the SGTL enable() function.


    Pete

  9. #9
    Senior Member+ Frank B's Avatar
    Join Date
    Apr 2014
    Location
    Germany NRW
    Posts
    5,679
    Quote Originally Posted by el_supremo View Post
    Hi Frank,
    Just tried the code in a sketch which routes microphone input straight to output on T3.6 at 180MHz. At 8000 and 11025, neither of them work but it works at 44100.
    This is calling your function immediately after the SGTL enable() function.


    Pete
    Ok, maybe it needs some additional settings (PLL?)
    I'll try it in a few days

  10. #10
    Senior Member+ Frank B's Avatar
    Join Date
    Apr 2014
    Location
    Germany NRW
    Posts
    5,679
    Here's the same for the internal DACs :

    Code:
    void setDACFreq(int freq) {
    const unsigned config = PDB_SC_TRGSEL(15) | PDB_SC_PDBEN | PDB_SC_CONT | PDB_SC_PDBIE | PDB_SC_DMAEN;
        PDB0_SC = 0;
        PDB0_IDLY = 1;
        PDB0_MOD = round((float)F_BUS / freq ) - 1;    
        PDB0_SC = config | PDB_SC_LDOK;
        PDB0_SC = config | PDB_SC_SWTRIG;
        PDB0_CH0C1 = 0x0101;    
    }
    edit: Added one line
    Last edited by Frank B; 08-06-2017 at 09:33 AM.

  11. #11
    Junior Member
    Join Date
    Nov 2015
    Posts
    15
    Quote Originally Posted by Frank B View Post
    Here's the same for the internal DACs :

    Code:
    void setDACFreq(int freq) {
    const unsigned config = PDB_SC_TRGSEL(15) | PDB_SC_PDBEN | PDB_SC_CONT | PDB_SC_PDBIE | PDB_SC_DMAEN;
        PDB0_IDLY = 1;
        PDB0_MOD = round((float)F_BUS / freq ) - 1;    
        PDB0_SC = config | PDB_SC_LDOK;
        PDB0_SC = config | PDB_SC_SWTRIG;
        PDB0_CH0C1 = 0x0101;    
    }
    Ha, this is exactly what I was working on in this thread. As usual, your solution is much better than mine (run-time adjustments to AUDIO_SAMPLE_RATE). Your solution works flawlessly, and it warps the audio if the sample rates don't match, like I was looking for. There have a been a number of threads around the web and this forum asking how to do this, so I just want to put in some keywords to help people find this later.


    change tempo, change playback speed, speed up a song, slow down a song, use other sample rates, pitch shifting, change audio speed, tempo changer

  12. #12
    Senior Member+ Frank B's Avatar
    Join Date
    Apr 2014
    Location
    Germany NRW
    Posts
    5,679
    @el_supremo,

    Well, the SGTL datasheet says, that it supports 8 and 11KHz.I guess, with some additional I2C-commands, it will work.
    I'll look tomorrow.

  13. #13
    Senior Member
    Join Date
    Nov 2012
    Posts
    1,166
    Thanks Frank.

    Pete

  14. #14
    Senior Member+ Frank B's Avatar
    Join Date
    Apr 2014
    Location
    Germany NRW
    Posts
    5,679
    Hm, is there was a way to trigger the ADCs from I2S, we could use them, too...
    Anyone knows if the pin-interrupts work with pins set to output?

    Edit:
    Or, even better, is it possible to trigger DMA with a pin-change ?
    Last edited by Frank B; 10-30-2016 at 08:19 PM.

  15. #15
    Senior Member+ Frank B's Avatar
    Join Date
    Apr 2014
    Location
    Germany NRW
    Posts
    5,679
    el_supremeo,
    i don't understand..
    please, can you provide a test-sketch that shows the problem ?

    Output works flawlessly:

    Code:
    #include <Audio.h>
    #include <Wire.h>
    #include <SPI.h>
    #include <SD.h>
    #include <SerialFlash.h>
    
    void setI2SFreq(int freq) {
      typedef struct {
        uint8_t mult;
        uint16_t div;
      } __attribute__((__packed__)) tmclk;
    
      const int numfreqs = 14;
      const int samplefreqs[numfreqs] = { 8000, 11025, 16000, 22050, 32000, 44100, 44117.64706 , 48000, 88200, 44117.64706 * 2, 96000, 176400, 44117.64706 * 4, 192000};
    
    #if (F_PLL==16000000)
      const tmclk clkArr[numfreqs] = {{16, 125}, {148, 839}, {32, 125}, {145, 411}, {64, 125}, {151, 214}, {12, 17}, {96, 125}, {151, 107}, {24, 17}, {192, 125}, {127, 45}, {48, 17}, {255, 83} };
    #elif (F_PLL==72000000)
      const tmclk clkArr[numfreqs] = {{32, 1125}, {49, 1250}, {64, 1125}, {49, 625}, {128, 1125}, {98, 625}, {8, 51}, {64, 375}, {196, 625}, {16, 51}, {128, 375}, {249, 397}, {32, 51}, {185, 271} };
    #elif (F_PLL==96000000)
      const tmclk clkArr[numfreqs] = {{8, 375}, {73, 2483}, {16, 375}, {147, 2500}, {32, 375}, {147, 1250}, {2, 17}, {16, 125}, {147, 625}, {4, 17}, {32, 125}, {151, 321}, {8, 17}, {64, 125} };
    #elif (F_PLL==120000000)
      const tmclk clkArr[numfreqs] = {{32, 1875}, {89, 3784}, {64, 1875}, {147, 3125}, {128, 1875}, {205, 2179}, {8, 85}, {64, 625}, {89, 473}, {16, 85}, {128, 625}, {178, 473}, {32, 85}, {145, 354} };
    #elif (F_PLL==144000000)
      const tmclk clkArr[numfreqs] = {{16, 1125}, {49, 2500}, {32, 1125}, {49, 1250}, {64, 1125}, {49, 625}, {4, 51}, {32, 375}, {98, 625}, {8, 51}, {64, 375}, {196, 625}, {16, 51}, {128, 375} };
    #elif (F_PLL==180000000)
      const tmclk clkArr[numfreqs] = {{46, 4043}, {49, 3125}, {73, 3208}, {98, 3125}, {183, 4021}, {196, 3125}, {16, 255}, {128, 1875}, {107, 853}, {32, 255}, {219, 1604}, {214, 853}, {64, 255}, {219, 802} };
    #elif (F_PLL==192000000)
      const tmclk clkArr[numfreqs] = {{4, 375}, {37, 2517}, {8, 375}, {73, 2483}, {16, 375}, {147, 2500}, {1, 17}, {8, 125}, {147, 1250}, {2, 17}, {16, 125}, {147, 625}, {4, 17}, {32, 125} };
    #elif (F_PLL==216000000)
      const tmclk clkArr[numfreqs] = {{32, 3375}, {49, 3750}, {64, 3375}, {49, 1875}, {128, 3375}, {98, 1875}, {8, 153}, {64, 1125}, {196, 1875}, {16, 153}, {128, 1125}, {226, 1081}, {32, 153}, {147, 646} };
    #elif (F_PLL==240000000)
      const tmclk clkArr[numfreqs] = {{16, 1875}, {29, 2466}, {32, 1875}, {89, 3784}, {64, 1875}, {147, 3125}, {4, 85}, {32, 625}, {205, 2179}, {8, 85}, {64, 625}, {89, 473}, {16, 85}, {128, 625} };
    #endif
    
      for (int f = 0; f < numfreqs; f++) {
        if ( freq == samplefreqs[f] ) {
          while (I2S0_MCR & I2S_MCR_DUF) ;
          I2S0_MDR = I2S_MDR_FRACT((clkArr[f].mult - 1)) | I2S_MDR_DIVIDE((clkArr[f].div - 1));
          return;
        }
      }
    }
    
    // GUItool: begin automatically generated code
    AudioSynthWaveform       waveform1;      //xy=110,75
    AudioOutputI2S           output;          //xy=303,78
    AudioConnection          patchCord1(waveform1, 0, output, 0);
    AudioConnection          patchCord2(waveform1, 0, output, 1);
    // GUItool: end automatically generated code
    AudioControlSGTL5000 codec;
    
    void setup() {
      const int freq = 1000;
      const int samplefreq = 8000;
      AudioMemory(15);
      codec.enable();
      codec.volume(0.35);  
      waveform1.begin(WAVEFORM_SINE);
      waveform1.frequency(AUDIO_SAMPLE_RATE_EXACT/samplefreq*freq);
      waveform1.amplitude(0.99); 
      setI2SFreq(samplefreq);
    }
    
    void loop() {
      /* 
      float vol = analogRead(15);
      vol = vol / 1024;
      codec.volume(vol);
      */
    }
    Last edited by Frank B; 10-31-2016 at 10:36 AM.

  16. #16
    Junior Member
    Join Date
    Aug 2017
    Posts
    19
    Hello Guys, Im trying this code to change the sampling rate to 48k but Im receiving the following errors:

    T3.6

    In function 'void setI2SFreq(int)':

    error: narrowing conversion of '4.41176484e+4f' from 'float' to 'int' inside { } [-Wnarrowing]

    const int samplefreqs[numfreqs] = { 8000, 11025, 16000, 22050, 32000, 44100, 44117.64706 , 48000, 88200, 44117.64706 * 2, 96000, 176400, 44117.64706 * 4, 192000};

    ^
    error: narrowing conversion of '8.82352969e+4f' from 'float' to 'int' inside { } [-Wnarrowing]

    narrowing conversion of '1.76470594e+5f' from 'float' to 'int' inside { } [-Wnarrowing]


    Does anybody know how to fix this and why it is happening?

    Thanks



    Code:
    #include <Audio.h>
    #include <Wire.h>
    #include <SPI.h>
    #include <SD.h>
    #include <SerialFlash.h>
    
    
    
    void setI2SFreq(int freq) {
      typedef struct {
        uint8_t mult;
        uint16_t div;
      } __attribute__((__packed__)) tmclk;
      const int numfreqs = 14;
      const int samplefreqs[numfreqs] = { 8000, 11025, 16000, 22050, 32000, 44100, 44117.64706 , 48000, 88200, 44117.64706 * 2, 96000, 176400, 44117.64706 * 4, 192000};
    
    #if (F_PLL==16000000)
      const tmclk clkArr[numfreqs] = {{16, 125}, {148, 839}, {32, 125}, {145, 411}, {64, 125}, {151, 214}, {12, 17}, {96, 125}, {151, 107}, {24, 17}, {192, 125}, {127, 45}, {48, 17}, {255, 83} };
    #elif (F_PLL==72000000)
      const tmclk clkArr[numfreqs] = {{32, 1125}, {49, 1250}, {64, 1125}, {49, 625}, {128, 1125}, {98, 625}, {8, 51}, {64, 375}, {196, 625}, {16, 51}, {128, 375}, {249, 397}, {32, 51}, {185, 271} };
    #elif (F_PLL==96000000)
      const tmclk clkArr[numfreqs] = {{8, 375}, {73, 2483}, {16, 375}, {147, 2500}, {32, 375}, {147, 1250}, {2, 17}, {16, 125}, {147, 625}, {4, 17}, {32, 125}, {151, 321}, {8, 17}, {64, 125} };
    #elif (F_PLL==120000000)
      const tmclk clkArr[numfreqs] = {{32, 1875}, {89, 3784}, {64, 1875}, {147, 3125}, {128, 1875}, {205, 2179}, {8, 85}, {64, 625}, {89, 473}, {16, 85}, {128, 625}, {178, 473}, {32, 85}, {145, 354} };
    #elif (F_PLL==144000000)
      const tmclk clkArr[numfreqs] = {{16, 1125}, {49, 2500}, {32, 1125}, {49, 1250}, {64, 1125}, {49, 625}, {4, 51}, {32, 375}, {98, 625}, {8, 51}, {64, 375}, {196, 625}, {16, 51}, {128, 375} };
    #elif (F_PLL==180000000)
      const tmclk clkArr[numfreqs] = {{46, 4043}, {49, 3125}, {73, 3208}, {98, 3125}, {183, 4021}, {196, 3125}, {16, 255}, {128, 1875}, {107, 853}, {32, 255}, {219, 1604}, {214, 853}, {64, 255}, {219, 802} };
    #elif (F_PLL==192000000)
      const tmclk clkArr[numfreqs] = {{4, 375}, {37, 2517}, {8, 375}, {73, 2483}, {16, 375}, {147, 2500}, {1, 17}, {8, 125}, {147, 1250}, {2, 17}, {16, 125}, {147, 625}, {4, 17}, {32, 125} };
    #elif (F_PLL==216000000)
      const tmclk clkArr[numfreqs] = {{32, 3375}, {49, 3750}, {64, 3375}, {49, 1875}, {128, 3375}, {98, 1875}, {8, 153}, {64, 1125}, {196, 1875}, {16, 153}, {128, 1125}, {226, 1081}, {32, 153}, {147, 646} };
    #elif (F_PLL==240000000)
      const tmclk clkArr[numfreqs] = {{16, 1875}, {29, 2466}, {32, 1875}, {89, 3784}, {64, 1875}, {147, 3125}, {4, 85}, {32, 625}, {205, 2179}, {8, 85}, {64, 625}, {89, 473}, {16, 85}, {128, 625} };
    #endif
    
      for (int f = 0; f < numfreqs; f++) {
        if ( freq == samplefreqs[f] ) {
          while (I2S0_MCR & I2S_MCR_DUF) ;
          I2S0_MDR = I2S_MDR_FRACT((clkArr[f].mult - 1)) | I2S_MDR_DIVIDE((clkArr[f].div - 1));
          return;
        }
      }
    }
    
    
    // GUItool: begin automatically generated code
    AudioInputI2S            i2s1;           //xy=168,145
    AudioRecordQueue         queue1;         //xy=360,62
    AudioRecordQueue         queue2;         //xy=389,145
    AudioConnection          patchCord1(i2s1, 0, queue1, 0);
    AudioConnection          patchCord2(i2s1, 1, queue2, 0);
    // GUItool: end automatically generated code
    
    AudioControlSGTL5000     sgtl5000_1;     //xy=265,212
    
    
    // which input on the audio shield will be used?
    //const int myInput = AUDIO_INPUT_LINEIN;
    const int myInput = AUDIO_INPUT_MIC;
    
    
    // Use these with the Teensy Audio Shield
    #define SDCARD_CS_PIN    10
    #define SDCARD_MOSI_PIN  7
    #define SDCARD_SCK_PIN   14
    
    // Use these with the Teensy 3.5 & 3.6 SD card
    //#define SDCARD_CS_PIN    BUILTIN_SDCARD // 254?
    //#define SDCARD_MOSI_PIN  11  // not actually used
    //#define SDCARD_SCK_PIN   13  // not actually used
    
    // Remember which mode we're doing
    int mode = 0;  // 0=stopped, 1=recording, 2=playing
    
    
    
    // The file where data is recorded
    File frec;
    
    void setup() {
      // record queue uses this memory to buffer incoming audio.
      AudioMemory(120); // 60
      const int samplefreq = 48000;
      // Enable the audio shield, select input, and enable output
      sgtl5000_1.enable();
      sgtl5000_1.inputSelect(myInput);
      sgtl5000_1.volume(0.5);
      setI2SFreq(samplefreq);
      
      // Initialize the SD card
      SPI.setMOSI(SDCARD_MOSI_PIN);
      SPI.setSCK(SDCARD_SCK_PIN);
      if (!(SD.begin(SDCARD_CS_PIN))) {
        // stop here if no SD card, but print a message
        while (1) {
          Serial.println("Unable to access the SD card");
          delay(500);
        }
      }
    
      startRecording();
    }
    
    
    void loop() {
      if (millis() > (0.2*60000) && mode == 1) {
        stopRecording();
      }
      else {
        if (mode == 1) continueRecording();
      }
    }
    
    void startRecording() {
      Serial.println("StartRecording");
      if (SD.exists("RECORD.RAW")) {
        SD.remove("RECORD.RAW");
      }
      frec = SD.open("RECORD.RAW", FILE_WRITE);
      if (frec) {
        Serial.println("File Open");
        queue1.begin();
        queue2.begin();
        mode = 1;
      }
    
    }
    
    // write all 512 bytes to the SD card   
    void continueRecording() {
      if (queue1.available() >= 2 && queue2.available() >= 2) {
        byte buffer[1024];
        byte bufferL[256];
        byte bufferR[256];
        memcpy(bufferL, queue1.readBuffer(), 256);
        memcpy(bufferR, queue2.readBuffer(), 256);
        queue1.freeBuffer();
        queue2.freeBuffer();
        int b = 0;
        for (int i = 0; i < 1024; i += 8) {
          buffer[i] = bufferL[b];
          buffer[i + 1] = bufferL[b + 1];
          buffer[i + 2] = bufferR[b];
          buffer[i + 3] = bufferR[b + 1];
          buffer[i+4] = bufferL[b];
          buffer[i + 5] = bufferL[b + 1];
          buffer[i + 6] = bufferR[b];
          buffer[i + 7] = bufferR[b + 1];
          b = b+2;
        }
        elapsedMicros usec = 0;
        frec.write(buffer, 1024);  //256 or 512 (dudes code)
        Serial.print("SD write, us=");
        Serial.println(usec);
      }
    }
    
    void stopRecording() {
      Serial.println("StopRecording");
      queue1.end();
      queue2.end();
      // flush buffer
      while (queue1.available() > 0 && queue2.available() > 0) {
        queue1.readBuffer();
        queue1.freeBuffer();
        queue2.readBuffer();
        queue2.freeBuffer();
      }
      frec.close(); // close file
      mode = 4;
    }
    Last edited by arturzorzo; 06-11-2018 at 05:24 PM.

  17. #17
    You can change the values in samplefreq[] vector that are floats, like 44117.64706 to just 44117. Then if you want that speed, call setI2SFreq[44117]. It is just used to find the right entry in the table. This works at all because int in the Teensy 3.x ARM processor is 32 bit.

    Here is an example where the values were explicitly made int. It also has a restricted selection of speeds, but that depends on the project. This is from the AVNA (Network Analyzer) project:
    Code:
    /* Variable sample rate from Frank B., see
       https://forum.pjrc.com/threads/38753-Discussion-about-a-simple-way-to-change-the-sample-rate
       As pointed out by Frank, the various routines, like waveform generator, are calibrated
       for 44.11765 and need to be corrected when other sample rates. See factorFreq below.
    
       K12 Peripheral manual:
       MCLD Divide sets the MCLK divide ratio such that: MCLK output = MCLK input * ( (FRACT + 1) / (DIVIDE + 1) ).
       FRACT must be set equal or less than the value in the DIVIDE field.
       The MCLK divide ratio
       can be altered while an SAI is using that master clock, although the change in the divide
       ratio takes several cycles. MCR[DUF] can be polled to determine when the divide ratio
       change has completed.
    */
    const uint16_t numFreqs = 5;
    // sampleFreqs[] is of limited utility, as the index nSampleRate describes the selection,
    // and sampleRateExact is the true rate, sometimes slightly different.
    const int sampleFreqs[numFreqs] = {44100, 44117, 48000, 96000, 100000};
    // Note Teensy 3.6:  F_CPU == 180000000, F_PLL == 180000000
    // setI2SFreq(if) returns exact sample frequency, that may differ very slightly from sampleFreqs[]
    double setI2SFreq(uint16_t iFreq)
    {
      typedef struct
      {
        uint8_t mult;
        uint16_t div;
      } __attribute__((__packed__)) tmclk;
      // 44117 is nickname for 44117.64706
    #if   (F_PLL==72000000)
      const tmclk clkArr[numFreqs] = {{98, 625}, {8, 51}, {64, 375}, {128, 375}, {16, 45} };
    #elif (F_PLL==96000000)
      const tmclk clkArr[numFreqs] = {{147, 1250}, {2, 17}, {16, 125}, {32, 125}, {20, 75} };
    #elif (F_PLL==120000000)
      const tmclk clkArr[numFreqs] = {{205, 2179}, {8, 85}, {64, 625}, {128, 625}, {16,75} };
    #elif (F_PLL==144000000)
      const tmclk clkArr[numFreqs] = {{49, 625}, {4, 51}, {32, 375}, {64, 375}, {8, 45} };
    #elif (F_PLL==16000000)
      const tmclk clkArr[numFreqs] = {{151, 214}, {12, 17}, {96, 125}, {192, 125}, {20,125} };
    #elif (F_PLL==168000000)
      const tmclk clkArr[numFreqs] = {{42, 625}, {8, 119}, {64, 875}, {128, 875}, {16, 185} };
    #elif (F_PLL==180000000)
      const tmclk clkArr[numFreqs] = {{196, 3125}, {16, 255}, {128, 1875}, {219, 1604}, {32, 225} };
    #elif (F_PLL==192000000)
      const tmclk clkArr[numFreqs] = {{147, 2500}, {1, 17}, {8, 125}, {16, 125}, {2, 15} };
    #elif (F_PLL==216000000)
      const tmclk clkArr[numFreqs] = {{98, 1875}, {8, 153}, {64, 1125}, {128, 1125}, {16, 135} };
    #elif (F_PLL==240000000)
      const tmclk clkArr[numfreqs] = {{147, 3125}, {4, 85}, {32, 625}, {64, 625}, {8, 75} };
    #endif
      while (I2S0_MCR & I2S_MCR_DUF) ;  // This is to make sure I2S controller is up to speed NEEDED??
      I2S0_MDR = I2S_MDR_FRACT((clkArr[iFreq].mult - 1)) | I2S_MDR_DIVIDE((clkArr[iFreq].div - 1));
      return  (double)F_PLL * (double)clkArr[iFreq].mult / (256.0 * (double)clkArr[iFreq].div);
    }
    Note, BTW, the slow speeds, below 44.1 are prone to spurs and noise, and faster sampling and decimation can give better results unless you are in the unusual case of not having enough processor.

  18. #18
    Senior Member
    Join Date
    Nov 2012
    Posts
    1,166
    Hi Frank,
    I used a simple microphone input to headphone output sketch and just got silence unless I chose the 44100 rate.

    What/where is audioutil.h?

    Pete

  19. #19
    Senior Member+ Frank B's Avatar
    Join Date
    Apr 2014
    Location
    Germany NRW
    Posts
    5,679
    audioutil. sorry, delete it, it's not needed.
    Can you post the sketch ? i've never used micropohone. Just to make sure, that the sketch i will use is correct.

  20. #20
    Senior Member
    Join Date
    Nov 2012
    Posts
    1,166
    Just tried your sketch and it looks like it is working. I'd like to try an audio filter at the sampling rate of 8000 - shouldn't take long to put together.

    Pete

  21. #21
    Senior Member+ Frank B's Avatar
    Join Date
    Apr 2014
    Location
    Germany NRW
    Posts
    5,679
    Pete, i've attached the mic
    Took some time, to find it... lol

  22. #22
    Senior Member+ Frank B's Avatar
    Join Date
    Apr 2014
    Location
    Germany NRW
    Posts
    5,679
    works! (????)
    Code:
    #include <Audio.h>
    #include <Wire.h>
    #include <SPI.h>
    #include <SD.h>
    #include <SerialFlash.h>
    
    
    void setI2SFreq(int freq) {
      typedef struct {
        uint8_t mult;
        uint16_t div;
      } __attribute__((__packed__)) tmclk;
      const int numfreqs = 14;
      const int samplefreqs[numfreqs] = { 8000, 11025, 16000, 22050, 32000, 44100, 44117.64706 , 48000, 88200, 44117.64706 * 2, 96000, 176400, 44117.64706 * 4, 192000};
    
    #if (F_PLL==16000000)
      const tmclk clkArr[numfreqs] = {{16, 125}, {148, 839}, {32, 125}, {145, 411}, {64, 125}, {151, 214}, {12, 17}, {96, 125}, {151, 107}, {24, 17}, {192, 125}, {127, 45}, {48, 17}, {255, 83} };
    #elif (F_PLL==72000000)
      const tmclk clkArr[numfreqs] = {{32, 1125}, {49, 1250}, {64, 1125}, {49, 625}, {128, 1125}, {98, 625}, {8, 51}, {64, 375}, {196, 625}, {16, 51}, {128, 375}, {249, 397}, {32, 51}, {185, 271} };
    #elif (F_PLL==96000000)
      const tmclk clkArr[numfreqs] = {{8, 375}, {73, 2483}, {16, 375}, {147, 2500}, {32, 375}, {147, 1250}, {2, 17}, {16, 125}, {147, 625}, {4, 17}, {32, 125}, {151, 321}, {8, 17}, {64, 125} };
    #elif (F_PLL==120000000)
      const tmclk clkArr[numfreqs] = {{32, 1875}, {89, 3784}, {64, 1875}, {147, 3125}, {128, 1875}, {205, 2179}, {8, 85}, {64, 625}, {89, 473}, {16, 85}, {128, 625}, {178, 473}, {32, 85}, {145, 354} };
    #elif (F_PLL==144000000)
      const tmclk clkArr[numfreqs] = {{16, 1125}, {49, 2500}, {32, 1125}, {49, 1250}, {64, 1125}, {49, 625}, {4, 51}, {32, 375}, {98, 625}, {8, 51}, {64, 375}, {196, 625}, {16, 51}, {128, 375} };
    #elif (F_PLL==180000000)
      const tmclk clkArr[numfreqs] = {{46, 4043}, {49, 3125}, {73, 3208}, {98, 3125}, {183, 4021}, {196, 3125}, {16, 255}, {128, 1875}, {107, 853}, {32, 255}, {219, 1604}, {214, 853}, {64, 255}, {219, 802} };
    #elif (F_PLL==192000000)
      const tmclk clkArr[numfreqs] = {{4, 375}, {37, 2517}, {8, 375}, {73, 2483}, {16, 375}, {147, 2500}, {1, 17}, {8, 125}, {147, 1250}, {2, 17}, {16, 125}, {147, 625}, {4, 17}, {32, 125} };
    #elif (F_PLL==216000000)
      const tmclk clkArr[numfreqs] = {{32, 3375}, {49, 3750}, {64, 3375}, {49, 1875}, {128, 3375}, {98, 1875}, {8, 153}, {64, 1125}, {196, 1875}, {16, 153}, {128, 1125}, {226, 1081}, {32, 153}, {147, 646} };
    #elif (F_PLL==240000000)
      const tmclk clkArr[numfreqs] = {{16, 1875}, {29, 2466}, {32, 1875}, {89, 3784}, {64, 1875}, {147, 3125}, {4, 85}, {32, 625}, {205, 2179}, {8, 85}, {64, 625}, {89, 473}, {16, 85}, {128, 625} };
    #endif
    
      for (int f = 0; f < numfreqs; f++) {
        if ( freq == samplefreqs[f] ) {
          while (I2S0_MCR & I2S_MCR_DUF) ;
          I2S0_MDR = I2S_MDR_FRACT((clkArr[f].mult - 1)) | I2S_MDR_DIVIDE((clkArr[f].div - 1));
          return;
        }
      }
    }
    
    
    // GUItool: begin automatically generated code
    AudioInputI2S            i2s1;           //xy=250,232
    AudioOutputI2S           i2s2;           //xy=455,243
    AudioConnection          patchCord1(i2s1, 0, i2s2, 0);
    AudioConnection          patchCord2(i2s1, 1, i2s2, 1);
    // GUItool: end automatically generated code
    
    AudioControlSGTL5000 sgtl5000_1;
    
    const int samplefreq = 8000;
      
    void setup() {
      Serial.begin(9600);
      AudioMemory(8);
      sgtl5000_1.enable();
      sgtl5000_1.volume(0.5);
      sgtl5000_1.inputSelect(AUDIO_INPUT_MIC);
      sgtl5000_1.micGain(36);
      setI2SFreq(samplefreq);
    }
    
    void loop() {}
    Last edited by Frank B; 10-31-2016 at 10:36 AM.

  23. #23
    Senior Member
    Join Date
    Nov 2012
    Posts
    1,166
    I've got a simple bandpass filter working at a sampling rate of 8000Hz but the audio quality is awful. When the audio is passed through unfiltered it sounds fine. When I switch in the filter, the filtering itself is obviously working but the audio quality is not good at all. I'll dig into what's going on with the filter. Maybe I haven't initialized it correctly or something like that.

    Pete

  24. #24
    Senior Member+ Frank B's Avatar
    Join Date
    Apr 2014
    Location
    Germany NRW
    Posts
    5,679
    But not a filter on the SGTL, right ?
    I guess, this will not work good.. we're lieing about the freq, so any filters on the SGTL can not work, with this simple patch. The SGTL still thinks, we're @ 44100 kHz

    For parts in the audio-lib, you' need to lie too (like in my sine-example above) :

    waveform1.frequency(AUDIO_SAMPLE_RATE_EXACT/samplefreq*freq);

  25. #25
    Senior Member
    Join Date
    Nov 2012
    Posts
    1,166
    Got it. As I thought. A bug. I hadn't specified the correct buffer size at one point. With the correct buffer size, the filter now works as expected.
    Fabulous. Well done Frank.

    Pete

Posting Permissions

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