How can I make multiple audio callbacks play simultaneously?

I am trying to call multiple AudioCallbacks simultaneously, but I can’t. I can only hear one of them. I think it can be due to the configuration of the output of each AudioCallback.
The idea is that each AudioCallback contains a different sound process and to be able to mix them later. How could I do this?

Here part of the code:

#include "daisy_seed.h" 
#include "daisysp.h" 
  
using namespace daisy;
using namespace daisysp;


DaisySeed  hardware;
Oscillator osc[32];

int bin[32];
float freq[32]; 

void Audio0Callback(float **in, float **out, size_t size)
{  
    for(size_t i = 0; i < size; i++)
    {  
         out[0][i] =  osc[0].Process();
         out[1][i] = osc[0].Process();
    }
}
void Audio1Callback(float **in, float **out, size_t size)
{  
    for(size_t i = 0; i < size; i++)
    {    
        out[0][i] =  osc[1].Process();
        out[1][i] = osc[1].Process();
    }
}
void Audio2Callback(float **in, float **out, size_t size)
{  
    for(size_t i = 0; i < size; i++)
    {    
        out[0][i] =  osc[2].Process();
        out[1][i] = osc[2].Process();
    }
}
void SetupOsc(float samplerate)
{
    for(int i = 0; i < 32; i++)
    {
        osc[i].Init(samplerate);
        osc[i].SetAmp(.7);
    }
}

void FreqOsc()
{
    for(int i = 0; i < 32; i++)
    {
        //NO FUNCIONAN!!  srand (time(NULL)); srand (getpid()); 
        freq[i] = 100.0 + rand() % 5000;
        osc[i].SetFreq(freq[i]);
    }
}
int main
{
    hardware.Configure();
    hardware.Init();
    float samplerate = hardware.AudioSampleRate();

    AdcChannelConfig adcConfig[2];
    adcConfig[0].InitSingle(hardware.GetPin(21));
    adcConfig[1].InitSingle(hardware.GetPin(22));
    hardware.adc.Init(adcConfig, 2);
    hardware.adc.Start(); 

    SetupOsc(samplerate);
    FreqOsc();

    int val = hardware.adc.GetFloat(0);
    
    for(int i = 0; i < 32; i++)
    {
        int temp = val >> i;
        bin[i] = temp& 0x00000001; /
    }

    if(bin[0] == 1)
    {
       hardware.StartAudio(Audio0Callback); 
    }
    if(bin[1] == 1)
    {
       hardware.StartAudio(Audio1Callback); 
    }
    if(bin[2] == 1)
    {
       hardware.StartAudio(Audio2Callback); 
    }
    
    for(;;) {}
}

I know that I could put the oscillators in the same AudioCallback but the idea is to be able to activate and deactivate their output based on a series of bits that I saved in an array. In the end I would like to create 32 AudioCallback. One for each cell in the array.

Thanks.

Your idea is wrong. There’s just 1 audio callback that you must set during patch initialization. You can do whatever mixing you want inside it.

In that case, how could I call different oscillators over time? When I call osc [i] .Process (); I can’t find a way to make it stop
For example:

void AudioCallback(float **in, float **out, size_t size)
    {  
        float out_osc0, out_osc1, out_osc2;
        for(size_t i = 0; i < size; i++)
        {  
             if(bin[0] == 1)
             {
                osc_out0 = osc[0].Process(); 
             }
             if(bin[1] == 1)
             {
                osc_out1 = osc[1].Process();
             }
             if(bin[2] == 1)
             {
                 osc_out2 = osc[2].Process();
              }

             out[0][i] =  osc_out0 + osc_out1 + osc_out2;
             out[1][i] = osc_out0 + osc_out1 + osc_out2;
        }
    }

This is not working for me.

I think your code should look something like this if you want to run 32 osc’s at the same time:

void AudioCallback(float *in, float *out, size_t size)
{  
	float sig;

    for(size_t i = 0; i < size; i += 2)
    {
		sig = 0;

		for (int j = 0; j < 32; j++)
		{
	        sig += osc[j].Process() / 32;
		}
        out[i] = sig;
        out[i + 1] = sig;
    }
}

You control the volume from each osc using for example an ADSR or a multiplication factor in the audio callback (instead of dividing by 32, you could multiply with 1/32 or 0 if you want that osc to be silent).

