using the eeprom for audio sample memory + Audio Library (playQueue Vs audio object)

Status
Not open for further replies.

martianredskies

Well-known member
I'm very new to the audio library, to help me get familiar i wanted to give myself a basic project. I wrote a small program that writes a 8-bit random number (0-255) to the onboard 4kb eeprom on startup.
the audio is sent through the playQueue object to a mixer in the audio library then out the USB Audio port. Typing "p" into the serial monitor will read out the sample data from address 0 to address 4095.

It works, but because i'm just playing back noise I'm not sure if i have scaled everything right. There are a lot of holes in what i understand about the playQueue object;

1. getBuffer() is supposed to point to a int16_t char*. Does that mean that full scale integer audio should be +/- 32,768?. In my example the numbers in the eeprom only are 8-bit (0-255). Does that need to be scaled to +/- 32k?
2. how difficult would it be to modify an audio object to avoid using the playQueue object to achieve the same result below?
3. any mistakes i'm doing below in relation to PlayQueue?

Thanks in advance


Code:
#include <EEPROM.h>

#include <MIDI.h>
#include <midi_UsbTransport.h>
#include <Audio.h>
#include <Wire.h>
#include <SPI.h>
#include <SD.h>
#include <SerialFlash.h>

// GUItool: begin automatically generated code
AudioPlayQueue           queue1;         //xy=295.1999969482422,762.4000244140625
AudioSynthNoiseWhite     noise1;         //xy=298.1999969482422,721.4000244140625
AudioMixer4              mixer1;         //xy=435,740
AudioOutputUSB           usb1;           //xy=558.2000122070312,738.4000244140625
AudioOutputAnalog        dac1;           //xy=576,658
AudioConnection          patchCord1(queue1, 0, mixer1, 1);
AudioConnection          patchCord2(noise1, 0, mixer1, 0);
AudioConnection          patchCord3(mixer1, 0, usb1, 0);
AudioConnection          patchCord4(mixer1, 0, usb1, 1);
AudioConnection          patchCord5(mixer1, dac1);
// GUItool: end automatically generated code




/** the current address in the EEPROM (i.e. which byte we're going to write to next) **/
uint16_t eeprom_length;
uint8_t randNumber;
uint8_t incomingByte;

char pcmBuffer[128];

void setup() {

  Serial.begin(9600);
  while (!Serial) {
    ; // wait for serial port to connect. Needed for Leonardo only
  }

  AudioMemory(196);
  noise1.amplitude(1);

  mixer1.gain(0, 0);
  mixer1.gain(1, 1);
  mixer1.gain(2, 0);
  mixer1.gain(3, 0);

  eeprom_length = EEPROM.length();
  Serial.printf("length of onboard eeprom is > %d bytes\n\n", eeprom_length);

  // write a random number from 0 to 255 (8-bit) to eeprom
  for (int i = 0; i < eeprom_length; i++) {
    randNumber = random(256); //8-bit

    Serial.printf("writing value %d to eeprom address > %d\n", randNumber, i);
    delayMicroseconds(22);
  }

  Serial.printf("\npress <p> to playback eeprom array\n");

}

void loop() {
  if (Serial.available() > 0) {
    // read the incoming byte:
    incomingByte = Serial.read();
    if (incomingByte == 'p') {

      uint8_t bufferCount = 0;

      for (uint16_t i = 0; i < eeprom_length; i++) {
        pcmBuffer[bufferCount] = EEPROM.read(i);
        bufferCount++;
        if (bufferCount > 127) {
          bufferCount = 0;
          int16_t *audioBuffer = queue1.getBuffer();
          if (audioBuffer != NULL) {
            // Copy the raw PCM audio data into the audio buffer.
            memcpy(audioBuffer, pcmBuffer, 128);
            // play buffer out usb
            queue1.playBuffer();
          }
        }
      }

      Serial.printf("\ntype <p> & hit <enter> to playback eeprom array\ndigits 0-9 <enter> sets volume of PlayQueueBuffer\n");
    }

    if (isDigit(incomingByte)) {
      incomingByte = incomingByte - '0'; //convert ascii digit to int
      mixer1.gain(1, float(incomingByte * .1));
      Serial.println(incomingByte);
    }
  }

}
 
I figured it out, i was able to learn from the code posted here https://gitlab.cs.washington.edu/kg...abde5d4/SoundBrainTeensy/SoundBrainTeensy.ino

I ended up loading a 4096byte 8bit clap sample (stored on SD) into the eeprom using the code below. From there it was easy to identify problems due to incorrect integer scaling Vs my previous noise sample.

Code:
eeprom_length = EEPROM.length();
  Serial.printf("length of onboard eeprom is > %d bytes\n\n", eeprom_length);

  if (!myFileIn.open("clap8.pcm", O_READ)) {
    Serial.printf("\nunable to open clap8.pcm for reading.");
    return;
  }

  uint8_t tmp;
  uint16_t counter = 0;

  while (myFileIn.available()) { // read from the file until there's nothing else in it:
    tmp = myFileIn.read();
    EEPROM.write(counter, tmp);
    counter++;
  }

  myFileIn.close();

To answer a few of my own questions;

1. Yes the integer audio needs to be scaled from "unsigned 8-bit" to "signed 16-bit". Easy enough to accomplish by multiplying the 8-bit eeprom value by * 257 and subtracting 32768. That'll give a range of +/-32767 for audio play queue.

I'm not sure how to match the samplerate, a 22,050khz sample will play twice the speed at 44,100khz. I guess you could repeat each value when writing to the audio buffer? That would only work for prfect divisions of 44,100 thoough.
 
Status
Not open for further replies.
Back
Top