Skip to content

Firmware library: variable playback rate for teensy audio library

License

Notifications You must be signed in to change notification settings

newdigate/teensy-variable-playback

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

variable rate playback for teensy audio library

Teensy 4.1 lib-teensy41 Ubuntu-x64 MIT license CMake made-for-VSCode Contributors Commits s

play 16-bit PCM raw or wav audio samples at variable playback rates on teensy

  • Note : this library only works with signed 16-bit integer samples. Floating point samples will not play.

  • for best performance, use SDXC UHS 30MB/sec Application Performance Class 2 (A2) class micro sd-card.

updates

  • 26/02/2022: v1.0.16:
    • add option for starting sample at begining or at loop start
    typedef enum play_start {
        play_start_sample,
        play_start_loop,
    };
    
    wave.setPlayStart(play_start::play_start_loop); 
  • 26/02/2022: v1.0.15:
    • added support for dual playback head for seemless looping
      • enable dual playback using linear crossfading
      • set crossfade duration in number of samples
          AudioPlaySdResmp         wave;      
          wave.setUseDualPlaybackHead(true);
          wave.setCrossfadeDurationInSamples(1000);
          wave.playRaw((int16_t*)kick_raw, kick_raw_len / 2, numberOfChannels);
          wave.setLoopStart(0); 
          wave.setLoopFinish(3000);
  • 16/06/2022: v1.0.14:
    • refactored code to generic classes
    • improve memory leaks
    • remove calls to StartUsingSPI(), StopUsingSPI(), __disable_irq(), __enable_irq()
    • intergated with SerialFlash and LittleFS
  • 25/09/2021: v1.0.13: positionMillis() implemented for AudioPlaySdResmp
  • 25/08/2021: v1.0.12: Skip over RIFF tags in .wav header
  • 12/08/2021: v1.0.11: When playing a mono sample, transmit on both channels (credit to @atoktoto)
  • 28/07/2021: v1.0.10: Fix issues when starting playback in reverse
  • 23/07/2021: v1.0.9: Fix issue which crashes teensy when playing multiple files from SD card using array of filenames
  • 21/07/2021: v1.0.8: Breaking changes
    • AudioPlaySdRawResmp and AudioPlaySdWaveResmp merged into a single class AudioPlaySdResmp
    • play(...) method changed to playRaw(...) and playWav(...), specify number of channels in parameters of playRaw
  • 13/07/2021: v1.0.7: added multi-channel resampling
  • 07/07/2021: v1.0.6: changed to using optimised floating point interpolation, sounds much better
  • 30/06/2021: v1.0.5: Optimised quadratic interpolation to use fixed pipeline of 4 samples and use integers instead of floating point
  • 25/06/2021: Quadratic interpolation is now working, but is disabled by default

contents

code structure

folder target description
examples teensy basic example how to use
extras linux some utils to make life easier
src teensy / linux extends teensy audio library
* adds AudioPlaySdResmp
* adds AudioPlayArrayResmp
test linux unit tests that run on linux

requirements

teensy 3.x & 4.x boards
with Teensyduino

Teensyduino^

  • This library is built on top of teensy audio library, intended for use with Teensy 3.x and Teensy 4.x boards.
  • Install using arduino/teensyduino library manager gui - search TeensyVariablePlayback
    • install using arduino library manager
without Teensyduino (for development)

cmake gcc-arm-none-eabi^ teensy-cmake-macros^ cores^ Audio^ SD^ Wire^ SPI^ SerialFlash^ arm_math^ SDFat^

  • using teensy-cmake-macros, this library can be compiled for teensy 3 and 4 boards without needing Teensyduino. This is mainly used to build the library when a commit is pushed, to verify there are no compile errors.
dependencies (click to expand image)

dependencies

