Skip to content

Instantly share code, notes, and snippets.

@newdigate
Created November 28, 2023 20:51
Show Gist options
  • Save newdigate/a93d0b90d6e0c11b8b43b230f6b20f9f to your computer and use it in GitHub Desktop.
Save newdigate/a93d0b90d6e0c11b8b43b230f6b20f9f to your computer and use it in GitHub Desktop.
teensy - psram and sd card playing using AudioPlayMemory and custom loader
  • must be MONO .RAW 44100 PCM signed 16bit int
  • much more stable than teensy variable playback, but no pitch control for now
/* Audio Library for Teensy
* Copyright (c) 2021, Nic Newdigate
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "flashloader.h"
namespace newdigate {
audiosample * flashloader::loadSample(const char *filename ) {
Serial.printf("Reading %s\n", filename);
//unsigned s = ((-_lastPointer-4) % 512);
//Serial.printf("Align size: %x\n", s);
//auto* align = (unsigned*)extmem_malloc (s);
File f = SD.open(filename, O_READ);
if (f) {
uint64_t size = f.size();
uint mod = size % 512;
size = size + mod;
if (f.size() < _bytesavailable) {
noInterrupts();
uint32_t total_read = 0;
auto *data = (uint32_t*)extmem_malloc( size + 4);
//_lastPointer = (uint32_t)data;
memset(data, 0, size + 4);
data[0] = (0x81 << 24) | (size / 2); // format == 01 PCM
int8_t *index = (int8_t*)data + 4;
while (f.available()) {
size_t bytesRead = f.read(index, flashloader_default_sd_buffersize);
if (bytesRead == -1)
break;
total_read += bytesRead;
index += bytesRead;
}
//memset(index, 0, mod);
interrupts();
_bytesavailable -= total_read;
audiosample *sample = new audiosample();
sample->sampledata = (int16_t*)data;
sample->samplesize = f.size();
Serial.printf("\tsample start %x\n", (uint32_t)data);
Serial.printf("\tsample size %d\n", sample->samplesize);
Serial.printf("\tavailable: %d\n", _bytesavailable);
return sample;
}
}
Serial.printf("not found %s\n", filename);
return nullptr;
}
}
/* Audio Library for Teensy
* Copyright (c) 2021, Nic Newdigate
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef TEENSY_SAMPLE_FLASHLOADER_FLASHLOADER_H
#define TEENSY_SAMPLE_FLASHLOADER_FLASHLOADER_H
#include <Arduino.h>
#include <SD.h>
extern "C" uint8_t external_psram_size;
namespace newdigate {
const uint32_t flashloader_default_sd_buffersize = 4 * 1024;
struct audiosample {
int16_t *sampledata;
uint32_t samplesize;
};
class flashloader {
public:
flashloader() {
_bytesavailable = external_psram_size * 1048576;
_lastPointer = 0x0A;
}
uint32_t _bytesavailable=0;
//uint32_t _lastPointer;
audiosample * loadSample(const char *filename );
};
};
#endif
#include <Audio.h>
#include <Wire.h>
#include <SPI.h>
#include <SD.h>
#include <SerialFlash.h>
#include <TeensyVariablePlayback.h>
#include "flashloader.h"
AudioPlayMemory rraw_a1; //xy=321,513
AudioPlaySdWav playSdWav1; //xy=308,257
AudioMixer4 mixer2; //xy=559,330
AudioMixer4 mixer1; //xy=573,235
AudioOutputI2S i2s1; //xy=764,272
AudioConnection patchCord01(rraw_a1, 0, mixer1, 1);
AudioConnection patchCord02(rraw_a1, 1, mixer2, 1);
AudioConnection patchCord03(playSdWav1, 0, mixer1, 0);
AudioConnection patchCord04(playSdWav1, 1, mixer2, 0);
AudioConnection patchCord05(mixer2, 0, i2s1, 1);
AudioConnection patchCord06(mixer1, 0, i2s1, 0);
AudioControlSGTL5000 sgtl5000_1; //xy=562,394
// GUItool: end automatically generated code
newdigate::audiosample *sample;
void setup() {
Serial.begin(115200);
if(CrashReport) {
Serial.print(CrashReport);
while(1); // stop if crashed, but you don't have to
}
if (!(SD.begin(BUILTIN_SDCARD))) {
while (1) {
Serial.println("Unable to access the SD card");
delay(500);
}
}
mixer1.gain(0, 0.25);
mixer2.gain(0, 0.25);
mixer1.gain(1, 0.75);
mixer2.gain(1, 0.75);
mixer1.gain(2, 0.50);
mixer2.gain(2, 0.50);
mixer1.gain(3, 0.75);
mixer2.gain(3, 0.75);
Serial.println("loading sample BASS0138.raw (BSS138M) to psram...");
newdigate::flashloader loader;
//sample = loader.loadSample("BASS0138.RAW");
sample = loader.loadSample("BSS138M.RAW");
delay(100);
AudioMemory(32);
sgtl5000_1.enable();
sgtl5000_1.volume(0.5);
}
void loop() {
if (playSdWav1.isPlaying() == false) {
Serial.println("Start playing 1");
if (playSdWav1.play("TEST.wav")) {
Serial.println("success...");
}
delay(10); // wait for library to parse WAV info
}
if (rraw_a1.isPlaying() == false) {
Serial.println("Start playing 2");
rraw_a1.play((const unsigned*)sample->sampledata);
delay(10); // wait for library to parse WAV info
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment