Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update WavPlayer to work with Daisy Patch with new libraries #266

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions patch_sm/WavPlayer/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# Project Name
TARGET = WavPlayer

# Sources
CPP_SOURCES = WavPlayer.cpp

# Library Locations
LIBDAISY_DIR = ../../libDaisy
DAISYSP_DIR = ../../DaisySP

# Includes FatFS source files within project.
USE_FATFS = 1

# Core location, and generic makefile.
SYSTEM_FILES_DIR = $(LIBDAISY_DIR)/core
include $(SYSTEM_FILES_DIR)/Makefile

163 changes: 163 additions & 0 deletions patch_sm/WavPlayer/WavPlayer.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
// # WavPlayer
// ## Description
// Fairly simply sample player.
// Loads the first file it encounters on the SD card ( probably with alphabetic sort ).
//
// Play .wav file from the SD Card.
//
// ozh Feb 2022 - port to Patch_sm hardware, specifically the Patch.init() Eurorack module
// Controls:
// Toggle switch will 1) start playing the selected .WAV file
// 2) control whether the file loops at its end
// Push button will restart playing the sample (upon release of the button).
// Gate 1 input will restart playing the sample (upon the rising edge of the gate).
//
// limitations: no file selection mechanism. Only the first file (ASCII name order) will be played.
//
// TODO:
// use a knob to select between (upto) 16 (mono 48kHz) .WAV files on the SD card (refernce USE_ENCODER code)

#include <stdio.h>
#include <string.h>

#include "daisy_patch_sm.h"

using namespace daisy;
using namespace patch_sm;

DaisyPatchSM hw;

SdmmcHandler sdcard;
FatFSInterface fsi;
WavPlayer sampler;

/** Switch objects */
Switch toggle; // toggle switch
Switch button; // push button

// switch off encoder because the Patch.init() does not have one
#ifndef USE_ENCODER
//#define USE_ENCODER
#endif
static bool gate_state = false, prev_gate_state = false;

void AudioCallback(AudioHandle::InterleavingInputBuffer in,
AudioHandle::InterleavingOutputBuffer out,
size_t size)
{
#ifdef USE_ENCODER
int32_t inc;
#endif

// Debounce digital controls
hw.ProcessDigitalControls();

// no encoder on Patch_sm, so none of this encoder code applies
// ozh - only the first file encountered on the SD card will be played.
#ifdef USE_ENCODER
// Change file with encoder.
inc = hw.encoder.Increment();
if(inc > 0)
{
size_t curfile;
curfile = sampler.GetCurrentFile();
if(curfile < sampler.GetNumberFiles() - 1)
{
sampler.Open(curfile + 1);
}
}
else if(inc < 0)
{
size_t curfile;
curfile = sampler.GetCurrentFile();
if(curfile > 0)
{
sampler.Open(curfile - 1);
}
}
#endif // USE_ENCODER

#define AUDIO_CHANNELS 2
for(size_t i = 0; i < size; i += AUDIO_CHANNELS)
{
out[i] = out[i + 1] = s162f(sampler.Stream()) * 0.5f;
}
}


int main(void)
{
// Init hardware
size_t blocksize = 4; // could make this 4 or 48, not critical here,
// cuz callback is very lightweight relative to the SD card read ( .Prepare() ) in the "while" loop below

hw.Init();

/* Initialize the switch
- We'll read the switch on pin B8
*/

static bool state, prev_state;
toggle.Init(hw.B8);

/* Initialize the switch
- We'll read the switch on pin B7
*/
button.Init(hw.B7);

SdmmcHandler::Config sd_cfg;
sd_cfg.Defaults();
sd_cfg.speed = SdmmcHandler::Speed::MEDIUM_SLOW; //MEDIUM_SLOW; SLOW;// OZH set it to slower speed for debugging
sdcard.Init(sd_cfg);
fsi.Init(FatFSInterface::Config::MEDIA_SD);
f_mount(&fsi.GetSDFileSystem(), "/", 1);

sampler.Init(fsi.GetSDPath());
sampler.SetLooping(false); // set to false to play just once

// SET LED to indicate Looping status. // ozh this works to show Looping status on the "boot" led on the Daisy Seed
hw.SetLed(sampler.GetLooping());

// Init Audio
hw.SetAudioBlockSize(blocksize);
hw.StartAudio(AudioCallback);

// Loop forever...
for(;;)
{
// Prepare buffers for sampler as needed
sampler.Prepare();

/** Debounce the button */
button.Debounce();
if(button.FallingEdge())
{
sampler.Restart();
}
else
{
// detect Rising Edge
prev_gate_state = gate_state;
gate_state = hw.gate_in_1.State();
/** Get the current gate in state */
if((gate_state)
&& (gate_state != prev_gate_state)) // gate is high, prev was low
{
sampler.Restart();
}
}
/** Debounce the switch */
toggle.Debounce();

/** Get the current toggle state */
prev_state = state; // see if it changed
state = toggle.Pressed(); // flipped up

if(state != prev_state)
{ // toggle detected
sampler.SetLooping(state); // loops if Patch.init() toggle switch is up
/** Set the onboard led to the current state */
hw.SetLed(state);
}
}
}
90 changes: 83 additions & 7 deletions seed/WavPlayer/WavPlayer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,26 +7,71 @@
//
#include <stdio.h>
#include <string.h>
#include "daisy_pod.h"
//#include "daisy_patch.h"