You can look at my code here (OscPocketD - Portable music tool (sequencing drums and synths) - #10 by StaffanMelin) to see how I mix different oscillators in the audio callback.

If this is not what you want, please elaborate on what your goal is. :slight_smile:

Staffan

1 Like

This method generates a single sample, you don’t need to stop anything.

Thank you very much @StaffanMelin and @antisvin.
The example you give me works for me.
Based on what you have told me, I will try to explain what I am trying to do. I am passing the value of the variable hardware.adc.GetFloat(0) to binary and storing the bits in a bin[32] vector that should be updated if the value of hardware.adc.GetFloat (0) changes. Afterwards, what I try is that the values stored in bin[], turn each oscillator on or off according to the equality bin [i] == 1. This I am applying on the amplitude of each oscillator in void AmpOsc () but it does not work for me.

The result should be that each oscillator independently sounds or not if I change the value of hardware.adc.GetFloat (0).

I hope you can understand me. My English and my programming experience are not good. :rofl: :smile:

int bin[32];
void AudioCallback(float *in, float *out, size_t size)
{  
    float sig;

    for(size_t i = 0; i < size; i += 2)
    {
        sig = 0;

        for (int j = 0; j < 32; j++)
        {
            sig += osc[j].Process() / 32);
        }
       
        out[i] = sig;
        out[i + 1] = sig;
    }
}
void SetupOsc(float samplerate)
{   
    //float sig[32];
    
    for(int i = 0; i < 32; i++)
    {
        osc[i].Init(samplerate);
    }
}
void AmpOsc(int bin[])
{   
    for(int i = 0; i < 32; i++)
    {
        if (bin[i] == 1)
        {
            osc[i].SetAmp(.7);
        }
        else
        {
            osc[i].SetAmp(0.0);
        }
    }
}
void FreqOsc()
{
    for(int i = 0; i < mod; i++)
    {
        freq[i] = 100.0 + rand() % 2000;
        osc[i].SetFreq(freq[i]);
    }
}
int main(void)
{
      hardware.Configure();
    hardware.Init();
    float samplerate = hardware.AudioSampleRate();
    
    AdcChannelConfig adcConfig[2];
    adcConfig[0].InitSingle(hardware.GetPin(21));
    adcConfig[1].InitSingle(hardware.GetPin(22));
    hardware.adc.Init(adcConfig, 2); 
    hardware.adc.Start(); 
    
    SetupOsc(samplerate);
    FreqOsc();

    //Decimal to binario
    //--------------
    int val = hardware.adc.GetFloat(0);
    for(int i = 0; i < mod; i++)
    {
        int temp = val >> i;
        bin[i] = temp& 0x00000001; 
    }
    AmpOsc(bin);

    hardware.StartAudio(AudioCallback); 
    for(;;) {}
}

Your english is not bad at all!

Your code should be structured more like this:

#define OSC_COUNT 32

int bin[OSC_COUNT];


void AudioCallback(float *in, float *out, size_t size)
{  
	float sig;
	float factor;

	int val = hardware.adc.GetFloat(0);
	for(int i = 0; i < OSC_COUNT; i++)
	{
		int temp = val >> i;
		bin[i] = temp& 0x00000001; 
	}

	for(size_t i = 0; i < size; i += 2)
	{
		sig = 0;

		for (int j = 0; j < OSC_COUNT; j++)
		{
			if (bin[j] == 1)
			{
				factor = 1 / 32.0f;
			} else {
				factor = 0;
			}
			sig += osc[j].Process() * factor;
		}
	   
		out[i] = sig;
		out[i + 1] = sig;
	}
}



void SetupOsc(float samplerate)
{   
	for (int i = 0; i < 32; i++)
	{
		osc[i].Init(samplerate);
		freq[i] = 100.0 + rand() % 2000;
		osc[i].SetFreq(freq[i]);
		osc[i].SetAmp(0.7);
	}
}

int main(void)
{
	hardware.Configure();
	hardware.Init();
	float samplerate = hardware.AudioSampleRate();
	
	AdcChannelConfig adcConfig[2];
	adcConfig[0].InitSingle(hardware.GetPin(21));
	adcConfig[1].InitSingle(hardware.GetPin(22));
	hardware.adc.Init(adcConfig, 2); 
	hardware.adc.Start(); 
	
	SetupOsc(samplerate);

	hardware.StartAudio(AudioCallback); 

	for(;;) {}
}

I’m not really sure how you are translating the pot values into 0:s or 1:s, but that is your problem! :smiley:

Remember that what happens in main() is only run once (except the for-loop at the end). The audio callback is run repeatedly. (It is a bit like setup() and loop() in Arduino.)

Good luck and please don’t hesitate to ask for more help!

Staffan
SWEDEN

1 Like