Direct audio samples into Audio Library objects

Status
Not open for further replies.

Teenfor3

Well-known member
I can use the audio library to play sounds, waveforms etc and all works very well, but is there a way to directly input the samples from a sound array or waveform and play continuous at various speeds or data rates.
I can do similar using and interval timer to analogwrite(A14, data) each data sample and I hear the sound as a complete sound waveform all samples. but have no other functions from the library.??
When using the audio library, it uses DSP, phase accum. etc so all samples for the complete wave are not read for all frequencies of playing. eg to get 2x speed out half of the samples are read and values interpolated.
I was wondering how I could read the data in as input and the use the rest of the library functions, filters, mixer etc on the data once inputted.
 
Thanks for reply, I had looked at this, but basically I don't know how or cannot get the "getBuffer()" to look at the data, It compiles outputs just random noise.???
attached is my basic code after reading through the VideoSDcard example.

Code:
include <Audio.h>
//#include <Wire.h>
//#include <SPI.h>
//#include <SD.h>
//#include <SerialFlash.h>

//#include <OctoWS2811.h>

// GUItool: begin automatically generated code
AudioPlayQueue           audio;         //xy=270,355
AudioOutputAnalog        dac1;           //xy=645,351
AudioConnection          patchCord1(audio, dac1);
// GUItool: end automatically generated code


int16_t  samples[128] = {
0,
1'
2,
3'
up to
127.....(this is array of 128 values range -30000. 0. +30000)
};


void setup() {

   AudioMemory(40);
  // put your setup code here, to run once:

}

void loop() {
  // put your main code here, to run repeatedly:

          int16_t *p = audio.getBuffer();
         
          audio.playBuffer();
    
}
 
getBuffer returns NULL if a buffer isn't available. Try this:
Code:
          int16_t *p = audio.getBuffer();
         
          if(p)audio.playBuffer();

EDIT. AND you need to copy the samples into the buffer:

Code:
          int16_t *p = audio.getBuffer();
          
          if(p) {
            for(int i = 0;i < 128;i++) {
              *p++ = samples[i];
            }
            audio.playBuffer();
          }
Pete
 
I posted a (fairly) simple example of using readBuffer/freeBuffer and getBuffer/Playbuffer here which might help you. It simply reads the stereo input (MIC or LINEIN) and plays it back to the headphone output. If a button is pushed it switches the left and right channels.

Pete
 
Thanks for your fast response, I am replying to your post #4....That is magic it works perfectly...thats the basics, will need to play with it to get different rates of playing sorted etc and controlled by timers etc so as rate not affected by what else the processor is doing. I will take a look at your #5 post tomorrow. is there any good bedtime reading on this stuff.??? Thanks
 
Looked at your sketch for recording and playing queues. I think I understand what it does recording mic or linein in a queue for each channel and allowing it to be switched and played etc.
As I see it instead of recording I want to play an already recorded array at various rates to give me different frequency as the rate is changed. Does playBuffer always play at same rate 44100 as audio library or can it be changed on demand.?? I get the "for next loop" working OK and it plays the 128 sample wave perfect no glitches......
 
Last edited:
The default sample rate is 44100Hz. You can change that rate at startup but I don't think you can change it on the fly and AFAIK you can only change it to a small range of frequencies (e.g. 8kHz, 11025Hz, 48kHz).
I think what you're trying to do is pitch shifting which is a non-trivial problem.

Pete
 
Yes, it is probably pitch shifting. playing wave array at various freqs and mixing and filtering.
Code:
const int16_t tone1[256] = {
0,
628,
1256,

256 element array

-1884,
-1256,
-629
};





const int16_t tone2[256] = {
0,
20872,
25928,

256 element array

25583,
-25929,
-20872
};



    
// Create IntervalTimer objects 
IntervalTimer myTimer;
IntervalTimer myTimer2;
IntervalTimer myTimer3;


int16_t dat1 = 0;
int16_t dat2 = 0;
int16_t cpdat = 0;
int samp = 0;
int samp2 = 0;
int onoff = 0;
int freq = 3;
int freq2 = 3;

void setup() {
  
 analogWriteResolution(12);
 analogReference(INTERNAL);

}

void play1(){
  dat1 = ((tone1[samp]+30000)/20);  // stream 1st wave repeating
  samp = samp + 1;
  if (samp > 255) {
    samp = 0;
  }
  return;
}

void play2(){
  dat2 = ((tone2[samp2]+30000)/20);  // stream 2nd wave repeating
  samp2 = samp2 + 1;
  if (samp2 > 255) {
    samp2 = 0;
  }
  return;
}

void playout(){
  cpdat = ((dat1 + dat2)/2);  // mix both streamed samples
   analogWrite(A14, cpdat); //play out to DAC
  return;
}

 void Controlonoff() {
      
    if (onoff == 0 && freq >= 15)
       {
      myTimer.end();     // turn timers off 
      myTimer2.end();
      myTimer3.end();
       }
    
        delay(100);
        
    if (onoff == 1)
    {
      freq = freq + 1;       //start timers at new freq
      freq2 = freq2 + 1;
                
      myTimer.begin(play1, freq);  
      myTimer2.begin(play2, freq2);  
      myTimer3.begin(playout, 22.6756);  // output at 44100
   
 delay(200);
    
      freq = freq + 1;
      freq2 = freq2 + 1;             // timer period update to change freq
        myTimer.update(freq);
        myTimer2.update(freq2);
    if (freq >= 20) freq = 2;
    if (freq2 >= 20) freq2 = 5;
    }

 }


   void loop() {    // start of loop xxxxxxxxxxxxxxxxxxxxxx
           onoff = !onoff;
    delay(200);
    Controlonoff();
    }            // end of loop ........   xxxxxxxxxxxxxxxx

This is outline of what I had been trying. It plays the audio arrays and mixes them and ends up with playing out to DAC. I could probably send the output cpdat instead via a queue to the audio library....???... will maybe try that next few days...
 
Status
Not open for further replies.
Back
Top