Skip to content

File main.cpp

File List > examples > WavWriter_Realtime > main.cpp

Go to the documentation of this file

Source Code

#include "daisy_seed.h"
#include <cmath>

using namespace daisy;

static constexpr const float    kTargetSr          = 48000.f;
static constexpr const size_t   kTransferSize      = 16384;
static constexpr const size_t   kFileDurationSamps = 96000; //< 2s @ 48kHz
static constexpr const uint32_t kStartupDelayMs    = 2000;

template <int freq>
struct SimpleOsc
{
    static constexpr float kTargetFreq = static_cast<float>(freq);
    static constexpr float kSignalIncrement
        = (M_TWOPI * kTargetFreq) * (1.f / kTargetSr);
    float phs_;
    SimpleOsc() : phs_(0.f) {}

    inline float RenderSample()
    {
        float signal = sin(phs_) * 0.5f;
        phs_ += kSignalIncrement;
        if(phs_ > M_TWOPI)
            phs_ -= M_TWOPI;
        return signal;
    }
};

enum class State
{
    Startup,
    Recording,
    Finalize,
    Done,
};

DaisySeed      hw;
SdmmcHandler   sdmmc;
FatFSInterface fsi;

WavWriter<kTransferSize> wav_writer;
State                    state = State::Startup;
SimpleOsc<220>           osc1;
SimpleOsc<330>           osc2;
size_t                   duration_counter = 0;

void AudioCallback(AudioHandle::InputBuffer  in,
                   AudioHandle::OutputBuffer out,
                   size_t                    size)
{
    switch(state)
    {
        case State::Recording:
            for(size_t i = 0; i < size; i++)
            {
                float samples[2] = {
                    osc1.RenderSample(),
                    osc2.RenderSample(),
                };
                wav_writer.Sample(samples);
                duration_counter++;
                if(duration_counter > kFileDurationSamps)
                {
                    state = State::Finalize;
                }
                out[0][i] = samples[0];
                out[1][i] = samples[1];
            }
            break;
        default:
            std::fill(out[0], out[0] + size, 0.f);
            std::fill(out[1], out[1] + size, 0.f);
            break;
    }
}


int main(void)
{
    hw.Init();
    state = State::Startup;

    SdmmcHandler::Config sd_cfg;
    sd_cfg.Defaults();
    sd_cfg.width = SdmmcHandler::BusWidth::BITS_1;
    sdmmc.Init(sd_cfg);
    FatFSInterface::Config fsi_cfg;
    fsi_cfg.media = FatFSInterface::Config::MEDIA_SD;
    fsi.Init(fsi_cfg);
    if(f_mount(&fsi.GetSDFileSystem(), "/", 0) != FR_OK)
    {
        while(1)
        {
            hw.SetLed((System::GetNow() & 127) > 63);
        }
    }

    WavWriter<kTransferSize>::Config cfg;
    cfg.bitspersample = 16;
    cfg.channels      = 2;
    cfg.samplerate    = kTargetSr;
    wav_writer.Init(cfg);


    hw.StartAudio(AudioCallback);


    uint32_t startup_time = System::GetNow();


    while(1)
    {
        auto now = daisy::System::GetNow();

        switch(state)
        {
            case State::Startup:
                if(now - startup_time > kStartupDelayMs)
                {
                    wav_writer.OpenFile("RealtimeWavFile.wav");
                    state = State::Recording;
                }
                // LED is solid during startup
                hw.SetLed(true);
                break;
            case State::Recording:
                // Check status of WAV file writing, and manage Disk I/O.
                // Audio callback will convert state to Finalize when it has
                // written the duration of files.
                wav_writer.Write();

                // Blink fast during recording:
                hw.SetLed((System::GetNow() & 127) > 63);
                break;
            case State::Finalize:
                // After the file is complete, we flush any remaining samples, and
                // update the WAV headers, etc.
                wav_writer.SaveFile();
                state = State::Done;
                // No LED activity for this state because its a blocking operation,
                // and should complete pretty quickly.
                break;
            case State::Done:
                // Blink Slowly to show success
                hw.SetLed((System::GetNow() & 1023) > 511);
                break;
        }
    }
}