Welcome, Guest. Please login or register. Did you miss your activation email?

Show Posts

This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.


Messages - pauly70605

Pages: [1]
1
Audio / Continuous sound stream from generator function
« on: February 17, 2017, 05:28:45 pm »
Hi, I have been having some trouble developing a project on SFML.

The idea:
I have a class object "boite" that contains a function s_xt that outputs a signal as a function of time and space based on its internal structure. What I would like to do is play this signal at a given location across time. Essentially, I need to sample the generator function s_xt(double x, double t) for a constant space value x and a variable time value t. This function is normalized such that the output is between zero and one. The function is subject to dynamic change, so writing to a .wav file is not a good idea.

The problem:
I need to output the function at a given spatial position directly to the sound card. Essentially the operation:
while(running)
{
     soundcard << boite.s_xt(x,t);
     t += dt;
}
 

Of course things are more complicated. I believe a soundstream is the answer to my question. Regular buffering will not work because the function is not harmonic, so there will always be discontinuities at the end of the buffer leading to clicking sounds.

An attempt at a solution:
I think that perhaps the way to do this is to have two buffers stores in an inherited class from sf::SoundStream. One buffer would be active, and the other buffer would be filled as the active one is played. So, when the program asks for more data and calls onGetData, we point the data chunk to the previous filled buffer, delete the old buffer, and then fill the next buffer from the generator function. 

class soundstream:

 
#ifndef SOUNDSTREAM_H
#define SOUNDSTREAM_H

#include <SFML/Audio.hpp>

#include "../boite/boite.h"

#define SOUNDSAMPLES 1500
#define DTSOUND 0.01
#define AMPSOUND 30000

class soundstream : public sf::SoundStream{
        public:
                // load the soundBox into the soundstream and intialize
                void load(boite* boxX)
                {
                        soundBox_m = boxX;               
                        t_m = 0;       
                        x_m = 0.5;
                        fillBuffer(activeBuffer_m);
                        // set the next buffer to null for the onGetData function
                        nextBuffer_m = nullptr;
                        initialize(1,44100);
                }

                // function to call to fill a buffer by sampling the soundBox
                void fillBuffer(sf::Int16* paramBuffer)
                {
                        // allocate a new block of memeory for the buffer
                        paramBuffer = new sf::Int16[SOUNDSAMPLES];
                        // fill
                        for(int i = 0; i < SOUNDSAMPLES; i++)
                        {
                                paramBuffer[i] = AMPSOUND * soundBox_m->s_xt(x_m, t_m).real(); // s_xt is a complex function, only play real part
                                // to make sure that we're not getting zeros, print the signal
                                std::cout << soundBox_m->s_xt(x_m, t_m) << '\n';
                                t_m += DTSOUND;
                               
                        }
                }
        private:
                // overload onGetData
                virtual bool onGetData(Chunk& data)
                {      
                        // if the next buffer is not null (first iteration) delete the current buffer and change the buffers
                        if(nextBuffer_m != nullptr)
                        {
                                delete activeBuffer_m;
                                activeBuffer_m = nextBuffer_m;
                        }

                        // point the data to the first sample of the new sample and set its count
                        data.samples = activeBuffer_m;
                        data.sampleCount = SOUNDSAMPLES;

                        // fill next sample
                        fillBuffer(nextBuffer_m);
                        return true;

                }
                // overlad onSeek as empty function (for now)
                virtual void onSeek(sf::Time timeOffset){};

                // internal time and position
                double x_m;
                double t_m;

                // two buffers
                sf::Int16* activeBuffer_m;
                sf::Int16* nextBuffer_m;

                // soundBox pointer            
                boite* soundBox_m;
};


#endif

 

basic main code idea

#include "boite.h"
#include "soundstream.h"

boite box1;
soundstream box1stream

int main()
{
     box1.defineS(params) // a bit more complicated, but that's the idea      
     box1stream.load(box1);
     box1stream.play();
}
     
 

What happens:
I get no sound.  The cout gives a sample of values on load, and another sample of values on play, but then stops. So it does not continue to sample for more than one iteration.

The Question:
Can someone please help? Either a way to fix this implementation, or a way to constantly output the values of the signal to the soundcard. Also, comments on the implementation would be nice as this is part of a larger project.

Thanks in advance!

Pages: [1]