// switch between Patch and Pod - the encoders are different
#ifndef USE_PATCH
#define USE_PATCH
#endif // USE_PATCH
#ifndef USE_PATCH_SM
//#define USE_PATCH_SM
// Patch_sm is like the POD in its Audio (2 channel) and lack of OLED display
// unlike the POD, it has no encoder, so we would have to use other controls like a knob and a pushbutton
#endif // USE_PATCH_SM

#ifdef USE_PATCH
#include "daisy_patch.h"
#else
#ifdef USE_PATCH_SM
#include "daisy_patch_sm.h"
#else
#include "daisy_pod.h"
#endif //USE_PATCH_SM
#endif // USE_PATCH

using namespace daisy;
#ifdef USE_PATCH_SM
using namespace patch_sm;
#endif //USE_PATCH_SM

#ifdef USE_PATCH
DaisyPatch hw;
#else
#ifdef USE_PATCH_SM
DaisyPatchSM hw;
#else
DaisyPod hw;
#endif //USE_PATCH_SM
#endif // USE_PATCH

//DaisyPatch hw;
DaisyPod hw;
SdmmcHandler sdcard;
FatFSInterface fsi;
WavPlayer sampler;

#ifdef USE_PATCH
void AudioCallback(AudioHandle::InputBuffer in,
AudioHandle::OutputBuffer out,
size_t size)
#else // Pod and Patch_sm
void AudioCallback(AudioHandle::InterleavingInputBuffer in,
AudioHandle::InterleavingOutputBuffer out,
size_t size)
#endif // USE_PATCH
{
int32_t inc;

// Debounce digital controls
hw.ProcessDigitalControls();

// turn the encoder support on and off, for debugging

#ifndef USE_PATCH_SM
// no encoder on Patch_sm
#ifndef USE_ENCODER
#define USE_ENCODER
#endif // USE_ENCODER
#endif // USE_PATCH_SM

#ifdef USE_ENCODER
// Change file with encoder.
inc = hw.encoder.Increment();
if(inc > 0)
Expand All @@ -47,6 +92,7 @@ void AudioCallback(AudioHandle::InterleavingInputBuffer in,
sampler.Open(curfile - 1);
}
}
#endif // USE_ENCODER

// if(hw.button1.RisingEdge())
// {
Expand All @@ -56,14 +102,28 @@ void AudioCallback(AudioHandle::InterleavingInputBuffer in,
// if(hw.button2.RisingEdge())
// {
// sampler.SetLooping(!sampler.GetLooping());
// ozh - the DaisyPatch::LED_2_B is a reference for the pre-OLED prototype of the Daisy
// 2/23/2022 use hw.seed.SetLed(bool state); // this is tested below
// //hw.SetLed(DaisyPatch::LED_2_B, sampler.GetLooping());
// //dsy_gpio_write(&hw.leds[DaisyPatch::LED_2_B],
// // static_cast<uint8_t>(!sampler.GetLooping()));
// }

for(size_t i = 0; i < size; i += 2)
#ifdef USE_PATCH
// this is a little counter intuitive.
// We have a channel and an index eg out[CHNL][i]
// so, we don't need to move forward 2 for the index
#define AUDIO_CHANNELS 1
#else // Pod and Patch_sm
#define AUDIO_CHANNELS 2
#endif // USE_PATCH
for(size_t i = 0; i < size; i += AUDIO_CHANNELS)
{
#ifdef USE_PATCH
out[0][i] = out[1][i] = s162f(sampler.Stream()) * 0.5f;
#else // Pod and Patch_sm
out[i] = out[i + 1] = s162f(sampler.Stream()) * 0.5f;
#endif
}
}

Expand All @@ -72,23 +132,39 @@ int main(void)
{
// Init hardware
size_t blocksize = 4;
//ozh - chg blocksize to match Init blocksize in daisy_patch.cpp
//AudioHandle::Config cfg;
//cfg.blocksize = 48;
//cfg.samplerate = SaiHandle::Config::SampleRate::SAI_48KHZ;

hw.Init();
// hw.ClearLeds();
SdmmcHandler::Config sd_cfg;
sd_cfg.Defaults();
sd_cfg.speed = SdmmcHandler::Speed::MEDIUM_SLOW; //MEDIUM_SLOW; SLOW;// OZH set it to slower speed for debugging
sdcard.Init(sd_cfg);
fsi.Init(FatFSInterface::Config::MEDIA_SD);
f_mount(&fsi.GetSDFileSystem(), "/", 1);

sampler.Init(fsi.GetSDPath());
sampler.SetLooping(true);
// test only ozh
//sampler.SetLooping(false);

// SET LED to indicate Looping status.
//hw.SetLed(DaisyPatch::LED_2_B, sampler.GetLooping());
// SET LED to indicate Looping status. // ozh this works to show Looping status on the "boot" led on the Daisy Seed
// different syntax for ORed conditions
#ifdef USE_PATCH
hw.seed.SetLed(sampler.GetLooping());
#else
#ifdef USE_PATCH_SM
hw.SetLed(sampler.GetLooping());
#endif
#endif // USE_PATCH

// Init Audio
hw.SetAudioBlockSize(blocksize);
hw.StartAudio(AudioCallback);

// Loop forever...
for(;;)
{
Expand Down