electro-smith / libDaisy

Hardware Library for the Daisy Audio Platform
https://www.electro-smith.com/daisy
MIT License
331 stars 143 forks source link

WavPlayer - Add flexibility for channel count, sample rate, and bit depth #495

Open stephenhensley opened 2 years ago

stephenhensley commented 2 years ago

The existing module was built for mono, 16-bit audio files at 48kHz

It should be pretty easy to support the channels/bitdepth.

For sample rate we'll have to decide if we just playback at the system samplerate, or change playback speed to match the system samplerate.

Since this module is separate from the overall audio engine, I don't think that it should be able to change the system samplerate itself.

MarianoDesivo commented 2 years ago

For playing stereo files I simply changed, in the AudioCallBack(), this:

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

with this:

for(size_t i = 0; i < size; i += 2)
    {
        out[i]              = s162f(sampler.Stream()) * 0.5f;
        out[i + 1]          = s162f(sampler.Stream()) * 0.5f;
    }
MarianoDesivo commented 2 years ago

What about polyphony? Do I have to create more than one WavPlayer object and they will execute independently?

stephenhensley commented 2 years ago

That's a great question, how would you expect/prefer to work with polyphony?

It would certainly be possible to manage multiple instances of a single WavPlayer, or some sort of PolyWavPlayer object could be made that internally manages the polyphony.

MarianoDesivo commented 2 years ago

Well, in Max/MSP I made a sort of PolyHandler which was in charge of executing different "WavPlayer objects" depending of how many notes the user played. I think it will be more tidy to do a PolyWavPlayer that internally manages that

It would certainly be possible to manage multiple instances of a single WavPlayer

Great, I will check that by creating a second wavPlayer object. Do I need to add anything else?

Is there any documentation or something about that? Or how to calculate/estimate how many wavPlayers can the Daisy handle?

MarianoDesivo commented 2 years ago

I tried using two wavPlayer instances, but one interrupts the other. They can't play at the same time

MarianoDesivo commented 2 years ago

I have made a polyHandler for oscillators controlled by MIDI, when I finish getting to work the code to play wav files from SDRAM I will modify it to add a polyHandler like this

class poly
{
  public:
    poly() {
        osc.Init(samplerate);
        osc.SetWaveform(Oscillator::WAVE_POLYBLEP_SAW);
    }
    ~poly() {}
    static const int        polyMax = 6; //cantidad de samplers
    std::vector<Oscillator> samplers;    //vector de osciladores
    float                   samplerate = 48000;
    daisysp::Oscillator osc;

    void recibirNoteON(NoteOnEvent& p)
    {
        osc.SetFreq(mtof(p.note));
        osc.frecuencia = p.note;
        osc.SetAmp((p.velocity / 127.0f));
        //si no estan todos los samplers ocupados:
        if(samplers.size() < polyMax)
        {
            samplers.insert(samplers.begin(),osc); //agregar la nota a la izquierda (principio del vector)
        }
        else
        {                        //si estan todos ocupados
            samplers.pop_back(); //saco la ultima nota presionada (la que estuvo mas tiempo presionada)
            samplers.insert(samplers.begin(), osc); //agregar la nota a la izquierda (principio del vector)
        }
    }

    void recibirNoteOFF(NoteOffEvent& p)
    {
        //borro el oscillador del vector que tenga el mismo numero de nota que el noteOffEvent
        samplers.erase(std::remove_if(samplers.begin(),
                                      samplers.end(),
                                      [&p](Oscillator const& o)
                                      { return p.note == o.frecuencia; }),
                       samplers.end());
        //[&nota](Oscillator const& o) {return nota == o.noteCMD; };
    }

  private:
};

Declare a poly polyHandler; Then on AudioCallback:

void AudioCallback(AudioHandle::InterleavingInputBuffer  in,
                   AudioHandle::InterleavingOutputBuffer out,
                   size_t                                size)
{
    float sig=0;
    for(size_t i = 0; i < size; i += 2)
    {
        for (auto& oscilador : polyHandler.samplers) {
            sig += oscilador.Process();
        }
        sig /= (float)polyHandler.polyMax;
        filt.Process(sig);
        out[i] = out[i + 1] = filt.Low();
    }
}