graphvis (click to expand)
graph G {
  graph[rankdir="LR"]
  "teensy variable playback" -- "teensy-cmake-macros" -- "cmake" [label="dev"]
  "teensy-cmake-macros" -- "arm-none-eabi-gcc"  [label="dev"]
  "PaulStoffregen/Audio.git" -- "PaulStoffregen/cores.git"
  "teensy variable playback" -- "PaulStoffregen/Audio.git"
  "PaulStoffregen/Audio.git" -- "PaulStoffregen/SD.git@Juse_Use_SdFat"
  "PaulStoffregen/SD.git@Juse_Use_SdFat" -- "PaulStoffregen/SPI.git"
  "PaulStoffregen/SD.git@Juse_Use_SdFat" -- "greiman/SdFat.git"
  "PaulStoffregen/Audio.git" -- "PaulStoffregen/Wire.git"
  "PaulStoffregen/Audio.git" -- "PaulStoffregen/SerialFlash.git"
  "PaulStoffregen/Audio.git" -- "PaulStoffregen/arm_math.git"
}
linux You can run and test this code on your linux computer. You can write a teensy sketch, and with a few modifications, you can redirect the audio input and output to and from your soundcard. [Soundio](https://github.com/newdigate/teensy-audio-x86-stubs/tree/main/extras/soundio) bindings are optional, you can also run sketches and tests with no audio input or output. You will need to install the following libraries.

cmake gcc or llvm teensy-x86-stubs^ teensy-audio-x86-stubs^ teensy-x86-sd-stubs^ boost-test

  • install boost unit-test library:
    • linux: sudo apt-get install -yq libboost-test-dev
    • macos: brew install boost

usage

Using with Teensyduino
  • To install the library, use the library manager in Teensyduino (search for TeensyVariablePlayback). Teensyduino should already have all the necessary dependencies pre-installed.

  • Have a look at the examples in the file menu to get started...

Developing with vscode

clone repo

> git clone https://github.com/newdigate/teensy-variable-playback.git
> cd teensy-variable-playback

teensy build

You don't need to download or install Teensyduino or Arduino to build the library or examples. Just clone the cores library and any dependencies to a common folder, denoted by DEPSPATH (in this case /home/nic/teensy_libraries).

clone dependencies (click to expand)
 > cd /home/nic/teensy_libraries
 > git clone https://github.com/PaulStoffregen/cores.git
 > git clone https://github.com/PaulStoffregen/Audio.git
 > git clone -b Juse_Use_SdFat https://github.com/PaulStoffregen/SD.git 
 > git clone https://github.com/PaulStoffregen/Wire.git
 > git clone https://github.com/PaulStoffregen/SPI.git
 > git clone https://github.com/PaulStoffregen/SerialFlash.git
 > git clone https://github.com/PaulStoffregen/arm_math.git
 > git clone https://github.com/greiman/SdFat.git
update COMPILERPATH and DEPSPATH in cmake/toolchains/teensy41.cmake
set(COMPILERPATH "/Applications/Arm/bin/")
set(DEPSPATH "/home/nic/teensy_libraries")
set(COREPATH "${DEPSPATH}/cores/teensy4/")
build hex file
  • If you run the commands below from the root repository directory, it will build the teensy-variable-playback library and all the examples.
  • If you run them from a sub-directory, it will build everything under the sub-directory. (You might need to adjust relative path in -DCMAKE_TOOLCHAIN_FILE:FILEPATH below)
> cd /home/nic/teensy-variable-playback
> mkdir cmake-build-debug
> cd cmake-build-debug
> cmake -DCMAKE_BUILD_TYPE=Debug -DCMAKE_TOOLCHAIN_FILE:FILEPATH="../cmake/toolchains/teensy41.cmake" ..
> make

linux build

build tests on linux

> ./build-linux.sh

build tests on win

> mkdir cmake-build-debug
> cd cmake-build-debug
> cmake -DCMAKE_BUILD_TYPE=Debug -DCMAKE_TOOLCHAIN_FILE:FILEPATH="../cmake/toolchains/linux.cmake" ..
> make

run tests

> cmake-build-debug/test/test_suite1

visual studio code

  • download vs code
    • required extensions
      • ms-vscode.cpptools
    • optional extensions
      • ms-vscode.cmake-tools
      • hbenl.vscode-test-explorer
      • ms-vscode.test-adapter-converter
      • nicnewdigate.boost-test-adapter-debug
  • open root folder of repository in visual studio code
  • open terminal in visual studio code build, build as above
  • (add breakpoint)
  • launch

example usage

example (click to expand)
#include <Arduino.h>
#include <Audio.h>
#include <TeensyVariablePlayback.h>

// GUItool: begin automatically generated code
AudioPlayArrayResmp      rraw_a1;        //xy=321,513
AudioOutputI2S           i2s1;           //xy=675,518
AudioConnection          patchCord1(rraw_a1, 0, i2s1, 0);
AudioConnection          patchCord2(rraw_a1, 0, i2s1, 1);
AudioControlSGTL5000     sgtl5000_1;     //xy=521,588
// GUItool: end automatically generated code

unsigned char kick_raw[] = {
  // ... little-endian 16-bit mono 44100 raw data, generated using linux cmd 'xxd -i kick.raw', raw file saved in Audacity
  0x99, 0x02, 0xd7, 0x02, 0xfa, 0x02, 0x5f, 0x03, 0xc1, 0x03, 0x2a, 0x04,
  0xad, 0x04, 0xa5, 0x05, 0x76, 0x06, 0x2f, 0x07, 0x9e, 0x07, 0xe2, 0x07,
  0x43, 0x08, 0x92, 0x08, 0xb2, 0x08, 0xe8, 0x08, 0x16, 0x09, 0xda, 0x08,
  // ... continued ... 
};
unsigned int kick_raw_len = 6350; // length in bytes == numsamples * 2

void setup() {
    AudioMemory(20);
    sgtl5000_1.enable();
    sgtl5000_1.volume(0.5f, 0.5f);
    rraw_a1.setPlaybackRate(0.5);
    rraw_a1.enableInterpolation(true);  
}

void loop() {
    if (!rraw_a1.isPlaying()) {
        delay(1000);
        rraw_a1.playRaw((int16_t *)kick_raw, kick_raw_len/2, 1);  //note: we give number of samples - NOT number of bytes!!!! 1 is for mono (2 for stereo, etc)
    }
}

credits

  • convert boost test report to junit xml format: Stuart Lange